From patchwork Wed Oct 31 09:41:16 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joseph Lo X-Patchwork-Id: 1677661 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork2.kernel.org (Postfix) with ESMTP id 70509DF2F6 for ; Wed, 31 Oct 2012 09:44:35 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TTUoR-0002m2-V2; Wed, 31 Oct 2012 09:42:16 +0000 Received: from hqemgate03.nvidia.com ([216.228.121.140]) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1TTUnp-0002Ye-Fb for linux-arm-kernel@lists.infradead.org; Wed, 31 Oct 2012 09:41:43 +0000 Received: from hqnvupgp05.nvidia.com (Not Verified[216.228.121.13]) by hqemgate03.nvidia.com id ; Wed, 31 Oct 2012 02:44:10 -0700 Received: from hqemhub03.nvidia.com ([172.17.108.22]) by hqnvupgp05.nvidia.com (PGP Universal service); Wed, 31 Oct 2012 02:41:36 -0700 X-PGP-Universal: processed; by hqnvupgp05.nvidia.com on Wed, 31 Oct 2012 02:41:36 -0700 Received: from localhost.localdomain (172.20.144.16) by hqemhub03.nvidia.com (172.20.150.15) with Microsoft SMTP Server (TLS) id 8.3.279.1; Wed, 31 Oct 2012 02:41:35 -0700 From: Joseph Lo To: Stephen Warren Subject: [PATCH V4 2/7] ARM: tegra: cpuidle: add CPU resume function Date: Wed, 31 Oct 2012 17:41:16 +0800 Message-ID: <1351676481-28425-3-git-send-email-josephl@nvidia.com> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1351676481-28425-1-git-send-email-josephl@nvidia.com> References: <1351676481-28425-1-git-send-email-josephl@nvidia.com> X-NVConfidentiality: public MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20121031_054137_824001_76BBCA1C X-CRM114-Status: GOOD ( 16.49 ) X-Spam-Score: -7.6 (-------) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-7.6 points) pts rule name description ---- ---------------------- -------------------------------------------------- -5.0 RCVD_IN_DNSWL_HI RBL: Sender listed at http://www.dnswl.org/, high trust [216.228.121.140 listed in list.dnswl.org] -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -0.0 SPF_PASS SPF: sender matches SPF record -0.7 RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: linux-tegra@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Joseph Lo X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org The CPU suspending on Tegra means CPU power gating. We add a resume function for taking care the CPUs that resume from power gating status. This function was been hooked to the reset handler. We take care everything here before go into kernel. Be aware of that, you may see the legacy power status "LP2" in the code which is exactly the same meaning of "CPU power down". Based on the work by: Scott Williams Colin Cross Gary King Signed-off-by: Joseph Lo --- V4: * rebased on next-20121031 * add ifdef of CONFIG_HAVE_ARM_SCU in tegra_resume, this can make the code re-usable for the future chips (e.g. A15) V3: * update subject and the commit message V2: * moving the code that only for Tegra30 inside the ifdef in the tegra_resume --- arch/arm/mach-tegra/headsmp.S | 60 +++++++++++++++++++++++++++++++++++++++++ arch/arm/mach-tegra/reset.c | 6 ++++ arch/arm/mach-tegra/sleep.h | 1 + 3 files changed, 67 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-tegra/headsmp.S b/arch/arm/mach-tegra/headsmp.S index 93f0370..82dc84b 100644 --- a/arch/arm/mach-tegra/headsmp.S +++ b/arch/arm/mach-tegra/headsmp.S @@ -68,6 +68,55 @@ ENTRY(tegra_secondary_startup) b secondary_startup ENDPROC(tegra_secondary_startup) +#ifdef CONFIG_PM_SLEEP +/* + * tegra_resume + * + * CPU boot vector when restarting the a CPU following + * an LP2 transition. Also branched to by LP0 and LP1 resume after + * re-enabling sdram. + */ +ENTRY(tegra_resume) + bl v7_invalidate_l1 + /* Enable coresight */ + mov32 r0, 0xC5ACCE55 + mcr p14, 0, r0, c7, c12, 6 + + cpu_id r0 + cmp r0, #0 @ CPU0? + bne cpu_resume @ no + +#ifdef CONFIG_ARCH_TEGRA_3x_SOC + /* Are we on Tegra20? */ + mov32 r6, TEGRA_APB_MISC_BASE + ldr r0, [r6, #APB_MISC_GP_HIDREV] + and r0, r0, #0xff00 + cmp r0, #(0x20 << 8) + beq 1f @ Yes + /* Clear the flow controller flags for this CPU. */ + mov32 r2, TEGRA_FLOW_CTRL_BASE + FLOW_CTRL_CPU0_CSR @ CPU0 CSR + ldr r1, [r2] + /* Clear event & intr flag */ + orr r1, r1, \ + #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG + movw r0, #0x0FFD @ enable, cluster_switch, immed, & bitmaps + bic r1, r1, r0 + str r1, [r2] +1: +#endif + +#ifdef CONFIG_HAVE_ARM_SCU + /* enable SCU */ + mov32 r0, TEGRA_ARM_PERIF_BASE + ldr r1, [r0] + orr r1, r1, #1 + str r1, [r0] +#endif + + b cpu_resume +ENDPROC(tegra_resume) +#endif + .align L1_CACHE_SHIFT ENTRY(__tegra_cpu_reset_handler_start) @@ -121,6 +170,17 @@ ENTRY(__tegra_cpu_reset_handler) 1: #endif + /* Waking up from LP2? */ + ldr r9, [r12, #RESET_DATA(MASK_LP2)] + tst r9, r11 @ if in_lp2 + beq __is_not_lp2 + ldr lr, [r12, #RESET_DATA(STARTUP_LP2)] + cmp lr, #0 + bleq __die @ no LP2 startup handler + bx lr + +__is_not_lp2: + #ifdef CONFIG_SMP /* * Can only be secondary boot (initial or hotplug) but CPU 0 diff --git a/arch/arm/mach-tegra/reset.c b/arch/arm/mach-tegra/reset.c index e05da7d..3fd89ec 100644 --- a/arch/arm/mach-tegra/reset.c +++ b/arch/arm/mach-tegra/reset.c @@ -25,6 +25,7 @@ #include "iomap.h" #include "irammap.h" #include "reset.h" +#include "sleep.h" #include "fuse.h" #define TEGRA_IRAM_RESET_BASE (TEGRA_IRAM_BASE + \ @@ -79,5 +80,10 @@ void __init tegra_cpu_reset_handler_init(void) virt_to_phys((void *)tegra_secondary_startup); #endif +#ifdef CONFIG_PM_SLEEP + __tegra_cpu_reset_handler_data[TEGRA_RESET_STARTUP_LP2] = + virt_to_phys((void *)tegra_resume); +#endif + tegra_cpu_reset_handler_enable(); } diff --git a/arch/arm/mach-tegra/sleep.h b/arch/arm/mach-tegra/sleep.h index 4889b28..addb83f 100644 --- a/arch/arm/mach-tegra/sleep.h +++ b/arch/arm/mach-tegra/sleep.h @@ -72,6 +72,7 @@ dsb .endm #else +void tegra_resume(void); #ifdef CONFIG_HOTPLUG_CPU void tegra20_hotplug_init(void);