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