arm cp15: setup mmu and enable dcache
RFC PATCH 2/2 arm cp15: setup mmu and enable dcache
This has been tested on at91sam9263 and STN8815. Again, I didn't check if it has bad effects
on non-arm926 cores.
Initially I had a "done" bit to only set up page tables at the beginning. However, since the aligmnent requirement was for the whole object file, this extra integer tool 16kB in BSS, so I chose to remove it.
Also, note not all boards use PHYS_SDRAM, but it looks like it's the most used name (more than CONFIG_SYS_DRAM_BASE for example).
Signed-off-by Alessandro Rubini <[email protected]>
--- lib_arm/cache-cp15.c | 37 +++++++++++++++++++++++++++++++++++++ 1 files changed, 37 insertions(+), 0 deletions(-)
lib_arm/cache-cp15.c +37 -0
@@ -32,6 +32,35 @@ static void cp_delay (void)/* copro seems to need some delay between reading and writing */ for (i =0 ; i <100 ; i++)nop (); + asmvolatile ("" : : :"memory" ); +} + +/* to activate the MMU we need to set up virtual memory: use 1M areas in bss */ +static inline void mmu_setup (void ) +{ +static u32 __attribute__((aligned (16384 ))) page_table[4096 ]; +int i; +u32 reg; + +/* Set up an identity-mapping for all 4GB, rw for everyone */ +for (i =0 ; i <4096 ; i++) + page_table[i] = i <<20 | (3 <<10 ) |0x12 ; +/* Then, enable cacheable and bufferable for RAM only */ +for (i =PHYS_SDRAM >>20 ; + i < (PHYS_SDRAM +PHYS_SDRAM_SIZE ) >>20 ; + i++) { + page_table[i] = i <<20 | (3 <<10 ) |0x1e ; + } +/* Copy the page table address to cp15 */ + asmvolatile ("mcr p15, 0, %0, c2, c0, 0" + : :"r" (page_table) :"memory" ); +/* Set the access control to all-supervisor */ + asmvolatile ("mcr p15, 0, %0, c3, c0, 0" + : :"r" (~0 )); +/* and enable the mmu */ + reg =get_cr ();/* get control reg. */ +cp_delay (); +set_cr (reg |CR_M ); }/* cache_bit must be either CR_I or CR_C */
@@ -39,6 +68,9 @@ static void cache_enable(uint32_t cache_bit) {uint32_t reg; +/* The data cache is not active unless the mmu is enabled too */ +if (cache_bit ==CR_C ) +mmu_setup (); reg =get_cr ();/* get control reg. */ cp_delay ();set_cr (reg | cache_bit);
@@ -49,6 +81,11 @@ static void cache_disable(uint32_t cache_bit) {uint32_t reg; +if (cache_bit ==CR_C ) { +/* if disabling data cache, disable mmu too */ + cache_bit |=CR_M ; +flush_cache (0 , ~0 ); + } reg =get_cr ();cp_delay ();set_cr (reg & ~cache_bit);
Signature · 1 line
1.6.0.2