diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-30 08:26:25 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-30 08:26:25 -0700 |
commit | 706d4b12f8d7edd28d7e879a77235472da393edb (patch) | |
tree | c9bc1ce06b1154a49da1d0d907cac544a818eb0e /arch/arm/mach-ux500 | |
parent | 3af54c9bd9e6f14f896aac1bb0e8405ae0bc7a44 (diff) | |
parent | 9bafc74163d8bccca9810159aab39be926fb877c (diff) |
Merge branch 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm
* 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm: (215 commits)
ARM: memblock: setup lowmem mappings using memblock
ARM: memblock: move meminfo into find_limits directly
ARM: memblock: convert free_highpages() to use memblock
ARM: move freeing of highmem pages out of mem_init()
ARM: memblock: convert memory detail printing to use memblock
ARM: memblock: use memblock to free memory into arm_bootmem_init()
ARM: memblock: use memblock when initializing memory allocators
ARM: ensure membank array is always sorted
ARM: 6466/1: implement flush_icache_all for the rest of the CPUs
ARM: 6464/2: fix spinlock recursion in adjust_pte()
ARM: fix memblock breakage
ARM: 6465/1: Fix data abort accessing proc_info from __lookup_processor_type
ARM: 6460/1: ixp2000: fix type of ixp2000_timer_interrupt
ARM: 6449/1: Fix for compiler warning of uninitialized variable.
ARM: 6445/1: fixup TCM memory types
ARM: imx: Add wake functionality to GPIO
ARM: mx5: Add gpio-keys to mx51 babbage board
ARM: imx: Add gpio-keys to plat-mxc
mx31_3ds: Fix spi registration
mx31_3ds: Fix the logic for detecting the debug board
...
Diffstat (limited to 'arch/arm/mach-ux500')
-rw-r--r-- | arch/arm/mach-ux500/cpu.c | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c index e0fd747e447..73fb1a551ec 100644 --- a/arch/arm/mach-ux500/cpu.c +++ b/arch/arm/mach-ux500/cpu.c @@ -10,6 +10,7 @@ #include <linux/io.h> #include <linux/clk.h> +#include <asm/cacheflush.h> #include <asm/hardware/cache-l2x0.h> #include <asm/hardware/gic.h> #include <asm/mach/map.h> @@ -71,6 +72,46 @@ void __init ux500_init_irq(void) } #ifdef CONFIG_CACHE_L2X0 +static inline void ux500_cache_wait(void __iomem *reg, unsigned long mask) +{ + /* wait for the operation to complete */ + while (readl(reg) & mask) + ; +} + +static inline void ux500_cache_sync(void) +{ + void __iomem *base = __io_address(UX500_L2CC_BASE); + writel(0, base + L2X0_CACHE_SYNC); + ux500_cache_wait(base + L2X0_CACHE_SYNC, 1); +} + +/* + * The L2 cache cannot be turned off in the non-secure world. + * Dummy until a secure service is in place. + */ +static void ux500_l2x0_disable(void) +{ +} + +/* + * This is only called when doing a kexec, just after turning off the L2 + * and L1 cache, and it is surrounded by a spinlock in the generic version. + * However, we're not really turning off the L2 cache right now and the + * PL310 does not support exclusive accesses (used to implement the spinlock). + * So, the invalidation needs to be done without the spinlock. + */ +static void ux500_l2x0_inv_all(void) +{ + void __iomem *l2x0_base = __io_address(UX500_L2CC_BASE); + uint32_t l2x0_way_mask = (1<<16) - 1; /* Bitmask of active ways */ + + /* invalidate all ways */ + writel(l2x0_way_mask, l2x0_base + L2X0_INV_WAY); + ux500_cache_wait(l2x0_base + L2X0_INV_WAY, l2x0_way_mask); + ux500_cache_sync(); +} + static int ux500_l2x0_init(void) { void __iomem *l2x0_base; @@ -80,6 +121,10 @@ static int ux500_l2x0_init(void) /* 64KB way size, 8 way associativity, force WA */ l2x0_init(l2x0_base, 0x3e060000, 0xc0000fff); + /* Override invalidate function */ + outer_cache.disable = ux500_l2x0_disable; + outer_cache.inv_all = ux500_l2x0_inv_all; + return 0; } early_initcall(ux500_l2x0_init); |