1
2
3
4
5
6
7
8
9
10
11
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#include <mach/clockdomain.h>
37
38
39static LIST_HEAD(pwrdm_list);
40
41
42
43
44
45static DEFINE_RWLOCK(pwrdm_rwlock);
46
47
48
49
50static u32 prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask)
51{
52 u32 v;
53
54 v = prm_read_mod_reg(domain, idx);
55 v &= mask;
56 v >>= __ffs(mask);
57
58 return v;
59}
60
61static struct powerdomain *_pwrdm_lookup(const char *name)
62{
63 struct powerdomain *pwrdm, *temp_pwrdm;
64
65 pwrdm = NULL;
66
67 list_for_each_entry(temp_pwrdm, &pwrdm_list, node) {
68 if (!strcmp(name, temp_pwrdm->name)) {
69 pwrdm = temp_pwrdm;
70 break;
71 }
72 }
73
74 return pwrdm;
75}
76
77
78static struct powerdomain *_pwrdm_deps_lookup(struct powerdomain *pwrdm,
79 struct pwrdm_dep *deps)
80{
81 struct pwrdm_dep *pd;
82
83 if (!pwrdm || !deps || !omap_chip_is(pwrdm->omap_chip))
84 return ERR_PTR(-EINVAL);
85
86 for (pd = deps; pd; pd++) {
87
88 if (!omap_chip_is(pd->omap_chip))
89 continue;
90
91 if (!pd->pwrdm && pd->pwrdm_name)
92 pd->pwrdm = pwrdm_lookup(pd->pwrdm_name);
93
94 if (pd->pwrdm == pwrdm)
95 break;
96
97 }
98
99 if (!pd)
100 return ERR_PTR(-ENOENT);
101
102 return pd->pwrdm;
103}
104
105
106
107
108
109
110
111
112
113
114
115
116void pwrdm_init(struct powerdomain **pwrdm_list)
117{
118 struct powerdomain **p = NULL;
119
120 if (pwrdm_list)
121 for (p = pwrdm_list; *p; p++)
122 pwrdm_register(*p);
123}
124
125
126
127
128
129
130
131
132
133int pwrdm_register(struct powerdomain *pwrdm)
134{
135 unsigned long flags;
136 int ret = -EINVAL;
137
138 if (!pwrdm)
139 return -EINVAL;
140
141 if (!omap_chip_is(pwrdm->omap_chip))
142 return -EINVAL;
143
144 write_lock_irqsave(&pwrdm_rwlock, flags);
145 if (_pwrdm_lookup(pwrdm->name)) {
146 ret = -EEXIST;
147 goto pr_unlock;
148 }
149
150 list_add(&pwrdm->node, &pwrdm_list);
151
152 pr_debug("powerdomain: registered %s\n", pwrdm->name);
153 ret = 0;
154
155pr_unlock:
156 write_unlock_irqrestore(&pwrdm_rwlock, flags);
157
158 return ret;
159}
160
161
162
163
164
165
166
167
168int pwrdm_unregister(struct powerdomain *pwrdm)
169{
170 unsigned long flags;
171
172 if (!pwrdm)
173 return -EINVAL;
174
175 write_lock_irqsave(&pwrdm_rwlock, flags);
176 list_del(&pwrdm->node);
177 write_unlock_irqrestore(&pwrdm_rwlock, flags);
178
179 pr_debug("powerdomain: unregistered %s\n", pwrdm->name);
180
181 return 0;
182}
183
184
185
186
187
188
189
190
191struct powerdomain *pwrdm_lookup(const char *name)
192{
193 struct powerdomain *pwrdm;
194 unsigned long flags;
195
196 if (!name)
197 return NULL;
198
199 read_lock_irqsave(&pwrdm_rwlock, flags);
200 pwrdm = _pwrdm_lookup(name);
201 read_unlock_irqrestore(&pwrdm_rwlock, flags);
202
203 return pwrdm;
204}
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm))
221{
222 struct powerdomain *temp_pwrdm;
223 unsigned long flags;
224 int ret = 0;
225
226 if (!fn)
227 return -EINVAL;
228
229 read_lock_irqsave(&pwrdm_rwlock, flags);
230 list_for_each_entry(temp_pwrdm, &pwrdm_list, node) {
231 ret = (*fn)(temp_pwrdm);
232 if (ret)
233 break;
234 }
235 read_unlock_irqrestore(&pwrdm_rwlock, flags);
236
237 return ret;
238}
239
240
241
242
243
244
245
246
247
248
249
250int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)
251{
252 unsigned long flags;
253 int i;
254 int ret = -EINVAL;
255
256 if (!pwrdm || !clkdm)
257 return -EINVAL;
258
259 pr_debug("powerdomain: associating clockdomain %s with powerdomain "
260 "%s\n", clkdm->name, pwrdm->name);
261
262 write_lock_irqsave(&pwrdm_rwlock, flags);
263
264 for (i = 0; i < PWRDM_MAX_CLKDMS; i++) {
265 if (!pwrdm->pwrdm_clkdms[i])
266 break;
267#ifdef DEBUG
268 if (pwrdm->pwrdm_clkdms[i] == clkdm) {
269 ret = -EINVAL;
270 goto pac_exit;
271 }
272#endif
273 }
274
275 if (i == PWRDM_MAX_CLKDMS) {
276 pr_debug("powerdomain: increase PWRDM_MAX_CLKDMS for "
277 "pwrdm %s clkdm %s\n", pwrdm->name, clkdm->name);
278 WARN_ON(1);
279 ret = -ENOMEM;
280 goto pac_exit;
281 }
282
283 pwrdm->pwrdm_clkdms[i] = clkdm;
284
285 ret = 0;
286
287pac_exit:
288 write_unlock_irqrestore(&pwrdm_rwlock, flags);
289
290 return ret;
291}
292
293
294
295
296
297
298
299
300
301
302
303int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)
304{
305 unsigned long flags;
306 int ret = -EINVAL;
307 int i;
308
309 if (!pwrdm || !clkdm)
310 return -EINVAL;
311
312 pr_debug("powerdomain: dissociating clockdomain %s from powerdomain "
313 "%s\n", clkdm->name, pwrdm->name);
314
315 write_lock_irqsave(&pwrdm_rwlock, flags);
316
317 for (i = 0; i < PWRDM_MAX_CLKDMS; i++)
318 if (pwrdm->pwrdm_clkdms[i] == clkdm)
319 break;
320
321 if (i == PWRDM_MAX_CLKDMS) {
322 pr_debug("powerdomain: clkdm %s not associated with pwrdm "
323 "%s ?!\n", clkdm->name, pwrdm->name);
324 ret = -ENOENT;
325 goto pdc_exit;
326 }
327
328 pwrdm->pwrdm_clkdms[i] = NULL;
329
330 ret = 0;
331
332pdc_exit:
333 write_unlock_irqrestore(&pwrdm_rwlock, flags);
334
335 return ret;
336}
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
354 int (*fn)(struct powerdomain *pwrdm,
355 struct clockdomain *clkdm))
356{
357 unsigned long flags;
358 int ret = 0;
359 int i;
360
361 if (!fn)
362 return -EINVAL;
363
364 read_lock_irqsave(&pwrdm_rwlock, flags);
365
366 for (i = 0; i < PWRDM_MAX_CLKDMS && !ret; i++)
367 ret = (*fn)(pwrdm, pwrdm->pwrdm_clkdms[i]);
368
369 read_unlock_irqrestore(&pwrdm_rwlock, flags);
370
371 return ret;
372}
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387int pwrdm_add_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
388{
389 struct powerdomain *p;
390
391 if (!pwrdm1)
392 return -EINVAL;
393
394 p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->wkdep_srcs);
395 if (IS_ERR(p)) {
396 pr_debug("powerdomain: hardware cannot set/clear wake up of "
397 "%s when %s wakes up\n", pwrdm1->name, pwrdm2->name);
398 return IS_ERR(p);
399 }
400
401 pr_debug("powerdomain: hardware will wake up %s when %s wakes up\n",
402 pwrdm1->name, pwrdm2->name);
403
404 prm_set_mod_reg_bits((1 << pwrdm2->dep_bit),
405 pwrdm1->prcm_offs, PM_WKDEP);
406
407 return 0;
408}
409
410
411
412
413
414
415
416
417
418
419
420int pwrdm_del_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
421{
422 struct powerdomain *p;
423
424 if (!pwrdm1)
425 return -EINVAL;
426
427 p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->wkdep_srcs);
428 if (IS_ERR(p)) {
429 pr_debug("powerdomain: hardware cannot set/clear wake up of "
430 "%s when %s wakes up\n", pwrdm1->name, pwrdm2->name);
431 return IS_ERR(p);
432 }
433
434 pr_debug("powerdomain: hardware will no longer wake up %s after %s "
435 "wakes up\n", pwrdm1->name, pwrdm2->name);
436
437 prm_clear_mod_reg_bits((1 << pwrdm2->dep_bit),
438 pwrdm1->prcm_offs, PM_WKDEP);
439
440 return 0;
441}
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457int pwrdm_read_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
458{
459 struct powerdomain *p;
460
461 if (!pwrdm1)
462 return -EINVAL;
463
464 p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->wkdep_srcs);
465 if (IS_ERR(p)) {
466 pr_debug("powerdomain: hardware cannot set/clear wake up of "
467 "%s when %s wakes up\n", pwrdm1->name, pwrdm2->name);
468 return IS_ERR(p);
469 }
470
471 return prm_read_mod_bits_shift(pwrdm1->prcm_offs, PM_WKDEP,
472 (1 << pwrdm2->dep_bit));
473}
474
475
476
477
478
479
480
481
482
483
484
485
486
487int pwrdm_add_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
488{
489 struct powerdomain *p;
490
491 if (!pwrdm1)
492 return -EINVAL;
493
494 if (!cpu_is_omap34xx())
495 return -EINVAL;
496
497 p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->sleepdep_srcs);
498 if (IS_ERR(p)) {
499 pr_debug("powerdomain: hardware cannot set/clear sleep "
500 "dependency affecting %s from %s\n", pwrdm1->name,
501 pwrdm2->name);
502 return IS_ERR(p);
503 }
504
505 pr_debug("powerdomain: will prevent %s from sleeping if %s is active\n",
506 pwrdm1->name, pwrdm2->name);
507
508 cm_set_mod_reg_bits((1 << pwrdm2->dep_bit),
509 pwrdm1->prcm_offs, OMAP3430_CM_SLEEPDEP);
510
511 return 0;
512}
513
514
515
516
517
518
519
520
521
522
523
524
525
526int pwrdm_del_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
527{
528 struct powerdomain *p;
529
530 if (!pwrdm1)
531 return -EINVAL;
532
533 if (!cpu_is_omap34xx())
534 return -EINVAL;
535
536 p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->sleepdep_srcs);
537 if (IS_ERR(p)) {
538 pr_debug("powerdomain: hardware cannot set/clear sleep "
539 "dependency affecting %s from %s\n", pwrdm1->name,
540 pwrdm2->name);
541 return IS_ERR(p);
542 }
543
544 pr_debug("powerdomain: will no longer prevent %s from sleeping if "
545 "%s is active\n", pwrdm1->name, pwrdm2->name);
546
547 cm_clear_mod_reg_bits((1 << pwrdm2->dep_bit),
548 pwrdm1->prcm_offs, OMAP3430_CM_SLEEPDEP);
549
550 return 0;
551}
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569int pwrdm_read_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
570{
571 struct powerdomain *p;
572
573 if (!pwrdm1)
574 return -EINVAL;
575
576 if (!cpu_is_omap34xx())
577 return -EINVAL;
578
579 p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->sleepdep_srcs);
580 if (IS_ERR(p)) {
581 pr_debug("powerdomain: hardware cannot set/clear sleep "
582 "dependency affecting %s from %s\n", pwrdm1->name,
583 pwrdm2->name);
584 return IS_ERR(p);
585 }
586
587 return prm_read_mod_bits_shift(pwrdm1->prcm_offs, OMAP3430_CM_SLEEPDEP,
588 (1 << pwrdm2->dep_bit));
589}
590
591
592
593
594
595
596
597
598int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm)
599{
600 if (!pwrdm)
601 return -EINVAL;
602
603 return pwrdm->banks;
604}
605
606
607
608
609
610
611
612
613
614
615
616
617int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
618{
619 if (!pwrdm)
620 return -EINVAL;
621
622 if (!(pwrdm->pwrsts & (1 << pwrst)))
623 return -EINVAL;
624
625 pr_debug("powerdomain: setting next powerstate for %s to %0x\n",
626 pwrdm->name, pwrst);
627
628 prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
629 (pwrst << OMAP_POWERSTATE_SHIFT),
630 pwrdm->prcm_offs, PM_PWSTCTRL);
631
632 return 0;
633}
634
635
636
637
638
639
640
641
642
643int pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
644{
645 if (!pwrdm)
646 return -EINVAL;
647
648 return prm_read_mod_bits_shift(pwrdm->prcm_offs, PM_PWSTCTRL,
649 OMAP_POWERSTATE_MASK);
650}
651
652
653
654
655
656
657
658
659
660int pwrdm_read_pwrst(struct powerdomain *pwrdm)
661{
662 if (!pwrdm)
663 return -EINVAL;
664
665 return prm_read_mod_bits_shift(pwrdm->prcm_offs, PM_PWSTST,
666 OMAP_POWERSTATEST_MASK);
667}
668
669
670
671
672
673
674
675
676
677int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
678{
679 if (!pwrdm)
680 return -EINVAL;
681
682 return prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST,
683 OMAP3430_LASTPOWERSTATEENTERED_MASK);
684}
685
686
687
688
689
690
691
692
693
694
695
696
697int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
698{
699 if (!pwrdm)
700 return -EINVAL;
701
702 if (!(pwrdm->pwrsts_logic_ret & (1 << pwrst)))
703 return -EINVAL;
704
705 pr_debug("powerdomain: setting next logic powerstate for %s to %0x\n",
706 pwrdm->name, pwrst);
707
708
709
710
711
712
713
714 prm_rmw_mod_reg_bits(OMAP3430_LOGICL1CACHERETSTATE,
715 (pwrst << __ffs(OMAP3430_LOGICL1CACHERETSTATE)),
716 pwrdm->prcm_offs, PM_PWSTCTRL);
717
718 return 0;
719}
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
736{
737 u32 m;
738
739 if (!pwrdm)
740 return -EINVAL;
741
742 if (pwrdm->banks < (bank + 1))
743 return -EEXIST;
744
745 if (!(pwrdm->pwrsts_mem_on[bank] & (1 << pwrst)))
746 return -EINVAL;
747
748 pr_debug("powerdomain: setting next memory powerstate for domain %s "
749 "bank %0x while pwrdm-ON to %0x\n", pwrdm->name, bank, pwrst);
750
751
752
753
754
755
756
757 switch (bank) {
758 case 0:
759 m = OMAP3430_SHAREDL1CACHEFLATONSTATE_MASK;
760 break;
761 case 1:
762 m = OMAP3430_L1FLATMEMONSTATE_MASK;
763 break;
764 case 2:
765 m = OMAP3430_SHAREDL2CACHEFLATONSTATE_MASK;
766 break;
767 case 3:
768 m = OMAP3430_L2FLATMEMONSTATE_MASK;
769 break;
770 default:
771 WARN_ON(1);
772 return -EEXIST;
773 }
774
775 prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)),
776 pwrdm->prcm_offs, PM_PWSTCTRL);
777
778 return 0;
779}
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
797{
798 u32 m;
799
800 if (!pwrdm)
801 return -EINVAL;
802
803 if (pwrdm->banks < (bank + 1))
804 return -EEXIST;
805
806 if (!(pwrdm->pwrsts_mem_ret[bank] & (1 << pwrst)))
807 return -EINVAL;
808
809 pr_debug("powerdomain: setting next memory powerstate for domain %s "
810 "bank %0x while pwrdm-RET to %0x\n", pwrdm->name, bank, pwrst);
811
812
813
814
815
816
817
818 switch (bank) {
819 case 0:
820 m = OMAP3430_SHAREDL1CACHEFLATRETSTATE;
821 break;
822 case 1:
823 m = OMAP3430_L1FLATMEMRETSTATE;
824 break;
825 case 2:
826 m = OMAP3430_SHAREDL2CACHEFLATRETSTATE;
827 break;
828 case 3:
829 m = OMAP3430_L2FLATMEMRETSTATE;
830 break;
831 default:
832 WARN_ON(1);
833 return -EEXIST;
834 }
835
836 prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs,
837 PM_PWSTCTRL);
838
839 return 0;
840}
841
842
843
844
845
846
847
848
849
850
851int pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
852{
853 if (!pwrdm)
854 return -EINVAL;
855
856 return prm_read_mod_bits_shift(pwrdm->prcm_offs, PM_PWSTST,
857 OMAP3430_LOGICSTATEST);
858}
859
860
861
862
863
864
865
866
867
868int pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm)
869{
870 if (!pwrdm)
871 return -EINVAL;
872
873
874
875
876
877
878
879 return prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST,
880 OMAP3430_LASTLOGICSTATEENTERED);
881}
882
883
884
885
886
887
888
889
890
891
892
893int pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
894{
895 u32 m;
896
897 if (!pwrdm)
898 return -EINVAL;
899
900 if (pwrdm->banks < (bank + 1))
901 return -EEXIST;
902
903
904
905
906
907
908
909 switch (bank) {
910 case 0:
911 m = OMAP3430_SHAREDL1CACHEFLATSTATEST_MASK;
912 break;
913 case 1:
914 m = OMAP3430_L1FLATMEMSTATEST_MASK;
915 break;
916 case 2:
917 m = OMAP3430_SHAREDL2CACHEFLATSTATEST_MASK;
918 break;
919 case 3:
920 m = OMAP3430_L2FLATMEMSTATEST_MASK;
921 break;
922 default:
923 WARN_ON(1);
924 return -EEXIST;
925 }
926
927 return prm_read_mod_bits_shift(pwrdm->prcm_offs, PM_PWSTST, m);
928}
929
930
931
932
933
934
935
936
937
938
939
940int pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
941{
942 u32 m;
943
944 if (!pwrdm)
945 return -EINVAL;
946
947 if (pwrdm->banks < (bank + 1))
948 return -EEXIST;
949
950
951
952
953
954
955
956 switch (bank) {
957 case 0:
958 m = OMAP3430_LASTMEM1STATEENTERED_MASK;
959 break;
960 case 1:
961 m = OMAP3430_LASTMEM2STATEENTERED_MASK;
962 break;
963 case 2:
964 m = OMAP3430_LASTSHAREDL2CACHEFLATSTATEENTERED_MASK;
965 break;
966 case 3:
967 m = OMAP3430_LASTL2FLATMEMSTATEENTERED_MASK;
968 break;
969 default:
970 WARN_ON(1);
971 return -EEXIST;
972 }
973
974 return prm_read_mod_bits_shift(pwrdm->prcm_offs,
975 OMAP3430_PM_PREPWSTST, m);
976}
977
978
979
980
981
982
983
984
985
986
987int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
988{
989 if (!pwrdm)
990 return -EINVAL;
991
992
993
994
995
996
997 pr_debug("powerdomain: clearing previous power state reg for %s\n",
998 pwrdm->name);
999
1000 prm_write_mod_reg(0, pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST);
1001
1002 return 0;
1003}
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016int pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm)
1017{
1018 if (!pwrdm)
1019 return -EINVAL;
1020
1021 if (!(pwrdm->flags & PWRDM_HAS_HDWR_SAR))
1022 return -EINVAL;
1023
1024 pr_debug("powerdomain: %s: setting SAVEANDRESTORE bit\n",
1025 pwrdm->name);
1026
1027 prm_rmw_mod_reg_bits(0, 1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT,
1028 pwrdm->prcm_offs, PM_PWSTCTRL);
1029
1030 return 0;
1031}
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044int pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm)
1045{
1046 if (!pwrdm)
1047 return -EINVAL;
1048
1049 if (!(pwrdm->flags & PWRDM_HAS_HDWR_SAR))
1050 return -EINVAL;
1051
1052 pr_debug("powerdomain: %s: clearing SAVEANDRESTORE bit\n",
1053 pwrdm->name);
1054
1055 prm_rmw_mod_reg_bits(1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT, 0,
1056 pwrdm->prcm_offs, PM_PWSTCTRL);
1057
1058 return 0;
1059}
1060
1061
1062
1063
1064
1065
1066
1067
1068bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm)
1069{
1070 return (pwrdm && pwrdm->flags & PWRDM_HAS_HDWR_SAR) ? 1 : 0;
1071}
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083int pwrdm_wait_transition(struct powerdomain *pwrdm)
1084{
1085 u32 c = 0;
1086
1087 if (!pwrdm)
1088 return -EINVAL;
1089
1090
1091
1092
1093
1094
1095
1096
1097 while ((prm_read_mod_reg(pwrdm->prcm_offs, PM_PWSTST) &
1098 OMAP_INTRANSITION) &&
1099 (c++ < PWRDM_TRANSITION_BAILOUT))
1100 udelay(1);
1101
1102 if (c >= PWRDM_TRANSITION_BAILOUT) {
1103 printk(KERN_ERR "powerdomain: waited too long for "
1104 "powerdomain %s to complete transition\n", pwrdm->name);
1105 return -EAGAIN;
1106 }
1107
1108 pr_debug("powerdomain: completed transition in %d loops\n", c);
1109
1110 return 0;
1111}
1112
1113
1114