From patchwork Wed Dec 5 10:01:53 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joseph Lo X-Patchwork-Id: 1840691 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork1.kernel.org (Postfix) with ESMTP id 7F1C33FCF2 for ; Wed, 5 Dec 2012 10:06:15 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TgBoy-00072D-PK; Wed, 05 Dec 2012 10:03: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 1TgBo8-0006mo-4p for linux-arm-kernel@lists.infradead.org; Wed, 05 Dec 2012 10:02:25 +0000 Received: from hqnvupgp07.nvidia.com (Not Verified[216.228.121.13]) by hqemgate03.nvidia.com id ; Wed, 05 Dec 2012 02:05:41 -0800 Received: from hqemhub02.nvidia.com ([172.17.108.22]) by hqnvupgp07.nvidia.com (PGP Universal service); Wed, 05 Dec 2012 02:01:28 -0800 X-PGP-Universal: processed; by hqnvupgp07.nvidia.com on Wed, 05 Dec 2012 02:01:28 -0800 Received: from localhost.localdomain (172.20.144.16) by hqemhub02.nvidia.com (172.20.150.31) with Microsoft SMTP Server (TLS) id 8.3.279.1; Wed, 5 Dec 2012 02:02:21 -0800 From: Joseph Lo To: Stephen Warren Subject: [PATCH V2 6/6] ARM: tegra20: cpuidle: apply coupled cpuidle for powered-down mode Date: Wed, 5 Dec 2012 18:01:53 +0800 Message-ID: <1354701715-24150-7-git-send-email-josephl@nvidia.com> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1354701715-24150-1-git-send-email-josephl@nvidia.com> References: <1354701715-24150-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-20121205_050224_475424_0FD42298 X-CRM114-Status: GOOD ( 16.12 ) 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 "powered-down" cpuidle mode of Tegra20 needs the CPU0 be the last one core to go into this mode before other core. The coupled cpuidle framework can help to sync the MPCore to coupled state then go into "powered-down" idle mode together. The driver can just assume the MPCore come into "powered-down" mode at the same time. No need to take care if the CPU_0 goes into this mode along and only can put it into safe idle mode (WFI). Signed-off-by: Joseph Lo --- V2: * handling the case of SGI pending before go into "powered-down" idle mode --- arch/arm/mach-tegra/Kconfig | 1 + arch/arm/mach-tegra/cpuidle-tegra20.c | 48 ++++++++++++++++++++------------ 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index e426d1b..e07241a 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -4,6 +4,7 @@ comment "NVIDIA Tegra options" config ARCH_TEGRA_2x_SOC bool "Enable support for Tegra20 family" + select ARCH_NEEDS_CPU_IDLE_COUPLED select ARCH_REQUIRE_GPIOLIB select ARM_ERRATA_720789 select ARM_ERRATA_742230 diff --git a/arch/arm/mach-tegra/cpuidle-tegra20.c b/arch/arm/mach-tegra/cpuidle-tegra20.c index a83a53b..13e3ae4 100644 --- a/arch/arm/mach-tegra/cpuidle-tegra20.c +++ b/arch/arm/mach-tegra/cpuidle-tegra20.c @@ -33,13 +33,16 @@ #include "pm.h" #include "sleep.h" #include "iomap.h" +#include "irq.h" #include "tegra_cpu_car.h" #include "flowctrl.h" #ifdef CONFIG_PM_SLEEP -static int tegra20_idle_lp2(struct cpuidle_device *dev, - struct cpuidle_driver *drv, - int index); +static atomic_t abort_flag; +static atomic_t abort_barrier; +static int tegra20_idle_lp2_coupled(struct cpuidle_device *dev, + struct cpuidle_driver *drv, + int index); #endif static struct cpuidle_driver tegra_idle_driver = { @@ -55,11 +58,12 @@ static struct cpuidle_driver tegra_idle_driver = { [0] = ARM_CPUIDLE_WFI_STATE_PWR(600), #ifdef CONFIG_PM_SLEEP [1] = { - .enter = tegra20_idle_lp2, + .enter = tegra20_idle_lp2_coupled, .exit_latency = 5000, .target_residency = 10000, .power_usage = 0, - .flags = CPUIDLE_FLAG_TIME_VALID, + .flags = CPUIDLE_FLAG_TIME_VALID | + CPUIDLE_FLAG_COUPLED, .name = "powered-down", .desc = "CPU power gated", }, @@ -178,28 +182,33 @@ static inline bool tegra20_idle_enter_lp2_cpu_1(struct cpuidle_device *dev, } #endif -static int __cpuinit tegra20_idle_lp2(struct cpuidle_device *dev, - struct cpuidle_driver *drv, - int index) +static int __cpuinit tegra20_idle_lp2_coupled(struct cpuidle_device *dev, + struct cpuidle_driver *drv, + int index) { u32 cpu = is_smp() ? cpu_logical_map(dev->cpu) : dev->cpu; bool entered_lp2 = false; - bool last_cpu; + + if (tegra_pending_sgi()) + atomic_inc(&abort_flag); + + cpuidle_coupled_parallel_barrier(dev, &abort_barrier); + + if (atomic_read(&abort_flag) > 0) { + cpuidle_coupled_parallel_barrier(dev, &abort_barrier); + atomic_set(&abort_flag, 0); /* clean flag for next coming */ + return -EINTR; + } local_fiq_disable(); - last_cpu = tegra_set_cpu_in_lp2(cpu); + tegra_set_cpu_in_lp2(cpu); cpu_pm_enter(); - if (cpu == 0) { - if (last_cpu) - entered_lp2 = tegra20_cpu_cluster_power_down(dev, drv, - index); - else - cpu_do_idle(); - } else { + if (cpu == 0) + entered_lp2 = tegra20_cpu_cluster_power_down(dev, drv, index); + else entered_lp2 = tegra20_idle_enter_lp2_cpu_1(dev, drv, index); - } cpu_pm_exit(); tegra_clear_cpu_in_lp2(cpu); @@ -232,6 +241,9 @@ int __init tegra20_cpuidle_init(void) for_each_possible_cpu(cpu) { dev = &per_cpu(tegra_idle_device, cpu); dev->cpu = cpu; +#ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED + dev->coupled_cpus = *cpu_online_mask; +#endif dev->state_count = drv->state_count; ret = cpuidle_register_device(dev);