dc03289d5deaee4b76982b420a0db5e10c6cc0e2
[pandora-kernel.git] / arch / arm / mach-omap2 / powerdomain.c
1 /*
2  * OMAP powerdomain control
3  *
4  * Copyright (C) 2007-2008 Texas Instruments, Inc.
5  * Copyright (C) 2007-2009 Nokia Corporation
6  *
7  * Written by Paul Walmsley
8  *
9  * Added OMAP4 specific support by Abhijit Pagare <abhijitpagare@ti.com>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License version 2 as
13  * published by the Free Software Foundation.
14  */
15 #undef DEBUG
16
17 #include <linux/kernel.h>
18 #include <linux/module.h>
19 #include <linux/types.h>
20 #include <linux/delay.h>
21 #include <linux/spinlock.h>
22 #include <linux/list.h>
23 #include <linux/errno.h>
24 #include <linux/err.h>
25 #include <linux/io.h>
26
27 #include <asm/atomic.h>
28
29 #include "cm.h"
30 #include "cm-regbits-34xx.h"
31 #include "cm-regbits-44xx.h"
32 #include "prm.h"
33 #include "prm-regbits-34xx.h"
34 #include "prm-regbits-44xx.h"
35
36 #include <plat/cpu.h>
37 #include <plat/powerdomain.h>
38 #include <plat/clockdomain.h>
39 #include <plat/prcm.h>
40
41 #include "pm.h"
42
43 enum {
44         PWRDM_STATE_NOW = 0,
45         PWRDM_STATE_PREV,
46 };
47
48 /* Variable holding value of the CPU dependent PWRSTCTRL Register Offset */
49 static u16 pwrstctrl_reg_offs;
50
51 /* Variable holding value of the CPU dependent PWRSTST Register Offset */
52 static u16 pwrstst_reg_offs;
53
54 /* OMAP3 and OMAP4 specific register bit initialisations
55  * Notice that the names here are not according to each power
56  * domain but the bit mapping used applies to all of them
57  */
58
59 /* OMAP3 and OMAP4 Memory Onstate Masks (common across all power domains) */
60 #define OMAP_MEM0_ONSTATE_MASK OMAP3430_SHAREDL1CACHEFLATONSTATE_MASK
61 #define OMAP_MEM1_ONSTATE_MASK OMAP3430_L1FLATMEMONSTATE_MASK
62 #define OMAP_MEM2_ONSTATE_MASK OMAP3430_SHAREDL2CACHEFLATONSTATE_MASK
63 #define OMAP_MEM3_ONSTATE_MASK OMAP3430_L2FLATMEMONSTATE_MASK
64 #define OMAP_MEM4_ONSTATE_MASK OMAP4430_OCP_NRET_BANK_ONSTATE_MASK
65
66 /* OMAP3 and OMAP4 Memory Retstate Masks (common across all power domains) */
67 #define OMAP_MEM0_RETSTATE_MASK OMAP3430_SHAREDL1CACHEFLATRETSTATE
68 #define OMAP_MEM1_RETSTATE_MASK OMAP3430_L1FLATMEMRETSTATE
69 #define OMAP_MEM2_RETSTATE_MASK OMAP3430_SHAREDL2CACHEFLATRETSTATE
70 #define OMAP_MEM3_RETSTATE_MASK OMAP3430_L2FLATMEMRETSTATE
71 #define OMAP_MEM4_RETSTATE_MASK OMAP4430_OCP_NRET_BANK_RETSTATE_MASK
72
73 /* OMAP3 and OMAP4 Memory Status bits */
74 #define OMAP_MEM0_STATEST_MASK OMAP3430_SHAREDL1CACHEFLATSTATEST_MASK
75 #define OMAP_MEM1_STATEST_MASK OMAP3430_L1FLATMEMSTATEST_MASK
76 #define OMAP_MEM2_STATEST_MASK OMAP3430_SHAREDL2CACHEFLATSTATEST_MASK
77 #define OMAP_MEM3_STATEST_MASK OMAP3430_L2FLATMEMSTATEST_MASK
78 #define OMAP_MEM4_STATEST_MASK OMAP4430_OCP_NRET_BANK_STATEST_MASK
79
80 /* pwrdm_list contains all registered struct powerdomains */
81 static LIST_HEAD(pwrdm_list);
82
83 /* Private functions */
84
85 static struct powerdomain *_pwrdm_lookup(const char *name)
86 {
87         struct powerdomain *pwrdm, *temp_pwrdm;
88
89         pwrdm = NULL;
90
91         list_for_each_entry(temp_pwrdm, &pwrdm_list, node) {
92                 if (!strcmp(name, temp_pwrdm->name)) {
93                         pwrdm = temp_pwrdm;
94                         break;
95                 }
96         }
97
98         return pwrdm;
99 }
100
101 /**
102  * _pwrdm_register - register a powerdomain
103  * @pwrdm: struct powerdomain * to register
104  *
105  * Adds a powerdomain to the internal powerdomain list.  Returns
106  * -EINVAL if given a null pointer, -EEXIST if a powerdomain is
107  * already registered by the provided name, or 0 upon success.
108  */
109 static int _pwrdm_register(struct powerdomain *pwrdm)
110 {
111         int i;
112
113         if (!pwrdm)
114                 return -EINVAL;
115
116         if (!omap_chip_is(pwrdm->omap_chip))
117                 return -EINVAL;
118
119         if (_pwrdm_lookup(pwrdm->name))
120                 return -EEXIST;
121
122         list_add(&pwrdm->node, &pwrdm_list);
123
124         /* Initialize the powerdomain's state counter */
125         for (i = 0; i < PWRDM_MAX_PWRSTS; i++)
126                 pwrdm->state_counter[i] = 0;
127
128         pwrdm_wait_transition(pwrdm);
129         pwrdm->state = pwrdm_read_pwrst(pwrdm);
130         pwrdm->state_counter[pwrdm->state] = 1;
131
132         pr_debug("powerdomain: registered %s\n", pwrdm->name);
133
134         return 0;
135 }
136
137 static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag)
138 {
139
140         int prev;
141         int state;
142
143         if (pwrdm == NULL)
144                 return -EINVAL;
145
146         state = pwrdm_read_pwrst(pwrdm);
147
148         switch (flag) {
149         case PWRDM_STATE_NOW:
150                 prev = pwrdm->state;
151                 break;
152         case PWRDM_STATE_PREV:
153                 prev = pwrdm_read_prev_pwrst(pwrdm);
154                 if (pwrdm->state != prev)
155                         pwrdm->state_counter[prev]++;
156                 break;
157         default:
158                 return -EINVAL;
159         }
160
161         if (state != prev)
162                 pwrdm->state_counter[state]++;
163
164         pm_dbg_update_time(pwrdm, prev);
165
166         pwrdm->state = state;
167
168         return 0;
169 }
170
171 static int _pwrdm_pre_transition_cb(struct powerdomain *pwrdm, void *unused)
172 {
173         pwrdm_clear_all_prev_pwrst(pwrdm);
174         _pwrdm_state_switch(pwrdm, PWRDM_STATE_NOW);
175         return 0;
176 }
177
178 static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm, void *unused)
179 {
180         _pwrdm_state_switch(pwrdm, PWRDM_STATE_PREV);
181         return 0;
182 }
183
184 /* Public functions */
185
186 /**
187  * pwrdm_init - set up the powerdomain layer
188  * @pwrdm_list: array of struct powerdomain pointers to register
189  *
190  * Loop through the array of powerdomains @pwrdm_list, registering all
191  * that are available on the current CPU. If pwrdm_list is supplied
192  * and not null, all of the referenced powerdomains will be
193  * registered.  No return value.  XXX pwrdm_list is not really a
194  * "list"; it is an array.  Rename appropriately.
195  */
196 void pwrdm_init(struct powerdomain **pwrdm_list)
197 {
198         struct powerdomain **p = NULL;
199
200         if (cpu_is_omap24xx() | cpu_is_omap34xx()) {
201                 pwrstctrl_reg_offs = OMAP2_PM_PWSTCTRL;
202                 pwrstst_reg_offs = OMAP2_PM_PWSTST;
203         } else if (cpu_is_omap44xx()) {
204                 pwrstctrl_reg_offs = OMAP4_PM_PWSTCTRL;
205                 pwrstst_reg_offs = OMAP4_PM_PWSTST;
206         } else {
207                 printk(KERN_ERR "Power Domain struct not supported for " \
208                                                         "this CPU\n");
209                 return;
210         }
211
212         if (pwrdm_list) {
213                 for (p = pwrdm_list; *p; p++)
214                         _pwrdm_register(*p);
215         }
216 }
217
218 /**
219  * pwrdm_lookup - look up a powerdomain by name, return a pointer
220  * @name: name of powerdomain
221  *
222  * Find a registered powerdomain by its name @name.  Returns a pointer
223  * to the struct powerdomain if found, or NULL otherwise.
224  */
225 struct powerdomain *pwrdm_lookup(const char *name)
226 {
227         struct powerdomain *pwrdm;
228
229         if (!name)
230                 return NULL;
231
232         pwrdm = _pwrdm_lookup(name);
233
234         return pwrdm;
235 }
236
237 /**
238  * pwrdm_for_each - call function on each registered clockdomain
239  * @fn: callback function *
240  *
241  * Call the supplied function @fn for each registered powerdomain.
242  * The callback function @fn can return anything but 0 to bail out
243  * early from the iterator.  Returns the last return value of the
244  * callback function, which should be 0 for success or anything else
245  * to indicate failure; or -EINVAL if the function pointer is null.
246  */
247 int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),
248                    void *user)
249 {
250         struct powerdomain *temp_pwrdm;
251         int ret = 0;
252
253         if (!fn)
254                 return -EINVAL;
255
256         list_for_each_entry(temp_pwrdm, &pwrdm_list, node) {
257                 ret = (*fn)(temp_pwrdm, user);
258                 if (ret)
259                         break;
260         }
261
262         return ret;
263 }
264
265 /**
266  * pwrdm_add_clkdm - add a clockdomain to a powerdomain
267  * @pwrdm: struct powerdomain * to add the clockdomain to
268  * @clkdm: struct clockdomain * to associate with a powerdomain
269  *
270  * Associate the clockdomain @clkdm with a powerdomain @pwrdm.  This
271  * enables the use of pwrdm_for_each_clkdm().  Returns -EINVAL if
272  * presented with invalid pointers; -ENOMEM if memory could not be allocated;
273  * or 0 upon success.
274  */
275 int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)
276 {
277         int i;
278         int ret = -EINVAL;
279
280         if (!pwrdm || !clkdm)
281                 return -EINVAL;
282
283         pr_debug("powerdomain: associating clockdomain %s with powerdomain "
284                  "%s\n", clkdm->name, pwrdm->name);
285
286         for (i = 0; i < PWRDM_MAX_CLKDMS; i++) {
287                 if (!pwrdm->pwrdm_clkdms[i])
288                         break;
289 #ifdef DEBUG
290                 if (pwrdm->pwrdm_clkdms[i] == clkdm) {
291                         ret = -EINVAL;
292                         goto pac_exit;
293                 }
294 #endif
295         }
296
297         if (i == PWRDM_MAX_CLKDMS) {
298                 pr_debug("powerdomain: increase PWRDM_MAX_CLKDMS for "
299                          "pwrdm %s clkdm %s\n", pwrdm->name, clkdm->name);
300                 WARN_ON(1);
301                 ret = -ENOMEM;
302                 goto pac_exit;
303         }
304
305         pwrdm->pwrdm_clkdms[i] = clkdm;
306
307         ret = 0;
308
309 pac_exit:
310         return ret;
311 }
312
313 /**
314  * pwrdm_del_clkdm - remove a clockdomain from a powerdomain
315  * @pwrdm: struct powerdomain * to add the clockdomain to
316  * @clkdm: struct clockdomain * to associate with a powerdomain
317  *
318  * Dissociate the clockdomain @clkdm from the powerdomain
319  * @pwrdm. Returns -EINVAL if presented with invalid pointers; -ENOENT
320  * if @clkdm was not associated with the powerdomain, or 0 upon
321  * success.
322  */
323 int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)
324 {
325         int ret = -EINVAL;
326         int i;
327
328         if (!pwrdm || !clkdm)
329                 return -EINVAL;
330
331         pr_debug("powerdomain: dissociating clockdomain %s from powerdomain "
332                  "%s\n", clkdm->name, pwrdm->name);
333
334         for (i = 0; i < PWRDM_MAX_CLKDMS; i++)
335                 if (pwrdm->pwrdm_clkdms[i] == clkdm)
336                         break;
337
338         if (i == PWRDM_MAX_CLKDMS) {
339                 pr_debug("powerdomain: clkdm %s not associated with pwrdm "
340                          "%s ?!\n", clkdm->name, pwrdm->name);
341                 ret = -ENOENT;
342                 goto pdc_exit;
343         }
344
345         pwrdm->pwrdm_clkdms[i] = NULL;
346
347         ret = 0;
348
349 pdc_exit:
350         return ret;
351 }
352
353 /**
354  * pwrdm_for_each_clkdm - call function on each clkdm in a pwrdm
355  * @pwrdm: struct powerdomain * to iterate over
356  * @fn: callback function *
357  *
358  * Call the supplied function @fn for each clockdomain in the powerdomain
359  * @pwrdm.  The callback function can return anything but 0 to bail
360  * out early from the iterator.  Returns -EINVAL if presented with
361  * invalid pointers; or passes along the last return value of the
362  * callback function, which should be 0 for success or anything else
363  * to indicate failure.
364  */
365 int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
366                          int (*fn)(struct powerdomain *pwrdm,
367                                    struct clockdomain *clkdm))
368 {
369         int ret = 0;
370         int i;
371
372         if (!fn)
373                 return -EINVAL;
374
375         for (i = 0; i < PWRDM_MAX_CLKDMS && !ret; i++)
376                 ret = (*fn)(pwrdm, pwrdm->pwrdm_clkdms[i]);
377
378         return ret;
379 }
380
381 /**
382  * pwrdm_get_mem_bank_count - get number of memory banks in this powerdomain
383  * @pwrdm: struct powerdomain *
384  *
385  * Return the number of controllable memory banks in powerdomain @pwrdm,
386  * starting with 1.  Returns -EINVAL if the powerdomain pointer is null.
387  */
388 int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm)
389 {
390         if (!pwrdm)
391                 return -EINVAL;
392
393         return pwrdm->banks;
394 }
395
396 /**
397  * pwrdm_set_next_pwrst - set next powerdomain power state
398  * @pwrdm: struct powerdomain * to set
399  * @pwrst: one of the PWRDM_POWER_* macros
400  *
401  * Set the powerdomain @pwrdm's next power state to @pwrst.  The powerdomain
402  * may not enter this state immediately if the preconditions for this state
403  * have not been satisfied.  Returns -EINVAL if the powerdomain pointer is
404  * null or if the power state is invalid for the powerdomin, or returns 0
405  * upon success.
406  */
407 int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
408 {
409         if (!pwrdm)
410                 return -EINVAL;
411
412         if (!(pwrdm->pwrsts & (1 << pwrst)))
413                 return -EINVAL;
414
415         pr_debug("powerdomain: setting next powerstate for %s to %0x\n",
416                  pwrdm->name, pwrst);
417
418         prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
419                              (pwrst << OMAP_POWERSTATE_SHIFT),
420                              pwrdm->prcm_offs, pwrstctrl_reg_offs);
421
422         return 0;
423 }
424
425 /**
426  * pwrdm_read_next_pwrst - get next powerdomain power state
427  * @pwrdm: struct powerdomain * to get power state
428  *
429  * Return the powerdomain @pwrdm's next power state.  Returns -EINVAL
430  * if the powerdomain pointer is null or returns the next power state
431  * upon success.
432  */
433 int pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
434 {
435         if (!pwrdm)
436                 return -EINVAL;
437
438         return prm_read_mod_bits_shift(pwrdm->prcm_offs,
439                                  pwrstctrl_reg_offs, OMAP_POWERSTATE_MASK);
440 }
441
442 /**
443  * pwrdm_read_pwrst - get current powerdomain power state
444  * @pwrdm: struct powerdomain * to get power state
445  *
446  * Return the powerdomain @pwrdm's current power state. Returns -EINVAL
447  * if the powerdomain pointer is null or returns the current power state
448  * upon success.
449  */
450 int pwrdm_read_pwrst(struct powerdomain *pwrdm)
451 {
452         if (!pwrdm)
453                 return -EINVAL;
454
455         return prm_read_mod_bits_shift(pwrdm->prcm_offs,
456                                  pwrstst_reg_offs, OMAP_POWERSTATEST_MASK);
457 }
458
459 /**
460  * pwrdm_read_prev_pwrst - get previous powerdomain power state
461  * @pwrdm: struct powerdomain * to get previous power state
462  *
463  * Return the powerdomain @pwrdm's previous power state.  Returns -EINVAL
464  * if the powerdomain pointer is null or returns the previous power state
465  * upon success.
466  */
467 int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
468 {
469         if (!pwrdm)
470                 return -EINVAL;
471
472         return prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST,
473                                         OMAP3430_LASTPOWERSTATEENTERED_MASK);
474 }
475
476 /**
477  * pwrdm_set_logic_retst - set powerdomain logic power state upon retention
478  * @pwrdm: struct powerdomain * to set
479  * @pwrst: one of the PWRDM_POWER_* macros
480  *
481  * Set the next power state @pwrst that the logic portion of the
482  * powerdomain @pwrdm will enter when the powerdomain enters retention.
483  * This will be either RETENTION or OFF, if supported.  Returns
484  * -EINVAL if the powerdomain pointer is null or the target power
485  * state is not not supported, or returns 0 upon success.
486  */
487 int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
488 {
489         if (!pwrdm)
490                 return -EINVAL;
491
492         if (!(pwrdm->pwrsts_logic_ret & (1 << pwrst)))
493                 return -EINVAL;
494
495         pr_debug("powerdomain: setting next logic powerstate for %s to %0x\n",
496                  pwrdm->name, pwrst);
497
498         /*
499          * The register bit names below may not correspond to the
500          * actual names of the bits in each powerdomain's register,
501          * but the type of value returned is the same for each
502          * powerdomain.
503          */
504         prm_rmw_mod_reg_bits(OMAP3430_LOGICL1CACHERETSTATE,
505                              (pwrst << __ffs(OMAP3430_LOGICL1CACHERETSTATE)),
506                                  pwrdm->prcm_offs, pwrstctrl_reg_offs);
507
508         return 0;
509 }
510
511 /**
512  * pwrdm_set_mem_onst - set memory power state while powerdomain ON
513  * @pwrdm: struct powerdomain * to set
514  * @bank: memory bank number to set (0-3)
515  * @pwrst: one of the PWRDM_POWER_* macros
516  *
517  * Set the next power state @pwrst that memory bank @bank of the
518  * powerdomain @pwrdm will enter when the powerdomain enters the ON
519  * state.  @bank will be a number from 0 to 3, and represents different
520  * types of memory, depending on the powerdomain.  Returns -EINVAL if
521  * the powerdomain pointer is null or the target power state is not
522  * not supported for this memory bank, -EEXIST if the target memory
523  * bank does not exist or is not controllable, or returns 0 upon
524  * success.
525  */
526 int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
527 {
528         u32 m;
529
530         if (!pwrdm)
531                 return -EINVAL;
532
533         if (pwrdm->banks < (bank + 1))
534                 return -EEXIST;
535
536         if (!(pwrdm->pwrsts_mem_on[bank] & (1 << pwrst)))
537                 return -EINVAL;
538
539         pr_debug("powerdomain: setting next memory powerstate for domain %s "
540                  "bank %0x while pwrdm-ON to %0x\n", pwrdm->name, bank, pwrst);
541
542         /*
543          * The register bit names below may not correspond to the
544          * actual names of the bits in each powerdomain's register,
545          * but the type of value returned is the same for each
546          * powerdomain.
547          */
548         switch (bank) {
549         case 0:
550                 m = OMAP_MEM0_ONSTATE_MASK;
551                 break;
552         case 1:
553                 m = OMAP_MEM1_ONSTATE_MASK;
554                 break;
555         case 2:
556                 m = OMAP_MEM2_ONSTATE_MASK;
557                 break;
558         case 3:
559                 m = OMAP_MEM3_ONSTATE_MASK;
560                 break;
561         case 4:
562                 m = OMAP_MEM4_ONSTATE_MASK;
563                 break;
564         default:
565                 WARN_ON(1); /* should never happen */
566                 return -EEXIST;
567         }
568
569         prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)),
570                              pwrdm->prcm_offs, pwrstctrl_reg_offs);
571
572         return 0;
573 }
574
575 /**
576  * pwrdm_set_mem_retst - set memory power state while powerdomain in RET
577  * @pwrdm: struct powerdomain * to set
578  * @bank: memory bank number to set (0-3)
579  * @pwrst: one of the PWRDM_POWER_* macros
580  *
581  * Set the next power state @pwrst that memory bank @bank of the
582  * powerdomain @pwrdm will enter when the powerdomain enters the
583  * RETENTION state.  Bank will be a number from 0 to 3, and represents
584  * different types of memory, depending on the powerdomain.  @pwrst
585  * will be either RETENTION or OFF, if supported.  Returns -EINVAL if
586  * the powerdomain pointer is null or the target power state is not
587  * not supported for this memory bank, -EEXIST if the target memory
588  * bank does not exist or is not controllable, or returns 0 upon
589  * success.
590  */
591 int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
592 {
593         u32 m;
594
595         if (!pwrdm)
596                 return -EINVAL;
597
598         if (pwrdm->banks < (bank + 1))
599                 return -EEXIST;
600
601         if (!(pwrdm->pwrsts_mem_ret[bank] & (1 << pwrst)))
602                 return -EINVAL;
603
604         pr_debug("powerdomain: setting next memory powerstate for domain %s "
605                  "bank %0x while pwrdm-RET to %0x\n", pwrdm->name, bank, pwrst);
606
607         /*
608          * The register bit names below may not correspond to the
609          * actual names of the bits in each powerdomain's register,
610          * but the type of value returned is the same for each
611          * powerdomain.
612          */
613         switch (bank) {
614         case 0:
615                 m = OMAP_MEM0_RETSTATE_MASK;
616                 break;
617         case 1:
618                 m = OMAP_MEM1_RETSTATE_MASK;
619                 break;
620         case 2:
621                 m = OMAP_MEM2_RETSTATE_MASK;
622                 break;
623         case 3:
624                 m = OMAP_MEM3_RETSTATE_MASK;
625                 break;
626         case 4:
627                 m = OMAP_MEM4_RETSTATE_MASK;
628                 break;
629         default:
630                 WARN_ON(1); /* should never happen */
631                 return -EEXIST;
632         }
633
634         prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs,
635                              pwrstctrl_reg_offs);
636
637         return 0;
638 }
639
640 /**
641  * pwrdm_read_logic_pwrst - get current powerdomain logic retention power state
642  * @pwrdm: struct powerdomain * to get current logic retention power state
643  *
644  * Return the power state that the logic portion of powerdomain @pwrdm
645  * will enter when the powerdomain enters retention.  Returns -EINVAL
646  * if the powerdomain pointer is null or returns the logic retention
647  * power state upon success.
648  */
649 int pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
650 {
651         if (!pwrdm)
652                 return -EINVAL;
653
654         return prm_read_mod_bits_shift(pwrdm->prcm_offs,
655                                  pwrstst_reg_offs, OMAP3430_LOGICSTATEST);
656 }
657
658 /**
659  * pwrdm_read_prev_logic_pwrst - get previous powerdomain logic power state
660  * @pwrdm: struct powerdomain * to get previous logic power state
661  *
662  * Return the powerdomain @pwrdm's previous logic power state.  Returns
663  * -EINVAL if the powerdomain pointer is null or returns the previous
664  * logic power state upon success.
665  */
666 int pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm)
667 {
668         if (!pwrdm)
669                 return -EINVAL;
670
671         /*
672          * The register bit names below may not correspond to the
673          * actual names of the bits in each powerdomain's register,
674          * but the type of value returned is the same for each
675          * powerdomain.
676          */
677         return prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST,
678                                         OMAP3430_LASTLOGICSTATEENTERED);
679 }
680
681 /**
682  * pwrdm_read_mem_pwrst - get current memory bank power state
683  * @pwrdm: struct powerdomain * to get current memory bank power state
684  * @bank: memory bank number (0-3)
685  *
686  * Return the powerdomain @pwrdm's current memory power state for bank
687  * @bank.  Returns -EINVAL if the powerdomain pointer is null, -EEXIST if
688  * the target memory bank does not exist or is not controllable, or
689  * returns the current memory power state upon success.
690  */
691 int pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
692 {
693         u32 m;
694
695         if (!pwrdm)
696                 return -EINVAL;
697
698         if (pwrdm->banks < (bank + 1))
699                 return -EEXIST;
700
701         if (pwrdm->flags & PWRDM_HAS_MPU_QUIRK)
702                 bank = 1;
703
704         /*
705          * The register bit names below may not correspond to the
706          * actual names of the bits in each powerdomain's register,
707          * but the type of value returned is the same for each
708          * powerdomain.
709          */
710         switch (bank) {
711         case 0:
712                 m = OMAP_MEM0_STATEST_MASK;
713                 break;
714         case 1:
715                 m = OMAP_MEM1_STATEST_MASK;
716                 break;
717         case 2:
718                 m = OMAP_MEM2_STATEST_MASK;
719                 break;
720         case 3:
721                 m = OMAP_MEM3_STATEST_MASK;
722                 break;
723         case 4:
724                 m = OMAP_MEM4_STATEST_MASK;
725                 break;
726         default:
727                 WARN_ON(1); /* should never happen */
728                 return -EEXIST;
729         }
730
731         return prm_read_mod_bits_shift(pwrdm->prcm_offs,
732                                          pwrstst_reg_offs, m);
733 }
734
735 /**
736  * pwrdm_read_prev_mem_pwrst - get previous memory bank power state
737  * @pwrdm: struct powerdomain * to get previous memory bank power state
738  * @bank: memory bank number (0-3)
739  *
740  * Return the powerdomain @pwrdm's previous memory power state for
741  * bank @bank.  Returns -EINVAL if the powerdomain pointer is null,
742  * -EEXIST if the target memory bank does not exist or is not
743  * controllable, or returns the previous memory power state upon
744  * success.
745  */
746 int pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
747 {
748         u32 m;
749
750         if (!pwrdm)
751                 return -EINVAL;
752
753         if (pwrdm->banks < (bank + 1))
754                 return -EEXIST;
755
756         if (pwrdm->flags & PWRDM_HAS_MPU_QUIRK)
757                 bank = 1;
758
759         /*
760          * The register bit names below may not correspond to the
761          * actual names of the bits in each powerdomain's register,
762          * but the type of value returned is the same for each
763          * powerdomain.
764          */
765         switch (bank) {
766         case 0:
767                 m = OMAP3430_LASTMEM1STATEENTERED_MASK;
768                 break;
769         case 1:
770                 m = OMAP3430_LASTMEM2STATEENTERED_MASK;
771                 break;
772         case 2:
773                 m = OMAP3430_LASTSHAREDL2CACHEFLATSTATEENTERED_MASK;
774                 break;
775         case 3:
776                 m = OMAP3430_LASTL2FLATMEMSTATEENTERED_MASK;
777                 break;
778         default:
779                 WARN_ON(1); /* should never happen */
780                 return -EEXIST;
781         }
782
783         return prm_read_mod_bits_shift(pwrdm->prcm_offs,
784                                         OMAP3430_PM_PREPWSTST, m);
785 }
786
787 /**
788  * pwrdm_clear_all_prev_pwrst - clear previous powerstate register for a pwrdm
789  * @pwrdm: struct powerdomain * to clear
790  *
791  * Clear the powerdomain's previous power state register @pwrdm.
792  * Clears the entire register, including logic and memory bank
793  * previous power states.  Returns -EINVAL if the powerdomain pointer
794  * is null, or returns 0 upon success.
795  */
796 int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
797 {
798         if (!pwrdm)
799                 return -EINVAL;
800
801         /*
802          * XXX should get the powerdomain's current state here;
803          * warn & fail if it is not ON.
804          */
805
806         pr_debug("powerdomain: clearing previous power state reg for %s\n",
807                  pwrdm->name);
808
809         prm_write_mod_reg(0, pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST);
810
811         return 0;
812 }
813
814 /**
815  * pwrdm_enable_hdwr_sar - enable automatic hardware SAR for a pwrdm
816  * @pwrdm: struct powerdomain *
817  *
818  * Enable automatic context save-and-restore upon power state change
819  * for some devices in the powerdomain @pwrdm.  Warning: this only
820  * affects a subset of devices in a powerdomain; check the TRM
821  * closely.  Returns -EINVAL if the powerdomain pointer is null or if
822  * the powerdomain does not support automatic save-and-restore, or
823  * returns 0 upon success.
824  */
825 int pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm)
826 {
827         if (!pwrdm)
828                 return -EINVAL;
829
830         if (!(pwrdm->flags & PWRDM_HAS_HDWR_SAR))
831                 return -EINVAL;
832
833         pr_debug("powerdomain: %s: setting SAVEANDRESTORE bit\n",
834                  pwrdm->name);
835
836         prm_rmw_mod_reg_bits(0, 1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT,
837                              pwrdm->prcm_offs, pwrstctrl_reg_offs);
838
839         return 0;
840 }
841
842 /**
843  * pwrdm_disable_hdwr_sar - disable automatic hardware SAR for a pwrdm
844  * @pwrdm: struct powerdomain *
845  *
846  * Disable automatic context save-and-restore upon power state change
847  * for some devices in the powerdomain @pwrdm.  Warning: this only
848  * affects a subset of devices in a powerdomain; check the TRM
849  * closely.  Returns -EINVAL if the powerdomain pointer is null or if
850  * the powerdomain does not support automatic save-and-restore, or
851  * returns 0 upon success.
852  */
853 int pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm)
854 {
855         if (!pwrdm)
856                 return -EINVAL;
857
858         if (!(pwrdm->flags & PWRDM_HAS_HDWR_SAR))
859                 return -EINVAL;
860
861         pr_debug("powerdomain: %s: clearing SAVEANDRESTORE bit\n",
862                  pwrdm->name);
863
864         prm_rmw_mod_reg_bits(1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT, 0,
865                              pwrdm->prcm_offs, pwrstctrl_reg_offs);
866
867         return 0;
868 }
869
870 /**
871  * pwrdm_has_hdwr_sar - test whether powerdomain supports hardware SAR
872  * @pwrdm: struct powerdomain *
873  *
874  * Returns 1 if powerdomain @pwrdm supports hardware save-and-restore
875  * for some devices, or 0 if it does not.
876  */
877 bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm)
878 {
879         return (pwrdm && pwrdm->flags & PWRDM_HAS_HDWR_SAR) ? 1 : 0;
880 }
881
882 /**
883  * pwrdm_wait_transition - wait for powerdomain power transition to finish
884  * @pwrdm: struct powerdomain * to wait for
885  *
886  * If the powerdomain @pwrdm is in the process of a state transition,
887  * spin until it completes the power transition, or until an iteration
888  * bailout value is reached. Returns -EINVAL if the powerdomain
889  * pointer is null, -EAGAIN if the bailout value was reached, or
890  * returns 0 upon success.
891  */
892 int pwrdm_wait_transition(struct powerdomain *pwrdm)
893 {
894         u32 c = 0;
895
896         if (!pwrdm)
897                 return -EINVAL;
898
899         /*
900          * REVISIT: pwrdm_wait_transition() may be better implemented
901          * via a callback and a periodic timer check -- how long do we expect
902          * powerdomain transitions to take?
903          */
904
905         /* XXX Is this udelay() value meaningful? */
906         while ((prm_read_mod_reg(pwrdm->prcm_offs, pwrstst_reg_offs) &
907                 OMAP_INTRANSITION) &&
908                (c++ < PWRDM_TRANSITION_BAILOUT))
909                         udelay(1);
910
911         if (c > PWRDM_TRANSITION_BAILOUT) {
912                 printk(KERN_ERR "powerdomain: waited too long for "
913                        "powerdomain %s to complete transition\n", pwrdm->name);
914                 return -EAGAIN;
915         }
916
917         pr_debug("powerdomain: completed transition in %d loops\n", c);
918
919         return 0;
920 }
921
922 int pwrdm_state_switch(struct powerdomain *pwrdm)
923 {
924         return _pwrdm_state_switch(pwrdm, PWRDM_STATE_NOW);
925 }
926
927 int pwrdm_clkdm_state_switch(struct clockdomain *clkdm)
928 {
929         if (clkdm != NULL && clkdm->pwrdm.ptr != NULL) {
930                 pwrdm_wait_transition(clkdm->pwrdm.ptr);
931                 return pwrdm_state_switch(clkdm->pwrdm.ptr);
932         }
933
934         return -EINVAL;
935 }
936
937 int pwrdm_pre_transition(void)
938 {
939         pwrdm_for_each(_pwrdm_pre_transition_cb, NULL);
940         return 0;
941 }
942
943 int pwrdm_post_transition(void)
944 {
945         pwrdm_for_each(_pwrdm_post_transition_cb, NULL);
946         return 0;
947 }
948