aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorDeepthi Dharwar <deepthi@linux.vnet.ibm.com>2011-10-28 06:50:42 -0400
committerLen Brown <len.brown@intel.com>2011-11-06 21:13:58 -0500
commit46bcfad7a819bd17ac4e831b04405152d59784ab (patch)
tree20041e788154d103edff2699f88d4a30320e3ee2 /arch/arm
parent4202735e8ab6ecfb0381631a0d0b58fefe0bd4e2 (diff)
cpuidle: Single/Global registration of idle states
This patch makes the cpuidle_states structure global (single copy) instead of per-cpu. The statistics needed on per-cpu basis by the governor are kept per-cpu. This simplifies the cpuidle subsystem as state registration is done by single cpu only. Having single copy of cpuidle_states saves memory. Rare case of asymmetric C-states can be handled within the cpuidle driver and architectures such as POWER do not have asymmetric C-states. Having single/global registration of all the idle states, dynamic C-state transitions on x86 are handled by the boot cpu. Here, the boot cpu would disable all the devices, re-populate the states and later enable all the devices, irrespective of the cpu that would receive the notification first. Reference: https://lkml.org/lkml/2011/4/25/83 Signed-off-by: Deepthi Dharwar <deepthi@linux.vnet.ibm.com> Signed-off-by: Trinabh Gupta <g.trinabh@gmail.com> Tested-by: Jean Pihet <j-pihet@ti.com> Reviewed-by: Kevin Hilman <khilman@ti.com> Acked-by: Arjan van de Ven <arjan@linux.intel.com> Acked-by: Kevin Hilman <khilman@ti.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/mach-at91/cpuidle.c31
-rw-r--r--arch/arm/mach-davinci/cpuidle.c39
-rw-r--r--arch/arm/mach-exynos4/cpuidle.c23
-rw-r--r--arch/arm/mach-kirkwood/cpuidle.c30
-rw-r--r--arch/arm/mach-omap2/cpuidle34xx.c73
5 files changed, 116 insertions, 80 deletions
diff --git a/arch/arm/mach-at91/cpuidle.c b/arch/arm/mach-at91/cpuidle.c
index 4696a0d61e2e..93178f67420e 100644
--- a/arch/arm/mach-at91/cpuidle.c
+++ b/arch/arm/mach-at91/cpuidle.c
@@ -33,6 +33,7 @@ static struct cpuidle_driver at91_idle_driver = {
33 33
34/* Actual code that puts the SoC in different idle states */ 34/* Actual code that puts the SoC in different idle states */
35static int at91_enter_idle(struct cpuidle_device *dev, 35static int at91_enter_idle(struct cpuidle_device *dev,
36 struct cpuidle_driver *drv,
36 int index) 37 int index)
37{ 38{
38 struct timeval before, after; 39 struct timeval before, after;
@@ -64,27 +65,29 @@ static int at91_enter_idle(struct cpuidle_device *dev,
64static int at91_init_cpuidle(void) 65static int at91_init_cpuidle(void)
65{ 66{
66 struct cpuidle_device *device; 67 struct cpuidle_device *device;
67 68 struct cpuidle_driver *driver = &at91_idle_driver;
68 cpuidle_register_driver(&at91_idle_driver);
69 69
70 device = &per_cpu(at91_cpuidle_device, smp_processor_id()); 70 device = &per_cpu(at91_cpuidle_device, smp_processor_id());
71 device->state_count = AT91_MAX_STATES; 71 device->state_count = AT91_MAX_STATES;
72 driver->state_count = AT91_MAX_STATES;
72 73
73 /* Wait for interrupt state */ 74 /* Wait for interrupt state */
74 device->states[0].enter = at91_enter_idle; 75 driver->states[0].enter = at91_enter_idle;
75 device->states[0].exit_latency = 1; 76 driver->states[0].exit_latency = 1;
76 device->states[0].target_residency = 10000; 77 driver->states[0].target_residency = 10000;
77 device->states[0].flags = CPUIDLE_FLAG_TIME_VALID; 78 driver->states[0].flags = CPUIDLE_FLAG_TIME_VALID;
78 strcpy(device->states[0].name, "WFI"); 79 strcpy(driver->states[0].name, "WFI");
79 strcpy(device->states[0].desc, "Wait for interrupt"); 80 strcpy(driver->states[0].desc, "Wait for interrupt");
80 81
81 /* Wait for interrupt and RAM self refresh state */ 82 /* Wait for interrupt and RAM self refresh state */
82 device->states[1].enter = at91_enter_idle; 83 driver->states[1].enter = at91_enter_idle;
83 device->states[1].exit_latency = 10; 84 driver->states[1].exit_latency = 10;
84 device->states[1].target_residency = 10000; 85 driver->states[1].target_residency = 10000;
85 device->states[1].flags = CPUIDLE_FLAG_TIME_VALID; 86 driver->states[1].flags = CPUIDLE_FLAG_TIME_VALID;
86 strcpy(device->states[1].name, "RAM_SR"); 87 strcpy(driver->states[1].name, "RAM_SR");
87 strcpy(device->states[1].desc, "WFI and RAM Self Refresh"); 88 strcpy(driver->states[1].desc, "WFI and RAM Self Refresh");
89
90 cpuidle_register_driver(&at91_idle_driver);
88 91
89 if (cpuidle_register_device(device)) { 92 if (cpuidle_register_device(device)) {
90 printk(KERN_ERR "at91_init_cpuidle: Failed registering\n"); 93 printk(KERN_ERR "at91_init_cpuidle: Failed registering\n");
diff --git a/arch/arm/mach-davinci/cpuidle.c b/arch/arm/mach-davinci/cpuidle.c
index f2d2f34603d9..dbeeccd00173 100644
--- a/arch/arm/mach-davinci/cpuidle.c
+++ b/arch/arm/mach-davinci/cpuidle.c
@@ -78,6 +78,7 @@ static struct davinci_ops davinci_states[DAVINCI_CPUIDLE_MAX_STATES] = {
78 78
79/* Actual code that puts the SoC in different idle states */ 79/* Actual code that puts the SoC in different idle states */
80static int davinci_enter_idle(struct cpuidle_device *dev, 80static int davinci_enter_idle(struct cpuidle_device *dev,
81 struct cpuidle_driver *drv,
81 int index) 82 int index)
82{ 83{
83 struct cpuidle_state_usage *state_usage = &dev->states_usage[index]; 84 struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
@@ -109,6 +110,7 @@ static int __init davinci_cpuidle_probe(struct platform_device *pdev)
109{ 110{
110 int ret; 111 int ret;
111 struct cpuidle_device *device; 112 struct cpuidle_device *device;
113 struct cpuidle_driver *driver = &davinci_idle_driver;
112 struct davinci_cpuidle_config *pdata = pdev->dev.platform_data; 114 struct davinci_cpuidle_config *pdata = pdev->dev.platform_data;
113 115
114 device = &per_cpu(davinci_cpuidle_device, smp_processor_id()); 116 device = &per_cpu(davinci_cpuidle_device, smp_processor_id());
@@ -120,32 +122,33 @@ static int __init davinci_cpuidle_probe(struct platform_device *pdev)
120 122
121 ddr2_reg_base = pdata->ddr2_ctlr_base; 123 ddr2_reg_base = pdata->ddr2_ctlr_base;
122 124
123 ret = cpuidle_register_driver(&davinci_idle_driver);
124 if (ret) {
125 dev_err(&pdev->dev, "failed to register driver\n");
126 return ret;
127 }
128
129 /* Wait for interrupt state */ 125 /* Wait for interrupt state */
130 device->states[0].enter = davinci_enter_idle; 126 driver->states[0].enter = davinci_enter_idle;
131 device->states[0].exit_latency = 1; 127 driver->states[0].exit_latency = 1;
132 device->states[0].target_residency = 10000; 128 driver->states[0].target_residency = 10000;
133 device->states[0].flags = CPUIDLE_FLAG_TIME_VALID; 129 driver->states[0].flags = CPUIDLE_FLAG_TIME_VALID;
134 strcpy(device->states[0].name, "WFI"); 130 strcpy(driver->states[0].name, "WFI");
135 strcpy(device->states[0].desc, "Wait for interrupt"); 131 strcpy(driver->states[0].desc, "Wait for interrupt");
136 132
137 /* Wait for interrupt and DDR self refresh state */ 133 /* Wait for interrupt and DDR self refresh state */
138 device->states[1].enter = davinci_enter_idle; 134 driver->states[1].enter = davinci_enter_idle;
139 device->states[1].exit_latency = 10; 135 driver->states[1].exit_latency = 10;
140 device->states[1].target_residency = 10000; 136 driver->states[1].target_residency = 10000;
141 device->states[1].flags = CPUIDLE_FLAG_TIME_VALID; 137 driver->states[1].flags = CPUIDLE_FLAG_TIME_VALID;
142 strcpy(device->states[1].name, "DDR SR"); 138 strcpy(driver->states[1].name, "DDR SR");
143 strcpy(device->states[1].desc, "WFI and DDR Self Refresh"); 139 strcpy(driver->states[1].desc, "WFI and DDR Self Refresh");
144 if (pdata->ddr2_pdown) 140 if (pdata->ddr2_pdown)
145 davinci_states[1].flags |= DAVINCI_CPUIDLE_FLAGS_DDR2_PWDN; 141 davinci_states[1].flags |= DAVINCI_CPUIDLE_FLAGS_DDR2_PWDN;
146 cpuidle_set_statedata(&device->states_usage[1], &davinci_states[1]); 142 cpuidle_set_statedata(&device->states_usage[1], &davinci_states[1]);
147 143
148 device->state_count = DAVINCI_CPUIDLE_MAX_STATES; 144 device->state_count = DAVINCI_CPUIDLE_MAX_STATES;
145 driver->state_count = DAVINCI_CPUIDLE_MAX_STATES;
146
147 ret = cpuidle_register_driver(&davinci_idle_driver);
148 if (ret) {
149 dev_err(&pdev->dev, "failed to register driver\n");
150 return ret;
151 }
149 152
150 ret = cpuidle_register_device(device); 153 ret = cpuidle_register_device(device);
151 if (ret) { 154 if (ret) {
diff --git a/arch/arm/mach-exynos4/cpuidle.c b/arch/arm/mach-exynos4/cpuidle.c
index ea026e72b977..35f6502144ae 100644
--- a/arch/arm/mach-exynos4/cpuidle.c
+++ b/arch/arm/mach-exynos4/cpuidle.c
@@ -16,6 +16,7 @@
16#include <asm/proc-fns.h> 16#include <asm/proc-fns.h>
17 17
18static int exynos4_enter_idle(struct cpuidle_device *dev, 18static int exynos4_enter_idle(struct cpuidle_device *dev,
19 struct cpuidle_driver *drv,
19 int index); 20 int index);
20 21
21static struct cpuidle_state exynos4_cpuidle_set[] = { 22static struct cpuidle_state exynos4_cpuidle_set[] = {
@@ -37,6 +38,7 @@ static struct cpuidle_driver exynos4_idle_driver = {
37}; 38};
38 39
39static int exynos4_enter_idle(struct cpuidle_device *dev, 40static int exynos4_enter_idle(struct cpuidle_device *dev,
41 struct cpuidle_driver *drv,
40 int index) 42 int index)
41{ 43{
42 struct timeval before, after; 44 struct timeval before, after;
@@ -60,22 +62,23 @@ static int __init exynos4_init_cpuidle(void)
60{ 62{
61 int i, max_cpuidle_state, cpu_id; 63 int i, max_cpuidle_state, cpu_id;
62 struct cpuidle_device *device; 64 struct cpuidle_device *device;
63 65 struct cpuidle_driver *drv = &exynos4_idle_driver;
66
67 /* Setup cpuidle driver */
68 drv->state_count = (sizeof(exynos4_cpuidle_set) /
69 sizeof(struct cpuidle_state));
70 max_cpuidle_state = drv->state_count;
71 for (i = 0; i < max_cpuidle_state; i++) {
72 memcpy(&drv->states[i], &exynos4_cpuidle_set[i],
73 sizeof(struct cpuidle_state));
74 }
64 cpuidle_register_driver(&exynos4_idle_driver); 75 cpuidle_register_driver(&exynos4_idle_driver);
65 76
66 for_each_cpu(cpu_id, cpu_online_mask) { 77 for_each_cpu(cpu_id, cpu_online_mask) {
67 device = &per_cpu(exynos4_cpuidle_device, cpu_id); 78 device = &per_cpu(exynos4_cpuidle_device, cpu_id);
68 device->cpu = cpu_id; 79 device->cpu = cpu_id;
69 80
70 device->state_count = (sizeof(exynos4_cpuidle_set) / 81 device->state_count = drv->state_count;
71 sizeof(struct cpuidle_state));
72
73 max_cpuidle_state = device->state_count;
74
75 for (i = 0; i < max_cpuidle_state; i++) {
76 memcpy(&device->states[i], &exynos4_cpuidle_set[i],
77 sizeof(struct cpuidle_state));
78 }
79 82
80 if (cpuidle_register_device(device)) { 83 if (cpuidle_register_device(device)) {
81 printk(KERN_ERR "CPUidle register device failed\n,"); 84 printk(KERN_ERR "CPUidle register device failed\n,");
diff --git a/arch/arm/mach-kirkwood/cpuidle.c b/arch/arm/mach-kirkwood/cpuidle.c
index 358dd80b3a07..ffd690dc3d33 100644
--- a/arch/arm/mach-kirkwood/cpuidle.c
+++ b/arch/arm/mach-kirkwood/cpuidle.c
@@ -32,6 +32,7 @@ static DEFINE_PER_CPU(struct cpuidle_device, kirkwood_cpuidle_device);
32 32
33/* Actual code that puts the SoC in different idle states */ 33/* Actual code that puts the SoC in different idle states */
34static int kirkwood_enter_idle(struct cpuidle_device *dev, 34static int kirkwood_enter_idle(struct cpuidle_device *dev,
35 struct cpuidle_driver *drv,
35 int index) 36 int index)
36{ 37{
37 struct timeval before, after; 38 struct timeval before, after;
@@ -68,28 +69,29 @@ static int kirkwood_enter_idle(struct cpuidle_device *dev,
68static int kirkwood_init_cpuidle(void) 69static int kirkwood_init_cpuidle(void)
69{ 70{
70 struct cpuidle_device *device; 71 struct cpuidle_device *device;
71 72 struct cpuidle_driver *driver = &kirkwood_idle_driver;
72 cpuidle_register_driver(&kirkwood_idle_driver);
73 73
74 device = &per_cpu(kirkwood_cpuidle_device, smp_processor_id()); 74 device = &per_cpu(kirkwood_cpuidle_device, smp_processor_id());
75 device->state_count = KIRKWOOD_MAX_STATES; 75 device->state_count = KIRKWOOD_MAX_STATES;
76 driver->state_count = KIRKWOOD_MAX_STATES;
76 77
77 /* Wait for interrupt state */ 78 /* Wait for interrupt state */
78 device->states[0].enter = kirkwood_enter_idle; 79 driver->states[0].enter = kirkwood_enter_idle;
79 device->states[0].exit_latency = 1; 80 driver->states[0].exit_latency = 1;
80 device->states[0].target_residency = 10000; 81 driver->states[0].target_residency = 10000;
81 device->states[0].flags = CPUIDLE_FLAG_TIME_VALID; 82 driver->states[0].flags = CPUIDLE_FLAG_TIME_VALID;
82 strcpy(device->states[0].name, "WFI"); 83 strcpy(driver->states[0].name, "WFI");
83 strcpy(device->states[0].desc, "Wait for interrupt"); 84 strcpy(driver->states[0].desc, "Wait for interrupt");
84 85
85 /* Wait for interrupt and DDR self refresh state */ 86 /* Wait for interrupt and DDR self refresh state */
86 device->states[1].enter = kirkwood_enter_idle; 87 driver->states[1].enter = kirkwood_enter_idle;
87 device->states[1].exit_latency = 10; 88 driver->states[1].exit_latency = 10;
88 device->states[1].target_residency = 10000; 89 driver->states[1].target_residency = 10000;
89 device->states[1].flags = CPUIDLE_FLAG_TIME_VALID; 90 driver->states[1].flags = CPUIDLE_FLAG_TIME_VALID;
90 strcpy(device->states[1].name, "DDR SR"); 91 strcpy(driver->states[1].name, "DDR SR");
91 strcpy(device->states[1].desc, "WFI and DDR Self Refresh"); 92 strcpy(driver->states[1].desc, "WFI and DDR Self Refresh");
92 93
94 cpuidle_register_driver(&kirkwood_idle_driver);
93 if (cpuidle_register_device(device)) { 95 if (cpuidle_register_device(device)) {
94 printk(KERN_ERR "kirkwood_init_cpuidle: Failed registering\n"); 96 printk(KERN_ERR "kirkwood_init_cpuidle: Failed registering\n");
95 return -EIO; 97 return -EIO;
diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
index d3fce7b97fcf..1fe35c24fba2 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -88,12 +88,14 @@ static int _cpuidle_deny_idle(struct powerdomain *pwrdm,
88/** 88/**
89 * omap3_enter_idle - Programs OMAP3 to enter the specified state 89 * omap3_enter_idle - Programs OMAP3 to enter the specified state
90 * @dev: cpuidle device 90 * @dev: cpuidle device
91 * @drv: cpuidle driver
91 * @index: the index of state to be entered 92 * @index: the index of state to be entered
92 * 93 *
93 * Called from the CPUidle framework to program the device to the 94 * Called from the CPUidle framework to program the device to the
94 * specified target state selected by the governor. 95 * specified target state selected by the governor.
95 */ 96 */
96static int omap3_enter_idle(struct cpuidle_device *dev, 97static int omap3_enter_idle(struct cpuidle_device *dev,
98 struct cpuidle_driver *drv,
97 int index) 99 int index)
98{ 100{
99 struct omap3_idle_statedata *cx = 101 struct omap3_idle_statedata *cx =
@@ -148,6 +150,7 @@ return_sleep_time:
148/** 150/**
149 * next_valid_state - Find next valid C-state 151 * next_valid_state - Find next valid C-state
150 * @dev: cpuidle device 152 * @dev: cpuidle device
153 * @drv: cpuidle driver
151 * @index: Index of currently selected c-state 154 * @index: Index of currently selected c-state
152 * 155 *
153 * If the state corresponding to index is valid, index is returned back 156 * If the state corresponding to index is valid, index is returned back
@@ -158,10 +161,11 @@ return_sleep_time:
158 * if it satisfies the enable_off_mode condition. 161 * if it satisfies the enable_off_mode condition.
159 */ 162 */
160static int next_valid_state(struct cpuidle_device *dev, 163static int next_valid_state(struct cpuidle_device *dev,
164 struct cpuidle_driver *drv,
161 int index) 165 int index)
162{ 166{
163 struct cpuidle_state_usage *curr_usage = &dev->states_usage[index]; 167 struct cpuidle_state_usage *curr_usage = &dev->states_usage[index];
164 struct cpuidle_state *curr = &dev->states[index]; 168 struct cpuidle_state *curr = &drv->states[index];
165 struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr_usage); 169 struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr_usage);
166 u32 mpu_deepest_state = PWRDM_POWER_RET; 170 u32 mpu_deepest_state = PWRDM_POWER_RET;
167 u32 core_deepest_state = PWRDM_POWER_RET; 171 u32 core_deepest_state = PWRDM_POWER_RET;
@@ -188,7 +192,7 @@ static int next_valid_state(struct cpuidle_device *dev,
188 192
189 /* Reach the current state starting at highest C-state */ 193 /* Reach the current state starting at highest C-state */
190 for (; idx >= 0; idx--) { 194 for (; idx >= 0; idx--) {
191 if (&dev->states[idx] == curr) { 195 if (&drv->states[idx] == curr) {
192 next_index = idx; 196 next_index = idx;
193 break; 197 break;
194 } 198 }
@@ -224,12 +228,14 @@ static int next_valid_state(struct cpuidle_device *dev,
224/** 228/**
225 * omap3_enter_idle_bm - Checks for any bus activity 229 * omap3_enter_idle_bm - Checks for any bus activity
226 * @dev: cpuidle device 230 * @dev: cpuidle device
231 * @drv: cpuidle driver
227 * @index: array index of target state to be programmed 232 * @index: array index of target state to be programmed
228 * 233 *
229 * This function checks for any pending activity and then programs 234 * This function checks for any pending activity and then programs
230 * the device to the specified or a safer state. 235 * the device to the specified or a safer state.
231 */ 236 */
232static int omap3_enter_idle_bm(struct cpuidle_device *dev, 237static int omap3_enter_idle_bm(struct cpuidle_device *dev,
238 struct cpuidle_driver *drv,
233 int index) 239 int index)
234{ 240{
235 int new_state_idx; 241 int new_state_idx;
@@ -238,7 +244,7 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
238 int ret; 244 int ret;
239 245
240 if (!omap3_can_sleep()) { 246 if (!omap3_can_sleep()) {
241 new_state_idx = dev->safe_state_index; 247 new_state_idx = drv->safe_state_index;
242 goto select_state; 248 goto select_state;
243 } 249 }
244 250
@@ -248,7 +254,7 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
248 */ 254 */
249 cam_state = pwrdm_read_pwrst(cam_pd); 255 cam_state = pwrdm_read_pwrst(cam_pd);
250 if (cam_state == PWRDM_POWER_ON) { 256 if (cam_state == PWRDM_POWER_ON) {
251 new_state_idx = dev->safe_state_index; 257 new_state_idx = drv->safe_state_index;
252 goto select_state; 258 goto select_state;
253 } 259 }
254 260
@@ -275,10 +281,10 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
275 if (per_next_state != per_saved_state) 281 if (per_next_state != per_saved_state)
276 pwrdm_set_next_pwrst(per_pd, per_next_state); 282 pwrdm_set_next_pwrst(per_pd, per_next_state);
277 283
278 new_state_idx = next_valid_state(dev, index); 284 new_state_idx = next_valid_state(dev, drv, index);
279 285
280select_state: 286select_state:
281 ret = omap3_enter_idle(dev, new_state_idx); 287 ret = omap3_enter_idle(dev, drv, new_state_idx);
282 288
283 /* Restore original PER state if it was modified */ 289 /* Restore original PER state if it was modified */
284 if (per_next_state != per_saved_state) 290 if (per_next_state != per_saved_state)
@@ -311,22 +317,30 @@ struct cpuidle_driver omap3_idle_driver = {
311 .owner = THIS_MODULE, 317 .owner = THIS_MODULE,
312}; 318};
313 319
314/* Helper to fill the C-state common data and register the driver_data */ 320/* Helper to fill the C-state common data*/
315static inline struct omap3_idle_statedata *_fill_cstate( 321static inline void _fill_cstate(struct cpuidle_driver *drv,
316 struct cpuidle_device *dev,
317 int idx, const char *descr) 322 int idx, const char *descr)
318{ 323{
319 struct omap3_idle_statedata *cx = &omap3_idle_data[idx]; 324 struct cpuidle_state *state = &drv->states[idx];
320 struct cpuidle_state *state = &dev->states[idx];
321 struct cpuidle_state_usage *state_usage = &dev->states_usage[idx];
322 325
323 state->exit_latency = cpuidle_params_table[idx].exit_latency; 326 state->exit_latency = cpuidle_params_table[idx].exit_latency;
324 state->target_residency = cpuidle_params_table[idx].target_residency; 327 state->target_residency = cpuidle_params_table[idx].target_residency;
325 state->flags = CPUIDLE_FLAG_TIME_VALID; 328 state->flags = CPUIDLE_FLAG_TIME_VALID;
326 state->enter = omap3_enter_idle_bm; 329 state->enter = omap3_enter_idle_bm;
327 cx->valid = cpuidle_params_table[idx].valid;
328 sprintf(state->name, "C%d", idx + 1); 330 sprintf(state->name, "C%d", idx + 1);
329 strncpy(state->desc, descr, CPUIDLE_DESC_LEN); 331 strncpy(state->desc, descr, CPUIDLE_DESC_LEN);
332
333}
334
335/* Helper to register the driver_data */
336static inline struct omap3_idle_statedata *_fill_cstate_usage(
337 struct cpuidle_device *dev,
338 int idx)
339{
340 struct omap3_idle_statedata *cx = &omap3_idle_data[idx];
341 struct cpuidle_state_usage *state_usage = &dev->states_usage[idx];
342
343 cx->valid = cpuidle_params_table[idx].valid;
330 cpuidle_set_statedata(state_usage, cx); 344 cpuidle_set_statedata(state_usage, cx);
331 345
332 return cx; 346 return cx;
@@ -341,6 +355,7 @@ static inline struct omap3_idle_statedata *_fill_cstate(
341int __init omap3_idle_init(void) 355int __init omap3_idle_init(void)
342{ 356{
343 struct cpuidle_device *dev; 357 struct cpuidle_device *dev;
358 struct cpuidle_driver *drv = &omap3_idle_driver;
344 struct omap3_idle_statedata *cx; 359 struct omap3_idle_statedata *cx;
345 360
346 mpu_pd = pwrdm_lookup("mpu_pwrdm"); 361 mpu_pd = pwrdm_lookup("mpu_pwrdm");
@@ -348,45 +363,52 @@ int __init omap3_idle_init(void)
348 per_pd = pwrdm_lookup("per_pwrdm"); 363 per_pd = pwrdm_lookup("per_pwrdm");
349 cam_pd = pwrdm_lookup("cam_pwrdm"); 364 cam_pd = pwrdm_lookup("cam_pwrdm");
350 365
351 cpuidle_register_driver(&omap3_idle_driver); 366
367 drv->safe_state_index = -1;
352 dev = &per_cpu(omap3_idle_dev, smp_processor_id()); 368 dev = &per_cpu(omap3_idle_dev, smp_processor_id());
353 dev->safe_state_index = -1;
354 369
355 /* C1 . MPU WFI + Core active */ 370 /* C1 . MPU WFI + Core active */
356 cx = _fill_cstate(dev, 0, "MPU ON + CORE ON"); 371 _fill_cstate(drv, 0, "MPU ON + CORE ON");
357 (&dev->states[0])->enter = omap3_enter_idle; 372 (&drv->states[0])->enter = omap3_enter_idle;
358 dev->safe_state_index = 0; 373 drv->safe_state_index = 0;
374 cx = _fill_cstate_usage(dev, 0);
359 cx->valid = 1; /* C1 is always valid */ 375 cx->valid = 1; /* C1 is always valid */
360 cx->mpu_state = PWRDM_POWER_ON; 376 cx->mpu_state = PWRDM_POWER_ON;
361 cx->core_state = PWRDM_POWER_ON; 377 cx->core_state = PWRDM_POWER_ON;
362 378
363 /* C2 . MPU WFI + Core inactive */ 379 /* C2 . MPU WFI + Core inactive */
364 cx = _fill_cstate(dev, 1, "MPU ON + CORE ON"); 380 _fill_cstate(drv, 1, "MPU ON + CORE ON");
381 cx = _fill_cstate_usage(dev, 1);
365 cx->mpu_state = PWRDM_POWER_ON; 382 cx->mpu_state = PWRDM_POWER_ON;
366 cx->core_state = PWRDM_POWER_ON; 383 cx->core_state = PWRDM_POWER_ON;
367 384
368 /* C3 . MPU CSWR + Core inactive */ 385 /* C3 . MPU CSWR + Core inactive */
369 cx = _fill_cstate(dev, 2, "MPU RET + CORE ON"); 386 _fill_cstate(drv, 2, "MPU RET + CORE ON");
387 cx = _fill_cstate_usage(dev, 2);
370 cx->mpu_state = PWRDM_POWER_RET; 388 cx->mpu_state = PWRDM_POWER_RET;
371 cx->core_state = PWRDM_POWER_ON; 389 cx->core_state = PWRDM_POWER_ON;
372 390
373 /* C4 . MPU OFF + Core inactive */ 391 /* C4 . MPU OFF + Core inactive */
374 cx = _fill_cstate(dev, 3, "MPU OFF + CORE ON"); 392 _fill_cstate(drv, 3, "MPU OFF + CORE ON");
393 cx = _fill_cstate_usage(dev, 3);
375 cx->mpu_state = PWRDM_POWER_OFF; 394 cx->mpu_state = PWRDM_POWER_OFF;
376 cx->core_state = PWRDM_POWER_ON; 395 cx->core_state = PWRDM_POWER_ON;
377 396
378 /* C5 . MPU RET + Core RET */ 397 /* C5 . MPU RET + Core RET */
379 cx = _fill_cstate(dev, 4, "MPU RET + CORE RET"); 398 _fill_cstate(drv, 4, "MPU RET + CORE RET");
399 cx = _fill_cstate_usage(dev, 4);
380 cx->mpu_state = PWRDM_POWER_RET; 400 cx->mpu_state = PWRDM_POWER_RET;
381 cx->core_state = PWRDM_POWER_RET; 401 cx->core_state = PWRDM_POWER_RET;
382 402
383 /* C6 . MPU OFF + Core RET */ 403 /* C6 . MPU OFF + Core RET */
384 cx = _fill_cstate(dev, 5, "MPU OFF + CORE RET"); 404 _fill_cstate(drv, 5, "MPU OFF + CORE RET");
405 cx = _fill_cstate_usage(dev, 5);
385 cx->mpu_state = PWRDM_POWER_OFF; 406 cx->mpu_state = PWRDM_POWER_OFF;
386 cx->core_state = PWRDM_POWER_RET; 407 cx->core_state = PWRDM_POWER_RET;
387 408
388 /* C7 . MPU OFF + Core OFF */ 409 /* C7 . MPU OFF + Core OFF */
389 cx = _fill_cstate(dev, 6, "MPU OFF + CORE OFF"); 410 _fill_cstate(drv, 6, "MPU OFF + CORE OFF");
411 cx = _fill_cstate_usage(dev, 6);
390 /* 412 /*
391 * Erratum i583: implementation for ES rev < Es1.2 on 3630. We cannot 413 * Erratum i583: implementation for ES rev < Es1.2 on 3630. We cannot
392 * enable OFF mode in a stable form for previous revisions. 414 * enable OFF mode in a stable form for previous revisions.
@@ -400,6 +422,9 @@ int __init omap3_idle_init(void)
400 cx->mpu_state = PWRDM_POWER_OFF; 422 cx->mpu_state = PWRDM_POWER_OFF;
401 cx->core_state = PWRDM_POWER_OFF; 423 cx->core_state = PWRDM_POWER_OFF;
402 424
425 drv->state_count = OMAP3_NUM_STATES;
426 cpuidle_register_driver(&omap3_idle_driver);
427
403 dev->state_count = OMAP3_NUM_STATES; 428 dev->state_count = OMAP3_NUM_STATES;
404 if (cpuidle_register_device(dev)) { 429 if (cpuidle_register_device(dev)) {
405 printk(KERN_ERR "%s: CPUidle register device failed\n", 430 printk(KERN_ERR "%s: CPUidle register device failed\n",