]> pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/arm/mach-omap2/powerdomain.c
ARM: OMAP2: Powerdomain: Add OMAP2/3 common powerdomains
[linux-2.6-omap-h63xx.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-2008 Nokia Corporation
6  *
7  * Written by Paul Walmsley
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License version 2 as
11  * published by the Free Software Foundation.
12  */
13 #ifdef CONFIG_OMAP_DEBUG_POWERDOMAIN
14 # define DEBUG
15 #endif
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 "prm.h"
32 #include "prm-regbits-34xx.h"
33
34 #include <mach/cpu.h>
35 #include <mach/powerdomain.h>
36
37 /* pwrdm_list contains all registered struct powerdomains */
38 static LIST_HEAD(pwrdm_list);
39
40 /*
41  * pwrdm_rwlock protects pwrdm_list add and del ops - also reused to
42  * protect pwrdm_clkdms[] during clkdm add/del ops
43  */
44 static DEFINE_RWLOCK(pwrdm_rwlock);
45
46
47 /* Private functions */
48
49 static u32 prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask)
50 {
51         u32 v;
52
53         v = prm_read_mod_reg(domain, idx);
54         v &= mask;
55         v >>= __ffs(mask);
56
57         return v;
58 }
59
60 static struct powerdomain *_pwrdm_lookup(const char *name)
61 {
62         struct powerdomain *pwrdm, *temp_pwrdm;
63
64         pwrdm = NULL;
65
66         list_for_each_entry(temp_pwrdm, &pwrdm_list, node) {
67                 if (!strcmp(name, temp_pwrdm->name)) {
68                         pwrdm = temp_pwrdm;
69                         break;
70                 }
71         }
72
73         return pwrdm;
74 }
75
76 /* _pwrdm_deps_lookup - look up the specified powerdomain in a pwrdm list */
77 static struct powerdomain *_pwrdm_deps_lookup(struct powerdomain *pwrdm,
78                                               struct pwrdm_dep *deps)
79 {
80         struct pwrdm_dep *pd;
81
82         if (!pwrdm || !deps || !omap_chip_is(pwrdm->omap_chip))
83                 return ERR_PTR(-EINVAL);
84
85         for (pd = deps; pd; pd++) {
86
87                 if (!omap_chip_is(pd->omap_chip))
88                         continue;
89
90                 if (!pd->pwrdm && pd->pwrdm_name)
91                         pd->pwrdm = pwrdm_lookup(pd->pwrdm_name);
92
93                 if (pd->pwrdm == pwrdm)
94                         break;
95
96         }
97
98         if (!pd)
99                 return ERR_PTR(-ENOENT);
100
101         return pd->pwrdm;
102 }
103
104
105 /* Public functions */
106
107 /**
108  * pwrdm_init - set up the powerdomain layer
109  *
110  * Loop through the list of powerdomains, registering all that are
111  * available on the current CPU. If pwrdm_list is supplied and not
112  * null, all of the referenced powerdomains will be registered.  No
113  * return value.
114  */
115 void pwrdm_init(struct powerdomain **pwrdm_list)
116 {
117         struct powerdomain **p = NULL;
118
119         if (pwrdm_list)
120                 for (p = pwrdm_list; *p; p++)
121                         pwrdm_register(*p);
122 }
123
124 /**
125  * pwrdm_register - register a powerdomain
126  * @pwrdm: struct powerdomain * to register
127  *
128  * Adds a powerdomain to the internal powerdomain list.  Returns
129  * -EINVAL if given a null pointer, -EEXIST if a powerdomain is
130  * already registered by the provided name, or 0 upon success.
131  */
132 int pwrdm_register(struct powerdomain *pwrdm)
133 {
134         unsigned long flags;
135         int ret = -EINVAL;
136
137         if (!pwrdm)
138                 return -EINVAL;
139
140         if (!omap_chip_is(pwrdm->omap_chip))
141                 return -EINVAL;
142
143         write_lock_irqsave(&pwrdm_rwlock, flags);
144         if (_pwrdm_lookup(pwrdm->name)) {
145                 ret = -EEXIST;
146                 goto pr_unlock;
147         }
148
149         list_add(&pwrdm->node, &pwrdm_list);
150
151         pr_debug("powerdomain: registered %s\n", pwrdm->name);
152         ret = 0;
153
154 pr_unlock:
155         write_unlock_irqrestore(&pwrdm_rwlock, flags);
156
157         return ret;
158 }
159
160 /**
161  * pwrdm_unregister - unregister a powerdomain
162  * @pwrdm: struct powerdomain * to unregister
163  *
164  * Removes a powerdomain from the internal powerdomain list.  Returns
165  * -EINVAL if pwrdm argument is NULL.
166  */
167 int pwrdm_unregister(struct powerdomain *pwrdm)
168 {
169         unsigned long flags;
170
171         if (!pwrdm)
172                 return -EINVAL;
173
174         write_lock_irqsave(&pwrdm_rwlock, flags);
175         list_del(&pwrdm->node);
176         write_unlock_irqrestore(&pwrdm_rwlock, flags);
177
178         pr_debug("powerdomain: unregistered %s\n", pwrdm->name);
179
180         return 0;
181 }
182
183 /**
184  * pwrdm_lookup - look up a powerdomain by name, return a pointer
185  * @name: name of powerdomain
186  *
187  * Find a registered powerdomain by its name.  Returns a pointer to the
188  * struct powerdomain if found, or NULL otherwise.
189  */
190 struct powerdomain *pwrdm_lookup(const char *name)
191 {
192         struct powerdomain *pwrdm;
193         unsigned long flags;
194
195         if (!name)
196                 return NULL;
197
198         read_lock_irqsave(&pwrdm_rwlock, flags);
199         pwrdm = _pwrdm_lookup(name);
200         read_unlock_irqrestore(&pwrdm_rwlock, flags);
201
202         return pwrdm;
203 }
204
205 /**
206  * pwrdm_for_each - call function on each registered clockdomain
207  * @fn: callback function *
208  *
209  * Call the supplied function for each registered powerdomain.  The
210  * callback function can return anything but 0 to bail out early from
211  * the iterator.  The callback function is called with the pwrdm_rwlock
212  * held for reading, so no powerdomain structure manipulation
213  * functions should be called from the callback, although hardware
214  * powerdomain control functions are fine.  Returns the last return
215  * value of the callback function, which should be 0 for success or
216  * anything else to indicate failure; or -EINVAL if the function
217  * pointer is null.
218  */
219 int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm))
220 {
221         struct powerdomain *temp_pwrdm;
222         unsigned long flags;
223         int ret = 0;
224
225         if (!fn)
226                 return -EINVAL;
227
228         read_lock_irqsave(&pwrdm_rwlock, flags);
229         list_for_each_entry(temp_pwrdm, &pwrdm_list, node) {
230                 ret = (*fn)(temp_pwrdm);
231                 if (ret)
232                         break;
233         }
234         read_unlock_irqrestore(&pwrdm_rwlock, flags);
235
236         return ret;
237 }
238
239 /**
240  * pwrdm_add_wkdep - add a wakeup dependency from pwrdm2 to pwrdm1
241  * @pwrdm1: wake this struct powerdomain * up (dependent)
242  * @pwrdm2: when this struct powerdomain * wakes up (source)
243  *
244  * When the powerdomain represented by pwrdm2 wakes up (due to an
245  * interrupt), wake up pwrdm1.  Implemented in hardware on the OMAP,
246  * this feature is designed to reduce wakeup latency of the dependent
247  * powerdomain.  Returns -EINVAL if presented with invalid powerdomain
248  * pointers, -ENOENT if pwrdm2 cannot wake up pwrdm1 in hardware, or
249  * 0 upon success.
250  */
251 int pwrdm_add_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
252 {
253         struct powerdomain *p;
254
255         if (!pwrdm1)
256                 return -EINVAL;
257
258         p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->wkdep_srcs);
259         if (IS_ERR(p)) {
260                 pr_debug("powerdomain: hardware cannot set/clear wake up of "
261                          "%s when %s wakes up\n", pwrdm1->name, pwrdm2->name);
262                 return IS_ERR(p);
263         }
264
265         pr_debug("powerdomain: hardware will wake up %s when %s wakes up\n",
266                  pwrdm1->name, pwrdm2->name);
267
268         prm_set_mod_reg_bits((1 << pwrdm2->dep_bit),
269                              pwrdm1->prcm_offs, PM_WKDEP);
270
271         return 0;
272 }
273
274 /**
275  * pwrdm_del_wkdep - remove a wakeup dependency from pwrdm2 to pwrdm1
276  * @pwrdm1: wake this struct powerdomain * up (dependent)
277  * @pwrdm2: when this struct powerdomain * wakes up (source)
278  *
279  * Remove a wakeup dependency that causes pwrdm1 to wake up when pwrdm2
280  * wakes up.  Returns -EINVAL if presented with invalid powerdomain
281  * pointers, -ENOENT if pwrdm2 cannot wake up pwrdm1 in hardware, or
282  * 0 upon success.
283  */
284 int pwrdm_del_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
285 {
286         struct powerdomain *p;
287
288         if (!pwrdm1)
289                 return -EINVAL;
290
291         p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->wkdep_srcs);
292         if (IS_ERR(p)) {
293                 pr_debug("powerdomain: hardware cannot set/clear wake up of "
294                          "%s when %s wakes up\n", pwrdm1->name, pwrdm2->name);
295                 return IS_ERR(p);
296         }
297
298         pr_debug("powerdomain: hardware will no longer wake up %s after %s "
299                  "wakes up\n", pwrdm1->name, pwrdm2->name);
300
301         prm_clear_mod_reg_bits((1 << pwrdm2->dep_bit),
302                                pwrdm1->prcm_offs, PM_WKDEP);
303
304         return 0;
305 }
306
307 /**
308  * pwrdm_read_wkdep - read wakeup dependency state from pwrdm2 to pwrdm1
309  * @pwrdm1: wake this struct powerdomain * up (dependent)
310  * @pwrdm2: when this struct powerdomain * wakes up (source)
311  *
312  * Return 1 if a hardware wakeup dependency exists wherein pwrdm1 will be
313  * awoken when pwrdm2 wakes up; 0 if dependency is not set; -EINVAL
314  * if either powerdomain pointer is invalid; or -ENOENT if the hardware
315  * is incapable.
316  *
317  * REVISIT: Currently this function only represents software-controllable
318  * wakeup dependencies.  Wakeup dependencies fixed in hardware are not
319  * yet handled here.
320  */
321 int pwrdm_read_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
322 {
323         struct powerdomain *p;
324
325         if (!pwrdm1)
326                 return -EINVAL;
327
328         p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->wkdep_srcs);
329         if (IS_ERR(p)) {
330                 pr_debug("powerdomain: hardware cannot set/clear wake up of "
331                          "%s when %s wakes up\n", pwrdm1->name, pwrdm2->name);
332                 return IS_ERR(p);
333         }
334
335         return prm_read_mod_bits_shift(pwrdm1->prcm_offs, PM_WKDEP,
336                                         (1 << pwrdm2->dep_bit));
337 }
338
339 /**
340  * pwrdm_add_sleepdep - add a sleep dependency from pwrdm2 to pwrdm1
341  * @pwrdm1: prevent this struct powerdomain * from sleeping (dependent)
342  * @pwrdm2: when this struct powerdomain * is active (source)
343  *
344  * Prevent pwrdm1 from automatically going inactive (and then to
345  * retention or off) if pwrdm2 is still active.  Returns -EINVAL if
346  * presented with invalid powerdomain pointers or called on a machine
347  * that does not support software-configurable hardware sleep dependencies,
348  * -ENOENT if the specified dependency cannot be set in hardware, or
349  * 0 upon success.
350  */
351 int pwrdm_add_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
352 {
353         struct powerdomain *p;
354
355         if (!pwrdm1)
356                 return -EINVAL;
357
358         if (!cpu_is_omap34xx())
359                 return -EINVAL;
360
361         p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->sleepdep_srcs);
362         if (IS_ERR(p)) {
363                 pr_debug("powerdomain: hardware cannot set/clear sleep "
364                          "dependency affecting %s from %s\n", pwrdm1->name,
365                          pwrdm2->name);
366                 return IS_ERR(p);
367         }
368
369         pr_debug("powerdomain: will prevent %s from sleeping if %s is active\n",
370                  pwrdm1->name, pwrdm2->name);
371
372         cm_set_mod_reg_bits((1 << pwrdm2->dep_bit),
373                             pwrdm1->prcm_offs, OMAP3430_CM_SLEEPDEP);
374
375         return 0;
376 }
377
378 /**
379  * pwrdm_del_sleepdep - remove a sleep dependency from pwrdm2 to pwrdm1
380  * @pwrdm1: prevent this struct powerdomain * from sleeping (dependent)
381  * @pwrdm2: when this struct powerdomain * is active (source)
382  *
383  * Allow pwrdm1 to automatically go inactive (and then to retention or
384  * off), independent of the activity state of pwrdm2.  Returns -EINVAL
385  * if presented with invalid powerdomain pointers or called on a machine
386  * that does not support software-configurable hardware sleep dependencies,
387  * -ENOENT if the specified dependency cannot be cleared in hardware, or
388  * 0 upon success.
389  */
390 int pwrdm_del_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
391 {
392         struct powerdomain *p;
393
394         if (!pwrdm1)
395                 return -EINVAL;
396
397         if (!cpu_is_omap34xx())
398                 return -EINVAL;
399
400         p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->sleepdep_srcs);
401         if (IS_ERR(p)) {
402                 pr_debug("powerdomain: hardware cannot set/clear sleep "
403                          "dependency affecting %s from %s\n", pwrdm1->name,
404                          pwrdm2->name);
405                 return IS_ERR(p);
406         }
407
408         pr_debug("powerdomain: will no longer prevent %s from sleeping if "
409                  "%s is active\n", pwrdm1->name, pwrdm2->name);
410
411         cm_clear_mod_reg_bits((1 << pwrdm2->dep_bit),
412                               pwrdm1->prcm_offs, OMAP3430_CM_SLEEPDEP);
413
414         return 0;
415 }
416
417 /**
418  * pwrdm_read_sleepdep - read sleep dependency state from pwrdm2 to pwrdm1
419  * @pwrdm1: prevent this struct powerdomain * from sleeping (dependent)
420  * @pwrdm2: when this struct powerdomain * is active (source)
421  *
422  * Return 1 if a hardware sleep dependency exists wherein pwrdm1 will
423  * not be allowed to automatically go inactive if pwrdm2 is active;
424  * 0 if pwrdm1's automatic power state inactivity transition is independent
425  * of pwrdm2's; -EINVAL if either powerdomain pointer is invalid or called
426  * on a machine that does not support software-configurable hardware sleep
427  * dependencies; or -ENOENT if the hardware is incapable.
428  *
429  * REVISIT: Currently this function only represents software-controllable
430  * sleep dependencies.  Sleep dependencies fixed in hardware are not
431  * yet handled here.
432  */
433 int pwrdm_read_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
434 {
435         struct powerdomain *p;
436
437         if (!pwrdm1)
438                 return -EINVAL;
439
440         if (!cpu_is_omap34xx())
441                 return -EINVAL;
442
443         p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->sleepdep_srcs);
444         if (IS_ERR(p)) {
445                 pr_debug("powerdomain: hardware cannot set/clear sleep "
446                          "dependency affecting %s from %s\n", pwrdm1->name,
447                          pwrdm2->name);
448                 return IS_ERR(p);
449         }
450
451         return prm_read_mod_bits_shift(pwrdm1->prcm_offs, OMAP3430_CM_SLEEPDEP,
452                                         (1 << pwrdm2->dep_bit));
453 }
454
455 /**
456  * pwrdm_get_mem_bank_count - get number of memory banks in this powerdomain
457  * @pwrdm: struct powerdomain *
458  *
459  * Return the number of controllable memory banks in powerdomain pwrdm,
460  * starting with 1.  Returns -EINVAL if the powerdomain pointer is null.
461  */
462 int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm)
463 {
464         if (!pwrdm)
465                 return -EINVAL;
466
467         return pwrdm->banks;
468 }
469
470 /**
471  * pwrdm_set_next_pwrst - set next powerdomain power state
472  * @pwrdm: struct powerdomain * to set
473  * @pwrst: one of the PWRDM_POWER_* macros
474  *
475  * Set the powerdomain pwrdm's next power state to pwrst.  The powerdomain
476  * may not enter this state immediately if the preconditions for this state
477  * have not been satisfied.  Returns -EINVAL if the powerdomain pointer is
478  * null or if the power state is invalid for the powerdomin, or returns 0
479  * upon success.
480  */
481 int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
482 {
483         if (!pwrdm)
484                 return -EINVAL;
485
486         if (!(pwrdm->pwrsts & (1 << pwrst)))
487                 return -EINVAL;
488
489         pr_debug("powerdomain: setting next powerstate for %s to %0x\n",
490                  pwrdm->name, pwrst);
491
492         prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
493                              (pwrst << OMAP_POWERSTATE_SHIFT),
494                              pwrdm->prcm_offs, PM_PWSTCTRL);
495
496         return 0;
497 }
498
499 /**
500  * pwrdm_read_next_pwrst - get next powerdomain power state
501  * @pwrdm: struct powerdomain * to get power state
502  *
503  * Return the powerdomain pwrdm's next power state.  Returns -EINVAL
504  * if the powerdomain pointer is null or returns the next power state
505  * upon success.
506  */
507 int pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
508 {
509         if (!pwrdm)
510                 return -EINVAL;
511
512         return prm_read_mod_bits_shift(pwrdm->prcm_offs, PM_PWSTCTRL,
513                                         OMAP_POWERSTATE_MASK);
514 }
515
516 /**
517  * pwrdm_read_pwrst - get current powerdomain power state
518  * @pwrdm: struct powerdomain * to get power state
519  *
520  * Return the powerdomain pwrdm's current power state.  Returns -EINVAL
521  * if the powerdomain pointer is null or returns the current power state
522  * upon success.
523  */
524 int pwrdm_read_pwrst(struct powerdomain *pwrdm)
525 {
526         if (!pwrdm)
527                 return -EINVAL;
528
529         return prm_read_mod_bits_shift(pwrdm->prcm_offs, PM_PWSTST,
530                                         OMAP_POWERSTATEST_MASK);
531 }
532
533 /**
534  * pwrdm_read_prev_pwrst - get previous powerdomain power state
535  * @pwrdm: struct powerdomain * to get previous power state
536  *
537  * Return the powerdomain pwrdm's previous power state.  Returns -EINVAL
538  * if the powerdomain pointer is null or returns the previous power state
539  * upon success.
540  */
541 int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
542 {
543         if (!pwrdm)
544                 return -EINVAL;
545
546         return prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST,
547                                         OMAP3430_LASTPOWERSTATEENTERED_MASK);
548 }
549
550 /**
551  * pwrdm_set_logic_retst - set powerdomain logic power state upon retention
552  * @pwrdm: struct powerdomain * to set
553  * @pwrst: one of the PWRDM_POWER_* macros
554  *
555  * Set the next power state that the logic portion of the powerdomain
556  * pwrdm will enter when the powerdomain enters retention.  This will
557  * be either RETENTION or OFF, if supported.  Returns -EINVAL if the
558  * powerdomain pointer is null or the target power state is not not
559  * supported, or returns 0 upon success.
560  */
561 int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
562 {
563         if (!pwrdm)
564                 return -EINVAL;
565
566         if (!(pwrdm->pwrsts_logic_ret & (1 << pwrst)))
567                 return -EINVAL;
568
569         pr_debug("powerdomain: setting next logic powerstate for %s to %0x\n",
570                  pwrdm->name, pwrst);
571
572         /*
573          * The register bit names below may not correspond to the
574          * actual names of the bits in each powerdomain's register,
575          * but the type of value returned is the same for each
576          * powerdomain.
577          */
578         prm_rmw_mod_reg_bits(OMAP3430_LOGICL1CACHERETSTATE,
579                              (pwrst << __ffs(OMAP3430_LOGICL1CACHERETSTATE)),
580                              pwrdm->prcm_offs, PM_PWSTCTRL);
581
582         return 0;
583 }
584
585 /**
586  * pwrdm_set_mem_onst - set memory power state while powerdomain ON
587  * @pwrdm: struct powerdomain * to set
588  * @bank: memory bank number to set (0-3)
589  * @pwrst: one of the PWRDM_POWER_* macros
590  *
591  * Set the next power state that memory bank x of the powerdomain
592  * pwrdm will enter when the powerdomain enters the ON state.  Bank
593  * will be a number from 0 to 3, and represents different types of
594  * memory, depending on the powerdomain.  Returns -EINVAL if the
595  * powerdomain pointer is null or the target power state is not not
596  * supported for this memory bank, -EEXIST if the target memory bank
597  * does not exist or is not controllable, or returns 0 upon success.
598  */
599 int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
600 {
601         u32 m;
602
603         if (!pwrdm)
604                 return -EINVAL;
605
606         if (pwrdm->banks < (bank + 1))
607                 return -EEXIST;
608
609         if (!(pwrdm->pwrsts_mem_on[bank] & (1 << pwrst)))
610                 return -EINVAL;
611
612         pr_debug("powerdomain: setting next memory powerstate for domain %s "
613                  "bank %0x while pwrdm-ON to %0x\n", pwrdm->name, bank, pwrst);
614
615         /*
616          * The register bit names below may not correspond to the
617          * actual names of the bits in each powerdomain's register,
618          * but the type of value returned is the same for each
619          * powerdomain.
620          */
621         switch (bank) {
622         case 0:
623                 m = OMAP3430_SHAREDL1CACHEFLATONSTATE_MASK;
624                 break;
625         case 1:
626                 m = OMAP3430_L1FLATMEMONSTATE_MASK;
627                 break;
628         case 2:
629                 m = OMAP3430_SHAREDL2CACHEFLATONSTATE_MASK;
630                 break;
631         case 3:
632                 m = OMAP3430_L2FLATMEMONSTATE_MASK;
633                 break;
634         default:
635                 WARN_ON(1); /* should never happen */
636                 return -EEXIST;
637         }
638
639         prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)),
640                              pwrdm->prcm_offs, PM_PWSTCTRL);
641
642         return 0;
643 }
644
645 /**
646  * pwrdm_set_mem_retst - set memory power state while powerdomain in RET
647  * @pwrdm: struct powerdomain * to set
648  * @bank: memory bank number to set (0-3)
649  * @pwrst: one of the PWRDM_POWER_* macros
650  *
651  * Set the next power state that memory bank x of the powerdomain
652  * pwrdm will enter when the powerdomain enters the RETENTION state.
653  * Bank will be a number from 0 to 3, and represents different types
654  * of memory, depending on the powerdomain.  pwrst will be either
655  * RETENTION or OFF, if supported. Returns -EINVAL if the powerdomain
656  * pointer is null or the target power state is not not supported for
657  * this memory bank, -EEXIST if the target memory bank does not exist
658  * or is not controllable, or returns 0 upon success.
659  */
660 int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
661 {
662         u32 m;
663
664         if (!pwrdm)
665                 return -EINVAL;
666
667         if (pwrdm->banks < (bank + 1))
668                 return -EEXIST;
669
670         if (!(pwrdm->pwrsts_mem_ret[bank] & (1 << pwrst)))
671                 return -EINVAL;
672
673         pr_debug("powerdomain: setting next memory powerstate for domain %s "
674                  "bank %0x while pwrdm-RET to %0x\n", pwrdm->name, bank, pwrst);
675
676         /*
677          * The register bit names below may not correspond to the
678          * actual names of the bits in each powerdomain's register,
679          * but the type of value returned is the same for each
680          * powerdomain.
681          */
682         switch (bank) {
683         case 0:
684                 m = OMAP3430_SHAREDL1CACHEFLATRETSTATE;
685                 break;
686         case 1:
687                 m = OMAP3430_L1FLATMEMRETSTATE;
688                 break;
689         case 2:
690                 m = OMAP3430_SHAREDL2CACHEFLATRETSTATE;
691                 break;
692         case 3:
693                 m = OMAP3430_L2FLATMEMRETSTATE;
694                 break;
695         default:
696                 WARN_ON(1); /* should never happen */
697                 return -EEXIST;
698         }
699
700         prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs,
701                              PM_PWSTCTRL);
702
703         return 0;
704 }
705
706 /**
707  * pwrdm_read_logic_pwrst - get current powerdomain logic retention power state
708  * @pwrdm: struct powerdomain * to get current logic retention power state
709  *
710  * Return the current power state that the logic portion of
711  * powerdomain pwrdm will enter
712  * Returns -EINVAL if the powerdomain pointer is null or returns the
713  * current logic retention power state upon success.
714  */
715 int pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
716 {
717         if (!pwrdm)
718                 return -EINVAL;
719
720         return prm_read_mod_bits_shift(pwrdm->prcm_offs, PM_PWSTST,
721                                         OMAP3430_LOGICSTATEST);
722 }
723
724 /**
725  * pwrdm_read_prev_logic_pwrst - get previous powerdomain logic power state
726  * @pwrdm: struct powerdomain * to get previous logic power state
727  *
728  * Return the powerdomain pwrdm's logic power state.  Returns -EINVAL
729  * if the powerdomain pointer is null or returns the previous logic
730  * power state upon success.
731  */
732 int pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm)
733 {
734         if (!pwrdm)
735                 return -EINVAL;
736
737         /*
738          * The register bit names below may not correspond to the
739          * actual names of the bits in each powerdomain's register,
740          * but the type of value returned is the same for each
741          * powerdomain.
742          */
743         return prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST,
744                                         OMAP3430_LASTLOGICSTATEENTERED);
745 }
746
747 /**
748  * pwrdm_read_mem_pwrst - get current memory bank power state
749  * @pwrdm: struct powerdomain * to get current memory bank power state
750  * @bank: memory bank number (0-3)
751  *
752  * Return the powerdomain pwrdm's current memory power state for bank
753  * x.  Returns -EINVAL if the powerdomain pointer is null, -EEXIST if
754  * the target memory bank does not exist or is not controllable, or
755  * returns the current memory power state upon success.
756  */
757 int pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
758 {
759         u32 m;
760
761         if (!pwrdm)
762                 return -EINVAL;
763
764         if (pwrdm->banks < (bank + 1))
765                 return -EEXIST;
766
767         /*
768          * The register bit names below may not correspond to the
769          * actual names of the bits in each powerdomain's register,
770          * but the type of value returned is the same for each
771          * powerdomain.
772          */
773         switch (bank) {
774         case 0:
775                 m = OMAP3430_SHAREDL1CACHEFLATSTATEST_MASK;
776                 break;
777         case 1:
778                 m = OMAP3430_L1FLATMEMSTATEST_MASK;
779                 break;
780         case 2:
781                 m = OMAP3430_SHAREDL2CACHEFLATSTATEST_MASK;
782                 break;
783         case 3:
784                 m = OMAP3430_L2FLATMEMSTATEST_MASK;
785                 break;
786         default:
787                 WARN_ON(1); /* should never happen */
788                 return -EEXIST;
789         }
790
791         return prm_read_mod_bits_shift(pwrdm->prcm_offs, PM_PWSTST, m);
792 }
793
794 /**
795  * pwrdm_read_prev_mem_pwrst - get previous memory bank power state
796  * @pwrdm: struct powerdomain * to get previous memory bank power state
797  * @bank: memory bank number (0-3)
798  *
799  * Return the powerdomain pwrdm's previous memory power state for bank
800  * x.  Returns -EINVAL if the powerdomain pointer is null, -EEXIST if
801  * the target memory bank does not exist or is not controllable, or
802  * returns the previous memory power state upon success.
803  */
804 int pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
805 {
806         u32 m;
807
808         if (!pwrdm)
809                 return -EINVAL;
810
811         if (pwrdm->banks < (bank + 1))
812                 return -EEXIST;
813
814         /*
815          * The register bit names below may not correspond to the
816          * actual names of the bits in each powerdomain's register,
817          * but the type of value returned is the same for each
818          * powerdomain.
819          */
820         switch (bank) {
821         case 0:
822                 m = OMAP3430_LASTMEM1STATEENTERED_MASK;
823                 break;
824         case 1:
825                 m = OMAP3430_LASTMEM2STATEENTERED_MASK;
826                 break;
827         case 2:
828                 m = OMAP3430_LASTSHAREDL2CACHEFLATSTATEENTERED_MASK;
829                 break;
830         case 3:
831                 m = OMAP3430_LASTL2FLATMEMSTATEENTERED_MASK;
832                 break;
833         default:
834                 WARN_ON(1); /* should never happen */
835                 return -EEXIST;
836         }
837
838         return prm_read_mod_bits_shift(pwrdm->prcm_offs,
839                                         OMAP3430_PM_PREPWSTST, m);
840 }
841
842 /**
843  * pwrdm_clear_all_prev_pwrst - clear previous powerstate register for a pwrdm
844  * @pwrdm: struct powerdomain * to clear
845  *
846  * Clear the powerdomain's previous power state register.  Clears the
847  * entire register, including logic and memory bank previous power states.
848  * Returns -EINVAL if the powerdomain pointer is null, or returns 0 upon
849  * success.
850  */
851 int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
852 {
853         if (!pwrdm)
854                 return -EINVAL;
855
856         /*
857          * XXX should get the powerdomain's current state here;
858          * warn & fail if it is not ON.
859          */
860
861         pr_debug("powerdomain: clearing previous power state reg for %s\n",
862                  pwrdm->name);
863
864         prm_write_mod_reg(0, pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST);
865
866         return 0;
867 }
868
869 /**
870  * pwrdm_wait_transition - wait for powerdomain power transition to finish
871  * @pwrdm: struct powerdomain * to wait for
872  *
873  * If the powerdomain pwrdm is in the process of a state transition,
874  * spin until it completes the power transition, or until an iteration
875  * bailout value is reached. Returns -EINVAL if the powerdomain
876  * pointer is null, -EAGAIN if the bailout value was reached, or
877  * returns 0 upon success.
878  */
879 int pwrdm_wait_transition(struct powerdomain *pwrdm)
880 {
881         u32 c = 0;
882
883         if (!pwrdm)
884                 return -EINVAL;
885
886         /*
887          * REVISIT: pwrdm_wait_transition() may be better implemented
888          * via a callback and a periodic timer check -- how long do we expect
889          * powerdomain transitions to take?
890          */
891
892         /* XXX Is this udelay() value meaningful? */
893         while ((prm_read_mod_reg(pwrdm->prcm_offs, PM_PWSTST) &
894                 OMAP_INTRANSITION) &&
895                (c++ < PWRDM_TRANSITION_BAILOUT))
896                 udelay(1);
897
898         if (c >= PWRDM_TRANSITION_BAILOUT) {
899                 printk(KERN_ERR "powerdomain: waited too long for "
900                        "powerdomain %s to complete transition\n", pwrdm->name);
901                 return -EAGAIN;
902         }
903
904         pr_debug("powerdomain: completed transition in %d loops\n", c);
905
906         return 0;
907 }
908
909