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