diff options
Diffstat (limited to 'arch/arm/mm/mmu.c')
| -rw-r--r-- | arch/arm/mm/mmu.c | 92 | 
1 files changed, 66 insertions, 26 deletions
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index e95a996ab78..e0d8565671a 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -34,6 +34,7 @@  #include <asm/mach/pci.h>  #include "mm.h" +#include "tcm.h"  /*   * empty_zero_page is a special page that is used for @@ -112,6 +113,7 @@ static struct cachepolicy cache_policies[] __initdata = {  	}  }; +#ifdef CONFIG_CPU_CP15  /*   * These are useful for identifying cache coherency   * problems by allowing the cache or the cache and @@ -210,6 +212,22 @@ void adjust_cr(unsigned long mask, unsigned long set)  }  #endif +#else /* ifdef CONFIG_CPU_CP15 */ + +static int __init early_cachepolicy(char *p) +{ +	pr_warning("cachepolicy kernel parameter not supported without cp15\n"); +} +early_param("cachepolicy", early_cachepolicy); + +static int __init noalign_setup(char *__unused) +{ +	pr_warning("noalign kernel parameter not supported without cp15\n"); +} +__setup("noalign", noalign_setup); + +#endif /* ifdef CONFIG_CPU_CP15 / else */ +  #define PROT_PTE_DEVICE		L_PTE_PRESENT|L_PTE_YOUNG|L_PTE_DIRTY|L_PTE_XN  #define PROT_SECT_DEVICE	PMD_TYPE_SECT|PMD_SECT_AP_WRITE @@ -598,39 +616,60 @@ static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr,  	} while (pte++, addr += PAGE_SIZE, addr != end);  } -static void __init alloc_init_section(pud_t *pud, unsigned long addr, -				      unsigned long end, phys_addr_t phys, -				      const struct mem_type *type) +static void __init map_init_section(pmd_t *pmd, unsigned long addr, +			unsigned long end, phys_addr_t phys, +			const struct mem_type *type)  { -	pmd_t *pmd = pmd_offset(pud, addr); - +#ifndef CONFIG_ARM_LPAE  	/* -	 * Try a section mapping - end, addr and phys must all be aligned -	 * to a section boundary.  Note that PMDs refer to the individual -	 * L1 entries, whereas PGDs refer to a group of L1 entries making -	 * up one logical pointer to an L2 table. +	 * In classic MMU format, puds and pmds are folded in to +	 * the pgds. pmd_offset gives the PGD entry. PGDs refer to a +	 * group of L1 entries making up one logical pointer to +	 * an L2 table (2MB), where as PMDs refer to the individual +	 * L1 entries (1MB). Hence increment to get the correct +	 * offset for odd 1MB sections. +	 * (See arch/arm/include/asm/pgtable-2level.h)  	 */ -	if (type->prot_sect && ((addr | end | phys) & ~SECTION_MASK) == 0) { -		pmd_t *p = pmd; - -#ifndef CONFIG_ARM_LPAE -		if (addr & SECTION_SIZE) -			pmd++; +	if (addr & SECTION_SIZE) +		pmd++;  #endif +	do { +		*pmd = __pmd(phys | type->prot_sect); +		phys += SECTION_SIZE; +	} while (pmd++, addr += SECTION_SIZE, addr != end); -		do { -			*pmd = __pmd(phys | type->prot_sect); -			phys += SECTION_SIZE; -		} while (pmd++, addr += SECTION_SIZE, addr != end); +	flush_pmd_entry(pmd); +} -		flush_pmd_entry(p); -	} else { +static void __init alloc_init_pmd(pud_t *pud, unsigned long addr, +				      unsigned long end, phys_addr_t phys, +				      const struct mem_type *type) +{ +	pmd_t *pmd = pmd_offset(pud, addr); +	unsigned long next; + +	do {  		/* -		 * No need to loop; pte's aren't interested in the -		 * individual L1 entries. +		 * With LPAE, we must loop over to map +		 * all the pmds for the given range.  		 */ -		alloc_init_pte(pmd, addr, end, __phys_to_pfn(phys), type); -	} +		next = pmd_addr_end(addr, end); + +		/* +		 * Try a section mapping - addr, next and phys must all be +		 * aligned to a section boundary. +		 */ +		if (type->prot_sect && +				((addr | next | phys) & ~SECTION_MASK) == 0) { +			map_init_section(pmd, addr, next, phys, type); +		} else { +			alloc_init_pte(pmd, addr, next, +						__phys_to_pfn(phys), type); +		} + +		phys += next - addr; + +	} while (pmd++, addr = next, addr != end);  }  static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr, @@ -641,7 +680,7 @@ static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr,  	do {  		next = pud_addr_end(addr, end); -		alloc_init_section(pud, addr, next, phys, type); +		alloc_init_pmd(pud, addr, next, phys, type);  		phys += next - addr;  	} while (pud++, addr = next, addr != end);  } @@ -1256,6 +1295,7 @@ void __init paging_init(struct machine_desc *mdesc)  	dma_contiguous_remap();  	devicemaps_init(mdesc);  	kmap_init(); +	tcm_init();  	top_pmd = pmd_off_k(0xffff0000);  |