diff options
author | Gary King <gking@nvidia.com> | 2010-02-10 18:18:43 -0800 |
---|---|---|
committer | Gary King <gking@nvidia.com> | 2010-02-10 20:23:54 -0800 |
commit | b3a8afcc5a36be796d8f25f5cd5764014e8b11de (patch) | |
tree | a6ccc6984db99ff317837c957a545a7774a46e76 /arch/arm/mm | |
parent | ab7fcb00afc6e6d23040e9f53932f38d34048f9b (diff) |
[ARM PL2X0] add optimizations for PL3x0-series controllers
the PL3x0 outer cache controllers are largely register-compatible with
the L2X0 controllers; however, the new controllers support atomic
maintenance operations, rather than mandating a polling loop inside
an IRQ-safe spinlock.
this change significantly reduces (>50%) the number of processor cycles
spent performing outer cache maintenance, which has shown up as a hot
spot in a number of places (USB, MMC, graphics rendering, etc.) on
Tegra 2 processors
Change-Id: I7e4f37ceea17241e8767ffea419a7751eae5eb23
Diffstat (limited to 'arch/arm/mm')
-rw-r--r-- | arch/arm/mm/Kconfig | 10 | ||||
-rw-r--r-- | arch/arm/mm/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/mm/cache-l2x0.c | 39 |
3 files changed, 38 insertions, 12 deletions
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index 63792321dddd..d03fd0c90a7e 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -762,12 +762,20 @@ config CACHE_TEGRA_CMC config CACHE_L2X0 bool "Enable the L2x0 outer cache controller" - depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || REALVIEW_EB_A9MP || MACH_REALVIEW_PBX || ARCH_TEGRA_2x_SOC + depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || REALVIEW_EB_A9MP || MACH_REALVIEW_PBX default y select OUTER_CACHE help This option enables the L2x0 PrimeCell. +config CACHE_PL3X0 + bool "Enable the PL3x0 outer cache controller" + depends on ARCH_TEGRA_2x_SOC + default y + select OUTER_CACHE + help + This option enables the PL3x0 PrimeCell. + config CACHE_XSC3L2 bool "Enable the L2 cache on XScale3" depends on CPU_XSC3 diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile index 267ca981702b..ff901c5fcd22 100644 --- a/arch/arm/mm/Makefile +++ b/arch/arm/mm/Makefile @@ -80,5 +80,6 @@ obj-$(CONFIG_CPU_V7M) += proc-v7m.o obj-$(CONFIG_CACHE_FEROCEON_L2) += cache-feroceon-l2.o obj-$(CONFIG_CACHE_TEGRA_CMC) += cache-tegra-cmc.o obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o +obj-$(CONFIG_CACHE_PL3X0) += cache-l2x0.o obj-$(CONFIG_CACHE_XSC3L2) += cache-xsc3l2.o diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 7a3270a5b3a6..ca8d1038afd4 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -1,5 +1,5 @@ /* - * arch/arm/mm/cache-l2x0.c - L210/L220 cache controller support + * arch/arm/mm/cache-l2x0.c - L210/L220/PL310 cache controller support * * Copyright (C) 2007 ARM Limited * @@ -30,7 +30,7 @@ static DEFINE_SPINLOCK(l2x0_lock); bool l2x0_disabled; static inline void sync_writel(unsigned long val, unsigned long reg, - unsigned long complete_mask) + unsigned long complete_mask) { unsigned long flags; @@ -51,6 +51,23 @@ static inline void cache_sync(void) sync_writel(0, L2X0_CACHE_SYNC, 1); } + +#ifdef CONFIG_CACHE_PL3X0 +static inline void maint_sync_writel(unsigned long val, unsigned long reg, + unsigned long complete_mask) +{ + writel(val, l2x0_base + reg); +} + +#define maint_cache_sync() + +#else + +#define maint_sync_writel sync_writel +#define maint_cache_sync() cache_sync() + +#endif + static inline void l2x0_inv_all(void) { /* invalidate all ways */ @@ -64,18 +81,18 @@ static void l2x0_inv_range(unsigned long start, unsigned long end) if (start & (CACHE_LINE_SIZE - 1)) { start &= ~(CACHE_LINE_SIZE - 1); - sync_writel(start, L2X0_CLEAN_INV_LINE_PA, 1); + maint_sync_writel(start, L2X0_CLEAN_INV_LINE_PA, 1); start += CACHE_LINE_SIZE; } if (end & (CACHE_LINE_SIZE - 1)) { end &= ~(CACHE_LINE_SIZE - 1); - sync_writel(end, L2X0_CLEAN_INV_LINE_PA, 1); + maint_sync_writel(end, L2X0_CLEAN_INV_LINE_PA, 1); } for (addr = start; addr < end; addr += CACHE_LINE_SIZE) - sync_writel(addr, L2X0_INV_LINE_PA, 1); - cache_sync(); + maint_sync_writel(addr, L2X0_INV_LINE_PA, 1); + maint_cache_sync(); } static void l2x0_clean_range(unsigned long start, unsigned long end) @@ -84,8 +101,8 @@ static void l2x0_clean_range(unsigned long start, unsigned long end) start &= ~(CACHE_LINE_SIZE - 1); for (addr = start; addr < end; addr += CACHE_LINE_SIZE) - sync_writel(addr, L2X0_CLEAN_LINE_PA, 1); - cache_sync(); + maint_sync_writel(addr, L2X0_CLEAN_LINE_PA, 1); + maint_cache_sync(); } static void l2x0_flush_range(unsigned long start, unsigned long end) @@ -95,15 +112,15 @@ static void l2x0_flush_range(unsigned long start, unsigned long end) start &= ~(CACHE_LINE_SIZE - 1); for (addr = start; addr < end; addr += CACHE_LINE_SIZE) sync_writel(addr, L2X0_CLEAN_INV_LINE_PA, 1); - cache_sync(); + maint_cache_sync(); } static void l2x0_sync(void) { - cache_sync(); + maint_sync_writel(0, L2X0_CACHE_SYNC, 1); } -void l2x0_deinit() +void l2x0_deinit(void) { /* FIXME: get num_ways from the cache config */ unsigned int num_ways = 8, i; |