]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/sh/mm/init.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6.25
[linux-2.6-omap-h63xx.git] / arch / sh / mm / init.c
index 79c309780f953a16bf65c621aae490ffe10e9c8d..53dde06073627d693d431fd308e6c647d87da30e 100644 (file)
@@ -23,6 +23,7 @@
 
 DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 pgd_t swapper_pg_dir[PTRS_PER_PGD];
+unsigned long cached_to_uncached = 0;
 
 void show_mem(void)
 {
@@ -99,7 +100,8 @@ static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot)
 
        set_pte(pte, pfn_pte(phys >> PAGE_SHIFT, prot));
 
-       flush_tlb_one(get_asid(), addr);
+       if (cached_to_uncached)
+               flush_tlb_one(get_asid(), addr);
 }
 
 /*
@@ -128,6 +130,37 @@ void __set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot)
 
        set_pte_phys(address, phys, prot);
 }
+
+void __init page_table_range_init(unsigned long start, unsigned long end,
+                                        pgd_t *pgd_base)
+{
+       pgd_t *pgd;
+       pud_t *pud;
+       pmd_t *pmd;
+       int pgd_idx;
+       unsigned long vaddr;
+
+       vaddr = start & PMD_MASK;
+       end = (end + PMD_SIZE - 1) & PMD_MASK;
+       pgd_idx = pgd_index(vaddr);
+       pgd = pgd_base + pgd_idx;
+
+       for ( ; (pgd_idx < PTRS_PER_PGD) && (vaddr != end); pgd++, pgd_idx++) {
+               BUG_ON(pgd_none(*pgd));
+               pud = pud_offset(pgd, 0);
+               BUG_ON(pud_none(*pud));
+               pmd = pmd_offset(pud, 0);
+
+               if (!pmd_present(*pmd)) {
+                       pte_t *pte_table;
+                       pte_table = (pte_t *)alloc_bootmem_low_pages(PAGE_SIZE);
+                       memset(pte_table, 0, PAGE_SIZE);
+                       pmd_populate_kernel(&init_mm, pmd, pte_table);
+               }
+
+               vaddr += PMD_SIZE;
+       }
+}
 #endif /* CONFIG_MMU */
 
 /*
@@ -147,6 +180,11 @@ void __init paging_init(void)
         * check for a null value. */
        set_TTB(swapper_pg_dir);
 
+       /* Populate the relevant portions of swapper_pg_dir so that
+        * we can use the fixmap entries without calling kmalloc.
+        * pte's will be filled in by __set_fixmap(). */
+       page_table_range_init(FIXADDR_START, FIXADDR_TOP, swapper_pg_dir);
+
        memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
 
        for_each_online_node(nid) {
@@ -164,6 +202,20 @@ void __init paging_init(void)
        }
 
        free_area_init_nodes(max_zone_pfns);
+
+#ifdef CONFIG_SUPERH32
+       /* Set up the uncached fixmap */
+       set_fixmap_nocache(FIX_UNCACHED, __pa(&__uncached_start));
+
+#ifdef CONFIG_29BIT
+       /*
+        * Handle trivial transitions between cached and uncached
+        * segments, making use of the 1:1 mapping relationship in
+        * 512MB lowmem.
+        */
+       cached_to_uncached = P2SEG - P1SEG;
+#endif
+#endif
 }
 
 static struct kcore_list kcore_mem, kcore_vmalloc;
@@ -276,7 +328,7 @@ int arch_add_memory(int nid, u64 start, u64 size)
        /* We only have ZONE_NORMAL, so this is easy.. */
        ret = __add_pages(pgdat->node_zones + ZONE_NORMAL, start_pfn, nr_pages);
        if (unlikely(ret))
-               printk("%s: Failed, __add_pages() == %d\n", __FUNCTION__, ret);
+               printk("%s: Failed, __add_pages() == %d\n", __func__, ret);
 
        return ret;
 }