From patchwork Fri Jan 4 16:59:59 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Lezcano X-Patchwork-Id: 13808 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 57DA223EC8 for ; Fri, 4 Jan 2013 17:00:14 +0000 (UTC) Received: from mail-vb0-f50.google.com (mail-vb0-f50.google.com [209.85.212.50]) by fiordland.canonical.com (Postfix) with ESMTP id F281EA197DA for ; Fri, 4 Jan 2013 17:00:13 +0000 (UTC) Received: by mail-vb0-f50.google.com with SMTP id ft2so5106813vbb.9 for ; Fri, 04 Jan 2013 09:00:13 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-received:x-forwarded-to:x-forwarded-for:delivered-to:x-received :received-spf:x-received:from:to:cc:subject:date:message-id:x-mailer :in-reply-to:references:x-gm-message-state; bh=9bMwnGsWijigqTz1b5/26ksl9nw/ry0jVyUNpcx+q2Y=; b=oIQ5Gx4UfzzoUZR2dAgC5IiBIsx+5gYajo7Gmmjmqfsydy9XbQCgPpvdfkwvXIO8aB GAMZfmoeLR9wHHEYoQJ29KAFn8LsKrTmZ+dXQOq/85aWn9uj++cgSxRW+hO0aHPNMwda qqiavUpjpjNXrb87P/7RgaOoqtpKLaP6+bjnRwY5biJje4UAnf6ixKFjLwm8kEnRmtTc 92eAgIkDvgxUEjT1jNleRYUdxrkj1hKNPABkp+dPieTm4Y9hJU/W4PgZ2yi/zJ2satIM F633ZqMgB9LOkK844viRHWa6+Q7bkNi5847rbhJFRBV2L0y4K3G2kgwDGTnO+qEwFEkZ 1NqQ== X-Received: by 10.52.70.205 with SMTP id o13mr67099627vdu.75.1357318812557; Fri, 04 Jan 2013 09:00:12 -0800 (PST) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.58.145.101 with SMTP id st5csp146430veb; Fri, 4 Jan 2013 09:00:12 -0800 (PST) X-Received: by 10.194.121.74 with SMTP id li10mr73920209wjb.5.1357318811632; Fri, 04 Jan 2013 09:00:11 -0800 (PST) Received: from mail-wg0-f47.google.com (mail-wg0-f47.google.com [74.125.82.47]) by mx.google.com with ESMTPS id o8si77070454wix.7.2013.01.04.09.00.11 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 04 Jan 2013 09:00:11 -0800 (PST) Received-SPF: neutral (google.com: 74.125.82.47 is neither permitted nor denied by best guess record for domain of daniel.lezcano@linaro.org) client-ip=74.125.82.47; Authentication-Results: mx.google.com; spf=neutral (google.com: 74.125.82.47 is neither permitted nor denied by best guess record for domain of daniel.lezcano@linaro.org) smtp.mail=daniel.lezcano@linaro.org Received: by mail-wg0-f47.google.com with SMTP id dq11so7470782wgb.2 for ; Fri, 04 Jan 2013 09:00:10 -0800 (PST) X-Received: by 10.194.21.70 with SMTP id t6mr84865039wje.42.1357318810570; Fri, 04 Jan 2013 09:00:10 -0800 (PST) Received: from mai.home (AToulouse-654-1-322-234.w86-199.abo.wanadoo.fr. [86.199.209.234]) by mx.google.com with ESMTPS id t17sm91133761wiv.6.2013.01.04.09.00.08 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 04 Jan 2013 09:00:09 -0800 (PST) From: Daniel Lezcano To: kgene.kim@samsung.com Cc: linux-arm-kernel@lists.infradead.org, linux-samsung-soc@vger.kernel.org, patches@linaro.org, linaro-dev@lists.linaro.org Subject: [PATCH 5/5] ARM: exynos: enable/disable cpuidle when cpu1 is down/up Date: Fri, 4 Jan 2013 17:59:59 +0100 Message-Id: <1357318799-24378-5-git-send-email-daniel.lezcano@linaro.org> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1357318799-24378-1-git-send-email-daniel.lezcano@linaro.org> References: <1357318799-24378-1-git-send-email-daniel.lezcano@linaro.org> X-Gm-Message-State: ALoCoQkj+LSwfjS4NaZiOTJjotGXpRwq23Rq/OX1KDx9jFCnkzhRbNdD7ylG/qN5zKqwspeNiHHV What we have now is (1) cpu0 going always to WFI when cpu1 is up, (2) cpu0 going to all states when cpu1 is down. In other words, cpuidle is disabled when cpu1 is up and enabled when cpu1 is down. This patch use the cpu hotplug notifier to enable/disable cpuidle, when the cpu1 is plugged or unplugged. That clarifies the code and make it simpler. Signed-off: Daniel Lezcano --- arch/arm/mach-exynos/cpuidle.c | 117 +++++++++++++++++++++++----------------- 1 file changed, 69 insertions(+), 48 deletions(-) diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c index e6f006b..d8f6f33 100644 --- a/arch/arm/mach-exynos/cpuidle.c +++ b/arch/arm/mach-exynos/cpuidle.c @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include #include #include @@ -36,31 +38,8 @@ #define S5P_CHECK_AFTR 0xFCBA0D10 -static int exynos4_enter_lowpower(struct cpuidle_device *dev, - struct cpuidle_driver *drv, - int index); - static struct cpuidle_device exynos4_cpuidle_device; -static struct cpuidle_driver exynos4_idle_driver = { - .name = "exynos4_idle", - .owner = THIS_MODULE, - .en_core_tk_irqen = 1, - .states = { - [0] = ARM_CPUIDLE_WFI_STATE, - [1] = { - .enter = exynos4_enter_lowpower, - .exit_latency = 300, - .target_residency = 100000, - .flags = CPUIDLE_FLAG_TIME_VALID, - .name = "C1", - .desc = "ARM power down", - }, - }, - .state_count = 2, - .safe_state_index = 0, -}; - /* Ext-GIC nIRQ/nFIQ is the only wakeup source in AFTR */ static void exynos4_set_wakeupmask(void) { @@ -93,9 +72,9 @@ static int idle_finisher(unsigned long flags) return 1; } -static int exynos4_enter_core0_aftr(struct cpuidle_device *dev, - struct cpuidle_driver *drv, - int index) +static int exynos4_enter_lowpower(struct cpuidle_device *dev, + struct cpuidle_driver *drv, + int index) { unsigned long tmp; @@ -143,22 +122,6 @@ static int exynos4_enter_core0_aftr(struct cpuidle_device *dev, return index; } -static int exynos4_enter_lowpower(struct cpuidle_device *dev, - struct cpuidle_driver *drv, - int index) -{ - int new_index = index; - - /* This mode only can be entered when other core's are offline */ - if (num_online_cpus() > 1) - new_index = drv->safe_state_index; - - if (new_index == 0) - return arm_cpuidle_simple_enter(dev, drv, new_index); - else - return exynos4_enter_core0_aftr(dev, drv, new_index); -} - static void __init exynos5_core_down_clk(void) { unsigned int tmp; @@ -191,6 +154,62 @@ static void __init exynos5_core_down_clk(void) __raw_writel(tmp, EXYNOS5_PWR_CTRL2); } +static int cpu_hotplug_notify(struct notifier_block *n, + unsigned long action, void *hcpu) +{ + int ret; + + /* + * cpu0 can't be shutdown on Origen, so this routine is + * called only for cpu1. + */ + + switch (action & 0xf) { + + case CPU_ONLINE: + cpuidle_pause_and_lock(); + cpuidle_disable_device(&exynos4_cpuidle_device); + cpuidle_resume_and_unlock(); + break; + + case CPU_DEAD: + if (!exynos4_cpuidle_device.registered) { + ret = cpuidle_register_device(&exynos4_cpuidle_device); + WARN_ONCE(ret, "Failed to register cpuidle device"); + } else { + cpuidle_pause_and_lock(); + cpuidle_enable_device(&exynos4_cpuidle_device); + cpuidle_resume_and_unlock(); + } + break; + } + + return NOTIFY_OK; +} + +static struct notifier_block cpu_hotplug_notifier = { + .notifier_call = cpu_hotplug_notify, +}; + +static struct cpuidle_driver exynos4_idle_driver = { + .name = "exynos4_idle", + .owner = THIS_MODULE, + .en_core_tk_irqen = 1, + .states = { + [0] = ARM_CPUIDLE_WFI_STATE, + [1] = { + .enter = exynos4_enter_lowpower, + .exit_latency = 300, + .target_residency = 100000, + .flags = CPUIDLE_FLAG_TIME_VALID, + .name = "C1", + .desc = "ARM power down", + }, + }, + .state_count = 2, + .safe_state_index = 0, +}; + static int __init exynos4_init_cpuidle(void) { int ret; @@ -204,12 +223,14 @@ static int __init exynos4_init_cpuidle(void) return ret; } - ret = cpuidle_register_device(&exynos4_cpuidle_device); - if (ret) { - printk(KERN_ERR "CPUidle register device failed\n"); - return ret; - } + ret = register_cpu_notifier(&cpu_hotplug_notifier); + if (ret) + goto out_unregister_driver; +out: + return ret; - return 0; +out_unregister_driver: + cpuidle_unregister_driver(&exynos4_idle_driver); + goto out; } device_initcall(exynos4_init_cpuidle);