summaryrefslogtreecommitdiff
path: root/arch/arm/mm
diff options
context:
space:
mode:
authorGary King <gking@nvidia.com>2010-02-10 18:18:43 -0800
committerGary King <gking@nvidia.com>2010-02-10 20:23:54 -0800
commitb3a8afcc5a36be796d8f25f5cd5764014e8b11de (patch)
treea6ccc6984db99ff317837c957a545a7774a46e76 /arch/arm/mm
parentab7fcb00afc6e6d23040e9f53932f38d34048f9b (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/Kconfig10
-rw-r--r--arch/arm/mm/Makefile1
-rw-r--r--arch/arm/mm/cache-l2x0.c39
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;