From patchwork Tue Dec 6 04:38:04 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob X-Patchwork-Id: 5503 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 3107523E10 for ; Tue, 6 Dec 2011 04:38:22 +0000 (UTC) Received: from mail-lpp01m010-f52.google.com (mail-lpp01m010-f52.google.com [209.85.215.52]) by fiordland.canonical.com (Postfix) with ESMTP id 1058CA182F0 for ; Tue, 6 Dec 2011 04:38:22 +0000 (UTC) Received: by mail-lpp01m010-f52.google.com with SMTP id m6so727409lag.11 for ; Mon, 05 Dec 2011 20:38:21 -0800 (PST) Received: by 10.152.106.115 with SMTP id gt19mr7924485lab.27.1323146301938; Mon, 05 Dec 2011 20:38:21 -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.152.41.198 with SMTP id h6cs296303lal; Mon, 5 Dec 2011 20:38:21 -0800 (PST) Received: by 10.229.47.208 with SMTP id o16mr2633785qcf.230.1323146299960; Mon, 05 Dec 2011 20:38:19 -0800 (PST) Received: from mail-qy0-f178.google.com (mail-qy0-f178.google.com [209.85.216.178]) by mx.google.com with ESMTPS id c9si1227811qap.45.2011.12.05.20.38.18 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 05 Dec 2011 20:38:19 -0800 (PST) Received-SPF: neutral (google.com: 209.85.216.178 is neither permitted nor denied by best guess record for domain of rob.lee@linaro.org) client-ip=209.85.216.178; Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.216.178 is neither permitted nor denied by best guess record for domain of rob.lee@linaro.org) smtp.mail=rob.lee@linaro.org Received: by mail-qy0-f178.google.com with SMTP id o15so2179464qcs.37 for ; Mon, 05 Dec 2011 20:38:18 -0800 (PST) Received: by 10.229.65.27 with SMTP id g27mr2678871qci.288.1323146296906; Mon, 05 Dec 2011 20:38:16 -0800 (PST) Received: from b18647-20 ([23.19.172.17]) by mx.google.com with ESMTPS id fm5sm29806936qab.20.2011.12.05.20.38.15 (version=SSLv3 cipher=OTHER); Mon, 05 Dec 2011 20:38:16 -0800 (PST) From: Robert Lee To: linux@arm.linux.org.uk, s.hauer@pengutronix.de Cc: shawn.guo@freescale.com, nicolas.ferre@atmel.com, linux@maxim.org.za, kgene.kim@samsung.com, amit.kachhap@linaro.org, magnus.damm@gmail.com, khilman@ti.com, nsekhar@ti.com, daniel.lezcano@linaro.org, mturquette@linaro.org, vincent.guittot@linaro.org, arnd.bergmann@linaro.org, amit.kucheria@linaro.org, linux-arm-kernel@lists.infradead.org, patches@linaro.org Subject: [RFC PATCH 1/8] ARM: Add commonly used cpuidle init code Date: Mon, 5 Dec 2011 22:38:04 -0600 Message-Id: <1323146291-10676-2-git-send-email-rob.lee@linaro.org> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1323146291-10676-1-git-send-email-rob.lee@linaro.org> References: <1323146291-10676-1-git-send-email-rob.lee@linaro.org> Add commonly used cpuidle init code to avoid unecessary duplication. Signed-off-by: Robert Lee --- arch/arm/common/Makefile | 1 + arch/arm/common/cpuidle.c | 132 ++++++++++++++++++++++++++++++++++++++++ arch/arm/include/asm/cpuidle.h | 25 ++++++++ 3 files changed, 158 insertions(+), 0 deletions(-) create mode 100644 arch/arm/common/cpuidle.c create mode 100644 arch/arm/include/asm/cpuidle.h diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile index 6ea9b6f..0865f69 100644 --- a/arch/arm/common/Makefile +++ b/arch/arm/common/Makefile @@ -17,3 +17,4 @@ obj-$(CONFIG_ARCH_IXP2000) += uengine.o obj-$(CONFIG_ARCH_IXP23XX) += uengine.o obj-$(CONFIG_PCI_HOST_ITE8152) += it8152.o obj-$(CONFIG_ARM_TIMER_SP804) += timer-sp.o +obj-$(CONFIG_CPU_IDLE) += cpuidle.o diff --git a/arch/arm/common/cpuidle.c b/arch/arm/common/cpuidle.c new file mode 100644 index 0000000..e9a46a3 --- /dev/null +++ b/arch/arm/common/cpuidle.c @@ -0,0 +1,132 @@ +/* + * Copyright 2011 Freescale Semiconductor, Inc. + * Copyright 2011 Linaro Ltd. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +/* + * This code performs provides some commonly used cpuidle setup functionality + * used by many ARM SoC platforms. Providing this functionality here + * reduces the duplication of this code for each ARM platform that uses it. + */ + +#include +#include +#include +#include +#include +#include +#include + +static struct cpuidle_device __percpu * arm_cpuidle_devices; + +static int (*mach_cpuidle)(struct cpuidle_device *dev, + struct cpuidle_driver *drv, + int index); + +static int arm_enter_idle(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) +{ + ktime_t time_start, time_end; + + local_irq_disable(); + local_fiq_disable(); + + time_start = ktime_get(); + + index = mach_cpuidle(dev, drv, index); + + time_end = ktime_get(); + + local_fiq_enable(); + local_irq_enable(); + + dev->last_residency = + (int)ktime_to_us(ktime_sub(time_end, time_start)); + + return index; +} + +void arm_cpuidle_devices_uninit(void) +{ + int cpu_id; + struct cpuidle_device *dev; + + for_each_possible_cpu(cpu_id) { + dev = per_cpu_ptr(arm_cpuidle_devices, cpu_id); + cpuidle_unregister_device(dev); + } + + free_percpu(arm_cpuidle_devices); + return; +} + +int __init arm_cpuidle_init(struct cpuidle_driver *drv, + int (*common_enter)(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index), + void *driver_data[]) +{ + struct cpuidle_device *dev; + int i, cpu_id; + + if (drv == NULL) { + pr_err("%s: cpuidle_driver pointer NULL\n", __func__); + return -EINVAL; + } + + if (drv->state_count > CPUIDLE_STATE_MAX) + pr_err("%s: state count exceeds maximum\n", __func__); + + mach_cpuidle = common_enter; + + /* if state enter function not specified, use common_enter function */ + for (i = 0; i < drv->state_count; i++) { + if (drv->states[i].enter == NULL) { + if (mach_cpuidle == NULL) { + pr_err("%s: 'enter' function pointer NULL\n", + __func__); + return -EINVAL; + } else + drv->states[i].enter = arm_enter_idle; + } + } + + if (cpuidle_register_driver(drv)) { + pr_err("%s: Failed to register cpuidle driver\n", __func__); + return -ENODEV; + } + + arm_cpuidle_devices = alloc_percpu(struct cpuidle_device); + if (arm_cpuidle_devices == NULL) { + cpuidle_unregister_driver(drv); + return -ENOMEM; + } + + /* initialize state data for each cpuidle_device */ + for_each_possible_cpu(cpu_id) { + + dev = per_cpu_ptr(arm_cpuidle_devices, cpu_id); + dev->cpu = cpu_id; + dev->state_count = drv->state_count; + + if (driver_data) + for (i = 0; i < dev->state_count; i++) { + dev->states_usage[i].driver_data = + driver_data[i]; + } + + if (cpuidle_register_device(dev)) { + pr_err("%s: Failed to register cpu %u\n", + __func__, cpu_id); + return -ENODEV; + } + } + + return 0; +} diff --git a/arch/arm/include/asm/cpuidle.h b/arch/arm/include/asm/cpuidle.h new file mode 100644 index 0000000..86faa74 --- /dev/null +++ b/arch/arm/include/asm/cpuidle.h @@ -0,0 +1,25 @@ +/* + * Copyright 2011 Freescale Semiconductor, Inc. + * Copyright 2011 Linaro Ltd. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#ifndef __ARCH_ARM_ASM_CPUIDLE_H__ +#define __ARCH_ARM_ASM_CPUIDLE_H__ + +#include + +extern int arm_cpuidle_init(struct cpuidle_driver *drv, + int (*common_enter)(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index), + void *driver_data[]); + +extern void arm_cpuidle_devices_uninit(void); + +#endif /* __ARCH_ARM_ASM_CPUIDLE_H__ */