diff options
Diffstat (limited to 'arch/arm/mach-omap2/powerdomain.c')
-rw-r--r-- | arch/arm/mach-omap2/powerdomain.c | 441 |
1 files changed, 152 insertions, 289 deletions
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c index 6527ec30dc17..eaed0df16699 100644 --- a/arch/arm/mach-omap2/powerdomain.c +++ b/arch/arm/mach-omap2/powerdomain.c | |||
@@ -15,27 +15,19 @@ | |||
15 | #undef DEBUG | 15 | #undef DEBUG |
16 | 16 | ||
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <linux/module.h> | ||
19 | #include <linux/types.h> | 18 | #include <linux/types.h> |
20 | #include <linux/delay.h> | ||
21 | #include <linux/spinlock.h> | ||
22 | #include <linux/list.h> | 19 | #include <linux/list.h> |
23 | #include <linux/errno.h> | 20 | #include <linux/errno.h> |
24 | #include <linux/err.h> | 21 | #include <linux/string.h> |
25 | #include <linux/io.h> | 22 | #include "cm2xxx_3xxx.h" |
26 | 23 | #include "prcm44xx.h" | |
27 | #include <asm/atomic.h> | 24 | #include "cm44xx.h" |
28 | 25 | #include "prm2xxx_3xxx.h" | |
29 | #include "cm.h" | 26 | #include "prm44xx.h" |
30 | #include "cm-regbits-34xx.h" | ||
31 | #include "cm-regbits-44xx.h" | ||
32 | #include "prm.h" | ||
33 | #include "prm-regbits-34xx.h" | ||
34 | #include "prm-regbits-44xx.h" | ||
35 | 27 | ||
36 | #include <plat/cpu.h> | 28 | #include <plat/cpu.h> |
37 | #include <plat/powerdomain.h> | 29 | #include "powerdomain.h" |
38 | #include <plat/clockdomain.h> | 30 | #include "clockdomain.h" |
39 | #include <plat/prcm.h> | 31 | #include <plat/prcm.h> |
40 | 32 | ||
41 | #include "pm.h" | 33 | #include "pm.h" |
@@ -45,41 +37,12 @@ enum { | |||
45 | PWRDM_STATE_PREV, | 37 | PWRDM_STATE_PREV, |
46 | }; | 38 | }; |
47 | 39 | ||
48 | /* Variable holding value of the CPU dependent PWRSTCTRL Register Offset */ | ||
49 | static u16 pwrstctrl_reg_offs; | ||
50 | |||
51 | /* Variable holding value of the CPU dependent PWRSTST Register Offset */ | ||
52 | static u16 pwrstst_reg_offs; | ||
53 | |||
54 | /* OMAP3 and OMAP4 specific register bit initialisations | ||
55 | * Notice that the names here are not according to each power | ||
56 | * domain but the bit mapping used applies to all of them | ||
57 | */ | ||
58 | |||
59 | /* OMAP3 and OMAP4 Memory Onstate Masks (common across all power domains) */ | ||
60 | #define OMAP_MEM0_ONSTATE_MASK OMAP3430_SHAREDL1CACHEFLATONSTATE_MASK | ||
61 | #define OMAP_MEM1_ONSTATE_MASK OMAP3430_L1FLATMEMONSTATE_MASK | ||
62 | #define OMAP_MEM2_ONSTATE_MASK OMAP3430_SHAREDL2CACHEFLATONSTATE_MASK | ||
63 | #define OMAP_MEM3_ONSTATE_MASK OMAP3430_L2FLATMEMONSTATE_MASK | ||
64 | #define OMAP_MEM4_ONSTATE_MASK OMAP4430_OCP_NRET_BANK_ONSTATE_MASK | ||
65 | |||
66 | /* OMAP3 and OMAP4 Memory Retstate Masks (common across all power domains) */ | ||
67 | #define OMAP_MEM0_RETSTATE_MASK OMAP3430_SHAREDL1CACHEFLATRETSTATE_MASK | ||
68 | #define OMAP_MEM1_RETSTATE_MASK OMAP3430_L1FLATMEMRETSTATE_MASK | ||
69 | #define OMAP_MEM2_RETSTATE_MASK OMAP3430_SHAREDL2CACHEFLATRETSTATE_MASK | ||
70 | #define OMAP_MEM3_RETSTATE_MASK OMAP3430_L2FLATMEMRETSTATE_MASK | ||
71 | #define OMAP_MEM4_RETSTATE_MASK OMAP4430_OCP_NRET_BANK_RETSTATE_MASK | ||
72 | |||
73 | /* OMAP3 and OMAP4 Memory Status bits */ | ||
74 | #define OMAP_MEM0_STATEST_MASK OMAP3430_SHAREDL1CACHEFLATSTATEST_MASK | ||
75 | #define OMAP_MEM1_STATEST_MASK OMAP3430_L1FLATMEMSTATEST_MASK | ||
76 | #define OMAP_MEM2_STATEST_MASK OMAP3430_SHAREDL2CACHEFLATSTATEST_MASK | ||
77 | #define OMAP_MEM3_STATEST_MASK OMAP3430_L2FLATMEMSTATEST_MASK | ||
78 | #define OMAP_MEM4_STATEST_MASK OMAP4430_OCP_NRET_BANK_STATEST_MASK | ||
79 | 40 | ||
80 | /* pwrdm_list contains all registered struct powerdomains */ | 41 | /* pwrdm_list contains all registered struct powerdomains */ |
81 | static LIST_HEAD(pwrdm_list); | 42 | static LIST_HEAD(pwrdm_list); |
82 | 43 | ||
44 | static struct pwrdm_ops *arch_pwrdm; | ||
45 | |||
83 | /* Private functions */ | 46 | /* Private functions */ |
84 | 47 | ||
85 | static struct powerdomain *_pwrdm_lookup(const char *name) | 48 | static struct powerdomain *_pwrdm_lookup(const char *name) |
@@ -110,12 +73,19 @@ static int _pwrdm_register(struct powerdomain *pwrdm) | |||
110 | { | 73 | { |
111 | int i; | 74 | int i; |
112 | 75 | ||
113 | if (!pwrdm) | 76 | if (!pwrdm || !pwrdm->name) |
114 | return -EINVAL; | 77 | return -EINVAL; |
115 | 78 | ||
116 | if (!omap_chip_is(pwrdm->omap_chip)) | 79 | if (!omap_chip_is(pwrdm->omap_chip)) |
117 | return -EINVAL; | 80 | return -EINVAL; |
118 | 81 | ||
82 | if (cpu_is_omap44xx() && | ||
83 | pwrdm->prcm_partition == OMAP4430_INVALID_PRCM_PARTITION) { | ||
84 | pr_err("powerdomain: %s: missing OMAP4 PRCM partition ID\n", | ||
85 | pwrdm->name); | ||
86 | return -EINVAL; | ||
87 | } | ||
88 | |||
119 | if (_pwrdm_lookup(pwrdm->name)) | 89 | if (_pwrdm_lookup(pwrdm->name)) |
120 | return -EEXIST; | 90 | return -EEXIST; |
121 | 91 | ||
@@ -211,6 +181,7 @@ static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm, void *unused) | |||
211 | /** | 181 | /** |
212 | * pwrdm_init - set up the powerdomain layer | 182 | * pwrdm_init - set up the powerdomain layer |
213 | * @pwrdm_list: array of struct powerdomain pointers to register | 183 | * @pwrdm_list: array of struct powerdomain pointers to register |
184 | * @custom_funcs: func pointers for arch specfic implementations | ||
214 | * | 185 | * |
215 | * Loop through the array of powerdomains @pwrdm_list, registering all | 186 | * Loop through the array of powerdomains @pwrdm_list, registering all |
216 | * that are available on the current CPU. If pwrdm_list is supplied | 187 | * that are available on the current CPU. If pwrdm_list is supplied |
@@ -218,21 +189,14 @@ static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm, void *unused) | |||
218 | * registered. No return value. XXX pwrdm_list is not really a | 189 | * registered. No return value. XXX pwrdm_list is not really a |
219 | * "list"; it is an array. Rename appropriately. | 190 | * "list"; it is an array. Rename appropriately. |
220 | */ | 191 | */ |
221 | void pwrdm_init(struct powerdomain **pwrdm_list) | 192 | void pwrdm_init(struct powerdomain **pwrdm_list, struct pwrdm_ops *custom_funcs) |
222 | { | 193 | { |
223 | struct powerdomain **p = NULL; | 194 | struct powerdomain **p = NULL; |
224 | 195 | ||
225 | if (cpu_is_omap24xx() || cpu_is_omap34xx()) { | 196 | if (!custom_funcs) |
226 | pwrstctrl_reg_offs = OMAP2_PM_PWSTCTRL; | 197 | WARN(1, "powerdomain: No custom pwrdm functions registered\n"); |
227 | pwrstst_reg_offs = OMAP2_PM_PWSTST; | 198 | else |
228 | } else if (cpu_is_omap44xx()) { | 199 | arch_pwrdm = custom_funcs; |
229 | pwrstctrl_reg_offs = OMAP4_PM_PWSTCTRL; | ||
230 | pwrstst_reg_offs = OMAP4_PM_PWSTST; | ||
231 | } else { | ||
232 | printk(KERN_ERR "Power Domain struct not supported for " \ | ||
233 | "this CPU\n"); | ||
234 | return; | ||
235 | } | ||
236 | 200 | ||
237 | if (pwrdm_list) { | 201 | if (pwrdm_list) { |
238 | for (p = pwrdm_list; *p; p++) | 202 | for (p = pwrdm_list; *p; p++) |
@@ -431,6 +395,8 @@ int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm) | |||
431 | */ | 395 | */ |
432 | int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst) | 396 | int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst) |
433 | { | 397 | { |
398 | int ret = -EINVAL; | ||
399 | |||
434 | if (!pwrdm) | 400 | if (!pwrdm) |
435 | return -EINVAL; | 401 | return -EINVAL; |
436 | 402 | ||
@@ -440,11 +406,10 @@ int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst) | |||
440 | pr_debug("powerdomain: setting next powerstate for %s to %0x\n", | 406 | pr_debug("powerdomain: setting next powerstate for %s to %0x\n", |
441 | pwrdm->name, pwrst); | 407 | pwrdm->name, pwrst); |
442 | 408 | ||
443 | prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK, | 409 | if (arch_pwrdm && arch_pwrdm->pwrdm_set_next_pwrst) |
444 | (pwrst << OMAP_POWERSTATE_SHIFT), | 410 | ret = arch_pwrdm->pwrdm_set_next_pwrst(pwrdm, pwrst); |
445 | pwrdm->prcm_offs, pwrstctrl_reg_offs); | ||
446 | 411 | ||
447 | return 0; | 412 | return ret; |
448 | } | 413 | } |
449 | 414 | ||
450 | /** | 415 | /** |
@@ -457,11 +422,15 @@ int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst) | |||
457 | */ | 422 | */ |
458 | int pwrdm_read_next_pwrst(struct powerdomain *pwrdm) | 423 | int pwrdm_read_next_pwrst(struct powerdomain *pwrdm) |
459 | { | 424 | { |
425 | int ret = -EINVAL; | ||
426 | |||
460 | if (!pwrdm) | 427 | if (!pwrdm) |
461 | return -EINVAL; | 428 | return -EINVAL; |
462 | 429 | ||
463 | return prm_read_mod_bits_shift(pwrdm->prcm_offs, | 430 | if (arch_pwrdm && arch_pwrdm->pwrdm_read_next_pwrst) |
464 | pwrstctrl_reg_offs, OMAP_POWERSTATE_MASK); | 431 | ret = arch_pwrdm->pwrdm_read_next_pwrst(pwrdm); |
432 | |||
433 | return ret; | ||
465 | } | 434 | } |
466 | 435 | ||
467 | /** | 436 | /** |
@@ -474,11 +443,15 @@ int pwrdm_read_next_pwrst(struct powerdomain *pwrdm) | |||
474 | */ | 443 | */ |
475 | int pwrdm_read_pwrst(struct powerdomain *pwrdm) | 444 | int pwrdm_read_pwrst(struct powerdomain *pwrdm) |
476 | { | 445 | { |
446 | int ret = -EINVAL; | ||
447 | |||
477 | if (!pwrdm) | 448 | if (!pwrdm) |
478 | return -EINVAL; | 449 | return -EINVAL; |
479 | 450 | ||
480 | return prm_read_mod_bits_shift(pwrdm->prcm_offs, | 451 | if (arch_pwrdm && arch_pwrdm->pwrdm_read_pwrst) |
481 | pwrstst_reg_offs, OMAP_POWERSTATEST_MASK); | 452 | ret = arch_pwrdm->pwrdm_read_pwrst(pwrdm); |
453 | |||
454 | return ret; | ||
482 | } | 455 | } |
483 | 456 | ||
484 | /** | 457 | /** |
@@ -491,11 +464,15 @@ int pwrdm_read_pwrst(struct powerdomain *pwrdm) | |||
491 | */ | 464 | */ |
492 | int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm) | 465 | int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm) |
493 | { | 466 | { |
467 | int ret = -EINVAL; | ||
468 | |||
494 | if (!pwrdm) | 469 | if (!pwrdm) |
495 | return -EINVAL; | 470 | return -EINVAL; |
496 | 471 | ||
497 | return prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST, | 472 | if (arch_pwrdm && arch_pwrdm->pwrdm_read_prev_pwrst) |
498 | OMAP3430_LASTPOWERSTATEENTERED_MASK); | 473 | ret = arch_pwrdm->pwrdm_read_prev_pwrst(pwrdm); |
474 | |||
475 | return ret; | ||
499 | } | 476 | } |
500 | 477 | ||
501 | /** | 478 | /** |
@@ -511,7 +488,7 @@ int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm) | |||
511 | */ | 488 | */ |
512 | int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst) | 489 | int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst) |
513 | { | 490 | { |
514 | u32 v; | 491 | int ret = -EINVAL; |
515 | 492 | ||
516 | if (!pwrdm) | 493 | if (!pwrdm) |
517 | return -EINVAL; | 494 | return -EINVAL; |
@@ -522,17 +499,10 @@ int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst) | |||
522 | pr_debug("powerdomain: setting next logic powerstate for %s to %0x\n", | 499 | pr_debug("powerdomain: setting next logic powerstate for %s to %0x\n", |
523 | pwrdm->name, pwrst); | 500 | pwrdm->name, pwrst); |
524 | 501 | ||
525 | /* | 502 | if (arch_pwrdm && arch_pwrdm->pwrdm_set_logic_retst) |
526 | * The register bit names below may not correspond to the | 503 | ret = arch_pwrdm->pwrdm_set_logic_retst(pwrdm, pwrst); |
527 | * actual names of the bits in each powerdomain's register, | ||
528 | * but the type of value returned is the same for each | ||
529 | * powerdomain. | ||
530 | */ | ||
531 | v = pwrst << __ffs(OMAP3430_LOGICL1CACHERETSTATE_MASK); | ||
532 | prm_rmw_mod_reg_bits(OMAP3430_LOGICL1CACHERETSTATE_MASK, v, | ||
533 | pwrdm->prcm_offs, pwrstctrl_reg_offs); | ||
534 | 504 | ||
535 | return 0; | 505 | return ret; |
536 | } | 506 | } |
537 | 507 | ||
538 | /** | 508 | /** |
@@ -552,7 +522,7 @@ int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst) | |||
552 | */ | 522 | */ |
553 | int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst) | 523 | int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst) |
554 | { | 524 | { |
555 | u32 m; | 525 | int ret = -EINVAL; |
556 | 526 | ||
557 | if (!pwrdm) | 527 | if (!pwrdm) |
558 | return -EINVAL; | 528 | return -EINVAL; |
@@ -566,37 +536,10 @@ int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst) | |||
566 | pr_debug("powerdomain: setting next memory powerstate for domain %s " | 536 | pr_debug("powerdomain: setting next memory powerstate for domain %s " |
567 | "bank %0x while pwrdm-ON to %0x\n", pwrdm->name, bank, pwrst); | 537 | "bank %0x while pwrdm-ON to %0x\n", pwrdm->name, bank, pwrst); |
568 | 538 | ||
569 | /* | 539 | if (arch_pwrdm && arch_pwrdm->pwrdm_set_mem_onst) |
570 | * The register bit names below may not correspond to the | 540 | ret = arch_pwrdm->pwrdm_set_mem_onst(pwrdm, bank, pwrst); |
571 | * actual names of the bits in each powerdomain's register, | ||
572 | * but the type of value returned is the same for each | ||
573 | * powerdomain. | ||
574 | */ | ||
575 | switch (bank) { | ||
576 | case 0: | ||
577 | m = OMAP_MEM0_ONSTATE_MASK; | ||
578 | break; | ||
579 | case 1: | ||
580 | m = OMAP_MEM1_ONSTATE_MASK; | ||
581 | break; | ||
582 | case 2: | ||
583 | m = OMAP_MEM2_ONSTATE_MASK; | ||
584 | break; | ||
585 | case 3: | ||
586 | m = OMAP_MEM3_ONSTATE_MASK; | ||
587 | break; | ||
588 | case 4: | ||
589 | m = OMAP_MEM4_ONSTATE_MASK; | ||
590 | break; | ||
591 | default: | ||
592 | WARN_ON(1); /* should never happen */ | ||
593 | return -EEXIST; | ||
594 | } | ||
595 | 541 | ||
596 | prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), | 542 | return ret; |
597 | pwrdm->prcm_offs, pwrstctrl_reg_offs); | ||
598 | |||
599 | return 0; | ||
600 | } | 543 | } |
601 | 544 | ||
602 | /** | 545 | /** |
@@ -617,7 +560,7 @@ int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst) | |||
617 | */ | 560 | */ |
618 | int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst) | 561 | int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst) |
619 | { | 562 | { |
620 | u32 m; | 563 | int ret = -EINVAL; |
621 | 564 | ||
622 | if (!pwrdm) | 565 | if (!pwrdm) |
623 | return -EINVAL; | 566 | return -EINVAL; |
@@ -631,37 +574,10 @@ int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst) | |||
631 | pr_debug("powerdomain: setting next memory powerstate for domain %s " | 574 | pr_debug("powerdomain: setting next memory powerstate for domain %s " |
632 | "bank %0x while pwrdm-RET to %0x\n", pwrdm->name, bank, pwrst); | 575 | "bank %0x while pwrdm-RET to %0x\n", pwrdm->name, bank, pwrst); |
633 | 576 | ||
634 | /* | 577 | if (arch_pwrdm && arch_pwrdm->pwrdm_set_mem_retst) |
635 | * The register bit names below may not correspond to the | 578 | ret = arch_pwrdm->pwrdm_set_mem_retst(pwrdm, bank, pwrst); |
636 | * actual names of the bits in each powerdomain's register, | ||
637 | * but the type of value returned is the same for each | ||
638 | * powerdomain. | ||
639 | */ | ||
640 | switch (bank) { | ||
641 | case 0: | ||
642 | m = OMAP_MEM0_RETSTATE_MASK; | ||
643 | break; | ||
644 | case 1: | ||
645 | m = OMAP_MEM1_RETSTATE_MASK; | ||
646 | break; | ||
647 | case 2: | ||
648 | m = OMAP_MEM2_RETSTATE_MASK; | ||
649 | break; | ||
650 | case 3: | ||
651 | m = OMAP_MEM3_RETSTATE_MASK; | ||
652 | break; | ||
653 | case 4: | ||
654 | m = OMAP_MEM4_RETSTATE_MASK; | ||
655 | break; | ||
656 | default: | ||
657 | WARN_ON(1); /* should never happen */ | ||
658 | return -EEXIST; | ||
659 | } | ||
660 | |||
661 | prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs, | ||
662 | pwrstctrl_reg_offs); | ||
663 | 579 | ||
664 | return 0; | 580 | return ret; |
665 | } | 581 | } |
666 | 582 | ||
667 | /** | 583 | /** |
@@ -675,11 +591,15 @@ int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst) | |||
675 | */ | 591 | */ |
676 | int pwrdm_read_logic_pwrst(struct powerdomain *pwrdm) | 592 | int pwrdm_read_logic_pwrst(struct powerdomain *pwrdm) |
677 | { | 593 | { |
594 | int ret = -EINVAL; | ||
595 | |||
678 | if (!pwrdm) | 596 | if (!pwrdm) |
679 | return -EINVAL; | 597 | return -EINVAL; |
680 | 598 | ||
681 | return prm_read_mod_bits_shift(pwrdm->prcm_offs, pwrstst_reg_offs, | 599 | if (arch_pwrdm && arch_pwrdm->pwrdm_read_logic_pwrst) |
682 | OMAP3430_LOGICSTATEST_MASK); | 600 | ret = arch_pwrdm->pwrdm_read_logic_pwrst(pwrdm); |
601 | |||
602 | return ret; | ||
683 | } | 603 | } |
684 | 604 | ||
685 | /** | 605 | /** |
@@ -692,17 +612,15 @@ int pwrdm_read_logic_pwrst(struct powerdomain *pwrdm) | |||
692 | */ | 612 | */ |
693 | int pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm) | 613 | int pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm) |
694 | { | 614 | { |
615 | int ret = -EINVAL; | ||
616 | |||
695 | if (!pwrdm) | 617 | if (!pwrdm) |
696 | return -EINVAL; | 618 | return -EINVAL; |
697 | 619 | ||
698 | /* | 620 | if (arch_pwrdm && arch_pwrdm->pwrdm_read_prev_logic_pwrst) |
699 | * The register bit names below may not correspond to the | 621 | ret = arch_pwrdm->pwrdm_read_prev_logic_pwrst(pwrdm); |
700 | * actual names of the bits in each powerdomain's register, | 622 | |
701 | * but the type of value returned is the same for each | 623 | return ret; |
702 | * powerdomain. | ||
703 | */ | ||
704 | return prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST, | ||
705 | OMAP3430_LASTLOGICSTATEENTERED_MASK); | ||
706 | } | 624 | } |
707 | 625 | ||
708 | /** | 626 | /** |
@@ -715,17 +633,15 @@ int pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm) | |||
715 | */ | 633 | */ |
716 | int pwrdm_read_logic_retst(struct powerdomain *pwrdm) | 634 | int pwrdm_read_logic_retst(struct powerdomain *pwrdm) |
717 | { | 635 | { |
636 | int ret = -EINVAL; | ||
637 | |||
718 | if (!pwrdm) | 638 | if (!pwrdm) |
719 | return -EINVAL; | 639 | return -EINVAL; |
720 | 640 | ||
721 | /* | 641 | if (arch_pwrdm && arch_pwrdm->pwrdm_read_logic_retst) |
722 | * The register bit names below may not correspond to the | 642 | ret = arch_pwrdm->pwrdm_read_logic_retst(pwrdm); |
723 | * actual names of the bits in each powerdomain's register, | 643 | |
724 | * but the type of value returned is the same for each | 644 | return ret; |
725 | * powerdomain. | ||
726 | */ | ||
727 | return prm_read_mod_bits_shift(pwrdm->prcm_offs, pwrstctrl_reg_offs, | ||
728 | OMAP3430_LOGICSTATEST_MASK); | ||
729 | } | 645 | } |
730 | 646 | ||
731 | /** | 647 | /** |
@@ -740,46 +656,21 @@ int pwrdm_read_logic_retst(struct powerdomain *pwrdm) | |||
740 | */ | 656 | */ |
741 | int pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank) | 657 | int pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank) |
742 | { | 658 | { |
743 | u32 m; | 659 | int ret = -EINVAL; |
744 | 660 | ||
745 | if (!pwrdm) | 661 | if (!pwrdm) |
746 | return -EINVAL; | 662 | return ret; |
747 | 663 | ||
748 | if (pwrdm->banks < (bank + 1)) | 664 | if (pwrdm->banks < (bank + 1)) |
749 | return -EEXIST; | 665 | return ret; |
750 | 666 | ||
751 | if (pwrdm->flags & PWRDM_HAS_MPU_QUIRK) | 667 | if (pwrdm->flags & PWRDM_HAS_MPU_QUIRK) |
752 | bank = 1; | 668 | bank = 1; |
753 | 669 | ||
754 | /* | 670 | if (arch_pwrdm && arch_pwrdm->pwrdm_read_mem_pwrst) |
755 | * The register bit names below may not correspond to the | 671 | ret = arch_pwrdm->pwrdm_read_mem_pwrst(pwrdm, bank); |
756 | * actual names of the bits in each powerdomain's register, | ||
757 | * but the type of value returned is the same for each | ||
758 | * powerdomain. | ||
759 | */ | ||
760 | switch (bank) { | ||
761 | case 0: | ||
762 | m = OMAP_MEM0_STATEST_MASK; | ||
763 | break; | ||
764 | case 1: | ||
765 | m = OMAP_MEM1_STATEST_MASK; | ||
766 | break; | ||
767 | case 2: | ||
768 | m = OMAP_MEM2_STATEST_MASK; | ||
769 | break; | ||
770 | case 3: | ||
771 | m = OMAP_MEM3_STATEST_MASK; | ||
772 | break; | ||
773 | case 4: | ||
774 | m = OMAP_MEM4_STATEST_MASK; | ||
775 | break; | ||
776 | default: | ||
777 | WARN_ON(1); /* should never happen */ | ||
778 | return -EEXIST; | ||
779 | } | ||
780 | 672 | ||
781 | return prm_read_mod_bits_shift(pwrdm->prcm_offs, | 673 | return ret; |
782 | pwrstst_reg_offs, m); | ||
783 | } | 674 | } |
784 | 675 | ||
785 | /** | 676 | /** |
@@ -795,43 +686,21 @@ int pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank) | |||
795 | */ | 686 | */ |
796 | int pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank) | 687 | int pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank) |
797 | { | 688 | { |
798 | u32 m; | 689 | int ret = -EINVAL; |
799 | 690 | ||
800 | if (!pwrdm) | 691 | if (!pwrdm) |
801 | return -EINVAL; | 692 | return ret; |
802 | 693 | ||
803 | if (pwrdm->banks < (bank + 1)) | 694 | if (pwrdm->banks < (bank + 1)) |
804 | return -EEXIST; | 695 | return ret; |
805 | 696 | ||
806 | if (pwrdm->flags & PWRDM_HAS_MPU_QUIRK) | 697 | if (pwrdm->flags & PWRDM_HAS_MPU_QUIRK) |
807 | bank = 1; | 698 | bank = 1; |
808 | 699 | ||
809 | /* | 700 | if (arch_pwrdm && arch_pwrdm->pwrdm_read_prev_mem_pwrst) |
810 | * The register bit names below may not correspond to the | 701 | ret = arch_pwrdm->pwrdm_read_prev_mem_pwrst(pwrdm, bank); |
811 | * actual names of the bits in each powerdomain's register, | ||
812 | * but the type of value returned is the same for each | ||
813 | * powerdomain. | ||
814 | */ | ||
815 | switch (bank) { | ||
816 | case 0: | ||
817 | m = OMAP3430_LASTMEM1STATEENTERED_MASK; | ||
818 | break; | ||
819 | case 1: | ||
820 | m = OMAP3430_LASTMEM2STATEENTERED_MASK; | ||
821 | break; | ||
822 | case 2: | ||
823 | m = OMAP3430_LASTSHAREDL2CACHEFLATSTATEENTERED_MASK; | ||
824 | break; | ||
825 | case 3: | ||
826 | m = OMAP3430_LASTL2FLATMEMSTATEENTERED_MASK; | ||
827 | break; | ||
828 | default: | ||
829 | WARN_ON(1); /* should never happen */ | ||
830 | return -EEXIST; | ||
831 | } | ||
832 | 702 | ||
833 | return prm_read_mod_bits_shift(pwrdm->prcm_offs, | 703 | return ret; |
834 | OMAP3430_PM_PREPWSTST, m); | ||
835 | } | 704 | } |
836 | 705 | ||
837 | /** | 706 | /** |
@@ -846,43 +715,18 @@ int pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank) | |||
846 | */ | 715 | */ |
847 | int pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank) | 716 | int pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank) |
848 | { | 717 | { |
849 | u32 m; | 718 | int ret = -EINVAL; |
850 | 719 | ||
851 | if (!pwrdm) | 720 | if (!pwrdm) |
852 | return -EINVAL; | 721 | return ret; |
853 | 722 | ||
854 | if (pwrdm->banks < (bank + 1)) | 723 | if (pwrdm->banks < (bank + 1)) |
855 | return -EEXIST; | 724 | return ret; |
856 | 725 | ||
857 | /* | 726 | if (arch_pwrdm && arch_pwrdm->pwrdm_read_mem_retst) |
858 | * The register bit names below may not correspond to the | 727 | ret = arch_pwrdm->pwrdm_read_mem_retst(pwrdm, bank); |
859 | * actual names of the bits in each powerdomain's register, | ||
860 | * but the type of value returned is the same for each | ||
861 | * powerdomain. | ||
862 | */ | ||
863 | switch (bank) { | ||
864 | case 0: | ||
865 | m = OMAP_MEM0_RETSTATE_MASK; | ||
866 | break; | ||
867 | case 1: | ||
868 | m = OMAP_MEM1_RETSTATE_MASK; | ||
869 | break; | ||
870 | case 2: | ||
871 | m = OMAP_MEM2_RETSTATE_MASK; | ||
872 | break; | ||
873 | case 3: | ||
874 | m = OMAP_MEM3_RETSTATE_MASK; | ||
875 | break; | ||
876 | case 4: | ||
877 | m = OMAP_MEM4_RETSTATE_MASK; | ||
878 | break; | ||
879 | default: | ||
880 | WARN_ON(1); /* should never happen */ | ||
881 | return -EEXIST; | ||
882 | } | ||
883 | 728 | ||
884 | return prm_read_mod_bits_shift(pwrdm->prcm_offs, | 729 | return ret; |
885 | pwrstctrl_reg_offs, m); | ||
886 | } | 730 | } |
887 | 731 | ||
888 | /** | 732 | /** |
@@ -896,8 +740,10 @@ int pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank) | |||
896 | */ | 740 | */ |
897 | int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm) | 741 | int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm) |
898 | { | 742 | { |
743 | int ret = -EINVAL; | ||
744 | |||
899 | if (!pwrdm) | 745 | if (!pwrdm) |
900 | return -EINVAL; | 746 | return ret; |
901 | 747 | ||
902 | /* | 748 | /* |
903 | * XXX should get the powerdomain's current state here; | 749 | * XXX should get the powerdomain's current state here; |
@@ -907,9 +753,10 @@ int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm) | |||
907 | pr_debug("powerdomain: clearing previous power state reg for %s\n", | 753 | pr_debug("powerdomain: clearing previous power state reg for %s\n", |
908 | pwrdm->name); | 754 | pwrdm->name); |
909 | 755 | ||
910 | prm_write_mod_reg(0, pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST); | 756 | if (arch_pwrdm && arch_pwrdm->pwrdm_clear_all_prev_pwrst) |
757 | ret = arch_pwrdm->pwrdm_clear_all_prev_pwrst(pwrdm); | ||
911 | 758 | ||
912 | return 0; | 759 | return ret; |
913 | } | 760 | } |
914 | 761 | ||
915 | /** | 762 | /** |
@@ -925,19 +772,21 @@ int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm) | |||
925 | */ | 772 | */ |
926 | int pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm) | 773 | int pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm) |
927 | { | 774 | { |
775 | int ret = -EINVAL; | ||
776 | |||
928 | if (!pwrdm) | 777 | if (!pwrdm) |
929 | return -EINVAL; | 778 | return ret; |
930 | 779 | ||
931 | if (!(pwrdm->flags & PWRDM_HAS_HDWR_SAR)) | 780 | if (!(pwrdm->flags & PWRDM_HAS_HDWR_SAR)) |
932 | return -EINVAL; | 781 | return ret; |
933 | 782 | ||
934 | pr_debug("powerdomain: %s: setting SAVEANDRESTORE bit\n", | 783 | pr_debug("powerdomain: %s: setting SAVEANDRESTORE bit\n", |
935 | pwrdm->name); | 784 | pwrdm->name); |
936 | 785 | ||
937 | prm_rmw_mod_reg_bits(0, 1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT, | 786 | if (arch_pwrdm && arch_pwrdm->pwrdm_enable_hdwr_sar) |
938 | pwrdm->prcm_offs, pwrstctrl_reg_offs); | 787 | ret = arch_pwrdm->pwrdm_enable_hdwr_sar(pwrdm); |
939 | 788 | ||
940 | return 0; | 789 | return ret; |
941 | } | 790 | } |
942 | 791 | ||
943 | /** | 792 | /** |
@@ -953,19 +802,21 @@ int pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm) | |||
953 | */ | 802 | */ |
954 | int pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm) | 803 | int pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm) |
955 | { | 804 | { |
805 | int ret = -EINVAL; | ||
806 | |||
956 | if (!pwrdm) | 807 | if (!pwrdm) |
957 | return -EINVAL; | 808 | return ret; |
958 | 809 | ||
959 | if (!(pwrdm->flags & PWRDM_HAS_HDWR_SAR)) | 810 | if (!(pwrdm->flags & PWRDM_HAS_HDWR_SAR)) |
960 | return -EINVAL; | 811 | return ret; |
961 | 812 | ||
962 | pr_debug("powerdomain: %s: clearing SAVEANDRESTORE bit\n", | 813 | pr_debug("powerdomain: %s: clearing SAVEANDRESTORE bit\n", |
963 | pwrdm->name); | 814 | pwrdm->name); |
964 | 815 | ||
965 | prm_rmw_mod_reg_bits(1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT, 0, | 816 | if (arch_pwrdm && arch_pwrdm->pwrdm_disable_hdwr_sar) |
966 | pwrdm->prcm_offs, pwrstctrl_reg_offs); | 817 | ret = arch_pwrdm->pwrdm_disable_hdwr_sar(pwrdm); |
967 | 818 | ||
968 | return 0; | 819 | return ret; |
969 | } | 820 | } |
970 | 821 | ||
971 | /** | 822 | /** |
@@ -992,6 +843,8 @@ bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm) | |||
992 | */ | 843 | */ |
993 | int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm) | 844 | int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm) |
994 | { | 845 | { |
846 | int ret = -EINVAL; | ||
847 | |||
995 | if (!pwrdm) | 848 | if (!pwrdm) |
996 | return -EINVAL; | 849 | return -EINVAL; |
997 | 850 | ||
@@ -1001,11 +854,10 @@ int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm) | |||
1001 | pr_debug("powerdomain: %s: setting LOWPOWERSTATECHANGE bit\n", | 854 | pr_debug("powerdomain: %s: setting LOWPOWERSTATECHANGE bit\n", |
1002 | pwrdm->name); | 855 | pwrdm->name); |
1003 | 856 | ||
1004 | prm_rmw_mod_reg_bits(OMAP4430_LOWPOWERSTATECHANGE_MASK, | 857 | if (arch_pwrdm && arch_pwrdm->pwrdm_set_lowpwrstchange) |
1005 | (1 << OMAP4430_LOWPOWERSTATECHANGE_SHIFT), | 858 | ret = arch_pwrdm->pwrdm_set_lowpwrstchange(pwrdm); |
1006 | pwrdm->prcm_offs, pwrstctrl_reg_offs); | ||
1007 | 859 | ||
1008 | return 0; | 860 | return ret; |
1009 | } | 861 | } |
1010 | 862 | ||
1011 | /** | 863 | /** |
@@ -1020,32 +872,15 @@ int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm) | |||
1020 | */ | 872 | */ |
1021 | int pwrdm_wait_transition(struct powerdomain *pwrdm) | 873 | int pwrdm_wait_transition(struct powerdomain *pwrdm) |
1022 | { | 874 | { |
1023 | u32 c = 0; | 875 | int ret = -EINVAL; |
1024 | 876 | ||
1025 | if (!pwrdm) | 877 | if (!pwrdm) |
1026 | return -EINVAL; | 878 | return -EINVAL; |
1027 | 879 | ||
1028 | /* | 880 | if (arch_pwrdm && arch_pwrdm->pwrdm_wait_transition) |
1029 | * REVISIT: pwrdm_wait_transition() may be better implemented | 881 | ret = arch_pwrdm->pwrdm_wait_transition(pwrdm); |
1030 | * via a callback and a periodic timer check -- how long do we expect | ||
1031 | * powerdomain transitions to take? | ||
1032 | */ | ||
1033 | |||
1034 | /* XXX Is this udelay() value meaningful? */ | ||
1035 | while ((prm_read_mod_reg(pwrdm->prcm_offs, pwrstst_reg_offs) & | ||
1036 | OMAP_INTRANSITION_MASK) && | ||
1037 | (c++ < PWRDM_TRANSITION_BAILOUT)) | ||
1038 | udelay(1); | ||
1039 | |||
1040 | if (c > PWRDM_TRANSITION_BAILOUT) { | ||
1041 | printk(KERN_ERR "powerdomain: waited too long for " | ||
1042 | "powerdomain %s to complete transition\n", pwrdm->name); | ||
1043 | return -EAGAIN; | ||
1044 | } | ||
1045 | |||
1046 | pr_debug("powerdomain: completed transition in %d loops\n", c); | ||
1047 | 882 | ||
1048 | return 0; | 883 | return ret; |
1049 | } | 884 | } |
1050 | 885 | ||
1051 | int pwrdm_state_switch(struct powerdomain *pwrdm) | 886 | int pwrdm_state_switch(struct powerdomain *pwrdm) |
@@ -1075,3 +910,31 @@ int pwrdm_post_transition(void) | |||
1075 | return 0; | 910 | return 0; |
1076 | } | 911 | } |
1077 | 912 | ||
913 | /** | ||
914 | * pwrdm_get_context_loss_count - get powerdomain's context loss count | ||
915 | * @pwrdm: struct powerdomain * to wait for | ||
916 | * | ||
917 | * Context loss count is the sum of powerdomain off-mode counter, the | ||
918 | * logic off counter and the per-bank memory off counter. Returns 0 | ||
919 | * (and WARNs) upon error, otherwise, returns the context loss count. | ||
920 | */ | ||
921 | u32 pwrdm_get_context_loss_count(struct powerdomain *pwrdm) | ||
922 | { | ||
923 | int i, count; | ||
924 | |||
925 | if (!pwrdm) { | ||
926 | WARN(1, "powerdomain: %s: pwrdm is null\n", __func__); | ||
927 | return 0; | ||
928 | } | ||
929 | |||
930 | count = pwrdm->state_counter[PWRDM_POWER_OFF]; | ||
931 | count += pwrdm->ret_logic_off_counter; | ||
932 | |||
933 | for (i = 0; i < pwrdm->banks; i++) | ||
934 | count += pwrdm->ret_mem_off_counter[i]; | ||
935 | |||
936 | pr_debug("powerdomain: %s: context loss count = %u\n", | ||
937 | pwrdm->name, count); | ||
938 | |||
939 | return count; | ||
940 | } | ||