diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2014-03-15 12:47:57 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2014-05-29 19:47:51 -0400 |
commit | 3b8bad5758113df34076dd868b6cab502bd4ee9a (patch) | |
tree | 11ff185c1001a0d278773643a025f17414d79f1b /arch | |
parent | da3627fbda8983e96fb087c358fab4d7661fd97d (diff) |
ARM: l2c: provide enable method
Providing an enable method gives L2 cache controllers a chance to do
special handling at enable time. This allows us to remove a hack in
l2x0_unlock() for Marvell Aurora L2 caches.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mm/cache-l2x0.c | 80 |
1 files changed, 62 insertions, 18 deletions
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 09fe0f5eada5..2adb82e7f4b3 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c | |||
@@ -29,7 +29,9 @@ | |||
29 | #include "cache-aurora-l2.h" | 29 | #include "cache-aurora-l2.h" |
30 | 30 | ||
31 | struct l2c_init_data { | 31 | struct l2c_init_data { |
32 | unsigned num_lock; | ||
32 | void (*of_parse)(const struct device_node *, u32 *, u32 *); | 33 | void (*of_parse)(const struct device_node *, u32 *, u32 *); |
34 | void (*enable)(void __iomem *, u32, unsigned); | ||
33 | void (*save)(void __iomem *); | 35 | void (*save)(void __iomem *); |
34 | struct outer_cache_fns outer_cache; | 36 | struct outer_cache_fns outer_cache; |
35 | }; | 37 | }; |
@@ -82,6 +84,36 @@ static inline void l2c_unlock(void __iomem *base, unsigned num) | |||
82 | } | 84 | } |
83 | } | 85 | } |
84 | 86 | ||
87 | /* | ||
88 | * Enable the L2 cache controller. This function must only be | ||
89 | * called when the cache controller is known to be disabled. | ||
90 | */ | ||
91 | static void l2c_enable(void __iomem *base, u32 aux, unsigned num_lock) | ||
92 | { | ||
93 | unsigned long flags; | ||
94 | |||
95 | l2c_unlock(base, num_lock); | ||
96 | |||
97 | writel_relaxed(aux, base + L2X0_AUX_CTRL); | ||
98 | |||
99 | local_irq_save(flags); | ||
100 | __l2c_op_way(base + L2X0_INV_WAY); | ||
101 | writel_relaxed(0, base + sync_reg_offset); | ||
102 | l2c_wait_mask(base + sync_reg_offset, 1); | ||
103 | local_irq_restore(flags); | ||
104 | |||
105 | writel_relaxed(L2X0_CTRL_EN, base + L2X0_CTRL); | ||
106 | } | ||
107 | |||
108 | static void l2c_disable(void) | ||
109 | { | ||
110 | void __iomem *base = l2x0_base; | ||
111 | |||
112 | outer_cache.flush_all(); | ||
113 | writel_relaxed(0, base + L2X0_CTRL); | ||
114 | dsb(st); | ||
115 | } | ||
116 | |||
85 | #ifdef CONFIG_CACHE_PL310 | 117 | #ifdef CONFIG_CACHE_PL310 |
86 | static inline void cache_wait(void __iomem *reg, unsigned long mask) | 118 | static inline void cache_wait(void __iomem *reg, unsigned long mask) |
87 | { | 119 | { |
@@ -325,9 +357,6 @@ static void l2x0_unlock(u32 cache_id) | |||
325 | case L2X0_CACHE_ID_PART_L310: | 357 | case L2X0_CACHE_ID_PART_L310: |
326 | lockregs = 8; | 358 | lockregs = 8; |
327 | break; | 359 | break; |
328 | case AURORA_CACHE_ID: | ||
329 | lockregs = 4; | ||
330 | break; | ||
331 | default: | 360 | default: |
332 | /* L210 and unknown types */ | 361 | /* L210 and unknown types */ |
333 | lockregs = 1; | 362 | lockregs = 1; |
@@ -337,7 +366,22 @@ static void l2x0_unlock(u32 cache_id) | |||
337 | l2c_unlock(l2x0_base, lockregs); | 366 | l2c_unlock(l2x0_base, lockregs); |
338 | } | 367 | } |
339 | 368 | ||
369 | static void l2x0_enable(void __iomem *base, u32 aux, unsigned num_lock) | ||
370 | { | ||
371 | /* Make sure that I&D is not locked down when starting */ | ||
372 | l2x0_unlock(readl_relaxed(base + L2X0_CACHE_ID)); | ||
373 | |||
374 | /* l2x0 controller is disabled */ | ||
375 | writel_relaxed(aux, base + L2X0_AUX_CTRL); | ||
376 | |||
377 | l2x0_inv_all(); | ||
378 | |||
379 | /* enable L2X0 */ | ||
380 | writel_relaxed(L2X0_CTRL_EN, base + L2X0_CTRL); | ||
381 | } | ||
382 | |||
340 | static const struct l2c_init_data l2x0_init_fns __initconst = { | 383 | static const struct l2c_init_data l2x0_init_fns __initconst = { |
384 | .enable = l2x0_enable, | ||
341 | .outer_cache = { | 385 | .outer_cache = { |
342 | .inv_range = l2x0_inv_range, | 386 | .inv_range = l2x0_inv_range, |
343 | .clean_range = l2x0_clean_range, | 387 | .clean_range = l2x0_clean_range, |
@@ -412,22 +456,11 @@ static void __init __l2c_init(const struct l2c_init_data *data, | |||
412 | l2x0_size = ways * way_size * SZ_1K; | 456 | l2x0_size = ways * way_size * SZ_1K; |
413 | 457 | ||
414 | /* | 458 | /* |
415 | * Check if l2x0 controller is already enabled. | 459 | * Check if l2x0 controller is already enabled. If we are booting |
416 | * If you are booting from non-secure mode | 460 | * in non-secure mode accessing the below registers will fault. |
417 | * accessing the below registers will fault. | ||
418 | */ | 461 | */ |
419 | if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) { | 462 | if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) |
420 | /* Make sure that I&D is not locked down when starting */ | 463 | data->enable(l2x0_base, aux, data->num_lock); |
421 | l2x0_unlock(cache_id); | ||
422 | |||
423 | /* l2x0 controller is disabled */ | ||
424 | writel_relaxed(aux, l2x0_base + L2X0_AUX_CTRL); | ||
425 | |||
426 | l2x0_inv_all(); | ||
427 | |||
428 | /* enable L2X0 */ | ||
429 | writel_relaxed(L2X0_CTRL_EN, l2x0_base + L2X0_CTRL); | ||
430 | } | ||
431 | 464 | ||
432 | /* Re-read it in case some bits are reserved. */ | 465 | /* Re-read it in case some bits are reserved. */ |
433 | aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL); | 466 | aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL); |
@@ -515,6 +548,7 @@ static void l2x0_resume(void) | |||
515 | 548 | ||
516 | static const struct l2c_init_data of_l2x0_data __initconst = { | 549 | static const struct l2c_init_data of_l2x0_data __initconst = { |
517 | .of_parse = l2x0_of_parse, | 550 | .of_parse = l2x0_of_parse, |
551 | .enable = l2x0_enable, | ||
518 | .outer_cache = { | 552 | .outer_cache = { |
519 | .inv_range = l2x0_inv_range, | 553 | .inv_range = l2x0_inv_range, |
520 | .clean_range = l2x0_clean_range, | 554 | .clean_range = l2x0_clean_range, |
@@ -620,7 +654,9 @@ static void pl310_resume(void) | |||
620 | } | 654 | } |
621 | 655 | ||
622 | static const struct l2c_init_data of_pl310_data __initconst = { | 656 | static const struct l2c_init_data of_pl310_data __initconst = { |
657 | .num_lock = 8, | ||
623 | .of_parse = pl310_of_parse, | 658 | .of_parse = pl310_of_parse, |
659 | .enable = l2c_enable, | ||
624 | .save = pl310_save, | 660 | .save = pl310_save, |
625 | .outer_cache = { | 661 | .outer_cache = { |
626 | .inv_range = l2x0_inv_range, | 662 | .inv_range = l2x0_inv_range, |
@@ -779,7 +815,9 @@ static void __init aurora_of_parse(const struct device_node *np, | |||
779 | } | 815 | } |
780 | 816 | ||
781 | static const struct l2c_init_data of_aurora_with_outer_data __initconst = { | 817 | static const struct l2c_init_data of_aurora_with_outer_data __initconst = { |
818 | .num_lock = 4, | ||
782 | .of_parse = aurora_of_parse, | 819 | .of_parse = aurora_of_parse, |
820 | .enable = l2c_enable, | ||
783 | .save = aurora_save, | 821 | .save = aurora_save, |
784 | .outer_cache = { | 822 | .outer_cache = { |
785 | .inv_range = aurora_inv_range, | 823 | .inv_range = aurora_inv_range, |
@@ -793,7 +831,9 @@ static const struct l2c_init_data of_aurora_with_outer_data __initconst = { | |||
793 | }; | 831 | }; |
794 | 832 | ||
795 | static const struct l2c_init_data of_aurora_no_outer_data __initconst = { | 833 | static const struct l2c_init_data of_aurora_no_outer_data __initconst = { |
834 | .num_lock = 4, | ||
796 | .of_parse = aurora_of_parse, | 835 | .of_parse = aurora_of_parse, |
836 | .enable = l2c_enable, | ||
797 | .save = aurora_save, | 837 | .save = aurora_save, |
798 | .outer_cache = { | 838 | .outer_cache = { |
799 | .resume = aurora_resume, | 839 | .resume = aurora_resume, |
@@ -942,7 +982,9 @@ static void bcm_flush_range(unsigned long start, unsigned long end) | |||
942 | } | 982 | } |
943 | 983 | ||
944 | static const struct l2c_init_data of_bcm_l2x0_data __initconst = { | 984 | static const struct l2c_init_data of_bcm_l2x0_data __initconst = { |
985 | .num_lock = 8, | ||
945 | .of_parse = pl310_of_parse, | 986 | .of_parse = pl310_of_parse, |
987 | .enable = l2c_enable, | ||
946 | .save = pl310_save, | 988 | .save = pl310_save, |
947 | .outer_cache = { | 989 | .outer_cache = { |
948 | .inv_range = bcm_inv_range, | 990 | .inv_range = bcm_inv_range, |
@@ -976,6 +1018,8 @@ static void tauros3_resume(void) | |||
976 | } | 1018 | } |
977 | 1019 | ||
978 | static const struct l2c_init_data of_tauros3_data __initconst = { | 1020 | static const struct l2c_init_data of_tauros3_data __initconst = { |
1021 | .num_lock = 8, | ||
1022 | .enable = l2c_enable, | ||
979 | .save = tauros3_save, | 1023 | .save = tauros3_save, |
980 | /* Tauros3 broadcasts L1 cache operations to L2 */ | 1024 | /* Tauros3 broadcasts L1 cache operations to L2 */ |
981 | .outer_cache = { | 1025 | .outer_cache = { |