OMAP3: cpuidle: re-organize the C-states data
[pandora-kernel.git] / arch / arm / mach-omap2 / cpuidle34xx.c
1 /*
2  * linux/arch/arm/mach-omap2/cpuidle34xx.c
3  *
4  * OMAP3 CPU IDLE Routines
5  *
6  * Copyright (C) 2008 Texas Instruments, Inc.
7  * Rajendra Nayak <rnayak@ti.com>
8  *
9  * Copyright (C) 2007 Texas Instruments, Inc.
10  * Karthik Dasu <karthik-dp@ti.com>
11  *
12  * Copyright (C) 2006 Nokia Corporation
13  * Tony Lindgren <tony@atomide.com>
14  *
15  * Copyright (C) 2005 Texas Instruments, Inc.
16  * Richard Woodruff <r-woodruff2@ti.com>
17  *
18  * Based on pm.c for omap2
19  *
20  * This program is free software; you can redistribute it and/or modify
21  * it under the terms of the GNU General Public License version 2 as
22  * published by the Free Software Foundation.
23  */
24
25 #include <linux/sched.h>
26 #include <linux/cpuidle.h>
27
28 #include <plat/prcm.h>
29 #include <plat/irqs.h>
30 #include "powerdomain.h"
31 #include "clockdomain.h"
32 #include <plat/serial.h>
33
34 #include "pm.h"
35 #include "control.h"
36
37 #ifdef CONFIG_CPU_IDLE
38
39 /*
40  * The latencies/thresholds for various C states have
41  * to be configured from the respective board files.
42  * These are some default values (which might not provide
43  * the best power savings) used on boards which do not
44  * pass these details from the board file.
45  */
46 static struct cpuidle_params cpuidle_params_table[] = {
47         /* C1 */
48         {2 + 2, 5, 1},
49         /* C2 */
50         {10 + 10, 30, 1},
51         /* C3 */
52         {50 + 50, 300, 1},
53         /* C4 */
54         {1500 + 1800, 4000, 1},
55         /* C5 */
56         {2500 + 7500, 12000, 1},
57         /* C6 */
58         {3000 + 8500, 15000, 1},
59         /* C7 */
60         {10000 + 30000, 300000, 1},
61 };
62 #define OMAP3_NUM_STATES ARRAY_SIZE(cpuidle_params_table)
63
64 /* Mach specific information to be recorded in the C-state driver_data */
65 struct omap3_idle_statedata {
66         u32 mpu_state;
67         u32 core_state;
68         u8 valid;
69 };
70 struct omap3_idle_statedata omap3_idle_data[OMAP3_NUM_STATES];
71
72 struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd;
73
74 static int omap3_idle_bm_check(void)
75 {
76         if (!omap3_can_sleep())
77                 return 1;
78         return 0;
79 }
80
81 static int _cpuidle_allow_idle(struct powerdomain *pwrdm,
82                                 struct clockdomain *clkdm)
83 {
84         clkdm_allow_idle(clkdm);
85         return 0;
86 }
87
88 static int _cpuidle_deny_idle(struct powerdomain *pwrdm,
89                                 struct clockdomain *clkdm)
90 {
91         clkdm_deny_idle(clkdm);
92         return 0;
93 }
94
95 /**
96  * omap3_enter_idle - Programs OMAP3 to enter the specified state
97  * @dev: cpuidle device
98  * @state: The target state to be programmed
99  *
100  * Called from the CPUidle framework to program the device to the
101  * specified target state selected by the governor.
102  */
103 static int omap3_enter_idle(struct cpuidle_device *dev,
104                         struct cpuidle_state *state)
105 {
106         struct omap3_idle_statedata *cx = cpuidle_get_statedata(state);
107         struct timespec ts_preidle, ts_postidle, ts_idle;
108         u32 mpu_state = cx->mpu_state, core_state = cx->core_state;
109
110         /* Used to keep track of the total time in idle */
111         getnstimeofday(&ts_preidle);
112
113         local_irq_disable();
114         local_fiq_disable();
115
116         pwrdm_set_next_pwrst(mpu_pd, mpu_state);
117         pwrdm_set_next_pwrst(core_pd, core_state);
118
119         if (omap_irq_pending() || need_resched())
120                 goto return_sleep_time;
121
122         /* Deny idle for C1 */
123         if (state == &dev->states[0]) {
124                 pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle);
125                 pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle);
126         }
127
128         /* Execute ARM wfi */
129         omap_sram_idle();
130
131         /* Re-allow idle for C1 */
132         if (state == &dev->states[0]) {
133                 pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle);
134                 pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle);
135         }
136
137 return_sleep_time:
138         getnstimeofday(&ts_postidle);
139         ts_idle = timespec_sub(ts_postidle, ts_preidle);
140
141         local_irq_enable();
142         local_fiq_enable();
143
144         return ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * USEC_PER_SEC;
145 }
146
147 /**
148  * next_valid_state - Find next valid c-state
149  * @dev: cpuidle device
150  * @state: Currently selected c-state
151  *
152  * If the current state is valid, it is returned back to the caller.
153  * Else, this function searches for a lower c-state which is still
154  * valid.
155  */
156 static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev,
157                                               struct cpuidle_state *curr)
158 {
159         struct cpuidle_state *next = NULL;
160         struct omap3_idle_statedata *cx;
161
162         cx = cpuidle_get_statedata(curr);
163
164         /* Check if current state is valid */
165         if (cx->valid) {
166                 return curr;
167         } else {
168                 int idx = OMAP3_NUM_STATES - 1;
169
170                 /*
171                  * Reach the current state starting at highest C-state
172                  */
173                 for (; idx >= 0; idx--) {
174                         if (&dev->states[idx] == curr) {
175                                 next = &dev->states[idx];
176                                 break;
177                         }
178                 }
179
180                 /*
181                  * Should never hit this condition.
182                  */
183                 WARN_ON(next == NULL);
184
185                 /*
186                  * Drop to next valid state.
187                  * Start search from the next (lower) state.
188                  */
189                 idx--;
190                 for (; idx >= 0; idx--) {
191                         cx = cpuidle_get_statedata(&dev->states[idx]);
192                         if (cx->valid) {
193                                 next = &dev->states[idx];
194                                 break;
195                         }
196                 }
197                 /*
198                  * C1 is always valid.
199                  * So, no need to check for 'next==NULL' outside this loop.
200                  */
201         }
202
203         return next;
204 }
205
206 /**
207  * omap3_enter_idle_bm - Checks for any bus activity
208  * @dev: cpuidle device
209  * @state: The target state to be programmed
210  *
211  * This function checks for any pending activity and then programs
212  * the device to the specified or a safer state.
213  */
214 static int omap3_enter_idle_bm(struct cpuidle_device *dev,
215                                struct cpuidle_state *state)
216 {
217         struct cpuidle_state *new_state = next_valid_state(dev, state);
218         u32 core_next_state, per_next_state = 0, per_saved_state = 0;
219         u32 cam_state;
220         struct omap3_idle_statedata *cx;
221         int ret;
222
223         if (omap3_idle_bm_check()) {
224                 BUG_ON(!dev->safe_state);
225                 new_state = dev->safe_state;
226                 goto select_state;
227         }
228
229         cx = cpuidle_get_statedata(state);
230         core_next_state = cx->core_state;
231
232         /*
233          * FIXME: we currently manage device-specific idle states
234          *        for PER and CORE in combination with CPU-specific
235          *        idle states.  This is wrong, and device-specific
236          *        idle management needs to be separated out into 
237          *        its own code.
238          */
239
240         /*
241          * Prevent idle completely if CAM is active.
242          * CAM does not have wakeup capability in OMAP3.
243          */
244         cam_state = pwrdm_read_pwrst(cam_pd);
245         if (cam_state == PWRDM_POWER_ON) {
246                 new_state = dev->safe_state;
247                 goto select_state;
248         }
249
250         /*
251          * Prevent PER off if CORE is not in retention or off as this
252          * would disable PER wakeups completely.
253          */
254         per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd);
255         if ((per_next_state == PWRDM_POWER_OFF) &&
256             (core_next_state > PWRDM_POWER_RET))
257                 per_next_state = PWRDM_POWER_RET;
258
259         /* Are we changing PER target state? */
260         if (per_next_state != per_saved_state)
261                 pwrdm_set_next_pwrst(per_pd, per_next_state);
262
263 select_state:
264         dev->last_state = new_state;
265         ret = omap3_enter_idle(dev, new_state);
266
267         /* Restore original PER state if it was modified */
268         if (per_next_state != per_saved_state)
269                 pwrdm_set_next_pwrst(per_pd, per_saved_state);
270
271         return ret;
272 }
273
274 DEFINE_PER_CPU(struct cpuidle_device, omap3_idle_dev);
275
276 /**
277  * omap3_cpuidle_update_states() - Update the cpuidle states
278  * @mpu_deepest_state:  Enable states up to and including this for mpu domain
279  * @core_deepest_state: Enable states up to and including this for core domain
280  *
281  * This goes through the list of states available and enables and disables the
282  * validity of C states based on deepest state that can be achieved for the
283  * variable domain
284  */
285 void omap3_cpuidle_update_states(u32 mpu_deepest_state, u32 core_deepest_state)
286 {
287         int i;
288
289         for (i = 0; i < OMAP3_NUM_STATES; i++) {
290                 struct omap3_idle_statedata *cx = &omap3_idle_data[i];
291
292                 if ((cx->mpu_state >= mpu_deepest_state) &&
293                     (cx->core_state >= core_deepest_state)) {
294                         cx->valid = 1;
295                 } else {
296                         cx->valid = 0;
297                 }
298         }
299 }
300
301 void omap3_pm_init_cpuidle(struct cpuidle_params *cpuidle_board_params)
302 {
303         int i;
304
305         if (!cpuidle_board_params)
306                 return;
307
308         for (i = 0; i < OMAP3_NUM_STATES; i++) {
309                 cpuidle_params_table[i].valid = cpuidle_board_params[i].valid;
310                 cpuidle_params_table[i].exit_latency =
311                         cpuidle_board_params[i].exit_latency;
312                 cpuidle_params_table[i].target_residency =
313                         cpuidle_board_params[i].target_residency;
314         }
315         return;
316 }
317
318 struct cpuidle_driver omap3_idle_driver = {
319         .name =         "omap3_idle",
320         .owner =        THIS_MODULE,
321 };
322
323 /* Fill in the state data from the mach tables and register the driver_data */
324 static inline struct omap3_idle_statedata *_fill_cstate(
325                                         struct cpuidle_device *dev,
326                                         int idx, const char *descr)
327 {
328         struct omap3_idle_statedata *cx = &omap3_idle_data[idx];
329         struct cpuidle_state *state = &dev->states[idx];
330
331         state->exit_latency     = cpuidle_params_table[idx].exit_latency;
332         state->target_residency = cpuidle_params_table[idx].target_residency;
333         state->flags            = CPUIDLE_FLAG_TIME_VALID;
334         state->enter            = omap3_enter_idle_bm;
335         cx->valid               = cpuidle_params_table[idx].valid;
336         sprintf(state->name, "C%d", idx + 1);
337         strncpy(state->desc, descr, CPUIDLE_DESC_LEN);
338         cpuidle_set_statedata(state, cx);
339
340         return cx;
341 }
342
343 /**
344  * omap3_idle_init - Init routine for OMAP3 idle
345  *
346  * Registers the OMAP3 specific cpuidle driver to the cpuidle
347  * framework with the valid set of states.
348  */
349 int __init omap3_idle_init(void)
350 {
351         struct cpuidle_device *dev;
352         struct omap3_idle_statedata *cx;
353
354         mpu_pd = pwrdm_lookup("mpu_pwrdm");
355         core_pd = pwrdm_lookup("core_pwrdm");
356         per_pd = pwrdm_lookup("per_pwrdm");
357         cam_pd = pwrdm_lookup("cam_pwrdm");
358
359         cpuidle_register_driver(&omap3_idle_driver);
360         dev = &per_cpu(omap3_idle_dev, smp_processor_id());
361
362         /* C1 . MPU WFI + Core active */
363         cx = _fill_cstate(dev, 0, "MPU ON + CORE ON");
364         (&dev->states[0])->enter = omap3_enter_idle;
365         dev->safe_state = &dev->states[0];
366         cx->valid = 1;  /* C1 is always valid */
367         cx->mpu_state = PWRDM_POWER_ON;
368         cx->core_state = PWRDM_POWER_ON;
369
370         /* C2 . MPU WFI + Core inactive */
371         cx = _fill_cstate(dev, 1, "MPU ON + CORE ON");
372         cx->mpu_state = PWRDM_POWER_ON;
373         cx->core_state = PWRDM_POWER_ON;
374
375         /* C3 . MPU CSWR + Core inactive */
376         cx = _fill_cstate(dev, 2, "MPU RET + CORE ON");
377         cx->mpu_state = PWRDM_POWER_RET;
378         cx->core_state = PWRDM_POWER_ON;
379
380         /* C4 . MPU OFF + Core inactive */
381         cx = _fill_cstate(dev, 3, "MPU OFF + CORE ON");
382         cx->mpu_state = PWRDM_POWER_OFF;
383         cx->core_state = PWRDM_POWER_ON;
384
385         /* C5 . MPU RET + Core RET */
386         cx = _fill_cstate(dev, 4, "MPU RET + CORE RET");
387         cx->mpu_state = PWRDM_POWER_RET;
388         cx->core_state = PWRDM_POWER_RET;
389
390         /* C6 . MPU OFF + Core RET */
391         cx = _fill_cstate(dev, 5, "MPU OFF + CORE RET");
392         cx->mpu_state = PWRDM_POWER_OFF;
393         cx->core_state = PWRDM_POWER_RET;
394
395         /* C7 . MPU OFF + Core OFF */
396         cx = _fill_cstate(dev, 6, "MPU OFF + CORE OFF");
397         /*
398          * Erratum i583: implementation for ES rev < Es1.2 on 3630. We cannot
399          * enable OFF mode in a stable form for previous revisions.
400          * We disable C7 state as a result.
401          */
402         if (IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583)) {
403                 cx->valid = 0;
404                 pr_warn("%s: core off state C7 disabled due to i583\n",
405                         __func__);
406         }
407         cx->mpu_state = PWRDM_POWER_OFF;
408         cx->core_state = PWRDM_POWER_OFF;
409
410         if (enable_off_mode)
411                 omap3_cpuidle_update_states(PWRDM_POWER_OFF, PWRDM_POWER_OFF);
412         else
413                 omap3_cpuidle_update_states(PWRDM_POWER_RET, PWRDM_POWER_RET);
414
415         dev->state_count = OMAP3_NUM_STATES;
416         if (cpuidle_register_device(dev)) {
417                 printk(KERN_ERR "%s: CPUidle register device failed\n",
418                        __func__);
419                 return -EIO;
420         }
421
422         return 0;
423 }
424 #else
425 int __init omap3_idle_init(void)
426 {
427         return 0;
428 }
429 #endif /* CONFIG_CPU_IDLE */