aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/powerdomain.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap2/powerdomain.c')
-rw-r--r--arch/arm/mach-omap2/powerdomain.c441
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 */
49static u16 pwrstctrl_reg_offs;
50
51/* Variable holding value of the CPU dependent PWRSTST Register Offset */
52static 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 */
81static LIST_HEAD(pwrdm_list); 42static LIST_HEAD(pwrdm_list);
82 43
44static struct pwrdm_ops *arch_pwrdm;
45
83/* Private functions */ 46/* Private functions */
84 47
85static struct powerdomain *_pwrdm_lookup(const char *name) 48static 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 */
221void pwrdm_init(struct powerdomain **pwrdm_list) 192void 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 */
432int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst) 396int 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 */
458int pwrdm_read_next_pwrst(struct powerdomain *pwrdm) 423int 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 */
475int pwrdm_read_pwrst(struct powerdomain *pwrdm) 444int 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 */
492int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm) 465int 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 */
512int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst) 489int 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 */
553int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst) 523int 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 */
618int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst) 561int 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 */
676int pwrdm_read_logic_pwrst(struct powerdomain *pwrdm) 592int 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 */
693int pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm) 613int 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 */
716int pwrdm_read_logic_retst(struct powerdomain *pwrdm) 634int 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 */
741int pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank) 657int 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 */
796int pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank) 687int 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 */
847int pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank) 716int 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 */
897int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm) 741int 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 */
926int pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm) 773int 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 */
954int pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm) 803int 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 */
993int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm) 844int 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 */
1021int pwrdm_wait_transition(struct powerdomain *pwrdm) 873int 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
1051int pwrdm_state_switch(struct powerdomain *pwrdm) 886int 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 */
921u32 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}