blob: a2d98718c6d78805871fa8db73ce68e649414d4a [file] [log] [blame]
Paul Walmsleyad67ef62008-08-19 11:08:40 +03001/*
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>
Paul Walmsley8420bb12008-08-19 11:08:44 +030036#include <mach/clockdomain.h>
Paul Walmsleyad67ef62008-08-19 11:08:40 +030037
Peter 'p2' De Schrijverba20bb12008-10-15 17:48:43 +030038enum {
39 PWRDM_STATE_NOW = 0,
40 PWRDM_STATE_PREV,
41};
42
Paul Walmsleyad67ef62008-08-19 11:08:40 +030043/* pwrdm_list contains all registered struct powerdomains */
44static LIST_HEAD(pwrdm_list);
45
46/*
47 * pwrdm_rwlock protects pwrdm_list add and del ops - also reused to
48 * protect pwrdm_clkdms[] during clkdm add/del ops
49 */
50static DEFINE_RWLOCK(pwrdm_rwlock);
51
52
53/* Private functions */
54
55static u32 prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask)
56{
57 u32 v;
58
59 v = prm_read_mod_reg(domain, idx);
60 v &= mask;
61 v >>= __ffs(mask);
62
63 return v;
64}
65
66static struct powerdomain *_pwrdm_lookup(const char *name)
67{
68 struct powerdomain *pwrdm, *temp_pwrdm;
69
70 pwrdm = NULL;
71
72 list_for_each_entry(temp_pwrdm, &pwrdm_list, node) {
73 if (!strcmp(name, temp_pwrdm->name)) {
74 pwrdm = temp_pwrdm;
75 break;
76 }
77 }
78
79 return pwrdm;
80}
81
82/* _pwrdm_deps_lookup - look up the specified powerdomain in a pwrdm list */
83static struct powerdomain *_pwrdm_deps_lookup(struct powerdomain *pwrdm,
84 struct pwrdm_dep *deps)
85{
86 struct pwrdm_dep *pd;
87
88 if (!pwrdm || !deps || !omap_chip_is(pwrdm->omap_chip))
89 return ERR_PTR(-EINVAL);
90
91 for (pd = deps; pd; pd++) {
92
93 if (!omap_chip_is(pd->omap_chip))
94 continue;
95
96 if (!pd->pwrdm && pd->pwrdm_name)
97 pd->pwrdm = pwrdm_lookup(pd->pwrdm_name);
98
99 if (pd->pwrdm == pwrdm)
100 break;
101
102 }
103
104 if (!pd)
105 return ERR_PTR(-ENOENT);
106
107 return pd->pwrdm;
108}
109
Peter 'p2' De Schrijverba20bb12008-10-15 17:48:43 +0300110static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag)
111{
112
113 int prev;
114 int state;
115
116 if (pwrdm == NULL)
117 return -EINVAL;
118
119 state = pwrdm_read_pwrst(pwrdm);
120
121 switch (flag) {
122 case PWRDM_STATE_NOW:
123 prev = pwrdm->state;
124 break;
125 case PWRDM_STATE_PREV:
126 prev = pwrdm_read_prev_pwrst(pwrdm);
127 if (pwrdm->state != prev)
128 pwrdm->state_counter[prev]++;
129 break;
130 default:
131 return -EINVAL;
132 }
133
134 if (state != prev)
135 pwrdm->state_counter[state]++;
136
137 pwrdm->state = state;
138
139 return 0;
140}
141
142static int _pwrdm_pre_transition_cb(struct powerdomain *pwrdm)
143{
144 pwrdm_clear_all_prev_pwrst(pwrdm);
145 _pwrdm_state_switch(pwrdm, PWRDM_STATE_NOW);
146 return 0;
147}
148
149static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm)
150{
151 _pwrdm_state_switch(pwrdm, PWRDM_STATE_PREV);
152 return 0;
153}
154
155static __init void _pwrdm_setup(struct powerdomain *pwrdm)
156{
157 int i;
158
159 for (i = 0; i < 4; i++)
160 pwrdm->state_counter[i] = 0;
161
162 pwrdm_wait_transition(pwrdm);
163 pwrdm->state = pwrdm_read_pwrst(pwrdm);
164 pwrdm->state_counter[pwrdm->state] = 1;
165
166}
Paul Walmsleyad67ef62008-08-19 11:08:40 +0300167
168/* Public functions */
169
170/**
171 * pwrdm_init - set up the powerdomain layer
172 *
173 * Loop through the list of powerdomains, registering all that are
174 * available on the current CPU. If pwrdm_list is supplied and not
175 * null, all of the referenced powerdomains will be registered. No
176 * return value.
177 */
178void pwrdm_init(struct powerdomain **pwrdm_list)
179{
180 struct powerdomain **p = NULL;
181
Peter 'p2' De Schrijverba20bb12008-10-15 17:48:43 +0300182 if (pwrdm_list) {
183 for (p = pwrdm_list; *p; p++) {
Paul Walmsleyad67ef62008-08-19 11:08:40 +0300184 pwrdm_register(*p);
Peter 'p2' De Schrijverba20bb12008-10-15 17:48:43 +0300185 _pwrdm_setup(*p);
186 }
187 }
Paul Walmsleyad67ef62008-08-19 11:08:40 +0300188}
189
190/**
191 * pwrdm_register - register a powerdomain
192 * @pwrdm: struct powerdomain * to register
193 *
194 * Adds a powerdomain to the internal powerdomain list. Returns
195 * -EINVAL if given a null pointer, -EEXIST if a powerdomain is
196 * already registered by the provided name, or 0 upon success.
197 */
198int pwrdm_register(struct powerdomain *pwrdm)
199{
200 unsigned long flags;
201 int ret = -EINVAL;
202
203 if (!pwrdm)
204 return -EINVAL;
205
206 if (!omap_chip_is(pwrdm->omap_chip))
207 return -EINVAL;
208
209 write_lock_irqsave(&pwrdm_rwlock, flags);
210 if (_pwrdm_lookup(pwrdm->name)) {
211 ret = -EEXIST;
212 goto pr_unlock;
213 }
214
215 list_add(&pwrdm->node, &pwrdm_list);
216
217 pr_debug("powerdomain: registered %s\n", pwrdm->name);
218 ret = 0;
219
220pr_unlock:
221 write_unlock_irqrestore(&pwrdm_rwlock, flags);
222
223 return ret;
224}
225
226/**
227 * pwrdm_unregister - unregister a powerdomain
228 * @pwrdm: struct powerdomain * to unregister
229 *
230 * Removes a powerdomain from the internal powerdomain list. Returns
231 * -EINVAL if pwrdm argument is NULL.
232 */
233int pwrdm_unregister(struct powerdomain *pwrdm)
234{
235 unsigned long flags;
236
237 if (!pwrdm)
238 return -EINVAL;
239
240 write_lock_irqsave(&pwrdm_rwlock, flags);
241 list_del(&pwrdm->node);
242 write_unlock_irqrestore(&pwrdm_rwlock, flags);
243
244 pr_debug("powerdomain: unregistered %s\n", pwrdm->name);
245
246 return 0;
247}
248
249/**
250 * pwrdm_lookup - look up a powerdomain by name, return a pointer
251 * @name: name of powerdomain
252 *
253 * Find a registered powerdomain by its name. Returns a pointer to the
254 * struct powerdomain if found, or NULL otherwise.
255 */
256struct powerdomain *pwrdm_lookup(const char *name)
257{
258 struct powerdomain *pwrdm;
259 unsigned long flags;
260
261 if (!name)
262 return NULL;
263
264 read_lock_irqsave(&pwrdm_rwlock, flags);
265 pwrdm = _pwrdm_lookup(name);
266 read_unlock_irqrestore(&pwrdm_rwlock, flags);
267
268 return pwrdm;
269}
270
271/**
272 * pwrdm_for_each - call function on each registered clockdomain
273 * @fn: callback function *
274 *
275 * Call the supplied function for each registered powerdomain. The
276 * callback function can return anything but 0 to bail out early from
277 * the iterator. The callback function is called with the pwrdm_rwlock
278 * held for reading, so no powerdomain structure manipulation
279 * functions should be called from the callback, although hardware
280 * powerdomain control functions are fine. Returns the last return
281 * value of the callback function, which should be 0 for success or
282 * anything else to indicate failure; or -EINVAL if the function
283 * pointer is null.
284 */
285int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm))
286{
287 struct powerdomain *temp_pwrdm;
288 unsigned long flags;
289 int ret = 0;
290
291 if (!fn)
292 return -EINVAL;
293
294 read_lock_irqsave(&pwrdm_rwlock, flags);
295 list_for_each_entry(temp_pwrdm, &pwrdm_list, node) {
296 ret = (*fn)(temp_pwrdm);
297 if (ret)
298 break;
299 }
300 read_unlock_irqrestore(&pwrdm_rwlock, flags);
301
302 return ret;
303}
304
305/**
Paul Walmsley8420bb12008-08-19 11:08:44 +0300306 * pwrdm_add_clkdm - add a clockdomain to a powerdomain
307 * @pwrdm: struct powerdomain * to add the clockdomain to
308 * @clkdm: struct clockdomain * to associate with a powerdomain
309 *
310 * Associate the clockdomain 'clkdm' with a powerdomain 'pwrdm'. This
311 * enables the use of pwrdm_for_each_clkdm(). Returns -EINVAL if
312 * presented with invalid pointers; -ENOMEM if memory could not be allocated;
313 * or 0 upon success.
314 */
315int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)
316{
317 unsigned long flags;
318 int i;
319 int ret = -EINVAL;
320
321 if (!pwrdm || !clkdm)
322 return -EINVAL;
323
324 pr_debug("powerdomain: associating clockdomain %s with powerdomain "
325 "%s\n", clkdm->name, pwrdm->name);
326
327 write_lock_irqsave(&pwrdm_rwlock, flags);
328
329 for (i = 0; i < PWRDM_MAX_CLKDMS; i++) {
330 if (!pwrdm->pwrdm_clkdms[i])
331 break;
332#ifdef DEBUG
333 if (pwrdm->pwrdm_clkdms[i] == clkdm) {
334 ret = -EINVAL;
335 goto pac_exit;
336 }
337#endif
338 }
339
340 if (i == PWRDM_MAX_CLKDMS) {
341 pr_debug("powerdomain: increase PWRDM_MAX_CLKDMS for "
342 "pwrdm %s clkdm %s\n", pwrdm->name, clkdm->name);
343 WARN_ON(1);
344 ret = -ENOMEM;
345 goto pac_exit;
346 }
347
348 pwrdm->pwrdm_clkdms[i] = clkdm;
349
350 ret = 0;
351
352pac_exit:
353 write_unlock_irqrestore(&pwrdm_rwlock, flags);
354
355 return ret;
356}
357
358/**
359 * pwrdm_del_clkdm - remove a clockdomain from a powerdomain
360 * @pwrdm: struct powerdomain * to add the clockdomain to
361 * @clkdm: struct clockdomain * to associate with a powerdomain
362 *
363 * Dissociate the clockdomain 'clkdm' from the powerdomain
364 * 'pwrdm'. Returns -EINVAL if presented with invalid pointers;
365 * -ENOENT if the clkdm was not associated with the powerdomain, or 0
366 * upon success.
367 */
368int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)
369{
370 unsigned long flags;
371 int ret = -EINVAL;
372 int i;
373
374 if (!pwrdm || !clkdm)
375 return -EINVAL;
376
377 pr_debug("powerdomain: dissociating clockdomain %s from powerdomain "
378 "%s\n", clkdm->name, pwrdm->name);
379
380 write_lock_irqsave(&pwrdm_rwlock, flags);
381
382 for (i = 0; i < PWRDM_MAX_CLKDMS; i++)
383 if (pwrdm->pwrdm_clkdms[i] == clkdm)
384 break;
385
386 if (i == PWRDM_MAX_CLKDMS) {
387 pr_debug("powerdomain: clkdm %s not associated with pwrdm "
388 "%s ?!\n", clkdm->name, pwrdm->name);
389 ret = -ENOENT;
390 goto pdc_exit;
391 }
392
393 pwrdm->pwrdm_clkdms[i] = NULL;
394
395 ret = 0;
396
397pdc_exit:
398 write_unlock_irqrestore(&pwrdm_rwlock, flags);
399
400 return ret;
401}
402
403/**
404 * pwrdm_for_each_clkdm - call function on each clkdm in a pwrdm
405 * @pwrdm: struct powerdomain * to iterate over
406 * @fn: callback function *
407 *
408 * Call the supplied function for each clockdomain in the powerdomain
409 * 'pwrdm'. The callback function can return anything but 0 to bail
410 * out early from the iterator. The callback function is called with
411 * the pwrdm_rwlock held for reading, so no powerdomain structure
412 * manipulation functions should be called from the callback, although
413 * hardware powerdomain control functions are fine. Returns -EINVAL
414 * if presented with invalid pointers; or passes along the last return
415 * value of the callback function, which should be 0 for success or
416 * anything else to indicate failure.
417 */
418int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
419 int (*fn)(struct powerdomain *pwrdm,
420 struct clockdomain *clkdm))
421{
422 unsigned long flags;
423 int ret = 0;
424 int i;
425
426 if (!fn)
427 return -EINVAL;
428
429 read_lock_irqsave(&pwrdm_rwlock, flags);
430
431 for (i = 0; i < PWRDM_MAX_CLKDMS && !ret; i++)
432 ret = (*fn)(pwrdm, pwrdm->pwrdm_clkdms[i]);
433
434 read_unlock_irqrestore(&pwrdm_rwlock, flags);
435
436 return ret;
437}
438
439
440/**
Paul Walmsleyad67ef62008-08-19 11:08:40 +0300441 * pwrdm_add_wkdep - add a wakeup dependency from pwrdm2 to pwrdm1
442 * @pwrdm1: wake this struct powerdomain * up (dependent)
443 * @pwrdm2: when this struct powerdomain * wakes up (source)
444 *
445 * When the powerdomain represented by pwrdm2 wakes up (due to an
446 * interrupt), wake up pwrdm1. Implemented in hardware on the OMAP,
447 * this feature is designed to reduce wakeup latency of the dependent
448 * powerdomain. Returns -EINVAL if presented with invalid powerdomain
449 * pointers, -ENOENT if pwrdm2 cannot wake up pwrdm1 in hardware, or
450 * 0 upon success.
451 */
452int pwrdm_add_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
453{
454 struct powerdomain *p;
455
456 if (!pwrdm1)
457 return -EINVAL;
458
459 p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->wkdep_srcs);
460 if (IS_ERR(p)) {
461 pr_debug("powerdomain: hardware cannot set/clear wake up of "
462 "%s when %s wakes up\n", pwrdm1->name, pwrdm2->name);
463 return IS_ERR(p);
464 }
465
466 pr_debug("powerdomain: hardware will wake up %s when %s wakes up\n",
467 pwrdm1->name, pwrdm2->name);
468
469 prm_set_mod_reg_bits((1 << pwrdm2->dep_bit),
470 pwrdm1->prcm_offs, PM_WKDEP);
471
472 return 0;
473}
474
475/**
476 * pwrdm_del_wkdep - remove a wakeup dependency from pwrdm2 to pwrdm1
477 * @pwrdm1: wake this struct powerdomain * up (dependent)
478 * @pwrdm2: when this struct powerdomain * wakes up (source)
479 *
480 * Remove a wakeup dependency that causes pwrdm1 to wake up when pwrdm2
481 * wakes up. Returns -EINVAL if presented with invalid powerdomain
482 * pointers, -ENOENT if pwrdm2 cannot wake up pwrdm1 in hardware, or
483 * 0 upon success.
484 */
485int pwrdm_del_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
486{
487 struct powerdomain *p;
488
489 if (!pwrdm1)
490 return -EINVAL;
491
492 p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->wkdep_srcs);
493 if (IS_ERR(p)) {
494 pr_debug("powerdomain: hardware cannot set/clear wake up of "
495 "%s when %s wakes up\n", pwrdm1->name, pwrdm2->name);
496 return IS_ERR(p);
497 }
498
499 pr_debug("powerdomain: hardware will no longer wake up %s after %s "
500 "wakes up\n", pwrdm1->name, pwrdm2->name);
501
502 prm_clear_mod_reg_bits((1 << pwrdm2->dep_bit),
503 pwrdm1->prcm_offs, PM_WKDEP);
504
505 return 0;
506}
507
508/**
509 * pwrdm_read_wkdep - read wakeup dependency state from pwrdm2 to pwrdm1
510 * @pwrdm1: wake this struct powerdomain * up (dependent)
511 * @pwrdm2: when this struct powerdomain * wakes up (source)
512 *
513 * Return 1 if a hardware wakeup dependency exists wherein pwrdm1 will be
514 * awoken when pwrdm2 wakes up; 0 if dependency is not set; -EINVAL
515 * if either powerdomain pointer is invalid; or -ENOENT if the hardware
516 * is incapable.
517 *
518 * REVISIT: Currently this function only represents software-controllable
519 * wakeup dependencies. Wakeup dependencies fixed in hardware are not
520 * yet handled here.
521 */
522int pwrdm_read_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
523{
524 struct powerdomain *p;
525
526 if (!pwrdm1)
527 return -EINVAL;
528
529 p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->wkdep_srcs);
530 if (IS_ERR(p)) {
531 pr_debug("powerdomain: hardware cannot set/clear wake up of "
532 "%s when %s wakes up\n", pwrdm1->name, pwrdm2->name);
533 return IS_ERR(p);
534 }
535
536 return prm_read_mod_bits_shift(pwrdm1->prcm_offs, PM_WKDEP,
537 (1 << pwrdm2->dep_bit));
538}
539
540/**
541 * pwrdm_add_sleepdep - add a sleep dependency from pwrdm2 to pwrdm1
542 * @pwrdm1: prevent this struct powerdomain * from sleeping (dependent)
543 * @pwrdm2: when this struct powerdomain * is active (source)
544 *
545 * Prevent pwrdm1 from automatically going inactive (and then to
546 * retention or off) if pwrdm2 is still active. Returns -EINVAL if
547 * presented with invalid powerdomain pointers or called on a machine
548 * that does not support software-configurable hardware sleep dependencies,
549 * -ENOENT if the specified dependency cannot be set in hardware, or
550 * 0 upon success.
551 */
552int pwrdm_add_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
553{
554 struct powerdomain *p;
555
556 if (!pwrdm1)
557 return -EINVAL;
558
559 if (!cpu_is_omap34xx())
560 return -EINVAL;
561
562 p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->sleepdep_srcs);
563 if (IS_ERR(p)) {
564 pr_debug("powerdomain: hardware cannot set/clear sleep "
565 "dependency affecting %s from %s\n", pwrdm1->name,
566 pwrdm2->name);
567 return IS_ERR(p);
568 }
569
570 pr_debug("powerdomain: will prevent %s from sleeping if %s is active\n",
571 pwrdm1->name, pwrdm2->name);
572
573 cm_set_mod_reg_bits((1 << pwrdm2->dep_bit),
574 pwrdm1->prcm_offs, OMAP3430_CM_SLEEPDEP);
575
576 return 0;
577}
578
579/**
580 * pwrdm_del_sleepdep - remove a sleep dependency from pwrdm2 to pwrdm1
581 * @pwrdm1: prevent this struct powerdomain * from sleeping (dependent)
582 * @pwrdm2: when this struct powerdomain * is active (source)
583 *
584 * Allow pwrdm1 to automatically go inactive (and then to retention or
585 * off), independent of the activity state of pwrdm2. Returns -EINVAL
586 * if presented with invalid powerdomain pointers or called on a machine
587 * that does not support software-configurable hardware sleep dependencies,
588 * -ENOENT if the specified dependency cannot be cleared in hardware, or
589 * 0 upon success.
590 */
591int pwrdm_del_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
592{
593 struct powerdomain *p;
594
595 if (!pwrdm1)
596 return -EINVAL;
597
598 if (!cpu_is_omap34xx())
599 return -EINVAL;
600
601 p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->sleepdep_srcs);
602 if (IS_ERR(p)) {
603 pr_debug("powerdomain: hardware cannot set/clear sleep "
604 "dependency affecting %s from %s\n", pwrdm1->name,
605 pwrdm2->name);
606 return IS_ERR(p);
607 }
608
609 pr_debug("powerdomain: will no longer prevent %s from sleeping if "
610 "%s is active\n", pwrdm1->name, pwrdm2->name);
611
612 cm_clear_mod_reg_bits((1 << pwrdm2->dep_bit),
613 pwrdm1->prcm_offs, OMAP3430_CM_SLEEPDEP);
614
615 return 0;
616}
617
618/**
619 * pwrdm_read_sleepdep - read sleep dependency state from pwrdm2 to pwrdm1
620 * @pwrdm1: prevent this struct powerdomain * from sleeping (dependent)
621 * @pwrdm2: when this struct powerdomain * is active (source)
622 *
623 * Return 1 if a hardware sleep dependency exists wherein pwrdm1 will
624 * not be allowed to automatically go inactive if pwrdm2 is active;
625 * 0 if pwrdm1's automatic power state inactivity transition is independent
626 * of pwrdm2's; -EINVAL if either powerdomain pointer is invalid or called
627 * on a machine that does not support software-configurable hardware sleep
628 * dependencies; or -ENOENT if the hardware is incapable.
629 *
630 * REVISIT: Currently this function only represents software-controllable
631 * sleep dependencies. Sleep dependencies fixed in hardware are not
632 * yet handled here.
633 */
634int pwrdm_read_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
635{
636 struct powerdomain *p;
637
638 if (!pwrdm1)
639 return -EINVAL;
640
641 if (!cpu_is_omap34xx())
642 return -EINVAL;
643
644 p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->sleepdep_srcs);
645 if (IS_ERR(p)) {
646 pr_debug("powerdomain: hardware cannot set/clear sleep "
647 "dependency affecting %s from %s\n", pwrdm1->name,
648 pwrdm2->name);
649 return IS_ERR(p);
650 }
651
652 return prm_read_mod_bits_shift(pwrdm1->prcm_offs, OMAP3430_CM_SLEEPDEP,
653 (1 << pwrdm2->dep_bit));
654}
655
656/**
657 * pwrdm_get_mem_bank_count - get number of memory banks in this powerdomain
658 * @pwrdm: struct powerdomain *
659 *
660 * Return the number of controllable memory banks in powerdomain pwrdm,
661 * starting with 1. Returns -EINVAL if the powerdomain pointer is null.
662 */
663int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm)
664{
665 if (!pwrdm)
666 return -EINVAL;
667
668 return pwrdm->banks;
669}
670
671/**
672 * pwrdm_set_next_pwrst - set next powerdomain power state
673 * @pwrdm: struct powerdomain * to set
674 * @pwrst: one of the PWRDM_POWER_* macros
675 *
676 * Set the powerdomain pwrdm's next power state to pwrst. The powerdomain
677 * may not enter this state immediately if the preconditions for this state
678 * have not been satisfied. Returns -EINVAL if the powerdomain pointer is
679 * null or if the power state is invalid for the powerdomin, or returns 0
680 * upon success.
681 */
682int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
683{
684 if (!pwrdm)
685 return -EINVAL;
686
687 if (!(pwrdm->pwrsts & (1 << pwrst)))
688 return -EINVAL;
689
690 pr_debug("powerdomain: setting next powerstate for %s to %0x\n",
691 pwrdm->name, pwrst);
692
693 prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
694 (pwrst << OMAP_POWERSTATE_SHIFT),
695 pwrdm->prcm_offs, PM_PWSTCTRL);
696
697 return 0;
698}
699
700/**
701 * pwrdm_read_next_pwrst - get next powerdomain power state
702 * @pwrdm: struct powerdomain * to get power state
703 *
704 * Return the powerdomain pwrdm's next power state. Returns -EINVAL
705 * if the powerdomain pointer is null or returns the next power state
706 * upon success.
707 */
708int pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
709{
710 if (!pwrdm)
711 return -EINVAL;
712
713 return prm_read_mod_bits_shift(pwrdm->prcm_offs, PM_PWSTCTRL,
714 OMAP_POWERSTATE_MASK);
715}
716
717/**
718 * pwrdm_read_pwrst - get current powerdomain power state
719 * @pwrdm: struct powerdomain * to get power state
720 *
721 * Return the powerdomain pwrdm's current power state. Returns -EINVAL
722 * if the powerdomain pointer is null or returns the current power state
723 * upon success.
724 */
725int pwrdm_read_pwrst(struct powerdomain *pwrdm)
726{
727 if (!pwrdm)
728 return -EINVAL;
729
730 return prm_read_mod_bits_shift(pwrdm->prcm_offs, PM_PWSTST,
731 OMAP_POWERSTATEST_MASK);
732}
733
734/**
735 * pwrdm_read_prev_pwrst - get previous powerdomain power state
736 * @pwrdm: struct powerdomain * to get previous power state
737 *
738 * Return the powerdomain pwrdm's previous power state. Returns -EINVAL
739 * if the powerdomain pointer is null or returns the previous power state
740 * upon success.
741 */
742int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
743{
744 if (!pwrdm)
745 return -EINVAL;
746
747 return prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST,
748 OMAP3430_LASTPOWERSTATEENTERED_MASK);
749}
750
751/**
752 * pwrdm_set_logic_retst - set powerdomain logic power state upon retention
753 * @pwrdm: struct powerdomain * to set
754 * @pwrst: one of the PWRDM_POWER_* macros
755 *
756 * Set the next power state that the logic portion of the powerdomain
757 * pwrdm will enter when the powerdomain enters retention. This will
758 * be either RETENTION or OFF, if supported. Returns -EINVAL if the
759 * powerdomain pointer is null or the target power state is not not
760 * supported, or returns 0 upon success.
761 */
762int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
763{
764 if (!pwrdm)
765 return -EINVAL;
766
767 if (!(pwrdm->pwrsts_logic_ret & (1 << pwrst)))
768 return -EINVAL;
769
770 pr_debug("powerdomain: setting next logic powerstate for %s to %0x\n",
771 pwrdm->name, pwrst);
772
773 /*
774 * The register bit names below may not correspond to the
775 * actual names of the bits in each powerdomain's register,
776 * but the type of value returned is the same for each
777 * powerdomain.
778 */
779 prm_rmw_mod_reg_bits(OMAP3430_LOGICL1CACHERETSTATE,
780 (pwrst << __ffs(OMAP3430_LOGICL1CACHERETSTATE)),
781 pwrdm->prcm_offs, PM_PWSTCTRL);
782
783 return 0;
784}
785
786/**
787 * pwrdm_set_mem_onst - set memory power state while powerdomain ON
788 * @pwrdm: struct powerdomain * to set
789 * @bank: memory bank number to set (0-3)
790 * @pwrst: one of the PWRDM_POWER_* macros
791 *
792 * Set the next power state that memory bank x of the powerdomain
793 * pwrdm will enter when the powerdomain enters the ON state. Bank
794 * will be a number from 0 to 3, and represents different types of
795 * memory, depending on the powerdomain. Returns -EINVAL if the
796 * powerdomain pointer is null or the target power state is not not
797 * supported for this memory bank, -EEXIST if the target memory bank
798 * does not exist or is not controllable, or returns 0 upon success.
799 */
800int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
801{
802 u32 m;
803
804 if (!pwrdm)
805 return -EINVAL;
806
807 if (pwrdm->banks < (bank + 1))
808 return -EEXIST;
809
810 if (!(pwrdm->pwrsts_mem_on[bank] & (1 << pwrst)))
811 return -EINVAL;
812
813 pr_debug("powerdomain: setting next memory powerstate for domain %s "
814 "bank %0x while pwrdm-ON to %0x\n", pwrdm->name, bank, pwrst);
815
816 /*
817 * The register bit names below may not correspond to the
818 * actual names of the bits in each powerdomain's register,
819 * but the type of value returned is the same for each
820 * powerdomain.
821 */
822 switch (bank) {
823 case 0:
824 m = OMAP3430_SHAREDL1CACHEFLATONSTATE_MASK;
825 break;
826 case 1:
827 m = OMAP3430_L1FLATMEMONSTATE_MASK;
828 break;
829 case 2:
830 m = OMAP3430_SHAREDL2CACHEFLATONSTATE_MASK;
831 break;
832 case 3:
833 m = OMAP3430_L2FLATMEMONSTATE_MASK;
834 break;
835 default:
836 WARN_ON(1); /* should never happen */
837 return -EEXIST;
838 }
839
840 prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)),
841 pwrdm->prcm_offs, PM_PWSTCTRL);
842
843 return 0;
844}
845
846/**
847 * pwrdm_set_mem_retst - set memory power state while powerdomain in RET
848 * @pwrdm: struct powerdomain * to set
849 * @bank: memory bank number to set (0-3)
850 * @pwrst: one of the PWRDM_POWER_* macros
851 *
852 * Set the next power state that memory bank x of the powerdomain
853 * pwrdm will enter when the powerdomain enters the RETENTION state.
854 * Bank will be a number from 0 to 3, and represents different types
855 * of memory, depending on the powerdomain. pwrst will be either
856 * RETENTION or OFF, if supported. Returns -EINVAL if the powerdomain
857 * pointer is null or the target power state is not not supported for
858 * this memory bank, -EEXIST if the target memory bank does not exist
859 * or is not controllable, or returns 0 upon success.
860 */
861int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
862{
863 u32 m;
864
865 if (!pwrdm)
866 return -EINVAL;
867
868 if (pwrdm->banks < (bank + 1))
869 return -EEXIST;
870
871 if (!(pwrdm->pwrsts_mem_ret[bank] & (1 << pwrst)))
872 return -EINVAL;
873
874 pr_debug("powerdomain: setting next memory powerstate for domain %s "
875 "bank %0x while pwrdm-RET to %0x\n", pwrdm->name, bank, pwrst);
876
877 /*
878 * The register bit names below may not correspond to the
879 * actual names of the bits in each powerdomain's register,
880 * but the type of value returned is the same for each
881 * powerdomain.
882 */
883 switch (bank) {
884 case 0:
885 m = OMAP3430_SHAREDL1CACHEFLATRETSTATE;
886 break;
887 case 1:
888 m = OMAP3430_L1FLATMEMRETSTATE;
889 break;
890 case 2:
891 m = OMAP3430_SHAREDL2CACHEFLATRETSTATE;
892 break;
893 case 3:
894 m = OMAP3430_L2FLATMEMRETSTATE;
895 break;
896 default:
897 WARN_ON(1); /* should never happen */
898 return -EEXIST;
899 }
900
901 prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs,
902 PM_PWSTCTRL);
903
904 return 0;
905}
906
907/**
908 * pwrdm_read_logic_pwrst - get current powerdomain logic retention power state
909 * @pwrdm: struct powerdomain * to get current logic retention power state
910 *
911 * Return the current power state that the logic portion of
912 * powerdomain pwrdm will enter
913 * Returns -EINVAL if the powerdomain pointer is null or returns the
914 * current logic retention power state upon success.
915 */
916int pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
917{
918 if (!pwrdm)
919 return -EINVAL;
920
921 return prm_read_mod_bits_shift(pwrdm->prcm_offs, PM_PWSTST,
922 OMAP3430_LOGICSTATEST);
923}
924
925/**
926 * pwrdm_read_prev_logic_pwrst - get previous powerdomain logic power state
927 * @pwrdm: struct powerdomain * to get previous logic power state
928 *
929 * Return the powerdomain pwrdm's logic power state. Returns -EINVAL
930 * if the powerdomain pointer is null or returns the previous logic
931 * power state upon success.
932 */
933int pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm)
934{
935 if (!pwrdm)
936 return -EINVAL;
937
938 /*
939 * The register bit names below may not correspond to the
940 * actual names of the bits in each powerdomain's register,
941 * but the type of value returned is the same for each
942 * powerdomain.
943 */
944 return prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST,
945 OMAP3430_LASTLOGICSTATEENTERED);
946}
947
948/**
949 * pwrdm_read_mem_pwrst - get current memory bank power state
950 * @pwrdm: struct powerdomain * to get current memory bank power state
951 * @bank: memory bank number (0-3)
952 *
953 * Return the powerdomain pwrdm's current memory power state for bank
954 * x. Returns -EINVAL if the powerdomain pointer is null, -EEXIST if
955 * the target memory bank does not exist or is not controllable, or
956 * returns the current memory power state upon success.
957 */
958int pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
959{
960 u32 m;
961
962 if (!pwrdm)
963 return -EINVAL;
964
965 if (pwrdm->banks < (bank + 1))
966 return -EEXIST;
967
968 /*
969 * The register bit names below may not correspond to the
970 * actual names of the bits in each powerdomain's register,
971 * but the type of value returned is the same for each
972 * powerdomain.
973 */
974 switch (bank) {
975 case 0:
976 m = OMAP3430_SHAREDL1CACHEFLATSTATEST_MASK;
977 break;
978 case 1:
979 m = OMAP3430_L1FLATMEMSTATEST_MASK;
980 break;
981 case 2:
982 m = OMAP3430_SHAREDL2CACHEFLATSTATEST_MASK;
983 break;
984 case 3:
985 m = OMAP3430_L2FLATMEMSTATEST_MASK;
986 break;
987 default:
988 WARN_ON(1); /* should never happen */
989 return -EEXIST;
990 }
991
992 return prm_read_mod_bits_shift(pwrdm->prcm_offs, PM_PWSTST, m);
993}
994
995/**
996 * pwrdm_read_prev_mem_pwrst - get previous memory bank power state
997 * @pwrdm: struct powerdomain * to get previous memory bank power state
998 * @bank: memory bank number (0-3)
999 *
1000 * Return the powerdomain pwrdm's previous memory power state for bank
1001 * x. Returns -EINVAL if the powerdomain pointer is null, -EEXIST if
1002 * the target memory bank does not exist or is not controllable, or
1003 * returns the previous memory power state upon success.
1004 */
1005int pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
1006{
1007 u32 m;
1008
1009 if (!pwrdm)
1010 return -EINVAL;
1011
1012 if (pwrdm->banks < (bank + 1))
1013 return -EEXIST;
1014
1015 /*
1016 * The register bit names below may not correspond to the
1017 * actual names of the bits in each powerdomain's register,
1018 * but the type of value returned is the same for each
1019 * powerdomain.
1020 */
1021 switch (bank) {
1022 case 0:
1023 m = OMAP3430_LASTMEM1STATEENTERED_MASK;
1024 break;
1025 case 1:
1026 m = OMAP3430_LASTMEM2STATEENTERED_MASK;
1027 break;
1028 case 2:
1029 m = OMAP3430_LASTSHAREDL2CACHEFLATSTATEENTERED_MASK;
1030 break;
1031 case 3:
1032 m = OMAP3430_LASTL2FLATMEMSTATEENTERED_MASK;
1033 break;
1034 default:
1035 WARN_ON(1); /* should never happen */
1036 return -EEXIST;
1037 }
1038
1039 return prm_read_mod_bits_shift(pwrdm->prcm_offs,
1040 OMAP3430_PM_PREPWSTST, m);
1041}
1042
1043/**
1044 * pwrdm_clear_all_prev_pwrst - clear previous powerstate register for a pwrdm
1045 * @pwrdm: struct powerdomain * to clear
1046 *
1047 * Clear the powerdomain's previous power state register. Clears the
1048 * entire register, including logic and memory bank previous power states.
1049 * Returns -EINVAL if the powerdomain pointer is null, or returns 0 upon
1050 * success.
1051 */
1052int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
1053{
1054 if (!pwrdm)
1055 return -EINVAL;
1056
1057 /*
1058 * XXX should get the powerdomain's current state here;
1059 * warn & fail if it is not ON.
1060 */
1061
1062 pr_debug("powerdomain: clearing previous power state reg for %s\n",
1063 pwrdm->name);
1064
1065 prm_write_mod_reg(0, pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST);
1066
1067 return 0;
1068}
1069
1070/**
Paul Walmsley0b7cbfb2008-06-25 18:09:37 -06001071 * pwrdm_enable_hdwr_sar - enable automatic hardware SAR for a pwrdm
1072 * @pwrdm: struct powerdomain *
1073 *
1074 * Enable automatic context save-and-restore upon power state change
1075 * for some devices in a powerdomain. Warning: this only affects a
1076 * subset of devices in a powerdomain; check the TRM closely. Returns
1077 * -EINVAL if the powerdomain pointer is null or if the powerdomain
1078 * does not support automatic save-and-restore, or returns 0 upon
1079 * success.
1080 */
1081int pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm)
1082{
1083 if (!pwrdm)
1084 return -EINVAL;
1085
1086 if (!(pwrdm->flags & PWRDM_HAS_HDWR_SAR))
1087 return -EINVAL;
1088
1089 pr_debug("powerdomain: %s: setting SAVEANDRESTORE bit\n",
1090 pwrdm->name);
1091
1092 prm_rmw_mod_reg_bits(0, 1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT,
1093 pwrdm->prcm_offs, PM_PWSTCTRL);
1094
1095 return 0;
1096}
1097
1098/**
1099 * pwrdm_disable_hdwr_sar - disable automatic hardware SAR for a pwrdm
1100 * @pwrdm: struct powerdomain *
1101 *
1102 * Disable automatic context save-and-restore upon power state change
1103 * for some devices in a powerdomain. Warning: this only affects a
1104 * subset of devices in a powerdomain; check the TRM closely. Returns
1105 * -EINVAL if the powerdomain pointer is null or if the powerdomain
1106 * does not support automatic save-and-restore, or returns 0 upon
1107 * success.
1108 */
1109int pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm)
1110{
1111 if (!pwrdm)
1112 return -EINVAL;
1113
1114 if (!(pwrdm->flags & PWRDM_HAS_HDWR_SAR))
1115 return -EINVAL;
1116
1117 pr_debug("powerdomain: %s: clearing SAVEANDRESTORE bit\n",
1118 pwrdm->name);
1119
1120 prm_rmw_mod_reg_bits(1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT, 0,
1121 pwrdm->prcm_offs, PM_PWSTCTRL);
1122
1123 return 0;
1124}
1125
1126/**
1127 * pwrdm_has_hdwr_sar - test whether powerdomain supports hardware SAR
1128 * @pwrdm: struct powerdomain *
1129 *
1130 * Returns 1 if powerdomain 'pwrdm' supports hardware save-and-restore
1131 * for some devices, or 0 if it does not.
1132 */
1133bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm)
1134{
1135 return (pwrdm && pwrdm->flags & PWRDM_HAS_HDWR_SAR) ? 1 : 0;
1136}
1137
1138/**
Paul Walmsleyad67ef62008-08-19 11:08:40 +03001139 * pwrdm_wait_transition - wait for powerdomain power transition to finish
1140 * @pwrdm: struct powerdomain * to wait for
1141 *
1142 * If the powerdomain pwrdm is in the process of a state transition,
1143 * spin until it completes the power transition, or until an iteration
1144 * bailout value is reached. Returns -EINVAL if the powerdomain
1145 * pointer is null, -EAGAIN if the bailout value was reached, or
1146 * returns 0 upon success.
1147 */
1148int pwrdm_wait_transition(struct powerdomain *pwrdm)
1149{
1150 u32 c = 0;
1151
1152 if (!pwrdm)
1153 return -EINVAL;
1154
1155 /*
1156 * REVISIT: pwrdm_wait_transition() may be better implemented
1157 * via a callback and a periodic timer check -- how long do we expect
1158 * powerdomain transitions to take?
1159 */
1160
1161 /* XXX Is this udelay() value meaningful? */
1162 while ((prm_read_mod_reg(pwrdm->prcm_offs, PM_PWSTST) &
1163 OMAP_INTRANSITION) &&
1164 (c++ < PWRDM_TRANSITION_BAILOUT))
1165 udelay(1);
1166
Roel Kluin26870692009-06-19 19:08:30 -06001167 if (c > PWRDM_TRANSITION_BAILOUT) {
Paul Walmsleyad67ef62008-08-19 11:08:40 +03001168 printk(KERN_ERR "powerdomain: waited too long for "
1169 "powerdomain %s to complete transition\n", pwrdm->name);
1170 return -EAGAIN;
1171 }
1172
1173 pr_debug("powerdomain: completed transition in %d loops\n", c);
1174
1175 return 0;
1176}
1177
Peter 'p2' De Schrijverba20bb12008-10-15 17:48:43 +03001178int pwrdm_state_switch(struct powerdomain *pwrdm)
1179{
1180 return _pwrdm_state_switch(pwrdm, PWRDM_STATE_NOW);
1181}
1182
1183int pwrdm_clkdm_state_switch(struct clockdomain *clkdm)
1184{
1185 if (clkdm != NULL && clkdm->pwrdm.ptr != NULL) {
1186 pwrdm_wait_transition(clkdm->pwrdm.ptr);
1187 return pwrdm_state_switch(clkdm->pwrdm.ptr);
1188 }
1189
1190 return -EINVAL;
1191}
1192int pwrdm_clk_state_switch(struct clk *clk)
1193{
1194 if (clk != NULL && clk->clkdm != NULL)
1195 return pwrdm_clkdm_state_switch(clk->clkdm);
1196 return -EINVAL;
1197}
1198
1199int pwrdm_pre_transition(void)
1200{
1201 pwrdm_for_each(_pwrdm_pre_transition_cb);
1202 return 0;
1203}
1204
1205int pwrdm_post_transition(void)
1206{
1207 pwrdm_for_each(_pwrdm_post_transition_cb);
1208 return 0;
1209}
Paul Walmsleyad67ef62008-08-19 11:08:40 +03001210