aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-imx
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-04-27 19:54:49 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-04-27 19:54:49 -0400
commite4f5a3adc454745fea35f1c312e14cbeba6e0ea4 (patch)
tree7dae08f7d3466fcf158808784ec3b706e6cafec6 /arch/arm/mach-imx
parentae6208301e1e37a203fab817b59279a0f5d774c6 (diff)
parenta8e39c35b5d09598e129aa9b5e6f35aa3a1915d9 (diff)
Merge branch 'pm-cpuidle'
* pm-cpuidle: (51 commits) cpuidle: add maintainer entry ARM: s3c64xx: cpuidle: use init/exit common routine SH: cpuidle: use init/exit common routine cpuidle: fix comment format ARM: imx: cpuidle: use init/exit common routine ARM: davinci: cpuidle: use init/exit common routine ARM: kirkwood: cpuidle: use init/exit common routine ARM: calxeda: cpuidle: use init/exit common routine ARM: tegra: cpuidle: use init/exit common routine for tegra3 ARM: tegra: cpuidle: use init/exit common routine for tegra2 ARM: OMAP4: cpuidle: use init/exit common routine ARM: shmobile: cpuidle: use init/exit common routine ARM: tegra: cpuidle: use init/exit common routine ARM: OMAP3: cpuidle: use init/exit common routine ARM: at91: cpuidle: use init/exit common routine ARM: ux500: cpuidle: use init/exit common routine cpuidle: make a single register function for all ARM: ux500: cpuidle: replace for_each_online_cpu by for_each_possible_cpu cpuidle: remove en_core_tk_irqen flag ARM: OMAP3: remove cpuidle_wrap_enter ...
Diffstat (limited to 'arch/arm/mach-imx')
-rw-r--r--arch/arm/mach-imx/Makefile2
-rw-r--r--arch/arm/mach-imx/cpuidle-imx5.c37
-rw-r--r--arch/arm/mach-imx/cpuidle-imx6q.c26
-rw-r--r--arch/arm/mach-imx/cpuidle.c80
-rw-r--r--arch/arm/mach-imx/cpuidle.h10
-rw-r--r--arch/arm/mach-imx/pm-imx5.c30
6 files changed, 46 insertions, 139 deletions
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index c4ce0906d76a..cb70961b6239 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -30,7 +30,7 @@ obj-$(CONFIG_MXC_DEBUG_BOARD) += 3ds_debugboard.o
30obj-$(CONFIG_CPU_FREQ_IMX) += cpufreq.o 30obj-$(CONFIG_CPU_FREQ_IMX) += cpufreq.o
31 31
32ifeq ($(CONFIG_CPU_IDLE),y) 32ifeq ($(CONFIG_CPU_IDLE),y)
33obj-y += cpuidle.o 33obj-$(CONFIG_SOC_IMX5) += cpuidle-imx5.o
34obj-$(CONFIG_SOC_IMX6Q) += cpuidle-imx6q.o 34obj-$(CONFIG_SOC_IMX6Q) += cpuidle-imx6q.o
35endif 35endif
36 36
diff --git a/arch/arm/mach-imx/cpuidle-imx5.c b/arch/arm/mach-imx/cpuidle-imx5.c
new file mode 100644
index 000000000000..5a47e3c6172f
--- /dev/null
+++ b/arch/arm/mach-imx/cpuidle-imx5.c
@@ -0,0 +1,37 @@
1/*
2 * Copyright (C) 2012 Freescale Semiconductor, Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/cpuidle.h>
10#include <linux/module.h>
11#include <asm/system_misc.h>
12
13static int imx5_cpuidle_enter(struct cpuidle_device *dev,
14 struct cpuidle_driver *drv, int index)
15{
16 arm_pm_idle();
17 return index;
18}
19
20static struct cpuidle_driver imx5_cpuidle_driver = {
21 .name = "imx5_cpuidle",
22 .owner = THIS_MODULE,
23 .states[0] = {
24 .enter = imx5_cpuidle_enter,
25 .exit_latency = 2,
26 .target_residency = 1,
27 .flags = CPUIDLE_FLAG_TIME_VALID,
28 .name = "IMX5 SRPG",
29 .desc = "CPU state retained,powered off",
30 },
31 .state_count = 1,
32};
33
34int __init imx5_cpuidle_init(void)
35{
36 return cpuidle_register(&imx5_cpuidle_driver, NULL);
37}
diff --git a/arch/arm/mach-imx/cpuidle-imx6q.c b/arch/arm/mach-imx/cpuidle-imx6q.c
index d533e2695f0e..23ddfb693b2d 100644
--- a/arch/arm/mach-imx/cpuidle-imx6q.c
+++ b/arch/arm/mach-imx/cpuidle-imx6q.c
@@ -6,7 +6,6 @@
6 * published by the Free Software Foundation. 6 * published by the Free Software Foundation.
7 */ 7 */
8 8
9#include <linux/clockchips.h>
10#include <linux/cpuidle.h> 9#include <linux/cpuidle.h>
11#include <linux/module.h> 10#include <linux/module.h>
12#include <asm/cpuidle.h> 11#include <asm/cpuidle.h>
@@ -21,10 +20,6 @@ static DEFINE_SPINLOCK(master_lock);
21static int imx6q_enter_wait(struct cpuidle_device *dev, 20static int imx6q_enter_wait(struct cpuidle_device *dev,
22 struct cpuidle_driver *drv, int index) 21 struct cpuidle_driver *drv, int index)
23{ 22{
24 int cpu = dev->cpu;
25
26 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
27
28 if (atomic_inc_return(&master) == num_online_cpus()) { 23 if (atomic_inc_return(&master) == num_online_cpus()) {
29 /* 24 /*
30 * With this lock, we prevent other cpu to exit and enter 25 * With this lock, we prevent other cpu to exit and enter
@@ -43,26 +38,13 @@ idle:
43 cpu_do_idle(); 38 cpu_do_idle();
44done: 39done:
45 atomic_dec(&master); 40 atomic_dec(&master);
46 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
47 41
48 return index; 42 return index;
49} 43}
50 44
51/*
52 * For each cpu, setup the broadcast timer because local timer
53 * stops for the states other than WFI.
54 */
55static void imx6q_setup_broadcast_timer(void *arg)
56{
57 int cpu = smp_processor_id();
58
59 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &cpu);
60}
61
62static struct cpuidle_driver imx6q_cpuidle_driver = { 45static struct cpuidle_driver imx6q_cpuidle_driver = {
63 .name = "imx6q_cpuidle", 46 .name = "imx6q_cpuidle",
64 .owner = THIS_MODULE, 47 .owner = THIS_MODULE,
65 .en_core_tk_irqen = 1,
66 .states = { 48 .states = {
67 /* WFI */ 49 /* WFI */
68 ARM_CPUIDLE_WFI_STATE, 50 ARM_CPUIDLE_WFI_STATE,
@@ -70,7 +52,8 @@ static struct cpuidle_driver imx6q_cpuidle_driver = {
70 { 52 {
71 .exit_latency = 50, 53 .exit_latency = 50,
72 .target_residency = 75, 54 .target_residency = 75,
73 .flags = CPUIDLE_FLAG_TIME_VALID, 55 .flags = CPUIDLE_FLAG_TIME_VALID |
56 CPUIDLE_FLAG_TIMER_STOP,
74 .enter = imx6q_enter_wait, 57 .enter = imx6q_enter_wait,
75 .name = "WAIT", 58 .name = "WAIT",
76 .desc = "Clock off", 59 .desc = "Clock off",
@@ -88,8 +71,5 @@ int __init imx6q_cpuidle_init(void)
88 /* Set chicken bit to get a reliable WAIT mode support */ 71 /* Set chicken bit to get a reliable WAIT mode support */
89 imx6q_set_chicken_bit(); 72 imx6q_set_chicken_bit();
90 73
91 /* Configure the broadcast timer on each cpu */ 74 return cpuidle_register(&imx6q_cpuidle_driver, NULL);
92 on_each_cpu(imx6q_setup_broadcast_timer, NULL, 1);
93
94 return imx_cpuidle_init(&imx6q_cpuidle_driver);
95} 75}
diff --git a/arch/arm/mach-imx/cpuidle.c b/arch/arm/mach-imx/cpuidle.c
deleted file mode 100644
index d4cb511a44a8..000000000000
--- a/arch/arm/mach-imx/cpuidle.c
+++ /dev/null
@@ -1,80 +0,0 @@
1/*
2 * Copyright 2012 Freescale Semiconductor, Inc.
3 * Copyright 2012 Linaro Ltd.
4 *
5 * The code contained herein is licensed under the GNU General Public
6 * License. You may obtain a copy of the GNU General Public License
7 * Version 2 or later at the following locations:
8 *
9 * http://www.opensource.org/licenses/gpl-license.html
10 * http://www.gnu.org/copyleft/gpl.html
11 */
12
13#include <linux/cpuidle.h>
14#include <linux/err.h>
15#include <linux/hrtimer.h>
16#include <linux/io.h>
17#include <linux/kernel.h>
18#include <linux/slab.h>
19
20static struct cpuidle_device __percpu * imx_cpuidle_devices;
21
22static void __init imx_cpuidle_devices_uninit(void)
23{
24 int cpu_id;
25 struct cpuidle_device *dev;
26
27 for_each_possible_cpu(cpu_id) {
28 dev = per_cpu_ptr(imx_cpuidle_devices, cpu_id);
29 cpuidle_unregister_device(dev);
30 }
31
32 free_percpu(imx_cpuidle_devices);
33}
34
35int __init imx_cpuidle_init(struct cpuidle_driver *drv)
36{
37 struct cpuidle_device *dev;
38 int cpu_id, ret;
39
40 if (drv->state_count > CPUIDLE_STATE_MAX) {
41 pr_err("%s: state_count exceeds maximum\n", __func__);
42 return -EINVAL;
43 }
44
45 ret = cpuidle_register_driver(drv);
46 if (ret) {
47 pr_err("%s: Failed to register cpuidle driver with error: %d\n",
48 __func__, ret);
49 return ret;
50 }
51
52 imx_cpuidle_devices = alloc_percpu(struct cpuidle_device);
53 if (imx_cpuidle_devices == NULL) {
54 ret = -ENOMEM;
55 goto unregister_drv;
56 }
57
58 /* initialize state data for each cpuidle_device */
59 for_each_possible_cpu(cpu_id) {
60 dev = per_cpu_ptr(imx_cpuidle_devices, cpu_id);
61 dev->cpu = cpu_id;
62 dev->state_count = drv->state_count;
63
64 ret = cpuidle_register_device(dev);
65 if (ret) {
66 pr_err("%s: Failed to register cpu %u, error: %d\n",
67 __func__, cpu_id, ret);
68 goto uninit;
69 }
70 }
71
72 return 0;
73
74uninit:
75 imx_cpuidle_devices_uninit();
76
77unregister_drv:
78 cpuidle_unregister_driver(drv);
79 return ret;
80}
diff --git a/arch/arm/mach-imx/cpuidle.h b/arch/arm/mach-imx/cpuidle.h
index e092d1359d94..786f98ecc145 100644
--- a/arch/arm/mach-imx/cpuidle.h
+++ b/arch/arm/mach-imx/cpuidle.h
@@ -10,18 +10,16 @@
10 * http://www.gnu.org/copyleft/gpl.html 10 * http://www.gnu.org/copyleft/gpl.html
11 */ 11 */
12 12
13#include <linux/cpuidle.h>
14
15#ifdef CONFIG_CPU_IDLE 13#ifdef CONFIG_CPU_IDLE
16extern int imx_cpuidle_init(struct cpuidle_driver *drv); 14extern int imx5_cpuidle_init(void);
17extern int imx6q_cpuidle_init(void); 15extern int imx6q_cpuidle_init(void);
18#else 16#else
19static inline int imx_cpuidle_init(struct cpuidle_driver *drv) 17static inline int imx5_cpuidle_init(void)
20{ 18{
21 return -ENODEV; 19 return 0;
22} 20}
23static inline int imx6q_cpuidle_init(void) 21static inline int imx6q_cpuidle_init(void)
24{ 22{
25 return -ENODEV; 23 return 0;
26} 24}
27#endif 25#endif
diff --git a/arch/arm/mach-imx/pm-imx5.c b/arch/arm/mach-imx/pm-imx5.c
index f67fd7ee8127..82e79c658eb2 100644
--- a/arch/arm/mach-imx/pm-imx5.c
+++ b/arch/arm/mach-imx/pm-imx5.c
@@ -149,33 +149,6 @@ static void imx5_pm_idle(void)
149 imx5_cpu_do_idle(); 149 imx5_cpu_do_idle();
150} 150}
151 151
152static int imx5_cpuidle_enter(struct cpuidle_device *dev,
153 struct cpuidle_driver *drv, int idx)
154{
155 int ret;
156
157 ret = imx5_cpu_do_idle();
158 if (ret < 0)
159 return ret;
160
161 return idx;
162}
163
164static struct cpuidle_driver imx5_cpuidle_driver = {
165 .name = "imx5_cpuidle",
166 .owner = THIS_MODULE,
167 .en_core_tk_irqen = 1,
168 .states[0] = {
169 .enter = imx5_cpuidle_enter,
170 .exit_latency = 2,
171 .target_residency = 1,
172 .flags = CPUIDLE_FLAG_TIME_VALID,
173 .name = "IMX5 SRPG",
174 .desc = "CPU state retained,powered off",
175 },
176 .state_count = 1,
177};
178
179static int __init imx5_pm_common_init(void) 152static int __init imx5_pm_common_init(void)
180{ 153{
181 int ret; 154 int ret;
@@ -193,8 +166,7 @@ static int __init imx5_pm_common_init(void)
193 /* Set the registers to the default cpu idle state. */ 166 /* Set the registers to the default cpu idle state. */
194 mx5_cpu_lp_set(IMX5_DEFAULT_CPU_IDLE_STATE); 167 mx5_cpu_lp_set(IMX5_DEFAULT_CPU_IDLE_STATE);
195 168
196 imx_cpuidle_init(&imx5_cpuidle_driver); 169 return imx5_cpuidle_init();
197 return 0;
198} 170}
199 171
200void __init imx51_pm_init(void) 172void __init imx51_pm_init(void)