diff options
Diffstat (limited to 'arch/arm/mm')
-rw-r--r-- | arch/arm/mm/Kconfig | 8 | ||||
-rw-r--r-- | arch/arm/mm/cache-feroceon-l2.c | 42 | ||||
-rw-r--r-- | arch/arm/mm/proc-feroceon.S | 12 |
3 files changed, 41 insertions, 21 deletions
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index ed15f876c725..330814d1ee25 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig | |||
@@ -735,6 +735,14 @@ config CACHE_FEROCEON_L2 | |||
735 | help | 735 | help |
736 | This option enables the Feroceon L2 cache controller. | 736 | This option enables the Feroceon L2 cache controller. |
737 | 737 | ||
738 | config CACHE_FEROCEON_L2_WRITETHROUGH | ||
739 | bool "Force Feroceon L2 cache write through" | ||
740 | depends on CACHE_FEROCEON_L2 | ||
741 | default n | ||
742 | help | ||
743 | Say Y here to use the Feroceon L2 cache in writethrough mode. | ||
744 | Unless you specifically require this, say N for writeback mode. | ||
745 | |||
738 | config CACHE_L2X0 | 746 | config CACHE_L2X0 |
739 | bool "Enable the L2x0 outer cache controller" | 747 | bool "Enable the L2x0 outer cache controller" |
740 | depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 | 748 | depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 |
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) | |||
48 | * L2 is PIPT and range operations only do a TLB lookup on | 48 | * L2 is PIPT and range operations only do a TLB lookup on |
49 | * the start address. | 49 | * the start address. |
50 | */ | 50 | */ |
51 | BUG_ON((start ^ end) & ~(PAGE_SIZE - 1)); | 51 | BUG_ON((start ^ end) >> PAGE_SHIFT); |
52 | 52 | ||
53 | raw_local_irq_save(flags); | 53 | raw_local_irq_save(flags); |
54 | __asm__("mcr p15, 1, %0, c15, c9, 4" : : "r" (start)); | 54 | __asm__("mcr p15, 1, %0, c15, c9, 4\n\t" |
55 | __asm__("mcr p15, 1, %0, c15, c9, 5" : : "r" (end)); | 55 | "mcr p15, 1, %1, c15, c9, 5" |
56 | : : "r" (start), "r" (end)); | ||
56 | raw_local_irq_restore(flags); | 57 | raw_local_irq_restore(flags); |
57 | } | 58 | } |
58 | 59 | ||
@@ -80,11 +81,12 @@ static inline void l2_inv_mva_range(unsigned long start, unsigned long end) | |||
80 | * L2 is PIPT and range operations only do a TLB lookup on | 81 | * L2 is PIPT and range operations only do a TLB lookup on |
81 | * the start address. | 82 | * the start address. |
82 | */ | 83 | */ |
83 | BUG_ON((start ^ end) & ~(PAGE_SIZE - 1)); | 84 | BUG_ON((start ^ end) >> PAGE_SHIFT); |
84 | 85 | ||
85 | raw_local_irq_save(flags); | 86 | raw_local_irq_save(flags); |
86 | __asm__("mcr p15, 1, %0, c15, c11, 4" : : "r" (start)); | 87 | __asm__("mcr p15, 1, %0, c15, c11, 4\n\t" |
87 | __asm__("mcr p15, 1, %0, c15, c11, 5" : : "r" (end)); | 88 | "mcr p15, 1, %1, c15, c11, 5" |
89 | : : "r" (start), "r" (end)); | ||
88 | raw_local_irq_restore(flags); | 90 | raw_local_irq_restore(flags); |
89 | } | 91 | } |
90 | 92 | ||
@@ -205,7 +207,7 @@ static void feroceon_l2_flush_range(unsigned long start, unsigned long end) | |||
205 | * time. These are necessary because the L2 cache can only be enabled | 207 | * time. These are necessary because the L2 cache can only be enabled |
206 | * or disabled while the L1 Dcache and Icache are both disabled. | 208 | * or disabled while the L1 Dcache and Icache are both disabled. |
207 | */ | 209 | */ |
208 | static void __init invalidate_and_disable_dcache(void) | 210 | static int __init flush_and_disable_dcache(void) |
209 | { | 211 | { |
210 | u32 cr; | 212 | u32 cr; |
211 | 213 | ||
@@ -217,7 +219,9 @@ static void __init invalidate_and_disable_dcache(void) | |||
217 | flush_cache_all(); | 219 | flush_cache_all(); |
218 | set_cr(cr & ~CR_C); | 220 | set_cr(cr & ~CR_C); |
219 | raw_local_irq_restore(flags); | 221 | raw_local_irq_restore(flags); |
222 | return 1; | ||
220 | } | 223 | } |
224 | return 0; | ||
221 | } | 225 | } |
222 | 226 | ||
223 | static void __init enable_dcache(void) | 227 | static void __init enable_dcache(void) |
@@ -225,18 +229,17 @@ static void __init enable_dcache(void) | |||
225 | u32 cr; | 229 | u32 cr; |
226 | 230 | ||
227 | cr = get_cr(); | 231 | cr = get_cr(); |
228 | if (!(cr & CR_C)) | 232 | set_cr(cr | CR_C); |
229 | set_cr(cr | CR_C); | ||
230 | } | 233 | } |
231 | 234 | ||
232 | static void __init __invalidate_icache(void) | 235 | static void __init __invalidate_icache(void) |
233 | { | 236 | { |
234 | int dummy; | 237 | int dummy; |
235 | 238 | ||
236 | __asm__ __volatile__("mcr p15, 0, %0, c7, c5, 0\n" : "=r" (dummy)); | 239 | __asm__ __volatile__("mcr p15, 0, %0, c7, c5, 0" : "=r" (dummy)); |
237 | } | 240 | } |
238 | 241 | ||
239 | static void __init invalidate_and_disable_icache(void) | 242 | static int __init invalidate_and_disable_icache(void) |
240 | { | 243 | { |
241 | u32 cr; | 244 | u32 cr; |
242 | 245 | ||
@@ -244,7 +247,9 @@ static void __init invalidate_and_disable_icache(void) | |||
244 | if (cr & CR_I) { | 247 | if (cr & CR_I) { |
245 | set_cr(cr & ~CR_I); | 248 | set_cr(cr & ~CR_I); |
246 | __invalidate_icache(); | 249 | __invalidate_icache(); |
250 | return 1; | ||
247 | } | 251 | } |
252 | return 0; | ||
248 | } | 253 | } |
249 | 254 | ||
250 | static void __init enable_icache(void) | 255 | static void __init enable_icache(void) |
@@ -252,8 +257,7 @@ static void __init enable_icache(void) | |||
252 | u32 cr; | 257 | u32 cr; |
253 | 258 | ||
254 | cr = get_cr(); | 259 | cr = get_cr(); |
255 | if (!(cr & CR_I)) | 260 | set_cr(cr | CR_I); |
256 | set_cr(cr | CR_I); | ||
257 | } | 261 | } |
258 | 262 | ||
259 | static inline u32 read_extra_features(void) | 263 | static inline u32 read_extra_features(void) |
@@ -291,13 +295,17 @@ static void __init enable_l2(void) | |||
291 | 295 | ||
292 | u = read_extra_features(); | 296 | u = read_extra_features(); |
293 | if (!(u & 0x00400000)) { | 297 | if (!(u & 0x00400000)) { |
298 | int i, d; | ||
299 | |||
294 | printk(KERN_INFO "Feroceon L2: Enabling L2\n"); | 300 | printk(KERN_INFO "Feroceon L2: Enabling L2\n"); |
295 | 301 | ||
296 | invalidate_and_disable_dcache(); | 302 | d = flush_and_disable_dcache(); |
297 | invalidate_and_disable_icache(); | 303 | i = invalidate_and_disable_icache(); |
298 | write_extra_features(u | 0x00400000); | 304 | write_extra_features(u | 0x00400000); |
299 | enable_icache(); | 305 | if (i) |
300 | enable_dcache(); | 306 | enable_icache(); |
307 | if (d) | ||
308 | enable_dcache(); | ||
301 | } | 309 | } |
302 | } | 310 | } |
303 | 311 | ||
diff --git a/arch/arm/mm/proc-feroceon.S b/arch/arm/mm/proc-feroceon.S index 2b8bb383755e..0fe1f8fc3488 100644 --- a/arch/arm/mm/proc-feroceon.S +++ b/arch/arm/mm/proc-feroceon.S | |||
@@ -80,7 +80,8 @@ ENTRY(cpu_feroceon_proc_fin) | |||
80 | msr cpsr_c, ip | 80 | msr cpsr_c, ip |
81 | bl feroceon_flush_kern_cache_all | 81 | bl feroceon_flush_kern_cache_all |
82 | 82 | ||
83 | #if defined(CONFIG_CACHE_FEROCEON_L2) && !defined(CONFIG_L2_CACHE_WRITETHROUGH) | 83 | #if defined(CONFIG_CACHE_FEROCEON_L2) && \ |
84 | !defined(CONFIG_CACHE_FEROCEON_L2_WRITETHROUGH) | ||
84 | mov r0, #0 | 85 | mov r0, #0 |
85 | mcr p15, 1, r0, c15, c9, 0 @ clean L2 | 86 | mcr p15, 1, r0, c15, c9, 0 @ clean L2 |
86 | mcr p15, 0, r0, c7, c10, 4 @ drain WB | 87 | mcr p15, 0, r0, c7, c10, 4 @ drain WB |
@@ -389,7 +390,8 @@ ENTRY(feroceon_range_cache_fns) | |||
389 | 390 | ||
390 | .align 5 | 391 | .align 5 |
391 | ENTRY(cpu_feroceon_dcache_clean_area) | 392 | ENTRY(cpu_feroceon_dcache_clean_area) |
392 | #if defined(CONFIG_CACHE_FEROCEON_L2) && !defined(CONFIG_L2_CACHE_WRITETHROUGH) | 393 | #if defined(CONFIG_CACHE_FEROCEON_L2) && \ |
394 | !defined(CONFIG_CACHE_FEROCEON_L2_WRITETHROUGH) | ||
393 | mov r2, r0 | 395 | mov r2, r0 |
394 | mov r3, r1 | 396 | mov r3, r1 |
395 | #endif | 397 | #endif |
@@ -397,7 +399,8 @@ ENTRY(cpu_feroceon_dcache_clean_area) | |||
397 | add r0, r0, #CACHE_DLINESIZE | 399 | add r0, r0, #CACHE_DLINESIZE |
398 | subs r1, r1, #CACHE_DLINESIZE | 400 | subs r1, r1, #CACHE_DLINESIZE |
399 | bhi 1b | 401 | bhi 1b |
400 | #if defined(CONFIG_CACHE_FEROCEON_L2) && !defined(CONFIG_L2_CACHE_WRITETHROUGH) | 402 | #if defined(CONFIG_CACHE_FEROCEON_L2) && \ |
403 | !defined(CONFIG_CACHE_FEROCEON_L2_WRITETHROUGH) | ||
401 | 1: mcr p15, 1, r2, c15, c9, 1 @ clean L2 entry | 404 | 1: mcr p15, 1, r2, c15, c9, 1 @ clean L2 entry |
402 | add r2, r2, #CACHE_DLINESIZE | 405 | add r2, r2, #CACHE_DLINESIZE |
403 | subs r3, r3, #CACHE_DLINESIZE | 406 | subs r3, r3, #CACHE_DLINESIZE |
@@ -449,7 +452,8 @@ ENTRY(cpu_feroceon_set_pte_ext) | |||
449 | armv3_set_pte_ext wc_disable=0 | 452 | armv3_set_pte_ext wc_disable=0 |
450 | mov r0, r0 | 453 | mov r0, r0 |
451 | mcr p15, 0, r0, c7, c10, 1 @ clean D entry | 454 | mcr p15, 0, r0, c7, c10, 1 @ clean D entry |
452 | #if defined(CONFIG_CACHE_FEROCEON_L2) && !defined(CONFIG_L2_CACHE_WRITETHROUGH) | 455 | #if defined(CONFIG_CACHE_FEROCEON_L2) && \ |
456 | !defined(CONFIG_CACHE_FEROCEON_L2_WRITETHROUGH) | ||
453 | mcr p15, 1, r0, c15, c9, 1 @ clean L2 entry | 457 | mcr p15, 1, r0, c15, c9, 1 @ clean L2 entry |
454 | #endif | 458 | #endif |
455 | mcr p15, 0, r0, c7, c10, 4 @ drain WB | 459 | mcr p15, 0, r0, c7, c10, 4 @ drain WB |