beagle, cache: activate cache command
RFC PATCH 18/19 beagle, cache: activate cache command
Signed-off-by Heiko Schocher <[email protected]>
--- arch/arm/cpu/armv7/omap3/cache.S | 82 ++++++++++++++++++++++++++++++++++++ arch/arm/include/asm/global_data.h | 3 + arch/arm/lib/board.c | 11 +++++ arch/arm/lib/cache-cp15.c | 33 +++++++++++---- arch/arm/lib/cache.c | 5 ++ common/cmd_bdinfo.c | 3 + include/configs/omap3_beagle.h | 1 + 7 files changed, 130 insertions(+), 8 deletions(-)
arch/arm/cpu/armv7/omap3/cache.S +82 -0
@@ -189,3 +189,85 @@ l2_cache_disable_EARLIER_THAN_ES2: str r3, [sp, #4] l2_cache_disable_END: ldmfd r13!, {r1, r2, r3, pc} + +.align 5 +.global v7_flush_dcache_all +.global v7_flush_cache_all + +/* + * v7_flush_dcache_all() + * + * Flush the whole D-cache. + * + * Corrupted registers: r0-r7, r9-r11 (r6 only in Thumb mode) + * + * - mm - mm_struct describing address space + */ +v7_flush_dcache_all: +# dmb @ ensure ordering with previous memory accesses + mrc p15, 1, r0, c0, c0, 1 @ read clidr + ands r3, r0, #0x7000000 @ extract loc from clidr + mov r3, r3, lsr #23 @ left align loc bit field + beq finished @ if loc is 0, then no need to clean + mov r10, #0 @ start clean at cache level 0 +loop1: + add r2, r10, r10, lsr #1 @ work out 3x current cache level + mov r1, r0, lsr r2 @ extract cache type bits from clidr + and r1, r1, #7 @ mask of the bits for current cache only + cmp r1, #2 @ see what cache we have at this level + blt skip @ skip if no cache, or just i-cache + mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr + mcr p15, 0, r10, c7, c5, 4 @ flush prefetch buffer, + @ with armv7 this is 'isb', + @ but we compile with armv5 + mrc p15, 1, r1, c0, c0, 0 @ read the new csidr + and r2, r1, #7 @ extract the length of the cache lines + add r2, r2, #4 @ add 4 (line length offset) + ldr r4, =0x3ff + ands r4, r4, r1, lsr #3 @ find maximum number on the way size + clz r5, r4 @ find bit position of way size increment + ldr r7, =0x7fff + ands r7, r7, r1, lsr #13 @ extract max number of the index size +loop2: + mov r9, r4 @ create working copy of max way size +loop3: + orr r11, r10, r9, lsl r5 @ factor way and cache number into r11 + orr r11, r11, r7, lsl r2 @ factor index number into r11 + mcr p15, 0, r11, c7, c14, 2 @ clean & invalidate by set/way + subs r9, r9, #1 @ decrement the way + bge loop3 + subs r7, r7, #1 @ decrement the index + bge loop2 +skip: + add r10, r10, #2 @ increment cache number + cmp r3, r10 + bgt loop1 +finished: + mov r10, #0 @ swith back to cache level 0 + mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr +# dsb + mcr p15, 0, r10, c7, c5, 4 @ flush prefetch buffer, + @ with armv7 this is 'isb', + @ but we compile with armv5 + mov pc, lr + +/* + * v7_flush_cache_all() + * + * Flush the entire cache system. + * The data cache flush is now achieved using atomic clean / invalidates + * working outwards from L1 cache. This is done using Set/Way based cache + * maintainance instructions. + * The instruction cache can still be invalidated back to the point of + * unification in a single instruction. + * + */ +v7_flush_cache_all: + stmfd sp!, {r0-r7, r9-r11, lr} + bl v7_flush_dcache_all + mov r0, #0 + mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate + ldmfd sp!, {r0-r7, r9-r11, lr} + mov pc, lr + +
arch/arm/include/asm/global_data.h +3 -0
@@ -59,6 +59,9 @@ typedef struct global_data {unsigned long irq_sp;/* irq stack pointer */ unsigned long start_addr_sp;/* start_addr_stackpointer */ unsigned long reloc_off; +#if !(defined(CONFIG_SYS_NO_ICACHE ) && defined(CONFIG_SYS_NO_DCACHE )) +unsigned long tlb_addr; +#endif void **jt;/* jump table */ } gd_t;
arch/arm/lib/board.c +11 -0
@@ -320,6 +320,17 @@ void board_init_f (ulong bootflag)debug ("Reserving %ldk for protected RAM at %08lx\n" , reg, addr);#endif /* CONFIG_PRAM */ +#if !(defined(CONFIG_SYS_NO_ICACHE ) && defined(CONFIG_SYS_NO_DCACHE )) +/* reserve TLB table */ + addr -= (4096 *4 ); + +/* round down to next 64 kB limit */ + addr &= ~(0x10000 -1 ); + + gd->tlb_addr = addr; +debug ("TLB table at: %08lx\n" , addr); +#endif +/* round down to next 4 kB limit */ addr &= ~(4096 -1 );debug ("Top of RAM usable for U-Boot at: %08lx\n" , addr);
arch/arm/lib/cache-cp15.c +25 -8
@@ -25,6 +25,9 @@#include <asm/system.h> #if !(defined(CONFIG_SYS_NO_ICACHE ) && defined(CONFIG_SYS_NO_DCACHE )) + +DECLARE_GLOBAL_DATA_PTR ; +static void cp_delay (void ) {volatile int i;
@@ -35,21 +38,32 @@ static void cp_delay (void) asmvolatile ("" : : :"memory" ); } -/* to activate the MMU we need to set up virtual memory: use 1M areas in bss */ +static inline void dram_bank_mmu_setup (int bank) +{ +u32 *page_table = (u32 *)gd->tlb_addr; +int i; + +debug ("%s: bank: %d\n" , __func__, bank); +for (i = gd->bd->bi_dram[bank].start >>20 ; + i < (gd->bd->bi_dram[bank].start + gd->bd->bi_dram[bank].size) >>20 ; + i++) { +/* C and B bit set */ + page_table[i] = i <<20 | (3 <<10 ) |0x1e ; + } +} + +/* to activate the MMU we need to set up virtual memory: use 1M areas */ static inline void mmu_setup (void ) { -static u32 __attribute__((aligned (16384 ))) page_table[4096 ]; +u32 *page_table = (u32 *)gd->tlb_addr;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 ; +for (i=0 ; i<CONFIG_NR_DRAM_BANKS ; ++i) { +dram_bank_mmu_setup (i); }/* Copy the page table address to cp15 */ asm volatile("mcr p15, 0, %0, c2, c0, 0"
@@ -61,7 +75,6 @@ static inline void mmu_setup(void) reg =get_cr ();/* get control reg. */ cp_delay ();set_cr (reg |CR_M ); - }/* cache_bit must be either CR_I or CR_C */
@@ -83,6 +96,10 @@ static void cache_disable(uint32_t cache_bit)uint32_t reg;if (cache_bit ==CR_C ) { +/* if cache isn;t enabled no need to disable */ + reg =get_cr (); +if ((reg &CR_C ) !=CR_C ) +return ;/* if disabling data cache, disable mmu too */ cache_bit |=CR_M ;flush_cache (0 , ~0 );
arch/arm/lib/cache.c +5 -0
@@ -38,5 +38,10 @@ void flush_cache (unsigned long dummy1, unsigned long dummy2)/* disable write buffer as well (page 2-22) */ asm("mcr p15, 0, %0, c7, c10, 4" : :"r" (0 ));#endif +#ifdef CONFIG_ARMCORTEXA8 +void v7_flush_cache_all (void ); + +v7_flush_cache_all (); +#endif return ; }
common/cmd_bdinfo.c +3 -0
@@ -343,6 +343,9 @@ int do_bdinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])printf ("ip_addr = %pI4\n" , &bd->bi_ip_addr);#endif printf ("baudrate = %d bps\n" , bd->bi_baudrate); +#if !(defined(CONFIG_SYS_NO_ICACHE ) && defined(CONFIG_SYS_NO_DCACHE )) +print_num ("TLB addr" , gd->tlb_addr); +#endif print_num ("relocaddr" , gd->relocaddr);print_num ("reloc off" , gd->reloc_off);print_num ("irq_sp" , gd->irq_sp);/* irq stack pointer */
include/configs/omap3_beagle.h +1 -0
@@ -120,6 +120,7 @@/* commands to include */ #include <config_cmd_default.h> +#define CONFIG_CMD_CACHE #define CONFIG_CMD_EXT2 /* EXT2 Support */ #define CONFIG_CMD_FAT /* FAT support */ #define CONFIG_CMD_JFFS2 /* JFFS2 Support */
Signature · 5 lines
1.6.2.5 -- DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
PATCH v2 18/19 beagle, cache: activate cache command
Signed-off-by Heiko Schocher <[email protected]>
---
- changes since v1:
rebased as patch "arm cp15: setup mmu and enable dcache" changed.
arch/arm/cpu/armv7/omap3/cache.S | 82 ++++++++++++++++++++++++++++++++++++ arch/arm/include/asm/global_data.h | 3 + arch/arm/lib/board.c | 11 +++++ arch/arm/lib/cache-cp15.c | 35 ++++++++++----- arch/arm/lib/cache.c | 5 ++ common/cmd_bdinfo.c | 3 + include/configs/omap3_beagle.h | 1 + 7 files changed, 128 insertions(+), 12 deletions(-)
arch/arm/cpu/armv7/omap3/cache.S +82 -0
@@ -189,3 +189,85 @@ l2_cache_disable_EARLIER_THAN_ES2: str r3, [sp, #4] l2_cache_disable_END: ldmfd r13!, {r1, r2, r3, pc} + +.align 5 +.global v7_flush_dcache_all +.global v7_flush_cache_all + +/* + * v7_flush_dcache_all() + * + * Flush the whole D-cache. + * + * Corrupted registers: r0-r7, r9-r11 (r6 only in Thumb mode) + * + * - mm - mm_struct describing address space + */ +v7_flush_dcache_all: +# dmb @ ensure ordering with previous memory accesses + mrc p15, 1, r0, c0, c0, 1 @ read clidr + ands r3, r0, #0x7000000 @ extract loc from clidr + mov r3, r3, lsr #23 @ left align loc bit field + beq finished @ if loc is 0, then no need to clean + mov r10, #0 @ start clean at cache level 0 +loop1: + add r2, r10, r10, lsr #1 @ work out 3x current cache level + mov r1, r0, lsr r2 @ extract cache type bits from clidr + and r1, r1, #7 @ mask of the bits for current cache only + cmp r1, #2 @ see what cache we have at this level + blt skip @ skip if no cache, or just i-cache + mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr + mcr p15, 0, r10, c7, c5, 4 @ flush prefetch buffer, + @ with armv7 this is 'isb', + @ but we compile with armv5 + mrc p15, 1, r1, c0, c0, 0 @ read the new csidr + and r2, r1, #7 @ extract the length of the cache lines + add r2, r2, #4 @ add 4 (line length offset) + ldr r4, =0x3ff + ands r4, r4, r1, lsr #3 @ find maximum number on the way size + clz r5, r4 @ find bit position of way size increment + ldr r7, =0x7fff + ands r7, r7, r1, lsr #13 @ extract max number of the index size +loop2: + mov r9, r4 @ create working copy of max way size +loop3: + orr r11, r10, r9, lsl r5 @ factor way and cache number into r11 + orr r11, r11, r7, lsl r2 @ factor index number into r11 + mcr p15, 0, r11, c7, c14, 2 @ clean & invalidate by set/way + subs r9, r9, #1 @ decrement the way + bge loop3 + subs r7, r7, #1 @ decrement the index + bge loop2 +skip: + add r10, r10, #2 @ increment cache number + cmp r3, r10 + bgt loop1 +finished: + mov r10, #0 @ swith back to cache level 0 + mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr +# dsb + mcr p15, 0, r10, c7, c5, 4 @ flush prefetch buffer, + @ with armv7 this is 'isb', + @ but we compile with armv5 + mov pc, lr + +/* + * v7_flush_cache_all() + * + * Flush the entire cache system. + * The data cache flush is now achieved using atomic clean / invalidates + * working outwards from L1 cache. This is done using Set/Way based cache + * maintainance instructions. + * The instruction cache can still be invalidated back to the point of + * unification in a single instruction. + * + */ +v7_flush_cache_all: + stmfd sp!, {r0-r7, r9-r11, lr} + bl v7_flush_dcache_all + mov r0, #0 + mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate + ldmfd sp!, {r0-r7, r9-r11, lr} + mov pc, lr + +
arch/arm/include/asm/global_data.h +3 -0
@@ -59,6 +59,9 @@ typedef struct global_data {unsigned long irq_sp;/* irq stack pointer */ unsigned long start_addr_sp;/* start_addr_stackpointer */ unsigned long reloc_off; +#if !(defined(CONFIG_SYS_NO_ICACHE ) && defined(CONFIG_SYS_NO_DCACHE )) +unsigned long tlb_addr; +#endif void **jt;/* jump table */ } gd_t;
arch/arm/lib/board.c +11 -0
@@ -320,6 +320,17 @@ void board_init_f (ulong bootflag)debug ("Reserving %ldk for protected RAM at %08lx\n" , reg, addr);#endif /* CONFIG_PRAM */ +#if !(defined(CONFIG_SYS_NO_ICACHE ) && defined(CONFIG_SYS_NO_DCACHE )) +/* reserve TLB table */ + addr -= (4096 *4 ); + +/* round down to next 64 kB limit */ + addr &= ~(0x10000 -1 ); + + gd->tlb_addr = addr; +debug ("TLB table at: %08lx\n" , addr); +#endif +/* round down to next 4 kB limit */ addr &= ~(4096 -1 );debug ("Top of RAM usable for U-Boot at: %08lx\n" , addr);
arch/arm/lib/cache-cp15.c +23 -12
@@ -44,24 +44,32 @@ static void cp_delay (void) 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 inline void dram_bank_mmu_setup (int bank) { -static u32 __attribute__((aligned (16384 ))) page_table[4096 ]; +u32 *page_table = (u32 *)gd->tlb_addr;bd_t *bd = gd->bd; -int i, j; +int i; + +debug ("%s: bank: %d\n" , __func__, bank); +for (i = bd->bi_dram[bank].start >>20 ; + i < (bd->bi_dram[bank].start + bd->bi_dram[bank].size) >>20 ; + i++) { + page_table[i] = i <<20 | (3 <<10 ) |CACHE_SETUP ; + } +} + +/* to activate the MMU we need to set up virtual memory: use 1M areas */ +static inline void mmu_setup (void ) +{ +u32 *page_table = (u32 *)gd->tlb_addr; +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 (j = 0 < CONFIG_NR_DRAM_BANKS; j++) { -for (i = bd->bi_dram[j].start >>20 ; - i < (bd->bi_dram[j].start + bd->bi_dram[j].size) >>20 ; - i++) { - page_table[i] = i <<20 | (3 <<10 ) |CACHE_SETUP ; - } +for (i =0 ; i <CONFIG_NR_DRAM_BANKS ; i++) { +dram_bank_mmu_setup (i); }/* Copy the page table address to cp15 */
@@ -74,7 +82,6 @@ static inline void mmu_setup(void) reg =get_cr ();/* get control reg. */ cp_delay ();set_cr (reg |CR_M ); - }/* cache_bit must be either CR_I or CR_C */
@@ -96,6 +103,10 @@ static void cache_disable(uint32_t cache_bit)uint32_t reg;if (cache_bit ==CR_C ) { +/* if cache isn;t enabled no need to disable */ + reg =get_cr (); +if ((reg &CR_C ) !=CR_C ) +return ;/* if disabling data cache, disable mmu too */ cache_bit |=CR_M ;flush_cache (0 , ~0 );
arch/arm/lib/cache.c +5 -0
@@ -38,5 +38,10 @@ void flush_cache (unsigned long dummy1, unsigned long dummy2)/* disable write buffer as well (page 2-22) */ asm("mcr p15, 0, %0, c7, c10, 4" : :"r" (0 ));#endif +#ifdef CONFIG_ARMCORTEXA8 +void v7_flush_cache_all (void ); + +v7_flush_cache_all (); +#endif return ; }
common/cmd_bdinfo.c +3 -0
@@ -343,6 +343,9 @@ int do_bdinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])printf ("ip_addr = %pI4\n" , &bd->bi_ip_addr);#endif printf ("baudrate = %d bps\n" , bd->bi_baudrate); +#if !(defined(CONFIG_SYS_NO_ICACHE ) && defined(CONFIG_SYS_NO_DCACHE )) +print_num ("TLB addr" , gd->tlb_addr); +#endif print_num ("relocaddr" , gd->relocaddr);print_num ("reloc off" , gd->reloc_off);print_num ("irq_sp" , gd->irq_sp);/* irq stack pointer */
include/configs/omap3_beagle.h +1 -0
@@ -120,6 +120,7 @@/* commands to include */ #include <config_cmd_default.h> +#define CONFIG_CMD_CACHE #define CONFIG_CMD_EXT2 /* EXT2 Support */ #define CONFIG_CMD_FAT /* FAT support */ #define CONFIG_CMD_JFFS2 /* JFFS2 Support */
Signature · 5 lines
1.6.2.5 -- DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
PATCH v2 18/19 beagle, cache: activate cache command
Quoted 5 lines · Heiko Schocher
Signed-off-by Heiko Schocher <[email protected]>---
- changes since v1:
?rebased as patch "arm cp15: setup mmu and enable dcache" ?changed.
Reviewed-by Ben Gardiner<[email protected]>
Thank you, Heiko. That's pretty much the patch I manually merged.
Best Regards,
Ben Gardiner
---
Nanometrics Inc.
http://www.nanometrics.ca