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