| From 1bf6d2c1bb23533af6930581cc39b74685bc29de Mon Sep 17 00:00:00 2001 |
| From: Linus Walleij <linus.walleij@linaro.org> |
| Date: Fri, 12 Aug 2011 13:54:42 +0200 |
| Subject: ARM: mach-ux500: unlock I&D l2x0 caches before init |
| |
| From: Linus Walleij <linus.walleij@linaro.org> |
| |
| commit 1bf6d2c1bb23533af6930581cc39b74685bc29de upstream. |
| |
| Apparently U8500 U-Boot versions may leave the l2x0 locked down |
| before executing the kernel. Make sure we unlock it before we |
| initialize the l2x0. This fixes a performance problem reported |
| by Jan Rinze. |
| |
| The l2x0 core has been modified to unlock the l2x0 by default, |
| but it will not touch the locking registers if the l2x0 was |
| already enabled, as on the ux500, so we need this quirk to |
| make sure it is properly turned off. |
| |
| Cc: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com> |
| Cc: Rabin Vincent <rabin.vincent@stericsson.com> |
| Cc: Adrian Bunk <adrian.bunk@movial.com> |
| Reported-by: Jan Rinze <janrinze@gmail.com> |
| Tested-by: Robert Marklund <robert.marklund@stericsson.com> |
| Signed-off-by: Linus Walleij <linus.walleij@linaro.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| arch/arm/mach-ux500/cpu.c | 25 ++++++++++++++++++++++++- |
| 1 file changed, 24 insertions(+), 1 deletion(-) |
| |
| --- a/arch/arm/mach-ux500/cpu.c |
| +++ b/arch/arm/mach-ux500/cpu.c |
| @@ -99,7 +99,27 @@ static void ux500_l2x0_inv_all(void) |
| ux500_cache_sync(); |
| } |
| |
| -static int ux500_l2x0_init(void) |
| +static int __init ux500_l2x0_unlock(void) |
| +{ |
| + int i; |
| + |
| + /* |
| + * Unlock Data and Instruction Lock if locked. Ux500 U-Boot versions |
| + * apparently locks both caches before jumping to the kernel. The |
| + * l2x0 core will not touch the unlock registers if the l2x0 is |
| + * already enabled, so we do it right here instead. The PL310 has |
| + * 8 sets of registers, one per possible CPU. |
| + */ |
| + for (i = 0; i < 8; i++) { |
| + writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_D_BASE + |
| + i * L2X0_LOCKDOWN_STRIDE); |
| + writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_I_BASE + |
| + i * L2X0_LOCKDOWN_STRIDE); |
| + } |
| + return 0; |
| +} |
| + |
| +static int __init ux500_l2x0_init(void) |
| { |
| if (cpu_is_u5500()) |
| l2x0_base = __io_address(U5500_L2CC_BASE); |
| @@ -108,6 +128,9 @@ static int ux500_l2x0_init(void) |
| else |
| ux500_unknown_soc(); |
| |
| + /* Unlock before init */ |
| + ux500_l2x0_unlock(); |
| + |
| /* 64KB way size, 8 way associativity, force WA */ |
| l2x0_init(l2x0_base, 0x3e060000, 0xc0000fff); |
| |