arm: tegra: secureos: disable L2 as part of sleep CPU SMC
Chris Johnson [Sat, 25 Aug 2012 00:27:58 +0000 (17:27 -0700)]
This is an alternate way to have the L2 disabled available with
later TL secureos versions.

In this version, the sleep CPU SMC which is the last one issued
before entering LP2 on CPU0, will also disable the L2 without a
flush of the secureos workspace.

Change-Id: I61c3caade6cb6f922b9d9f9ca0739bc6ae4e78cd
Signed-off-by: Hyung Taek Ryoo <hryoo@nvidia.com>
Reviewed-on: http://git-master/r/128951
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: James Zhao <jamesz@nvidia.com>
Reviewed-by: Yu-Huan Hsu <yhsu@nvidia.com>

arch/arm/mach-tegra/common.c
arch/arm/mach-tegra/pm.c

index c5401e6..8364589 100644 (file)
@@ -227,8 +227,6 @@ static __initdata struct tegra_clk_init_table common_clk_init_table[] = {
 };
 
 #ifdef CONFIG_TRUSTED_FOUNDATIONS
-#define CACHE_LINE_SIZE                32
-
 static inline void tegra_l2x0_disable_tz(void)
 {
        static u32 l2x0_way_mask;
@@ -244,20 +242,19 @@ static inline void tegra_l2x0_disable_tz(void)
                l2x0_way_mask = (1 << ways) - 1;
        }
 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
-       /* flush all ways on disable */
+       /* flush all ways on any 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");
-
-               /* 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 */
+       if (tegra_is_cpu_in_lp2(0) == false) {
+               /*
+                * If entering LP0/LP1, ask secureos to fully flush and
+                * disable the L2.
+                *
+                * If entering LP2, L2 disable is handled by the secureos
+                * as part of the tegra_sleep_cpu() SMC. This SMC indicates
+                * no more secureos tasks will be scheduled, allowing it
+                * to optimize out L2 flushes on its side.
+                */
                tegra_generic_smc_uncached(0xFFFFF100,
                                                0x00000002, l2x0_way_mask);
        }
index 2cdfdfe..b20b512 100644 (file)
@@ -579,6 +579,16 @@ static void tegra_sleep_core(enum tegra_suspend_mode mode,
 static inline void tegra_sleep_cpu(unsigned long v2p)
 {
 #ifdef CONFIG_TRUSTED_FOUNDATIONS
+       if (tegra_is_cpu_in_lp2(0)) {
+               struct thread_info *thread;
+
+               /* flush thread state (sleep SMC will also disable L2) */
+               thread = current_thread_info();
+               BUG_ON(!thread);
+
+               __cpuc_flush_dcache_area(thread, THREAD_SIZE);
+               outer_flush_range(__pa(thread), __pa(thread) + THREAD_SIZE);
+       }
        tegra_generic_smc_uncached(0xFFFFFFFC, 0xFFFFFFE4,
                                   (TEGRA_RESET_HANDLER_BASE +
                                    tegra_cpu_reset_handler_offset));