aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2
diff options
context:
space:
mode:
authorRajendra Nayak <rnayak@ti.com>2010-12-21 22:01:19 -0500
committerPaul Walmsley <paul@pwsan.com>2010-12-21 22:01:19 -0500
commit9b7fc907d9378f86eb6b823bbe84ec9ed584b091 (patch)
treeb4519c2eb01d58ca4a407048bcb3fd83cf846e1f /arch/arm/mach-omap2
parent12627578523d2d9396cae76b1dad0ed3dccf1730 (diff)
OMAP: powerdomain: Arch specific funcs for mem control
Define the following architecture specific funtions for omap2/3/4 .pwrdm_set_mem_onst .pwrdm_set_mem_retst .pwrdm_read_mem_pwrst .pwrdm_read_prev_mem_pwrst .pwrdm_read_mem_retst .pwrdm_clear_all_prev_pwrst .pwrdm_enable_hdwr_sar .pwrdm_disable_hdwr_sar .pwrdm_wait_transition .pwrdm_set_lowpwrstchange Convert the platform-independent framework to call these functions. Signed-off-by: Rajendra Nayak <rnayak@ti.com> [paul@pwsan.com: rearranged Makefile changes] Signed-off-by: Paul Walmsley <paul@pwsan.com> Cc: Benoit Cousson <b-cousson@ti.com> Cc: Kevin Hilman <khilman@deeprootsystems.com> Reviewed-by: Kevin Hilman <khilman@deeprootsystems.com> Tested-by: Kevin Hilman <khilman@deeprootsystems.com> Tested-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Diffstat (limited to 'arch/arm/mach-omap2')
-rw-r--r--arch/arm/mach-omap2/Makefile2
-rw-r--r--arch/arm/mach-omap2/powerdomain-common.c111
-rw-r--r--arch/arm/mach-omap2/powerdomain.c303
-rw-r--r--arch/arm/mach-omap2/powerdomain2xxx_3xxx.c131
-rw-r--r--arch/arm/mach-omap2/powerdomain44xx.c85
-rw-r--r--arch/arm/mach-omap2/powerdomains.h5
6 files changed, 389 insertions, 248 deletions
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index c43948c8d543..1a1e978cd4bf 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -78,7 +78,7 @@ obj-$(CONFIG_ARCH_OMAP3) += prcm.o cm.o
78obj-$(CONFIG_ARCH_OMAP4) += prcm.o cm4xxx.o 78obj-$(CONFIG_ARCH_OMAP4) += prcm.o cm4xxx.o
79 79
80# OMAP powerdomain framework 80# OMAP powerdomain framework
81powerdomain-common += powerdomain.o powerdomains_data.o 81powerdomain-common += powerdomain.o powerdomains_data.o powerdomain-common.o
82obj-$(CONFIG_ARCH_OMAP2) += $(powerdomain-common) \ 82obj-$(CONFIG_ARCH_OMAP2) += $(powerdomain-common) \
83 powerdomain2xxx_3xxx.o 83 powerdomain2xxx_3xxx.o
84obj-$(CONFIG_ARCH_OMAP3) += $(powerdomain-common) \ 84obj-$(CONFIG_ARCH_OMAP3) += $(powerdomain-common) \
diff --git a/arch/arm/mach-omap2/powerdomain-common.c b/arch/arm/mach-omap2/powerdomain-common.c
new file mode 100644
index 000000000000..cb01c7a3689a
--- /dev/null
+++ b/arch/arm/mach-omap2/powerdomain-common.c
@@ -0,0 +1,111 @@
1/*
2 * linux/arch/arm/mach-omap2/powerdomain-common.c
3 * Contains common powerdomain framework functions
4 *
5 * Copyright (C) 2010 Texas Instruments, Inc.
6 * Copyright (C) 2010 Nokia Corporation
7 *
8 * Derived from mach-omap2/powerdomain.c written by Paul Walmsley
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#include <linux/errno.h>
16#include <linux/kernel.h>
17#include "pm.h"
18#include "cm.h"
19#include "cm-regbits-34xx.h"
20#include "cm-regbits-44xx.h"
21#include "prm-regbits-34xx.h"
22#include "prm-regbits-44xx.h"
23#include "powerdomains.h"
24
25/*
26 * OMAP3 and OMAP4 specific register bit initialisations
27 * Notice that the names here are not according to each power
28 * domain but the bit mapping used applies to all of them
29 */
30/* OMAP3 and OMAP4 Memory Onstate Masks (common across all power domains) */
31#define OMAP_MEM0_ONSTATE_MASK OMAP3430_SHAREDL1CACHEFLATONSTATE_MASK
32#define OMAP_MEM1_ONSTATE_MASK OMAP3430_L1FLATMEMONSTATE_MASK
33#define OMAP_MEM2_ONSTATE_MASK OMAP3430_SHAREDL2CACHEFLATONSTATE_MASK
34#define OMAP_MEM3_ONSTATE_MASK OMAP3430_L2FLATMEMONSTATE_MASK
35#define OMAP_MEM4_ONSTATE_MASK OMAP4430_OCP_NRET_BANK_ONSTATE_MASK
36
37/* OMAP3 and OMAP4 Memory Retstate Masks (common across all power domains) */
38#define OMAP_MEM0_RETSTATE_MASK OMAP3430_SHAREDL1CACHEFLATRETSTATE_MASK
39#define OMAP_MEM1_RETSTATE_MASK OMAP3430_L1FLATMEMRETSTATE_MASK
40#define OMAP_MEM2_RETSTATE_MASK OMAP3430_SHAREDL2CACHEFLATRETSTATE_MASK
41#define OMAP_MEM3_RETSTATE_MASK OMAP3430_L2FLATMEMRETSTATE_MASK
42#define OMAP_MEM4_RETSTATE_MASK OMAP4430_OCP_NRET_BANK_RETSTATE_MASK
43
44/* OMAP3 and OMAP4 Memory Status bits */
45#define OMAP_MEM0_STATEST_MASK OMAP3430_SHAREDL1CACHEFLATSTATEST_MASK
46#define OMAP_MEM1_STATEST_MASK OMAP3430_L1FLATMEMSTATEST_MASK
47#define OMAP_MEM2_STATEST_MASK OMAP3430_SHAREDL2CACHEFLATSTATEST_MASK
48#define OMAP_MEM3_STATEST_MASK OMAP3430_L2FLATMEMSTATEST_MASK
49#define OMAP_MEM4_STATEST_MASK OMAP4430_OCP_NRET_BANK_STATEST_MASK
50
51/* Common Internal functions used across OMAP rev's*/
52u32 omap2_pwrdm_get_mem_bank_onstate_mask(u8 bank)
53{
54 switch (bank) {
55 case 0:
56 return OMAP_MEM0_ONSTATE_MASK;
57 case 1:
58 return OMAP_MEM1_ONSTATE_MASK;
59 case 2:
60 return OMAP_MEM2_ONSTATE_MASK;
61 case 3:
62 return OMAP_MEM3_ONSTATE_MASK;
63 case 4:
64 return OMAP_MEM4_ONSTATE_MASK;
65 default:
66 WARN_ON(1); /* should never happen */
67 return -EEXIST;
68 }
69 return 0;
70}
71
72u32 omap2_pwrdm_get_mem_bank_retst_mask(u8 bank)
73{
74 switch (bank) {
75 case 0:
76 return OMAP_MEM0_RETSTATE_MASK;
77 case 1:
78 return OMAP_MEM1_RETSTATE_MASK;
79 case 2:
80 return OMAP_MEM2_RETSTATE_MASK;
81 case 3:
82 return OMAP_MEM3_RETSTATE_MASK;
83 case 4:
84 return OMAP_MEM4_RETSTATE_MASK;
85 default:
86 WARN_ON(1); /* should never happen */
87 return -EEXIST;
88 }
89 return 0;
90}
91
92u32 omap2_pwrdm_get_mem_bank_stst_mask(u8 bank)
93{
94 switch (bank) {
95 case 0:
96 return OMAP_MEM0_STATEST_MASK;
97 case 1:
98 return OMAP_MEM1_STATEST_MASK;
99 case 2:
100 return OMAP_MEM2_STATEST_MASK;
101 case 3:
102 return OMAP_MEM3_STATEST_MASK;
103 case 4:
104 return OMAP_MEM4_STATEST_MASK;
105 default:
106 WARN_ON(1); /* should never happen */
107 return -EEXIST;
108 }
109 return 0;
110}
111
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index 562a3fe9db5b..620672135768 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -15,23 +15,10 @@
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>
26
27#include <asm/atomic.h>
28
29#include "cm.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 22
36#include <plat/cpu.h> 23#include <plat/cpu.h>
37#include <plat/powerdomain.h> 24#include <plat/powerdomain.h>
@@ -45,37 +32,6 @@ enum {
45 PWRDM_STATE_PREV, 32 PWRDM_STATE_PREV,
46}; 33};
47 34
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 35
80/* pwrdm_list contains all registered struct powerdomains */ 36/* pwrdm_list contains all registered struct powerdomains */
81static LIST_HEAD(pwrdm_list); 37static LIST_HEAD(pwrdm_list);
@@ -225,18 +181,6 @@ void pwrdm_init(struct powerdomain **pwrdm_list, struct pwrdm_ops *custom_funcs)
225{ 181{
226 struct powerdomain **p = NULL; 182 struct powerdomain **p = NULL;
227 183
228 if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
229 pwrstctrl_reg_offs = OMAP2_PM_PWSTCTRL;
230 pwrstst_reg_offs = OMAP2_PM_PWSTST;
231 } else if (cpu_is_omap44xx()) {
232 pwrstctrl_reg_offs = OMAP4_PM_PWSTCTRL;
233 pwrstst_reg_offs = OMAP4_PM_PWSTST;
234 } else {
235 printk(KERN_ERR "Power Domain struct not supported for " \
236 "this CPU\n");
237 return;
238 }
239
240 if (!custom_funcs) 184 if (!custom_funcs)
241 WARN(1, "powerdomain: No custom pwrdm functions registered\n"); 185 WARN(1, "powerdomain: No custom pwrdm functions registered\n");
242 else 186 else
@@ -566,7 +510,7 @@ int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
566 */ 510 */
567int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst) 511int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
568{ 512{
569 u32 m; 513 int ret = -EINVAL;
570 514
571 if (!pwrdm) 515 if (!pwrdm)
572 return -EINVAL; 516 return -EINVAL;
@@ -580,37 +524,10 @@ int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
580 pr_debug("powerdomain: setting next memory powerstate for domain %s " 524 pr_debug("powerdomain: setting next memory powerstate for domain %s "
581 "bank %0x while pwrdm-ON to %0x\n", pwrdm->name, bank, pwrst); 525 "bank %0x while pwrdm-ON to %0x\n", pwrdm->name, bank, pwrst);
582 526
583 /* 527 if (arch_pwrdm && arch_pwrdm->pwrdm_set_mem_onst)
584 * The register bit names below may not correspond to the 528 ret = arch_pwrdm->pwrdm_set_mem_onst(pwrdm, bank, pwrst);
585 * actual names of the bits in each powerdomain's register,
586 * but the type of value returned is the same for each
587 * powerdomain.
588 */
589 switch (bank) {
590 case 0:
591 m = OMAP_MEM0_ONSTATE_MASK;
592 break;
593 case 1:
594 m = OMAP_MEM1_ONSTATE_MASK;
595 break;
596 case 2:
597 m = OMAP_MEM2_ONSTATE_MASK;
598 break;
599 case 3:
600 m = OMAP_MEM3_ONSTATE_MASK;
601 break;
602 case 4:
603 m = OMAP_MEM4_ONSTATE_MASK;
604 break;
605 default:
606 WARN_ON(1); /* should never happen */
607 return -EEXIST;
608 }
609
610 prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)),
611 pwrdm->prcm_offs, pwrstctrl_reg_offs);
612 529
613 return 0; 530 return ret;
614} 531}
615 532
616/** 533/**
@@ -631,7 +548,7 @@ int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
631 */ 548 */
632int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst) 549int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
633{ 550{
634 u32 m; 551 int ret = -EINVAL;
635 552
636 if (!pwrdm) 553 if (!pwrdm)
637 return -EINVAL; 554 return -EINVAL;
@@ -645,37 +562,10 @@ int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
645 pr_debug("powerdomain: setting next memory powerstate for domain %s " 562 pr_debug("powerdomain: setting next memory powerstate for domain %s "
646 "bank %0x while pwrdm-RET to %0x\n", pwrdm->name, bank, pwrst); 563 "bank %0x while pwrdm-RET to %0x\n", pwrdm->name, bank, pwrst);
647 564
648 /* 565 if (arch_pwrdm && arch_pwrdm->pwrdm_set_mem_retst)
649 * The register bit names below may not correspond to the 566 ret = arch_pwrdm->pwrdm_set_mem_retst(pwrdm, bank, pwrst);
650 * actual names of the bits in each powerdomain's register,
651 * but the type of value returned is the same for each
652 * powerdomain.
653 */
654 switch (bank) {
655 case 0:
656 m = OMAP_MEM0_RETSTATE_MASK;
657 break;
658 case 1:
659 m = OMAP_MEM1_RETSTATE_MASK;
660 break;
661 case 2:
662 m = OMAP_MEM2_RETSTATE_MASK;
663 break;
664 case 3:
665 m = OMAP_MEM3_RETSTATE_MASK;
666 break;
667 case 4:
668 m = OMAP_MEM4_RETSTATE_MASK;
669 break;
670 default:
671 WARN_ON(1); /* should never happen */
672 return -EEXIST;
673 }
674
675 prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs,
676 pwrstctrl_reg_offs);
677 567
678 return 0; 568 return ret;
679} 569}
680 570
681/** 571/**
@@ -754,46 +644,21 @@ int pwrdm_read_logic_retst(struct powerdomain *pwrdm)
754 */ 644 */
755int pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank) 645int pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
756{ 646{
757 u32 m; 647 int ret = -EINVAL;
758 648
759 if (!pwrdm) 649 if (!pwrdm)
760 return -EINVAL; 650 return ret;
761 651
762 if (pwrdm->banks < (bank + 1)) 652 if (pwrdm->banks < (bank + 1))
763 return -EEXIST; 653 return ret;
764 654
765 if (pwrdm->flags & PWRDM_HAS_MPU_QUIRK) 655 if (pwrdm->flags & PWRDM_HAS_MPU_QUIRK)
766 bank = 1; 656 bank = 1;
767 657
768 /* 658 if (arch_pwrdm && arch_pwrdm->pwrdm_read_mem_pwrst)
769 * The register bit names below may not correspond to the 659 ret = arch_pwrdm->pwrdm_read_mem_pwrst(pwrdm, bank);
770 * actual names of the bits in each powerdomain's register,
771 * but the type of value returned is the same for each
772 * powerdomain.
773 */
774 switch (bank) {
775 case 0:
776 m = OMAP_MEM0_STATEST_MASK;
777 break;
778 case 1:
779 m = OMAP_MEM1_STATEST_MASK;
780 break;
781 case 2:
782 m = OMAP_MEM2_STATEST_MASK;
783 break;
784 case 3:
785 m = OMAP_MEM3_STATEST_MASK;
786 break;
787 case 4:
788 m = OMAP_MEM4_STATEST_MASK;
789 break;
790 default:
791 WARN_ON(1); /* should never happen */
792 return -EEXIST;
793 }
794 660
795 return prm_read_mod_bits_shift(pwrdm->prcm_offs, 661 return ret;
796 pwrstst_reg_offs, m);
797} 662}
798 663
799/** 664/**
@@ -809,43 +674,21 @@ int pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
809 */ 674 */
810int pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank) 675int pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
811{ 676{
812 u32 m; 677 int ret = -EINVAL;
813 678
814 if (!pwrdm) 679 if (!pwrdm)
815 return -EINVAL; 680 return ret;
816 681
817 if (pwrdm->banks < (bank + 1)) 682 if (pwrdm->banks < (bank + 1))
818 return -EEXIST; 683 return ret;
819 684
820 if (pwrdm->flags & PWRDM_HAS_MPU_QUIRK) 685 if (pwrdm->flags & PWRDM_HAS_MPU_QUIRK)
821 bank = 1; 686 bank = 1;
822 687
823 /* 688 if (arch_pwrdm && arch_pwrdm->pwrdm_read_prev_mem_pwrst)
824 * The register bit names below may not correspond to the 689 ret = arch_pwrdm->pwrdm_read_prev_mem_pwrst(pwrdm, bank);
825 * actual names of the bits in each powerdomain's register,
826 * but the type of value returned is the same for each
827 * powerdomain.
828 */
829 switch (bank) {
830 case 0:
831 m = OMAP3430_LASTMEM1STATEENTERED_MASK;
832 break;
833 case 1:
834 m = OMAP3430_LASTMEM2STATEENTERED_MASK;
835 break;
836 case 2:
837 m = OMAP3430_LASTSHAREDL2CACHEFLATSTATEENTERED_MASK;
838 break;
839 case 3:
840 m = OMAP3430_LASTL2FLATMEMSTATEENTERED_MASK;
841 break;
842 default:
843 WARN_ON(1); /* should never happen */
844 return -EEXIST;
845 }
846 690
847 return prm_read_mod_bits_shift(pwrdm->prcm_offs, 691 return ret;
848 OMAP3430_PM_PREPWSTST, m);
849} 692}
850 693
851/** 694/**
@@ -860,43 +703,18 @@ int pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
860 */ 703 */
861int pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank) 704int pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
862{ 705{
863 u32 m; 706 int ret = -EINVAL;
864 707
865 if (!pwrdm) 708 if (!pwrdm)
866 return -EINVAL; 709 return ret;
867 710
868 if (pwrdm->banks < (bank + 1)) 711 if (pwrdm->banks < (bank + 1))
869 return -EEXIST; 712 return ret;
870 713
871 /* 714 if (arch_pwrdm && arch_pwrdm->pwrdm_read_mem_retst)
872 * The register bit names below may not correspond to the 715 ret = arch_pwrdm->pwrdm_read_mem_retst(pwrdm, bank);
873 * actual names of the bits in each powerdomain's register,
874 * but the type of value returned is the same for each
875 * powerdomain.
876 */
877 switch (bank) {
878 case 0:
879 m = OMAP_MEM0_RETSTATE_MASK;
880 break;
881 case 1:
882 m = OMAP_MEM1_RETSTATE_MASK;
883 break;
884 case 2:
885 m = OMAP_MEM2_RETSTATE_MASK;
886 break;
887 case 3:
888 m = OMAP_MEM3_RETSTATE_MASK;
889 break;
890 case 4:
891 m = OMAP_MEM4_RETSTATE_MASK;
892 break;
893 default:
894 WARN_ON(1); /* should never happen */
895 return -EEXIST;
896 }
897 716
898 return prm_read_mod_bits_shift(pwrdm->prcm_offs, 717 return ret;
899 pwrstctrl_reg_offs, m);
900} 718}
901 719
902/** 720/**
@@ -910,8 +728,10 @@ int pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
910 */ 728 */
911int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm) 729int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
912{ 730{
731 int ret = -EINVAL;
732
913 if (!pwrdm) 733 if (!pwrdm)
914 return -EINVAL; 734 return ret;
915 735
916 /* 736 /*
917 * XXX should get the powerdomain's current state here; 737 * XXX should get the powerdomain's current state here;
@@ -921,9 +741,10 @@ int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
921 pr_debug("powerdomain: clearing previous power state reg for %s\n", 741 pr_debug("powerdomain: clearing previous power state reg for %s\n",
922 pwrdm->name); 742 pwrdm->name);
923 743
924 prm_write_mod_reg(0, pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST); 744 if (arch_pwrdm && arch_pwrdm->pwrdm_clear_all_prev_pwrst)
745 ret = arch_pwrdm->pwrdm_clear_all_prev_pwrst(pwrdm);
925 746
926 return 0; 747 return ret;
927} 748}
928 749
929/** 750/**
@@ -939,19 +760,21 @@ int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
939 */ 760 */
940int pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm) 761int pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm)
941{ 762{
763 int ret = -EINVAL;
764
942 if (!pwrdm) 765 if (!pwrdm)
943 return -EINVAL; 766 return ret;
944 767
945 if (!(pwrdm->flags & PWRDM_HAS_HDWR_SAR)) 768 if (!(pwrdm->flags & PWRDM_HAS_HDWR_SAR))
946 return -EINVAL; 769 return ret;
947 770
948 pr_debug("powerdomain: %s: setting SAVEANDRESTORE bit\n", 771 pr_debug("powerdomain: %s: setting SAVEANDRESTORE bit\n",
949 pwrdm->name); 772 pwrdm->name);
950 773
951 prm_rmw_mod_reg_bits(0, 1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT, 774 if (arch_pwrdm && arch_pwrdm->pwrdm_enable_hdwr_sar)
952 pwrdm->prcm_offs, pwrstctrl_reg_offs); 775 ret = arch_pwrdm->pwrdm_enable_hdwr_sar(pwrdm);
953 776
954 return 0; 777 return ret;
955} 778}
956 779
957/** 780/**
@@ -967,19 +790,21 @@ int pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm)
967 */ 790 */
968int pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm) 791int pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm)
969{ 792{
793 int ret = -EINVAL;
794
970 if (!pwrdm) 795 if (!pwrdm)
971 return -EINVAL; 796 return ret;
972 797
973 if (!(pwrdm->flags & PWRDM_HAS_HDWR_SAR)) 798 if (!(pwrdm->flags & PWRDM_HAS_HDWR_SAR))
974 return -EINVAL; 799 return ret;
975 800
976 pr_debug("powerdomain: %s: clearing SAVEANDRESTORE bit\n", 801 pr_debug("powerdomain: %s: clearing SAVEANDRESTORE bit\n",
977 pwrdm->name); 802 pwrdm->name);
978 803
979 prm_rmw_mod_reg_bits(1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT, 0, 804 if (arch_pwrdm && arch_pwrdm->pwrdm_disable_hdwr_sar)
980 pwrdm->prcm_offs, pwrstctrl_reg_offs); 805 ret = arch_pwrdm->pwrdm_disable_hdwr_sar(pwrdm);
981 806
982 return 0; 807 return ret;
983} 808}
984 809
985/** 810/**
@@ -1006,6 +831,8 @@ bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm)
1006 */ 831 */
1007int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm) 832int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)
1008{ 833{
834 int ret = -EINVAL;
835
1009 if (!pwrdm) 836 if (!pwrdm)
1010 return -EINVAL; 837 return -EINVAL;
1011 838
@@ -1015,11 +842,10 @@ int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)
1015 pr_debug("powerdomain: %s: setting LOWPOWERSTATECHANGE bit\n", 842 pr_debug("powerdomain: %s: setting LOWPOWERSTATECHANGE bit\n",
1016 pwrdm->name); 843 pwrdm->name);
1017 844
1018 prm_rmw_mod_reg_bits(OMAP4430_LOWPOWERSTATECHANGE_MASK, 845 if (arch_pwrdm && arch_pwrdm->pwrdm_set_lowpwrstchange)
1019 (1 << OMAP4430_LOWPOWERSTATECHANGE_SHIFT), 846 ret = arch_pwrdm->pwrdm_set_lowpwrstchange(pwrdm);
1020 pwrdm->prcm_offs, pwrstctrl_reg_offs);
1021 847
1022 return 0; 848 return ret;
1023} 849}
1024 850
1025/** 851/**
@@ -1034,32 +860,15 @@ int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)
1034 */ 860 */
1035int pwrdm_wait_transition(struct powerdomain *pwrdm) 861int pwrdm_wait_transition(struct powerdomain *pwrdm)
1036{ 862{
1037 u32 c = 0; 863 int ret = -EINVAL;
1038 864
1039 if (!pwrdm) 865 if (!pwrdm)
1040 return -EINVAL; 866 return -EINVAL;
1041 867
1042 /* 868 if (arch_pwrdm && arch_pwrdm->pwrdm_wait_transition)
1043 * REVISIT: pwrdm_wait_transition() may be better implemented 869 ret = arch_pwrdm->pwrdm_wait_transition(pwrdm);
1044 * via a callback and a periodic timer check -- how long do we expect
1045 * powerdomain transitions to take?
1046 */
1047 870
1048 /* XXX Is this udelay() value meaningful? */ 871 return ret;
1049 while ((prm_read_mod_reg(pwrdm->prcm_offs, pwrstst_reg_offs) &
1050 OMAP_INTRANSITION_MASK) &&
1051 (c++ < PWRDM_TRANSITION_BAILOUT))
1052 udelay(1);
1053
1054 if (c > PWRDM_TRANSITION_BAILOUT) {
1055 printk(KERN_ERR "powerdomain: waited too long for "
1056 "powerdomain %s to complete transition\n", pwrdm->name);
1057 return -EAGAIN;
1058 }
1059
1060 pr_debug("powerdomain: completed transition in %d loops\n", c);
1061
1062 return 0;
1063} 872}
1064 873
1065int pwrdm_state_switch(struct powerdomain *pwrdm) 874int pwrdm_state_switch(struct powerdomain *pwrdm)
diff --git a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c b/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
index b7ea191539e5..6cdf67860cb3 100644
--- a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
+++ b/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
@@ -41,6 +41,50 @@ static int omap2_pwrdm_read_pwrst(struct powerdomain *pwrdm)
41 OMAP2_PM_PWSTST, OMAP_POWERSTATEST_MASK); 41 OMAP2_PM_PWSTST, OMAP_POWERSTATEST_MASK);
42} 42}
43 43
44static int omap2_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank,
45 u8 pwrst)
46{
47 u32 m;
48
49 m = omap2_pwrdm_get_mem_bank_onstate_mask(bank);
50
51 prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs,
52 OMAP2_PM_PWSTCTRL);
53
54 return 0;
55}
56
57static int omap2_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank,
58 u8 pwrst)
59{
60 u32 m;
61
62 m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
63
64 prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs,
65 OMAP2_PM_PWSTCTRL);
66
67 return 0;
68}
69
70static int omap2_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
71{
72 u32 m;
73
74 m = omap2_pwrdm_get_mem_bank_stst_mask(bank);
75
76 return prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP2_PM_PWSTST, m);
77}
78
79static int omap2_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
80{
81 u32 m;
82
83 m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
84
85 return prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL, m);
86}
87
44static int omap2_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst) 88static int omap2_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
45{ 89{
46 u32 v; 90 u32 v;
@@ -52,6 +96,33 @@ static int omap2_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
52 return 0; 96 return 0;
53} 97}
54 98
99static int omap2_pwrdm_wait_transition(struct powerdomain *pwrdm)
100{
101 u32 c = 0;
102
103 /*
104 * REVISIT: pwrdm_wait_transition() may be better implemented
105 * via a callback and a periodic timer check -- how long do we expect
106 * powerdomain transitions to take?
107 */
108
109 /* XXX Is this udelay() value meaningful? */
110 while ((prm_read_mod_reg(pwrdm->prcm_offs, OMAP2_PM_PWSTST) &
111 OMAP_INTRANSITION_MASK) &&
112 (c++ < PWRDM_TRANSITION_BAILOUT))
113 udelay(1);
114
115 if (c > PWRDM_TRANSITION_BAILOUT) {
116 printk(KERN_ERR "powerdomain: waited too long for "
117 "powerdomain %s to complete transition\n", pwrdm->name);
118 return -EAGAIN;
119 }
120
121 pr_debug("powerdomain: completed transition in %d loops\n", c);
122
123 return 0;
124}
125
55/* Applicable only for OMAP3. Not supported on OMAP2 */ 126/* Applicable only for OMAP3. Not supported on OMAP2 */
56static int omap3_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm) 127static int omap3_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
57{ 128{
@@ -77,11 +148,62 @@ static int omap3_pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm)
77 OMAP3430_LASTLOGICSTATEENTERED_MASK); 148 OMAP3430_LASTLOGICSTATEENTERED_MASK);
78} 149}
79 150
151static int omap3_get_mem_bank_lastmemst_mask(u8 bank)
152{
153 switch (bank) {
154 case 0:
155 return OMAP3430_LASTMEM1STATEENTERED_MASK;
156 case 1:
157 return OMAP3430_LASTMEM2STATEENTERED_MASK;
158 case 2:
159 return OMAP3430_LASTSHAREDL2CACHEFLATSTATEENTERED_MASK;
160 case 3:
161 return OMAP3430_LASTL2FLATMEMSTATEENTERED_MASK;
162 default:
163 WARN_ON(1); /* should never happen */
164 return -EEXIST;
165 }
166 return 0;
167}
168
169static int omap3_pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
170{
171 u32 m;
172
173 m = omap3_get_mem_bank_lastmemst_mask(bank);
174
175 return prm_read_mod_bits_shift(pwrdm->prcm_offs,
176 OMAP3430_PM_PREPWSTST, m);
177}
178
179static int omap3_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
180{
181 prm_write_mod_reg(0, pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST);
182 return 0;
183}
184
185static int omap3_pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm)
186{
187 return prm_rmw_mod_reg_bits(0, 1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT,
188 pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL);
189}
190
191static int omap3_pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm)
192{
193 return prm_rmw_mod_reg_bits(1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT, 0,
194 pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL);
195}
196
80struct pwrdm_ops omap2_pwrdm_operations = { 197struct pwrdm_ops omap2_pwrdm_operations = {
81 .pwrdm_set_next_pwrst = omap2_pwrdm_set_next_pwrst, 198 .pwrdm_set_next_pwrst = omap2_pwrdm_set_next_pwrst,
82 .pwrdm_read_next_pwrst = omap2_pwrdm_read_next_pwrst, 199 .pwrdm_read_next_pwrst = omap2_pwrdm_read_next_pwrst,
83 .pwrdm_read_pwrst = omap2_pwrdm_read_pwrst, 200 .pwrdm_read_pwrst = omap2_pwrdm_read_pwrst,
84 .pwrdm_set_logic_retst = omap2_pwrdm_set_logic_retst, 201 .pwrdm_set_logic_retst = omap2_pwrdm_set_logic_retst,
202 .pwrdm_set_mem_onst = omap2_pwrdm_set_mem_onst,
203 .pwrdm_set_mem_retst = omap2_pwrdm_set_mem_retst,
204 .pwrdm_read_mem_pwrst = omap2_pwrdm_read_mem_pwrst,
205 .pwrdm_read_mem_retst = omap2_pwrdm_read_mem_retst,
206 .pwrdm_wait_transition = omap2_pwrdm_wait_transition,
85}; 207};
86 208
87struct pwrdm_ops omap3_pwrdm_operations = { 209struct pwrdm_ops omap3_pwrdm_operations = {
@@ -93,4 +215,13 @@ struct pwrdm_ops omap3_pwrdm_operations = {
93 .pwrdm_read_logic_pwrst = omap3_pwrdm_read_logic_pwrst, 215 .pwrdm_read_logic_pwrst = omap3_pwrdm_read_logic_pwrst,
94 .pwrdm_read_logic_retst = omap3_pwrdm_read_logic_retst, 216 .pwrdm_read_logic_retst = omap3_pwrdm_read_logic_retst,
95 .pwrdm_read_prev_logic_pwrst = omap3_pwrdm_read_prev_logic_pwrst, 217 .pwrdm_read_prev_logic_pwrst = omap3_pwrdm_read_prev_logic_pwrst,
218 .pwrdm_set_mem_onst = omap2_pwrdm_set_mem_onst,
219 .pwrdm_set_mem_retst = omap2_pwrdm_set_mem_retst,
220 .pwrdm_read_mem_pwrst = omap2_pwrdm_read_mem_pwrst,
221 .pwrdm_read_mem_retst = omap2_pwrdm_read_mem_retst,
222 .pwrdm_read_prev_mem_pwrst = omap3_pwrdm_read_prev_mem_pwrst,
223 .pwrdm_clear_all_prev_pwrst = omap3_pwrdm_clear_all_prev_pwrst,
224 .pwrdm_enable_hdwr_sar = omap3_pwrdm_enable_hdwr_sar,
225 .pwrdm_disable_hdwr_sar = omap3_pwrdm_disable_hdwr_sar,
226 .pwrdm_wait_transition = omap2_pwrdm_wait_transition,
96}; 227};
diff --git a/arch/arm/mach-omap2/powerdomain44xx.c b/arch/arm/mach-omap2/powerdomain44xx.c
index 996790acebc9..123a25f3b96f 100644
--- a/arch/arm/mach-omap2/powerdomain44xx.c
+++ b/arch/arm/mach-omap2/powerdomain44xx.c
@@ -47,6 +47,14 @@ static int omap4_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
47 OMAP4430_LASTPOWERSTATEENTERED_MASK); 47 OMAP4430_LASTPOWERSTATEENTERED_MASK);
48} 48}
49 49
50static int omap4_pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)
51{
52 prm_rmw_mod_reg_bits(OMAP4430_LOWPOWERSTATECHANGE_MASK,
53 (1 << OMAP4430_LOWPOWERSTATECHANGE_SHIFT),
54 pwrdm->prcm_offs, OMAP4_PM_PWSTCTRL);
55 return 0;
56}
57
50static int omap4_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst) 58static int omap4_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
51{ 59{
52 u32 v; 60 u32 v;
@@ -58,6 +66,32 @@ static int omap4_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
58 return 0; 66 return 0;
59} 67}
60 68
69static int omap4_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank,
70 u8 pwrst)
71{
72 u32 m;
73
74 m = omap2_pwrdm_get_mem_bank_onstate_mask(bank);
75
76 prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs,
77 OMAP4_PM_PWSTCTRL);
78
79 return 0;
80}
81
82static int omap4_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank,
83 u8 pwrst)
84{
85 u32 m;
86
87 m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
88
89 prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs,
90 OMAP4_PM_PWSTCTRL);
91
92 return 0;
93}
94
61static int omap4_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm) 95static int omap4_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
62{ 96{
63 return prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP4_PM_PWSTST, 97 return prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP4_PM_PWSTST,
@@ -70,12 +104,63 @@ static int omap4_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
70 OMAP4430_LOGICRETSTATE_MASK); 104 OMAP4430_LOGICRETSTATE_MASK);
71} 105}
72 106
107static int omap4_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
108{
109 u32 m;
110
111 m = omap2_pwrdm_get_mem_bank_stst_mask(bank);
112
113 return prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP4_PM_PWSTST, m);
114}
115
116static int omap4_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
117{
118 u32 m;
119
120 m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
121
122 return prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP4_PM_PWSTCTRL, m);
123}
124
125static int omap4_pwrdm_wait_transition(struct powerdomain *pwrdm)
126{
127 u32 c = 0;
128
129 /*
130 * REVISIT: pwrdm_wait_transition() may be better implemented
131 * via a callback and a periodic timer check -- how long do we expect
132 * powerdomain transitions to take?
133 */
134
135 /* XXX Is this udelay() value meaningful? */
136 while ((prm_read_mod_reg(pwrdm->prcm_offs, OMAP4_PM_PWSTST) &
137 OMAP_INTRANSITION_MASK) &&
138 (c++ < PWRDM_TRANSITION_BAILOUT))
139 udelay(1);
140
141 if (c > PWRDM_TRANSITION_BAILOUT) {
142 printk(KERN_ERR "powerdomain: waited too long for "
143 "powerdomain %s to complete transition\n", pwrdm->name);
144 return -EAGAIN;
145 }
146
147 pr_debug("powerdomain: completed transition in %d loops\n", c);
148
149 return 0;
150}
151
73struct pwrdm_ops omap4_pwrdm_operations = { 152struct pwrdm_ops omap4_pwrdm_operations = {
74 .pwrdm_set_next_pwrst = omap4_pwrdm_set_next_pwrst, 153 .pwrdm_set_next_pwrst = omap4_pwrdm_set_next_pwrst,
75 .pwrdm_read_next_pwrst = omap4_pwrdm_read_next_pwrst, 154 .pwrdm_read_next_pwrst = omap4_pwrdm_read_next_pwrst,
76 .pwrdm_read_pwrst = omap4_pwrdm_read_pwrst, 155 .pwrdm_read_pwrst = omap4_pwrdm_read_pwrst,
77 .pwrdm_read_prev_pwrst = omap4_pwrdm_read_prev_pwrst, 156 .pwrdm_read_prev_pwrst = omap4_pwrdm_read_prev_pwrst,
157 .pwrdm_set_lowpwrstchange = omap4_pwrdm_set_lowpwrstchange,
78 .pwrdm_set_logic_retst = omap4_pwrdm_set_logic_retst, 158 .pwrdm_set_logic_retst = omap4_pwrdm_set_logic_retst,
79 .pwrdm_read_logic_pwrst = omap4_pwrdm_read_logic_pwrst, 159 .pwrdm_read_logic_pwrst = omap4_pwrdm_read_logic_pwrst,
80 .pwrdm_read_logic_retst = omap4_pwrdm_read_logic_retst, 160 .pwrdm_read_logic_retst = omap4_pwrdm_read_logic_retst,
161 .pwrdm_read_mem_pwrst = omap4_pwrdm_read_mem_pwrst,
162 .pwrdm_read_mem_retst = omap4_pwrdm_read_mem_retst,
163 .pwrdm_set_mem_onst = omap4_pwrdm_set_mem_onst,
164 .pwrdm_set_mem_retst = omap4_pwrdm_set_mem_retst,
165 .pwrdm_wait_transition = omap4_pwrdm_wait_transition,
81}; 166};
diff --git a/arch/arm/mach-omap2/powerdomains.h b/arch/arm/mach-omap2/powerdomains.h
index e57bc41ef4aa..55cd8e6aa104 100644
--- a/arch/arm/mach-omap2/powerdomains.h
+++ b/arch/arm/mach-omap2/powerdomains.h
@@ -19,4 +19,9 @@ extern struct pwrdm_ops omap2_pwrdm_operations;
19extern struct pwrdm_ops omap3_pwrdm_operations; 19extern struct pwrdm_ops omap3_pwrdm_operations;
20extern struct pwrdm_ops omap4_pwrdm_operations; 20extern struct pwrdm_ops omap4_pwrdm_operations;
21 21
22/* Common Internal functions used across OMAP rev's */
23extern u32 omap2_pwrdm_get_mem_bank_onstate_mask(u8 bank);
24extern u32 omap2_pwrdm_get_mem_bank_retst_mask(u8 bank);
25extern u32 omap2_pwrdm_get_mem_bank_stst_mask(u8 bank);
26
22#endif /* ARCH_ARM_MACH_OMAP2_POWERDOMAINS */ 27#endif /* ARCH_ARM_MACH_OMAP2_POWERDOMAINS */