summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/common.c
diff options
context:
space:
mode:
authorHyung Taek Ryoo <hryoo@nvidia.com>2012-07-31 15:43:34 -0700
committerSimone Willett <swillett@nvidia.com>2012-08-06 12:12:31 -0700
commit9bf22a62cd071336282e3fa5d999f898e77119d1 (patch)
tree123fcf5de57343f49ff6d07639235d82e04e0a87 /arch/arm/mach-tegra/common.c
parent76fd6572b00e780a2a00cc2ee21b9f30d968cb5e (diff)
arm: tegra: optimize L2 enable/disable paths for secureos
For the CONFIG_TRUSTED_FOUNDATION code paths, differentiate L2 enable vs. reenable, which are different SMCs (won't trigger an invalidate in the case of a reenable). On an L2 disable SMC, optionally pass a 0 for the L2 ways arg, which skips the full clean/invalidate (and simply just disabled the L2). In order to safely skip flushing the L2 on the disable, we have to be careful what we dirty from the type we flush the L1 and disable the L2. Bug 939415 Signed-off-by: Chris Johnson<cwj@nvidia.com> Change-Id: I756d2ceda83d5d8d6bc5670218e9d874d5e5f62a Reviewed-on: http://git-master/r/119786 Reviewed-by: Simone Willett <swillett@nvidia.com> Tested-by: Simone Willett <swillett@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra/common.c')
-rw-r--r--arch/arm/mach-tegra/common.c118
1 files changed, 51 insertions, 67 deletions
diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c
index b914d5d71462..85eb11f64118 100644
--- a/arch/arm/mach-tegra/common.c
+++ b/arch/arm/mach-tegra/common.c
@@ -2,7 +2,7 @@
* arch/arm/mach-tegra/common.c
*
* Copyright (C) 2010 Google, Inc.
- * Copyright (C) 2010-2012 NVIDIA Corporation
+ * Copyright (C) 2010-2012, NVIDIA Corporation. All rights reserved.
*
* Author:
* Colin Cross <ccross@android.com>
@@ -226,61 +226,13 @@ static __initdata struct tegra_clk_init_table common_clk_init_table[] = {
{ NULL, NULL, 0, 0},
};
-#ifdef CONFIG_CACHE_L2X0
#ifdef CONFIG_TRUSTED_FOUNDATIONS
-static void tegra_cache_smc(bool enable, u32 arg)
-{
- void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000;
- bool need_affinity_switch;
- bool can_switch_affinity;
- bool l2x0_enabled;
- cpumask_t local_cpu_mask;
- cpumask_t saved_cpu_mask;
- unsigned long flags;
- long ret;
-
- /*
- * ISSUE : Some registers of PL310 controler must be written
- * from Secure context (and from CPU0)!
- *
- * When called form Normal we obtain an abort or do nothing.
- * Instructions that must be called in Secure:
- * - Write to Control register (L2X0_CTRL==0x100)
- * - Write in Auxiliary controler (L2X0_AUX_CTRL==0x104)
- * - Invalidate all entries (L2X0_INV_WAY==0x77C),
- * mandatory at boot time.
- * - Tag and Data RAM Latency Control Registers
- * (0x108 & 0x10C) must be written in Secure.
- */
- need_affinity_switch = (smp_processor_id() != 0);
- can_switch_affinity = !irqs_disabled();
-
- WARN_ON(need_affinity_switch && !can_switch_affinity);
- if (need_affinity_switch && can_switch_affinity) {
- cpu_set(0, local_cpu_mask);
- sched_getaffinity(0, &saved_cpu_mask);
- ret = sched_setaffinity(0, &local_cpu_mask);
- WARN_ON(ret != 0);
- }
-
- local_irq_save(flags);
- l2x0_enabled = readl_relaxed(p + L2X0_CTRL) & 1;
- if (enable && !l2x0_enabled)
- tegra_generic_smc(0xFFFFF100, 0x00000001, arg);
- else if (!enable && l2x0_enabled)
- tegra_generic_smc(0xFFFFF100, 0x00000002, arg);
- local_irq_restore(flags);
-
- if (need_affinity_switch && can_switch_affinity) {
- ret = sched_setaffinity(0, &saved_cpu_mask);
- WARN_ON(ret != 0);
- }
-}
+#define CACHE_LINE_SIZE 32
-static void tegra_l2x0_disable(void)
+static inline void tegra_l2x0_disable_tz(void)
{
- unsigned long flags;
static u32 l2x0_way_mask;
+ BUG_ON(smp_processor_id() != 0);
if (!l2x0_way_mask) {
void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000;
@@ -291,30 +243,62 @@ static void tegra_l2x0_disable(void)
ways = (aux_ctrl & (1 << 16)) ? 16 : 8;
l2x0_way_mask = (1 << ways) - 1;
}
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
+ /* flush all ways on disable */
+ tegra_generic_smc_uncached(0xFFFFF100, 0x00000002, l2x0_way_mask);
+#elif defined(CONFIG_ARCH_TEGRA_3x_SOC)
+ if (tegra_is_cpu_in_lp2(0)) {
+ register unsigned long sp asm ("sp");
- local_irq_save(flags);
- tegra_cache_smc(false, l2x0_way_mask);
- local_irq_restore(flags);
+ /* flush only the stack, if entering LP2 */
+ __cpuc_flush_dcache_area((void *)sp, (CACHE_LINE_SIZE * 2));
+ outer_flush_range(__pa(sp), __pa(sp) + (CACHE_LINE_SIZE * 2));
+
+ /* pass zero arg, so secureos flushes only its workspace */
+ tegra_generic_smc_uncached(0xFFFFF100, 0x00000002, 0x0);
+ } else {
+ /* flush all ways on disable, if entering LP0/LP1 */
+ tegra_generic_smc_uncached(0xFFFFF100,
+ 0x00000002, l2x0_way_mask);
+ }
+#endif
}
-#endif /* CONFIG_TRUSTED_FOUNDATIONS */
-void tegra_init_cache(bool init)
+static inline void tegra_init_cache_tz(bool init)
{
void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000;
u32 aux_ctrl;
-#ifdef CONFIG_TRUSTED_FOUNDATIONS
- /* issue the SMC to enable the L2 */
- aux_ctrl = readl_relaxed(p + L2X0_AUX_CTRL);
- tegra_cache_smc(true, aux_ctrl);
+ BUG_ON(smp_processor_id() != 0);
+
+ if (init) {
+ /* init L2 from secureos */
+ tegra_generic_smc(0xFFFFF100, 0x00000001, 0x0);
+
+ /* common init called for outer call hookup */
+ aux_ctrl = readl_relaxed(p + L2X0_AUX_CTRL);
+ l2x0_init(p, aux_ctrl, 0xFFFFFFFF);
- /* after init, reread aux_ctrl and register handlers */
- aux_ctrl = readl_relaxed(p + L2X0_AUX_CTRL);
- l2x0_init(p, aux_ctrl, 0xFFFFFFFF);
+ /* use our outer_disable() routine */
+ outer_cache.disable = tegra_l2x0_disable_tz;
+ } else {
+ /* reenable L2 in secureos */
+ aux_ctrl = readl_relaxed(p + L2X0_AUX_CTRL);
+ tegra_generic_smc_uncached(0xFFFFF100, 0x00000004, aux_ctrl);
+ }
+}
+#endif /* CONFIG_TRUSTED_FOUNDATIONS */
- /* override outer_disable() with our disable */
- outer_cache.disable = tegra_l2x0_disable;
+#ifdef CONFIG_CACHE_L2X0
+void tegra_init_cache(bool init)
+{
+#ifdef CONFIG_TRUSTED_FOUNDATIONS
+ /* enable/re-enable of L2 handled by secureos */
+ return tegra_init_cache_tz(init);
#else
+ void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000;
+ u32 aux_ctrl;
+
#if defined(CONFIG_ARCH_TEGRA_2x_SOC)
writel_relaxed(0x331, p + L2X0_TAG_LATENCY_CTRL);
writel_relaxed(0x441, p + L2X0_DATA_LATENCY_CTRL);
@@ -364,7 +348,7 @@ void tegra_init_cache(bool init)
l2x0_enable();
#endif
}
-#endif
+#endif /* CONFIG_CACHE_L2X0 */
static void __init tegra_init_power(void)
{