From patchwork Wed Dec 5 10:01:55 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joseph Lo X-Patchwork-Id: 1840721 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 C0465DF266 for ; Wed, 5 Dec 2012 10:06:50 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TgBpS-0007Kt-RP; Wed, 05 Dec 2012 10:03:47 +0000 Received: from hqemgate03.nvidia.com ([216.228.121.140]) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1TgBoD-0006o0-V1 for linux-arm-kernel@lists.infradead.org; Wed, 05 Dec 2012 10:02:31 +0000 Received: from hqnvupgp05.nvidia.com (Not Verified[216.228.121.13]) by hqemgate03.nvidia.com id ; Wed, 05 Dec 2012 02:05:46 -0800 Received: from hqemhub02.nvidia.com ([172.17.108.22]) by hqnvupgp05.nvidia.com (PGP Universal service); Wed, 05 Dec 2012 02:02:28 -0800 X-PGP-Universal: processed; by hqnvupgp05.nvidia.com on Wed, 05 Dec 2012 02:02: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:27 -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:55 +0800 Message-ID: <1354701715-24150-9-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> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20121205_050230_228624_650C71B8 X-CRM114-Status: GOOD ( 13.54 ) 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 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 config ARCH_TEGRA_3x_SOC bool "Enable support for Tegra30 family" + select ARCH_NEEDS_CPU_IDLE_COUPLED select ARCH_REQUIRE_GPIOLIB select ARM_ERRATA_743622 select ARM_ERRATA_751472 diff --git a/arch/arm/mach-tegra/cpuidle-tegra30.c b/arch/arm/mach-tegra/cpuidle-tegra30.c index 5e8cbf5..f880350 100644 --- a/arch/arm/mach-tegra/cpuidle-tegra30.c +++ b/arch/arm/mach-tegra/cpuidle-tegra30.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -30,14 +31,18 @@ #include #include +#include "irq.h" #include "pm.h" #include "sleep.h" #include "tegra_cpu_car.h" #ifdef CONFIG_PM_SLEEP -static int tegra30_idle_lp2(struct cpuidle_device *dev, - struct cpuidle_driver *drv, - int index); +static bool abort_flag; +static atomic_t abort_barrier; +static cpumask_t cpus_out_lp2; +static int tegra30_idle_lp2_coupled(struct cpuidle_device *dev, + struct cpuidle_driver *drv, + int index); #endif static struct cpuidle_driver tegra_idle_driver = { @@ -53,11 +58,12 @@ static struct cpuidle_driver tegra_idle_driver = { [0] = ARM_CPUIDLE_WFI_STATE_PWR(600), #ifdef CONFIG_PM_SLEEP [1] = { - .enter = tegra30_idle_lp2, + .enter = tegra30_idle_lp2_coupled, .exit_latency = 2000, .target_residency = 2200, .power_usage = 0, - .flags = CPUIDLE_FLAG_TIME_VALID, + .flags = CPUIDLE_FLAG_TIME_VALID | + CPUIDLE_FLAG_COUPLED, .name = "powered-down", .desc = "CPU power gated", }, @@ -79,8 +85,8 @@ static bool tegra30_cpu_cluster_power_down(struct cpuidle_device *dev, /* All CPUs entering LP2 is not working. * Don't let CPU0 enter LP2 when any secondary CPU is online. */ - if (num_online_cpus() > 1 || !tegra_cpu_rail_off_ready()) { - cpu_do_idle(); + if (num_online_cpus() > 1 && !tegra_cpu_rail_off_ready()) { +// cpu_do_idle(); return false; } @@ -94,6 +100,13 @@ static bool tegra30_cpu_cluster_power_down(struct cpuidle_device *dev, } #ifdef CONFIG_SMP +static void tegra30_wake_up_secondary_cpus(u32 cpu) +{ +// if (!cpumask_test_cpu(cpu, &cpus_out_lp2)) + arch_send_wakeup_ipi_mask(cpumask_of(cpu)); +// gic_raise_softirq(cpumask_of(cpu), 0); +} + static bool tegra30_cpu_core_power_down(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) @@ -113,6 +126,11 @@ static bool tegra30_cpu_core_power_down(struct cpuidle_device *dev, return true; } #else +static inline void tegra30_wake_up_secondary_cpus(u32 cpu) +{ + return; +} + static inline bool tegra30_cpu_core_power_down(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) @@ -121,36 +139,56 @@ static inline bool tegra30_cpu_core_power_down(struct cpuidle_device *dev, } #endif -static int __cpuinit tegra30_idle_lp2(struct cpuidle_device *dev, - struct cpuidle_driver *drv, - int index) +static int __cpuinit tegra30_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; +int i; + abort_flag = tegra_pending_irq(); + cpumask_clear(&cpus_out_lp2); + cpuidle_coupled_parallel_barrier(dev, &abort_barrier); +//printk(KERN_EMERG "cpu %d in\n", cpu); + if (abort_flag) + 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 = tegra30_cpu_cluster_power_down(dev, drv, - index); - else - cpu_do_idle(); + while (num_online_cpus() > 1 && !tegra_cpu_rail_off_ready()) { + cpu_relax(); + +// if (!cpumask_empty(&cpus_out_lp2)) +// goto out; + } + entered_lp2 = tegra30_cpu_cluster_power_down(dev, drv, index); + +out: +// if (!entered_lp2) { +// int i; + for_each_online_cpu(i) + if (i != cpu) + tegra30_wake_up_secondary_cpus(i); +// } } else { entered_lp2 = tegra30_cpu_core_power_down(dev, drv, index); + cpumask_set_cpu(cpu, &cpus_out_lp2); } + cpu_pm_exit(); tegra_clear_cpu_in_lp2(cpu); - +// +// local_fiq_enable(); smp_rmb(); - +//printk(KERN_EMERG "cpu %d out\n", cpu); +cpuidle_coupled_parallel_barrier(dev, &abort_barrier); return (entered_lp2) ? index : 0; } #endif @@ -175,6 +213,9 @@ int __init tegra30_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);