diff options
author | Nicolas Pitre | 2008-09-11 15:14:59 -0400 |
---|---|---|
committer | Nicolas Pitre | 2008-09-30 13:41:54 -0400 |
commit | 99c6bb390cf599b9e0aa6e69beacc4e5d875bf77 (patch) | |
tree | d30e32867cd161001e5ae6fecc51a52f469bbaff /arch/arm | |
parent | 92a5de80e5c53c56d098ea3cb6266138efd892f6 (diff) |
[ARM] Feroceon: small cleanups to L2 cache code
- Make sure that coprocessor instructions for range ops are contiguous
and not reordered.
- s/invalidate_and_disable_dcache/flush_and_disable_dcache/
- Don't re-enable I/D caches if they were not enabled initially.
- Change some masks to shifts for better generated code.
Signed-off-by: Nicolas Pitre <nico@marvell.com>
Acked-by: Lennert Buytenhek <buytenh@marvell.com>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/mm/cache-feroceon-l2.c | 42 |
1 files changed, 25 insertions, 17 deletions
diff --git a/arch/arm/mm/cache-feroceon-l2.c b/arch/arm/mm/cache-feroceon-l2.c index 7b5a25d81576..13cdae8b0d44 100644 --- a/arch/arm/mm/cache-feroceon-l2.c +++ b/arch/arm/mm/cache-feroceon-l2.c @@ -48,11 +48,12 @@ static inline void l2_clean_mva_range(unsigned long start, unsigned long end) * L2 is PIPT and range operations only do a TLB lookup on * the start address. */ - BUG_ON((start ^ end) & ~(PAGE_SIZE - 1)); + BUG_ON((start ^ end) >> PAGE_SHIFT); raw_local_irq_save(flags); - __asm__("mcr p15, 1, %0, c15, c9, 4" : : "r" (start)); - __asm__("mcr p15, 1, %0, c15, c9, 5" : : "r" (end)); + __asm__("mcr p15, 1, %0, c15, c9, 4\n\t" + "mcr p15, 1, %1, c15, c9, 5" + : : "r" (start), "r" (end)); raw_local_irq_restore(flags); } @@ -80,11 +81,12 @@ static inline void l2_inv_mva_range(unsigned long start, unsigned long end) * L2 is PIPT and range operations only do a TLB lookup on * the start address. */ - BUG_ON((start ^ end) & ~(PAGE_SIZE - 1)); + BUG_ON((start ^ end) >> PAGE_SHIFT); raw_local_irq_save(flags); - __asm__("mcr p15, 1, %0, c15, c11, 4" : : "r" (start)); - __asm__("mcr p15, 1, %0, c15, c11, 5" : : "r" (end)); + __asm__("mcr p15, 1, %0, c15, c11, 4\n\t" + "mcr p15, 1, %1, c15, c11, 5" + : : "r" (start), "r" (end)); raw_local_irq_restore(flags); } @@ -205,7 +207,7 @@ static void feroceon_l2_flush_range(unsigned long start, unsigned long end) * time. These are necessary because the L2 cache can only be enabled * or disabled while the L1 Dcache and Icache are both disabled. */ -static void __init invalidate_and_disable_dcache(void) +static int __init flush_and_disable_dcache(void) { u32 cr; @@ -217,7 +219,9 @@ static void __init invalidate_and_disable_dcache(void) flush_cache_all(); set_cr(cr & ~CR_C); raw_local_irq_restore(flags); + return 1; } + return 0; } static void __init enable_dcache(void) @@ -225,18 +229,17 @@ static void __init enable_dcache(void) u32 cr; cr = get_cr(); - if (!(cr & CR_C)) - set_cr(cr | CR_C); + set_cr(cr | CR_C); } static void __init __invalidate_icache(void) { int dummy; - __asm__ __volatile__("mcr p15, 0, %0, c7, c5, 0\n" : "=r" (dummy)); + __asm__ __volatile__("mcr p15, 0, %0, c7, c5, 0" : "=r" (dummy)); } -static void __init invalidate_and_disable_icache(void) +static int __init invalidate_and_disable_icache(void) { u32 cr; @@ -244,7 +247,9 @@ static void __init invalidate_and_disable_icache(void) if (cr & CR_I) { set_cr(cr & ~CR_I); __invalidate_icache(); + return 1; } + return 0; } static void __init enable_icache(void) @@ -252,8 +257,7 @@ static void __init enable_icache(void) u32 cr; cr = get_cr(); - if (!(cr & CR_I)) - set_cr(cr | CR_I); + set_cr(cr | CR_I); } static inline u32 read_extra_features(void) @@ -291,13 +295,17 @@ static void __init enable_l2(void) u = read_extra_features(); if (!(u & 0x00400000)) { + int i, d; + printk(KERN_INFO "Feroceon L2: Enabling L2\n"); - invalidate_and_disable_dcache(); - invalidate_and_disable_icache(); + d = flush_and_disable_dcache(); + i = invalidate_and_disable_icache(); write_extra_features(u | 0x00400000); - enable_icache(); - enable_dcache(); + if (i) + enable_icache(); + if (d) + enable_dcache(); } } |