[PATCH] ARM: Samsung: Basic CPUIDLE Support

Amit Daniel Kachhap amit.kachhap at linaro.org
Thu Mar 10 05:11:25 UTC 2011


This patch supports cpuidle framework for samsung S5PV310. Currently,
Only one idle state is possible to use, but more idle states can
be added followed by this patch.

Signed-off-by: Jaecheol Lee <jc.lee at samsung.com>
Signed-off-by: Amit Daniel Kachhap <amit.kachhap at linaro.org>
---
Rebasing the patch for linaro 2.6.38 kernel. This patch adds basic cpuidle 
infrastructure and fixes the launchpad bug(bug id: 723543). This patch is 
under review in samsung mailing list. 
http://www.spinics.net/lists/linux-samsung-soc/msg04268.html

 arch/arm/mach-s5pv310/Makefile  |    1 +
 arch/arm/mach-s5pv310/cpuidle.c |   87 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 88 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-s5pv310/cpuidle.c

diff --git a/arch/arm/mach-s5pv310/Makefile b/arch/arm/mach-s5pv310/Makefile
index 036fb38..c5db0fa 100644
--- a/arch/arm/mach-s5pv310/Makefile
+++ b/arch/arm/mach-s5pv310/Makefile
@@ -15,6 +15,7 @@ obj-				:=
 obj-$(CONFIG_CPU_S5PV310)	+= cpu.o init.o clock.o irq-combiner.o
 obj-$(CONFIG_CPU_S5PV310)	+= setup-i2c0.o time.o gpiolib.o irq-eint.o dma.o
 obj-$(CONFIG_CPU_FREQ)		+= cpufreq.o
+obj-$(CONFIG_CPU_IDLE)		+= cpuidle.o
 
 obj-$(CONFIG_SMP)		+= platsmp.o headsmp.o
 obj-$(CONFIG_LOCAL_TIMERS)	+= localtimer.o
diff --git a/arch/arm/mach-s5pv310/cpuidle.c b/arch/arm/mach-s5pv310/cpuidle.c
new file mode 100644
index 0000000..f35b537
--- /dev/null
+++ b/arch/arm/mach-s5pv310/cpuidle.c
@@ -0,0 +1,87 @@
+/* linux/arch/arm/mach-s5pv310/cpuidle.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/cpuidle.h>
+#include <linux/io.h>
+
+#include <asm/proc-fns.h>
+
+static int s5pv310_enter_idle(struct cpuidle_device *dev,
+			      struct cpuidle_state *state);
+
+static struct cpuidle_state s5pv310_cpuidle_set[] = {
+	[0] = {
+		.enter			= s5pv310_enter_idle,
+		.exit_latency		= 1,
+		.target_residency	= 100000,
+		.flags			= CPUIDLE_FLAG_TIME_VALID,
+		.name			= "IDLE",
+		.desc			= "ARM clock gating(WFI)",
+	},
+};
+
+static DEFINE_PER_CPU(struct cpuidle_device, s5pv310_cpuidle_device);
+
+static struct cpuidle_driver s5pv310_idle_driver = {
+	.name		= "s5pv310_idle",
+	.owner		= THIS_MODULE,
+};
+
+static int s5pv310_enter_idle(struct cpuidle_device *dev,
+			      struct cpuidle_state *state)
+{
+	struct timeval before, after;
+	int idle_time;
+
+	local_irq_disable();
+	do_gettimeofday(&before);
+
+	cpu_do_idle();
+
+	do_gettimeofday(&after);
+	local_irq_enable();
+	idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
+		    (after.tv_usec - before.tv_usec);
+
+	return idle_time;
+}
+
+static int __init s5pv310_init_cpuidle(void)
+{
+	int i, max_cpuidle_state, cpu_id;
+	struct cpuidle_device *device;
+
+	cpuidle_register_driver(&s5pv310_idle_driver);
+
+	for_each_cpu(cpu_id, cpu_online_mask) {
+		device = &per_cpu(s5pv310_cpuidle_device, cpu_id);
+		device->cpu = cpu_id;
+
+		device->state_count = (sizeof(s5pv310_cpuidle_set) /
+					       sizeof(struct cpuidle_state));
+
+		max_cpuidle_state = device->state_count;
+
+		for (i = 0; i < max_cpuidle_state; i++) {
+			memcpy(&device->states[i], &s5pv310_cpuidle_set[i],
+					sizeof(struct cpuidle_state));
+		}
+
+		if (cpuidle_register_device(device)) {
+			printk(KERN_ERR "CPUidle register device failed\n,");
+			return -EIO;
+		}
+	}
+	return 0;
+}
+
+device_initcall(s5pv310_init_cpuidle);
-- 
1.7.1




More information about the linaro-dev mailing list