From 02e75d648899df96b79a4f98380679f48b91e3d4 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Mon, 4 Mar 2013 17:05:57 -0700 Subject: ARM: tegra: remove save/restore of CPU diag register Prior to this change, {save,restore}_cpu_arch_register() collaborated to maintain the value of the CPU diagnostic register across power cycles. This was required to maintain any CPU errata workaround enable bits in that register. However, now that the Tegra reset vector code always enables all required workarounds, there is no need to save and restore the diagnostic register; it is always explicitly programmed in the required manner. Hence, remove the save/restore logic. This has the advantage that the kernel always directly controls the value of this register every boot, rather than relying on a bootloader or other kernel code having previously written the correct value into it. This makes CPU0 (which was previously saved/restored) and CPUn (which should have been set up by the reset vector) be controlled in exactly the same way, which is easier to debug/find/... In particular, when converting Tegra to a multi-platform kernel, the CPU0 diagnostic register value initially comes from the bootloader. Most Tegra bootloaders don't yet enable all required CPU bug workarounds. The previous commit updates the kernel to do so on any CPU power cycle. However, the save/restore code ends up over-writing the value with the old bootloader-driven value instead of the now more-likely-to-be-correct kernel value! Even irrespective of multi-platform conversion, this change limits the kernel's exposure to any WARs the bootloader didn't enable for CPU0: on the very first LP2 transition (CPU power-saving which power-cycles the CPU), the correct value will be enabled. Signed-off-by: Stephen Warren --- arch/arm/mach-tegra/pm.c | 19 ------------------- 1 file changed, 19 deletions(-) (limited to 'arch/arm/mach-tegra/pm.c') diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c index 523604de666..0494f739c95 100644 --- a/arch/arm/mach-tegra/pm.c +++ b/arch/arm/mach-tegra/pm.c @@ -46,26 +46,11 @@ #define PMC_CPUPWROFF_TIMER 0xcc #ifdef CONFIG_PM_SLEEP -static unsigned int g_diag_reg; static DEFINE_SPINLOCK(tegra_lp2_lock); static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE); static struct clk *tegra_pclk; void (*tegra_tear_down_cpu)(void); -void save_cpu_arch_register(void) -{ - /* read diagnostic register */ - asm("mrc p15, 0, %0, c15, c0, 1" : "=r"(g_diag_reg) : : "cc"); - return; -} - -void restore_cpu_arch_register(void) -{ - /* write diagnostic register */ - asm("mcr p15, 0, %0, c15, c0, 1" : : "r"(g_diag_reg) : "cc"); - return; -} - static void set_power_timers(unsigned long us_on, unsigned long us_off) { unsigned long long ticks; @@ -119,8 +104,6 @@ static void restore_cpu_complex(void) tegra_cpu_clock_resume(); flowctrl_cpu_suspend_exit(cpu); - - restore_cpu_arch_register(); } /* @@ -145,8 +128,6 @@ static void suspend_cpu_complex(void) tegra_cpu_clock_suspend(); flowctrl_cpu_suspend_enter(cpu); - - save_cpu_arch_register(); } void tegra_clear_cpu_in_lp2(int phy_cpu_id) -- cgit v1.2.3-70-g09d2 From 2058842e6d7833e41be7cc2434465e69bcd51d45 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 23 Apr 2013 15:36:26 +0200 Subject: ARM: tegra: call cpu_do_idle from C code When building a kernel for multiple CPU architecture levels, cpu_do_idle() is a macro for an indirect function call, which cannot be called from assembly code as Tegra does. Adding a trivial C wrapper for this function lets us build a tegra kernel with ARMv6 support enabled. Signed-off-by: Arnd Bergmann Acked-by: Joseph Lo Cc: Stephen Warren --- arch/arm/mach-tegra/pm.c | 5 +++++ arch/arm/mach-tegra/sleep-tegra20.S | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'arch/arm/mach-tegra/pm.c') diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c index 0494f739c95..04a8e06f59a 100644 --- a/arch/arm/mach-tegra/pm.c +++ b/arch/arm/mach-tegra/pm.c @@ -162,6 +162,11 @@ bool tegra_set_cpu_in_lp2(int phy_cpu_id) return last_cpu; } +int tegra_cpu_do_idle(void) +{ + return cpu_do_idle(); +} + static int tegra_sleep_cpu(unsigned long v2p) { /* Switch to the identity mapping. */ diff --git a/arch/arm/mach-tegra/sleep-tegra20.S b/arch/arm/mach-tegra/sleep-tegra20.S index 9f6bfafdd51..e3f2417c420 100644 --- a/arch/arm/mach-tegra/sleep-tegra20.S +++ b/arch/arm/mach-tegra/sleep-tegra20.S @@ -197,7 +197,7 @@ ENTRY(tegra20_sleep_cpu_secondary_finish) mov r3, #CPU_RESETTABLE str r3, [r0] - bl cpu_do_idle + bl tegra_cpu_do_idle /* * cpu may be reset while in wfi, which will return through -- cgit v1.2.3-70-g09d2