diff options
-rw-r--r-- | arch/arm/mach-omap2/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/mach-omap2/powerdomain2xxx_3xxx.c | 242 | ||||
-rw-r--r-- | arch/arm/mach-omap2/powerdomain33xx.c | 229 | ||||
-rw-r--r-- | arch/arm/mach-omap2/powerdomain44xx.c | 285 | ||||
-rw-r--r-- | arch/arm/mach-omap2/prm2xxx.c | 41 | ||||
-rw-r--r-- | arch/arm/mach-omap2/prm2xxx_3xxx.c | 112 | ||||
-rw-r--r-- | arch/arm/mach-omap2/prm2xxx_3xxx.h | 13 | ||||
-rw-r--r-- | arch/arm/mach-omap2/prm33xx.c | 202 | ||||
-rw-r--r-- | arch/arm/mach-omap2/prm3xxx.c | 107 | ||||
-rw-r--r-- | arch/arm/mach-omap2/prm44xx.c | 265 |
10 files changed, 739 insertions, 758 deletions
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 20849604be94..7404e3d48cea 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile | |||
@@ -95,6 +95,7 @@ endif | |||
95 | # PRCM | 95 | # PRCM |
96 | obj-y += prcm.o prm_common.o | 96 | obj-y += prcm.o prm_common.o |
97 | obj-$(CONFIG_ARCH_OMAP2) += cm2xxx_3xxx.o prm2xxx_3xxx.o | 97 | obj-$(CONFIG_ARCH_OMAP2) += cm2xxx_3xxx.o prm2xxx_3xxx.o |
98 | obj-$(CONFIG_ARCH_OMAP2) += prm2xxx.o | ||
98 | obj-$(CONFIG_ARCH_OMAP3) += cm2xxx_3xxx.o prm2xxx_3xxx.o | 99 | obj-$(CONFIG_ARCH_OMAP3) += cm2xxx_3xxx.o prm2xxx_3xxx.o |
99 | obj-$(CONFIG_ARCH_OMAP3) += prm3xxx.o | 100 | obj-$(CONFIG_ARCH_OMAP3) += prm3xxx.o |
100 | obj-$(CONFIG_ARCH_OMAP3) += vc3xxx_data.o vp3xxx_data.o | 101 | obj-$(CONFIG_ARCH_OMAP3) += vc3xxx_data.o vp3xxx_data.o |
diff --git a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c b/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c deleted file mode 100644 index 3950ccfe5f4a..000000000000 --- a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c +++ /dev/null | |||
@@ -1,242 +0,0 @@ | |||
1 | /* | ||
2 | * OMAP2 and OMAP3 powerdomain control | ||
3 | * | ||
4 | * Copyright (C) 2009-2011 Texas Instruments, Inc. | ||
5 | * Copyright (C) 2007-2009 Nokia Corporation | ||
6 | * | ||
7 | * Derived from mach-omap2/powerdomain.c written by Paul Walmsley | ||
8 | * Rajendra Nayak <rnayak@ti.com> | ||
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/io.h> | ||
16 | #include <linux/errno.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/bug.h> | ||
19 | |||
20 | #include <plat/prcm.h> | ||
21 | |||
22 | #include "powerdomain.h" | ||
23 | #include "prm.h" | ||
24 | #include "prm-regbits-24xx.h" | ||
25 | #include "prm-regbits-34xx.h" | ||
26 | |||
27 | |||
28 | /* Common functions across OMAP2 and OMAP3 */ | ||
29 | static int omap2_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst) | ||
30 | { | ||
31 | omap2_prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK, | ||
32 | (pwrst << OMAP_POWERSTATE_SHIFT), | ||
33 | pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL); | ||
34 | return 0; | ||
35 | } | ||
36 | |||
37 | static int omap2_pwrdm_read_next_pwrst(struct powerdomain *pwrdm) | ||
38 | { | ||
39 | return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, | ||
40 | OMAP2_PM_PWSTCTRL, | ||
41 | OMAP_POWERSTATE_MASK); | ||
42 | } | ||
43 | |||
44 | static int omap2_pwrdm_read_pwrst(struct powerdomain *pwrdm) | ||
45 | { | ||
46 | return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, | ||
47 | OMAP2_PM_PWSTST, | ||
48 | OMAP_POWERSTATEST_MASK); | ||
49 | } | ||
50 | |||
51 | static int omap2_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, | ||
52 | u8 pwrst) | ||
53 | { | ||
54 | u32 m; | ||
55 | |||
56 | m = omap2_pwrdm_get_mem_bank_onstate_mask(bank); | ||
57 | |||
58 | omap2_prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs, | ||
59 | OMAP2_PM_PWSTCTRL); | ||
60 | |||
61 | return 0; | ||
62 | } | ||
63 | |||
64 | static int omap2_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, | ||
65 | u8 pwrst) | ||
66 | { | ||
67 | u32 m; | ||
68 | |||
69 | m = omap2_pwrdm_get_mem_bank_retst_mask(bank); | ||
70 | |||
71 | omap2_prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs, | ||
72 | OMAP2_PM_PWSTCTRL); | ||
73 | |||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | static int omap2_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank) | ||
78 | { | ||
79 | u32 m; | ||
80 | |||
81 | m = omap2_pwrdm_get_mem_bank_stst_mask(bank); | ||
82 | |||
83 | return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP2_PM_PWSTST, | ||
84 | m); | ||
85 | } | ||
86 | |||
87 | static int omap2_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank) | ||
88 | { | ||
89 | u32 m; | ||
90 | |||
91 | m = omap2_pwrdm_get_mem_bank_retst_mask(bank); | ||
92 | |||
93 | return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, | ||
94 | OMAP2_PM_PWSTCTRL, m); | ||
95 | } | ||
96 | |||
97 | static int omap2_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst) | ||
98 | { | ||
99 | u32 v; | ||
100 | |||
101 | v = pwrst << __ffs(OMAP3430_LOGICL1CACHERETSTATE_MASK); | ||
102 | omap2_prm_rmw_mod_reg_bits(OMAP3430_LOGICL1CACHERETSTATE_MASK, v, | ||
103 | pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL); | ||
104 | |||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | static int omap2_pwrdm_wait_transition(struct powerdomain *pwrdm) | ||
109 | { | ||
110 | u32 c = 0; | ||
111 | |||
112 | /* | ||
113 | * REVISIT: pwrdm_wait_transition() may be better implemented | ||
114 | * via a callback and a periodic timer check -- how long do we expect | ||
115 | * powerdomain transitions to take? | ||
116 | */ | ||
117 | |||
118 | /* XXX Is this udelay() value meaningful? */ | ||
119 | while ((omap2_prm_read_mod_reg(pwrdm->prcm_offs, OMAP2_PM_PWSTST) & | ||
120 | OMAP_INTRANSITION_MASK) && | ||
121 | (c++ < PWRDM_TRANSITION_BAILOUT)) | ||
122 | udelay(1); | ||
123 | |||
124 | if (c > PWRDM_TRANSITION_BAILOUT) { | ||
125 | pr_err("powerdomain: %s: waited too long to complete transition\n", | ||
126 | pwrdm->name); | ||
127 | return -EAGAIN; | ||
128 | } | ||
129 | |||
130 | pr_debug("powerdomain: completed transition in %d loops\n", c); | ||
131 | |||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | /* Applicable only for OMAP3. Not supported on OMAP2 */ | ||
136 | static int omap3_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm) | ||
137 | { | ||
138 | return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, | ||
139 | OMAP3430_PM_PREPWSTST, | ||
140 | OMAP3430_LASTPOWERSTATEENTERED_MASK); | ||
141 | } | ||
142 | |||
143 | static int omap3_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm) | ||
144 | { | ||
145 | return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, | ||
146 | OMAP2_PM_PWSTST, | ||
147 | OMAP3430_LOGICSTATEST_MASK); | ||
148 | } | ||
149 | |||
150 | static int omap3_pwrdm_read_logic_retst(struct powerdomain *pwrdm) | ||
151 | { | ||
152 | return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, | ||
153 | OMAP2_PM_PWSTCTRL, | ||
154 | OMAP3430_LOGICSTATEST_MASK); | ||
155 | } | ||
156 | |||
157 | static int omap3_pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm) | ||
158 | { | ||
159 | return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, | ||
160 | OMAP3430_PM_PREPWSTST, | ||
161 | OMAP3430_LASTLOGICSTATEENTERED_MASK); | ||
162 | } | ||
163 | |||
164 | static int omap3_get_mem_bank_lastmemst_mask(u8 bank) | ||
165 | { | ||
166 | switch (bank) { | ||
167 | case 0: | ||
168 | return OMAP3430_LASTMEM1STATEENTERED_MASK; | ||
169 | case 1: | ||
170 | return OMAP3430_LASTMEM2STATEENTERED_MASK; | ||
171 | case 2: | ||
172 | return OMAP3430_LASTSHAREDL2CACHEFLATSTATEENTERED_MASK; | ||
173 | case 3: | ||
174 | return OMAP3430_LASTL2FLATMEMSTATEENTERED_MASK; | ||
175 | default: | ||
176 | WARN_ON(1); /* should never happen */ | ||
177 | return -EEXIST; | ||
178 | } | ||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | static int omap3_pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank) | ||
183 | { | ||
184 | u32 m; | ||
185 | |||
186 | m = omap3_get_mem_bank_lastmemst_mask(bank); | ||
187 | |||
188 | return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, | ||
189 | OMAP3430_PM_PREPWSTST, m); | ||
190 | } | ||
191 | |||
192 | static int omap3_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm) | ||
193 | { | ||
194 | omap2_prm_write_mod_reg(0, pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST); | ||
195 | return 0; | ||
196 | } | ||
197 | |||
198 | static int omap3_pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm) | ||
199 | { | ||
200 | return omap2_prm_rmw_mod_reg_bits(0, | ||
201 | 1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT, | ||
202 | pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL); | ||
203 | } | ||
204 | |||
205 | static int omap3_pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm) | ||
206 | { | ||
207 | return omap2_prm_rmw_mod_reg_bits(1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT, | ||
208 | 0, pwrdm->prcm_offs, | ||
209 | OMAP2_PM_PWSTCTRL); | ||
210 | } | ||
211 | |||
212 | struct pwrdm_ops omap2_pwrdm_operations = { | ||
213 | .pwrdm_set_next_pwrst = omap2_pwrdm_set_next_pwrst, | ||
214 | .pwrdm_read_next_pwrst = omap2_pwrdm_read_next_pwrst, | ||
215 | .pwrdm_read_pwrst = omap2_pwrdm_read_pwrst, | ||
216 | .pwrdm_set_logic_retst = omap2_pwrdm_set_logic_retst, | ||
217 | .pwrdm_set_mem_onst = omap2_pwrdm_set_mem_onst, | ||
218 | .pwrdm_set_mem_retst = omap2_pwrdm_set_mem_retst, | ||
219 | .pwrdm_read_mem_pwrst = omap2_pwrdm_read_mem_pwrst, | ||
220 | .pwrdm_read_mem_retst = omap2_pwrdm_read_mem_retst, | ||
221 | .pwrdm_wait_transition = omap2_pwrdm_wait_transition, | ||
222 | }; | ||
223 | |||
224 | struct pwrdm_ops omap3_pwrdm_operations = { | ||
225 | .pwrdm_set_next_pwrst = omap2_pwrdm_set_next_pwrst, | ||
226 | .pwrdm_read_next_pwrst = omap2_pwrdm_read_next_pwrst, | ||
227 | .pwrdm_read_pwrst = omap2_pwrdm_read_pwrst, | ||
228 | .pwrdm_read_prev_pwrst = omap3_pwrdm_read_prev_pwrst, | ||
229 | .pwrdm_set_logic_retst = omap2_pwrdm_set_logic_retst, | ||
230 | .pwrdm_read_logic_pwrst = omap3_pwrdm_read_logic_pwrst, | ||
231 | .pwrdm_read_logic_retst = omap3_pwrdm_read_logic_retst, | ||
232 | .pwrdm_read_prev_logic_pwrst = omap3_pwrdm_read_prev_logic_pwrst, | ||
233 | .pwrdm_set_mem_onst = omap2_pwrdm_set_mem_onst, | ||
234 | .pwrdm_set_mem_retst = omap2_pwrdm_set_mem_retst, | ||
235 | .pwrdm_read_mem_pwrst = omap2_pwrdm_read_mem_pwrst, | ||
236 | .pwrdm_read_mem_retst = omap2_pwrdm_read_mem_retst, | ||
237 | .pwrdm_read_prev_mem_pwrst = omap3_pwrdm_read_prev_mem_pwrst, | ||
238 | .pwrdm_clear_all_prev_pwrst = omap3_pwrdm_clear_all_prev_pwrst, | ||
239 | .pwrdm_enable_hdwr_sar = omap3_pwrdm_enable_hdwr_sar, | ||
240 | .pwrdm_disable_hdwr_sar = omap3_pwrdm_disable_hdwr_sar, | ||
241 | .pwrdm_wait_transition = omap2_pwrdm_wait_transition, | ||
242 | }; | ||
diff --git a/arch/arm/mach-omap2/powerdomain33xx.c b/arch/arm/mach-omap2/powerdomain33xx.c deleted file mode 100644 index 67c5663899b6..000000000000 --- a/arch/arm/mach-omap2/powerdomain33xx.c +++ /dev/null | |||
@@ -1,229 +0,0 @@ | |||
1 | /* | ||
2 | * AM33XX Powerdomain control | ||
3 | * | ||
4 | * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/ | ||
5 | * | ||
6 | * Derived from mach-omap2/powerdomain44xx.c written by Rajendra Nayak | ||
7 | * <rnayak@ti.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License as | ||
11 | * published by the Free Software Foundation version 2. | ||
12 | * | ||
13 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
14 | * kind, whether express or implied; without even the implied warranty | ||
15 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | */ | ||
18 | |||
19 | #include <linux/io.h> | ||
20 | #include <linux/errno.h> | ||
21 | #include <linux/delay.h> | ||
22 | |||
23 | #include <plat/prcm.h> | ||
24 | |||
25 | #include "powerdomain.h" | ||
26 | #include "prm33xx.h" | ||
27 | #include "prm-regbits-33xx.h" | ||
28 | |||
29 | |||
30 | static int am33xx_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst) | ||
31 | { | ||
32 | am33xx_prm_rmw_reg_bits(OMAP_POWERSTATE_MASK, | ||
33 | (pwrst << OMAP_POWERSTATE_SHIFT), | ||
34 | pwrdm->prcm_offs, pwrdm->pwrstctrl_offs); | ||
35 | return 0; | ||
36 | } | ||
37 | |||
38 | static int am33xx_pwrdm_read_next_pwrst(struct powerdomain *pwrdm) | ||
39 | { | ||
40 | u32 v; | ||
41 | |||
42 | v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs); | ||
43 | v &= OMAP_POWERSTATE_MASK; | ||
44 | v >>= OMAP_POWERSTATE_SHIFT; | ||
45 | |||
46 | return v; | ||
47 | } | ||
48 | |||
49 | static int am33xx_pwrdm_read_pwrst(struct powerdomain *pwrdm) | ||
50 | { | ||
51 | u32 v; | ||
52 | |||
53 | v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs); | ||
54 | v &= OMAP_POWERSTATEST_MASK; | ||
55 | v >>= OMAP_POWERSTATEST_SHIFT; | ||
56 | |||
57 | return v; | ||
58 | } | ||
59 | |||
60 | static int am33xx_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm) | ||
61 | { | ||
62 | u32 v; | ||
63 | |||
64 | v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs); | ||
65 | v &= AM33XX_LASTPOWERSTATEENTERED_MASK; | ||
66 | v >>= AM33XX_LASTPOWERSTATEENTERED_SHIFT; | ||
67 | |||
68 | return v; | ||
69 | } | ||
70 | |||
71 | static int am33xx_pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm) | ||
72 | { | ||
73 | am33xx_prm_rmw_reg_bits(AM33XX_LOWPOWERSTATECHANGE_MASK, | ||
74 | (1 << AM33XX_LOWPOWERSTATECHANGE_SHIFT), | ||
75 | pwrdm->prcm_offs, pwrdm->pwrstctrl_offs); | ||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | static int am33xx_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm) | ||
80 | { | ||
81 | am33xx_prm_rmw_reg_bits(AM33XX_LASTPOWERSTATEENTERED_MASK, | ||
82 | AM33XX_LASTPOWERSTATEENTERED_MASK, | ||
83 | pwrdm->prcm_offs, pwrdm->pwrstst_offs); | ||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | static int am33xx_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst) | ||
88 | { | ||
89 | u32 m; | ||
90 | |||
91 | m = pwrdm->logicretstate_mask; | ||
92 | if (!m) | ||
93 | return -EINVAL; | ||
94 | |||
95 | am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)), | ||
96 | pwrdm->prcm_offs, pwrdm->pwrstctrl_offs); | ||
97 | |||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | static int am33xx_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm) | ||
102 | { | ||
103 | u32 v; | ||
104 | |||
105 | v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs); | ||
106 | v &= AM33XX_LOGICSTATEST_MASK; | ||
107 | v >>= AM33XX_LOGICSTATEST_SHIFT; | ||
108 | |||
109 | return v; | ||
110 | } | ||
111 | |||
112 | static int am33xx_pwrdm_read_logic_retst(struct powerdomain *pwrdm) | ||
113 | { | ||
114 | u32 v, m; | ||
115 | |||
116 | m = pwrdm->logicretstate_mask; | ||
117 | if (!m) | ||
118 | return -EINVAL; | ||
119 | |||
120 | v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs); | ||
121 | v &= m; | ||
122 | v >>= __ffs(m); | ||
123 | |||
124 | return v; | ||
125 | } | ||
126 | |||
127 | static int am33xx_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, | ||
128 | u8 pwrst) | ||
129 | { | ||
130 | u32 m; | ||
131 | |||
132 | m = pwrdm->mem_on_mask[bank]; | ||
133 | if (!m) | ||
134 | return -EINVAL; | ||
135 | |||
136 | am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)), | ||
137 | pwrdm->prcm_offs, pwrdm->pwrstctrl_offs); | ||
138 | |||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | static int am33xx_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, | ||
143 | u8 pwrst) | ||
144 | { | ||
145 | u32 m; | ||
146 | |||
147 | m = pwrdm->mem_ret_mask[bank]; | ||
148 | if (!m) | ||
149 | return -EINVAL; | ||
150 | |||
151 | am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)), | ||
152 | pwrdm->prcm_offs, pwrdm->pwrstctrl_offs); | ||
153 | |||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | static int am33xx_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank) | ||
158 | { | ||
159 | u32 m, v; | ||
160 | |||
161 | m = pwrdm->mem_pwrst_mask[bank]; | ||
162 | if (!m) | ||
163 | return -EINVAL; | ||
164 | |||
165 | v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs); | ||
166 | v &= m; | ||
167 | v >>= __ffs(m); | ||
168 | |||
169 | return v; | ||
170 | } | ||
171 | |||
172 | static int am33xx_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank) | ||
173 | { | ||
174 | u32 m, v; | ||
175 | |||
176 | m = pwrdm->mem_retst_mask[bank]; | ||
177 | if (!m) | ||
178 | return -EINVAL; | ||
179 | |||
180 | v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs); | ||
181 | v &= m; | ||
182 | v >>= __ffs(m); | ||
183 | |||
184 | return v; | ||
185 | } | ||
186 | |||
187 | static int am33xx_pwrdm_wait_transition(struct powerdomain *pwrdm) | ||
188 | { | ||
189 | u32 c = 0; | ||
190 | |||
191 | /* | ||
192 | * REVISIT: pwrdm_wait_transition() may be better implemented | ||
193 | * via a callback and a periodic timer check -- how long do we expect | ||
194 | * powerdomain transitions to take? | ||
195 | */ | ||
196 | |||
197 | /* XXX Is this udelay() value meaningful? */ | ||
198 | while ((am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs) | ||
199 | & OMAP_INTRANSITION_MASK) && | ||
200 | (c++ < PWRDM_TRANSITION_BAILOUT)) | ||
201 | udelay(1); | ||
202 | |||
203 | if (c > PWRDM_TRANSITION_BAILOUT) { | ||
204 | pr_err("powerdomain: %s: waited too long to complete transition\n", | ||
205 | pwrdm->name); | ||
206 | return -EAGAIN; | ||
207 | } | ||
208 | |||
209 | pr_debug("powerdomain: completed transition in %d loops\n", c); | ||
210 | |||
211 | return 0; | ||
212 | } | ||
213 | |||
214 | struct pwrdm_ops am33xx_pwrdm_operations = { | ||
215 | .pwrdm_set_next_pwrst = am33xx_pwrdm_set_next_pwrst, | ||
216 | .pwrdm_read_next_pwrst = am33xx_pwrdm_read_next_pwrst, | ||
217 | .pwrdm_read_pwrst = am33xx_pwrdm_read_pwrst, | ||
218 | .pwrdm_read_prev_pwrst = am33xx_pwrdm_read_prev_pwrst, | ||
219 | .pwrdm_set_logic_retst = am33xx_pwrdm_set_logic_retst, | ||
220 | .pwrdm_read_logic_pwrst = am33xx_pwrdm_read_logic_pwrst, | ||
221 | .pwrdm_read_logic_retst = am33xx_pwrdm_read_logic_retst, | ||
222 | .pwrdm_clear_all_prev_pwrst = am33xx_pwrdm_clear_all_prev_pwrst, | ||
223 | .pwrdm_set_lowpwrstchange = am33xx_pwrdm_set_lowpwrstchange, | ||
224 | .pwrdm_read_mem_pwrst = am33xx_pwrdm_read_mem_pwrst, | ||
225 | .pwrdm_read_mem_retst = am33xx_pwrdm_read_mem_retst, | ||
226 | .pwrdm_set_mem_onst = am33xx_pwrdm_set_mem_onst, | ||
227 | .pwrdm_set_mem_retst = am33xx_pwrdm_set_mem_retst, | ||
228 | .pwrdm_wait_transition = am33xx_pwrdm_wait_transition, | ||
229 | }; | ||
diff --git a/arch/arm/mach-omap2/powerdomain44xx.c b/arch/arm/mach-omap2/powerdomain44xx.c deleted file mode 100644 index aceb4f464c9b..000000000000 --- a/arch/arm/mach-omap2/powerdomain44xx.c +++ /dev/null | |||
@@ -1,285 +0,0 @@ | |||
1 | /* | ||
2 | * OMAP4 powerdomain control | ||
3 | * | ||
4 | * Copyright (C) 2009-2010, 2012 Texas Instruments, Inc. | ||
5 | * Copyright (C) 2007-2009 Nokia Corporation | ||
6 | * | ||
7 | * Derived from mach-omap2/powerdomain.c written by Paul Walmsley | ||
8 | * Rajendra Nayak <rnayak@ti.com> | ||
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/io.h> | ||
16 | #include <linux/errno.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/bug.h> | ||
19 | |||
20 | #include "powerdomain.h" | ||
21 | #include <plat/prcm.h> | ||
22 | #include "prm2xxx_3xxx.h" | ||
23 | #include "prm44xx.h" | ||
24 | #include "prminst44xx.h" | ||
25 | #include "prm-regbits-44xx.h" | ||
26 | |||
27 | static int omap4_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst) | ||
28 | { | ||
29 | omap4_prminst_rmw_inst_reg_bits(OMAP_POWERSTATE_MASK, | ||
30 | (pwrst << OMAP_POWERSTATE_SHIFT), | ||
31 | pwrdm->prcm_partition, | ||
32 | pwrdm->prcm_offs, OMAP4_PM_PWSTCTRL); | ||
33 | return 0; | ||
34 | } | ||
35 | |||
36 | static int omap4_pwrdm_read_next_pwrst(struct powerdomain *pwrdm) | ||
37 | { | ||
38 | u32 v; | ||
39 | |||
40 | v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs, | ||
41 | OMAP4_PM_PWSTCTRL); | ||
42 | v &= OMAP_POWERSTATE_MASK; | ||
43 | v >>= OMAP_POWERSTATE_SHIFT; | ||
44 | |||
45 | return v; | ||
46 | } | ||
47 | |||
48 | static int omap4_pwrdm_read_pwrst(struct powerdomain *pwrdm) | ||
49 | { | ||
50 | u32 v; | ||
51 | |||
52 | v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs, | ||
53 | OMAP4_PM_PWSTST); | ||
54 | v &= OMAP_POWERSTATEST_MASK; | ||
55 | v >>= OMAP_POWERSTATEST_SHIFT; | ||
56 | |||
57 | return v; | ||
58 | } | ||
59 | |||
60 | static int omap4_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm) | ||
61 | { | ||
62 | u32 v; | ||
63 | |||
64 | v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs, | ||
65 | OMAP4_PM_PWSTST); | ||
66 | v &= OMAP4430_LASTPOWERSTATEENTERED_MASK; | ||
67 | v >>= OMAP4430_LASTPOWERSTATEENTERED_SHIFT; | ||
68 | |||
69 | return v; | ||
70 | } | ||
71 | |||
72 | static int omap4_pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm) | ||
73 | { | ||
74 | omap4_prminst_rmw_inst_reg_bits(OMAP4430_LOWPOWERSTATECHANGE_MASK, | ||
75 | (1 << OMAP4430_LOWPOWERSTATECHANGE_SHIFT), | ||
76 | pwrdm->prcm_partition, | ||
77 | pwrdm->prcm_offs, OMAP4_PM_PWSTCTRL); | ||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | static int omap4_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm) | ||
82 | { | ||
83 | omap4_prminst_rmw_inst_reg_bits(OMAP4430_LASTPOWERSTATEENTERED_MASK, | ||
84 | OMAP4430_LASTPOWERSTATEENTERED_MASK, | ||
85 | pwrdm->prcm_partition, | ||
86 | pwrdm->prcm_offs, OMAP4_PM_PWSTST); | ||
87 | return 0; | ||
88 | } | ||
89 | |||
90 | static int omap4_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst) | ||
91 | { | ||
92 | u32 v; | ||
93 | |||
94 | v = pwrst << __ffs(OMAP4430_LOGICRETSTATE_MASK); | ||
95 | omap4_prminst_rmw_inst_reg_bits(OMAP4430_LOGICRETSTATE_MASK, v, | ||
96 | pwrdm->prcm_partition, pwrdm->prcm_offs, | ||
97 | OMAP4_PM_PWSTCTRL); | ||
98 | |||
99 | return 0; | ||
100 | } | ||
101 | |||
102 | static int omap4_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, | ||
103 | u8 pwrst) | ||
104 | { | ||
105 | u32 m; | ||
106 | |||
107 | m = omap2_pwrdm_get_mem_bank_onstate_mask(bank); | ||
108 | |||
109 | omap4_prminst_rmw_inst_reg_bits(m, (pwrst << __ffs(m)), | ||
110 | pwrdm->prcm_partition, pwrdm->prcm_offs, | ||
111 | OMAP4_PM_PWSTCTRL); | ||
112 | |||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | static int omap4_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, | ||
117 | u8 pwrst) | ||
118 | { | ||
119 | u32 m; | ||
120 | |||
121 | m = omap2_pwrdm_get_mem_bank_retst_mask(bank); | ||
122 | |||
123 | omap4_prminst_rmw_inst_reg_bits(m, (pwrst << __ffs(m)), | ||
124 | pwrdm->prcm_partition, pwrdm->prcm_offs, | ||
125 | OMAP4_PM_PWSTCTRL); | ||
126 | |||
127 | return 0; | ||
128 | } | ||
129 | |||
130 | static int omap4_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm) | ||
131 | { | ||
132 | u32 v; | ||
133 | |||
134 | v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs, | ||
135 | OMAP4_PM_PWSTST); | ||
136 | v &= OMAP4430_LOGICSTATEST_MASK; | ||
137 | v >>= OMAP4430_LOGICSTATEST_SHIFT; | ||
138 | |||
139 | return v; | ||
140 | } | ||
141 | |||
142 | static int omap4_pwrdm_read_logic_retst(struct powerdomain *pwrdm) | ||
143 | { | ||
144 | u32 v; | ||
145 | |||
146 | v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs, | ||
147 | OMAP4_PM_PWSTCTRL); | ||
148 | v &= OMAP4430_LOGICRETSTATE_MASK; | ||
149 | v >>= OMAP4430_LOGICRETSTATE_SHIFT; | ||
150 | |||
151 | return v; | ||
152 | } | ||
153 | |||
154 | /** | ||
155 | * omap4_pwrdm_read_prev_logic_pwrst - read the previous logic powerstate | ||
156 | * @pwrdm: struct powerdomain * to read the state for | ||
157 | * | ||
158 | * Reads the previous logic powerstate for a powerdomain. This | ||
159 | * function must determine the previous logic powerstate by first | ||
160 | * checking the previous powerstate for the domain. If that was OFF, | ||
161 | * then logic has been lost. If previous state was RETENTION, the | ||
162 | * function reads the setting for the next retention logic state to | ||
163 | * see the actual value. In every other case, the logic is | ||
164 | * retained. Returns either PWRDM_POWER_OFF or PWRDM_POWER_RET | ||
165 | * depending whether the logic was retained or not. | ||
166 | */ | ||
167 | static int omap4_pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm) | ||
168 | { | ||
169 | int state; | ||
170 | |||
171 | state = omap4_pwrdm_read_prev_pwrst(pwrdm); | ||
172 | |||
173 | if (state == PWRDM_POWER_OFF) | ||
174 | return PWRDM_POWER_OFF; | ||
175 | |||
176 | if (state != PWRDM_POWER_RET) | ||
177 | return PWRDM_POWER_RET; | ||
178 | |||
179 | return omap4_pwrdm_read_logic_retst(pwrdm); | ||
180 | } | ||
181 | |||
182 | static int omap4_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank) | ||
183 | { | ||
184 | u32 m, v; | ||
185 | |||
186 | m = omap2_pwrdm_get_mem_bank_stst_mask(bank); | ||
187 | |||
188 | v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs, | ||
189 | OMAP4_PM_PWSTST); | ||
190 | v &= m; | ||
191 | v >>= __ffs(m); | ||
192 | |||
193 | return v; | ||
194 | } | ||
195 | |||
196 | static int omap4_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank) | ||
197 | { | ||
198 | u32 m, v; | ||
199 | |||
200 | m = omap2_pwrdm_get_mem_bank_retst_mask(bank); | ||
201 | |||
202 | v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs, | ||
203 | OMAP4_PM_PWSTCTRL); | ||
204 | v &= m; | ||
205 | v >>= __ffs(m); | ||
206 | |||
207 | return v; | ||
208 | } | ||
209 | |||
210 | /** | ||
211 | * omap4_pwrdm_read_prev_mem_pwrst - reads the previous memory powerstate | ||
212 | * @pwrdm: struct powerdomain * to read mem powerstate for | ||
213 | * @bank: memory bank index | ||
214 | * | ||
215 | * Reads the previous memory powerstate for a powerdomain. This | ||
216 | * function must determine the previous memory powerstate by first | ||
217 | * checking the previous powerstate for the domain. If that was OFF, | ||
218 | * then logic has been lost. If previous state was RETENTION, the | ||
219 | * function reads the setting for the next memory retention state to | ||
220 | * see the actual value. In every other case, the logic is | ||
221 | * retained. Returns either PWRDM_POWER_OFF or PWRDM_POWER_RET | ||
222 | * depending whether logic was retained or not. | ||
223 | */ | ||
224 | static int omap4_pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank) | ||
225 | { | ||
226 | int state; | ||
227 | |||
228 | state = omap4_pwrdm_read_prev_pwrst(pwrdm); | ||
229 | |||
230 | if (state == PWRDM_POWER_OFF) | ||
231 | return PWRDM_POWER_OFF; | ||
232 | |||
233 | if (state != PWRDM_POWER_RET) | ||
234 | return PWRDM_POWER_RET; | ||
235 | |||
236 | return omap4_pwrdm_read_mem_retst(pwrdm, bank); | ||
237 | } | ||
238 | |||
239 | static int omap4_pwrdm_wait_transition(struct powerdomain *pwrdm) | ||
240 | { | ||
241 | u32 c = 0; | ||
242 | |||
243 | /* | ||
244 | * REVISIT: pwrdm_wait_transition() may be better implemented | ||
245 | * via a callback and a periodic timer check -- how long do we expect | ||
246 | * powerdomain transitions to take? | ||
247 | */ | ||
248 | |||
249 | /* XXX Is this udelay() value meaningful? */ | ||
250 | while ((omap4_prminst_read_inst_reg(pwrdm->prcm_partition, | ||
251 | pwrdm->prcm_offs, | ||
252 | OMAP4_PM_PWSTST) & | ||
253 | OMAP_INTRANSITION_MASK) && | ||
254 | (c++ < PWRDM_TRANSITION_BAILOUT)) | ||
255 | udelay(1); | ||
256 | |||
257 | if (c > PWRDM_TRANSITION_BAILOUT) { | ||
258 | pr_err("powerdomain: %s: waited too long to complete transition\n", | ||
259 | pwrdm->name); | ||
260 | return -EAGAIN; | ||
261 | } | ||
262 | |||
263 | pr_debug("powerdomain: completed transition in %d loops\n", c); | ||
264 | |||
265 | return 0; | ||
266 | } | ||
267 | |||
268 | struct pwrdm_ops omap4_pwrdm_operations = { | ||
269 | .pwrdm_set_next_pwrst = omap4_pwrdm_set_next_pwrst, | ||
270 | .pwrdm_read_next_pwrst = omap4_pwrdm_read_next_pwrst, | ||
271 | .pwrdm_read_pwrst = omap4_pwrdm_read_pwrst, | ||
272 | .pwrdm_read_prev_pwrst = omap4_pwrdm_read_prev_pwrst, | ||
273 | .pwrdm_set_lowpwrstchange = omap4_pwrdm_set_lowpwrstchange, | ||
274 | .pwrdm_clear_all_prev_pwrst = omap4_pwrdm_clear_all_prev_pwrst, | ||
275 | .pwrdm_set_logic_retst = omap4_pwrdm_set_logic_retst, | ||
276 | .pwrdm_read_logic_pwrst = omap4_pwrdm_read_logic_pwrst, | ||
277 | .pwrdm_read_prev_logic_pwrst = omap4_pwrdm_read_prev_logic_pwrst, | ||
278 | .pwrdm_read_logic_retst = omap4_pwrdm_read_logic_retst, | ||
279 | .pwrdm_read_mem_pwrst = omap4_pwrdm_read_mem_pwrst, | ||
280 | .pwrdm_read_mem_retst = omap4_pwrdm_read_mem_retst, | ||
281 | .pwrdm_read_prev_mem_pwrst = omap4_pwrdm_read_prev_mem_pwrst, | ||
282 | .pwrdm_set_mem_onst = omap4_pwrdm_set_mem_onst, | ||
283 | .pwrdm_set_mem_retst = omap4_pwrdm_set_mem_retst, | ||
284 | .pwrdm_wait_transition = omap4_pwrdm_wait_transition, | ||
285 | }; | ||
diff --git a/arch/arm/mach-omap2/prm2xxx.c b/arch/arm/mach-omap2/prm2xxx.c new file mode 100644 index 000000000000..218ef6a1f11e --- /dev/null +++ b/arch/arm/mach-omap2/prm2xxx.c | |||
@@ -0,0 +1,41 @@ | |||
1 | /* | ||
2 | * OMAP2xxx PRM module functions | ||
3 | * | ||
4 | * Copyright (C) 2010-2012 Texas Instruments, Inc. | ||
5 | * Copyright (C) 2010 Nokia Corporation | ||
6 | * Benoît Cousson | ||
7 | * Paul Walmsley | ||
8 | * Rajendra Nayak <rnayak@ti.com> | ||
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/kernel.h> | ||
16 | #include <linux/errno.h> | ||
17 | #include <linux/err.h> | ||
18 | #include <linux/io.h> | ||
19 | #include <linux/irq.h> | ||
20 | |||
21 | #include "common.h" | ||
22 | #include <plat/cpu.h> | ||
23 | #include <plat/prcm.h> | ||
24 | |||
25 | #include "vp.h" | ||
26 | #include "powerdomain.h" | ||
27 | #include "prm2xxx.h" | ||
28 | #include "cm2xxx_3xxx.h" | ||
29 | #include "prm-regbits-24xx.h" | ||
30 | |||
31 | struct pwrdm_ops omap2_pwrdm_operations = { | ||
32 | .pwrdm_set_next_pwrst = omap2_pwrdm_set_next_pwrst, | ||
33 | .pwrdm_read_next_pwrst = omap2_pwrdm_read_next_pwrst, | ||
34 | .pwrdm_read_pwrst = omap2_pwrdm_read_pwrst, | ||
35 | .pwrdm_set_logic_retst = omap2_pwrdm_set_logic_retst, | ||
36 | .pwrdm_set_mem_onst = omap2_pwrdm_set_mem_onst, | ||
37 | .pwrdm_set_mem_retst = omap2_pwrdm_set_mem_retst, | ||
38 | .pwrdm_read_mem_pwrst = omap2_pwrdm_read_mem_pwrst, | ||
39 | .pwrdm_read_mem_retst = omap2_pwrdm_read_mem_retst, | ||
40 | .pwrdm_wait_transition = omap2_pwrdm_wait_transition, | ||
41 | }; | ||
diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.c b/arch/arm/mach-omap2/prm2xxx_3xxx.c index 0d6cc543987d..bdddf5ca67c4 100644 --- a/arch/arm/mach-omap2/prm2xxx_3xxx.c +++ b/arch/arm/mach-omap2/prm2xxx_3xxx.c | |||
@@ -17,7 +17,7 @@ | |||
17 | #include <linux/io.h> | 17 | #include <linux/io.h> |
18 | 18 | ||
19 | #include "common.h" | 19 | #include "common.h" |
20 | 20 | #include "powerdomain.h" | |
21 | #include "prm2xxx_3xxx.h" | 21 | #include "prm2xxx_3xxx.h" |
22 | #include "prm-regbits-24xx.h" | 22 | #include "prm-regbits-24xx.h" |
23 | 23 | ||
@@ -98,3 +98,113 @@ int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift, u8 st_shift) | |||
98 | return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0; | 98 | return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0; |
99 | } | 99 | } |
100 | 100 | ||
101 | |||
102 | /* Powerdomain low-level functions */ | ||
103 | |||
104 | /* Common functions across OMAP2 and OMAP3 */ | ||
105 | int omap2_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst) | ||
106 | { | ||
107 | omap2_prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK, | ||
108 | (pwrst << OMAP_POWERSTATE_SHIFT), | ||
109 | pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL); | ||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | int omap2_pwrdm_read_next_pwrst(struct powerdomain *pwrdm) | ||
114 | { | ||
115 | return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, | ||
116 | OMAP2_PM_PWSTCTRL, | ||
117 | OMAP_POWERSTATE_MASK); | ||
118 | } | ||
119 | |||
120 | int omap2_pwrdm_read_pwrst(struct powerdomain *pwrdm) | ||
121 | { | ||
122 | return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, | ||
123 | OMAP2_PM_PWSTST, | ||
124 | OMAP_POWERSTATEST_MASK); | ||
125 | } | ||
126 | |||
127 | int omap2_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, | ||
128 | u8 pwrst) | ||
129 | { | ||
130 | u32 m; | ||
131 | |||
132 | m = omap2_pwrdm_get_mem_bank_onstate_mask(bank); | ||
133 | |||
134 | omap2_prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs, | ||
135 | OMAP2_PM_PWSTCTRL); | ||
136 | |||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | int omap2_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, | ||
141 | u8 pwrst) | ||
142 | { | ||
143 | u32 m; | ||
144 | |||
145 | m = omap2_pwrdm_get_mem_bank_retst_mask(bank); | ||
146 | |||
147 | omap2_prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs, | ||
148 | OMAP2_PM_PWSTCTRL); | ||
149 | |||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | int omap2_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank) | ||
154 | { | ||
155 | u32 m; | ||
156 | |||
157 | m = omap2_pwrdm_get_mem_bank_stst_mask(bank); | ||
158 | |||
159 | return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP2_PM_PWSTST, | ||
160 | m); | ||
161 | } | ||
162 | |||
163 | int omap2_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank) | ||
164 | { | ||
165 | u32 m; | ||
166 | |||
167 | m = omap2_pwrdm_get_mem_bank_retst_mask(bank); | ||
168 | |||
169 | return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, | ||
170 | OMAP2_PM_PWSTCTRL, m); | ||
171 | } | ||
172 | |||
173 | int omap2_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst) | ||
174 | { | ||
175 | u32 v; | ||
176 | |||
177 | v = pwrst << __ffs(OMAP_LOGICRETSTATE_MASK); | ||
178 | omap2_prm_rmw_mod_reg_bits(OMAP_LOGICRETSTATE_MASK, v, pwrdm->prcm_offs, | ||
179 | OMAP2_PM_PWSTCTRL); | ||
180 | |||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | int omap2_pwrdm_wait_transition(struct powerdomain *pwrdm) | ||
185 | { | ||
186 | u32 c = 0; | ||
187 | |||
188 | /* | ||
189 | * REVISIT: pwrdm_wait_transition() may be better implemented | ||
190 | * via a callback and a periodic timer check -- how long do we expect | ||
191 | * powerdomain transitions to take? | ||
192 | */ | ||
193 | |||
194 | /* XXX Is this udelay() value meaningful? */ | ||
195 | while ((omap2_prm_read_mod_reg(pwrdm->prcm_offs, OMAP2_PM_PWSTST) & | ||
196 | OMAP_INTRANSITION_MASK) && | ||
197 | (c++ < PWRDM_TRANSITION_BAILOUT)) | ||
198 | udelay(1); | ||
199 | |||
200 | if (c > PWRDM_TRANSITION_BAILOUT) { | ||
201 | pr_err("powerdomain: %s: waited too long to complete transition\n", | ||
202 | pwrdm->name); | ||
203 | return -EAGAIN; | ||
204 | } | ||
205 | |||
206 | pr_debug("powerdomain: completed transition in %d loops\n", c); | ||
207 | |||
208 | return 0; | ||
209 | } | ||
210 | |||
diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.h b/arch/arm/mach-omap2/prm2xxx_3xxx.h index 8d09a1ac9311..706b0262f3f0 100644 --- a/arch/arm/mach-omap2/prm2xxx_3xxx.h +++ b/arch/arm/mach-omap2/prm2xxx_3xxx.h | |||
@@ -50,6 +50,7 @@ | |||
50 | #ifndef __ASSEMBLER__ | 50 | #ifndef __ASSEMBLER__ |
51 | 51 | ||
52 | #include <linux/io.h> | 52 | #include <linux/io.h> |
53 | #include "powerdomain.h" | ||
53 | 54 | ||
54 | /* Power/reset management domain register get/set */ | 55 | /* Power/reset management domain register get/set */ |
55 | static inline u32 omap2_prm_read_mod_reg(s16 module, u16 idx) | 56 | static inline u32 omap2_prm_read_mod_reg(s16 module, u16 idx) |
@@ -103,6 +104,18 @@ extern int omap2_prm_is_hardreset_asserted(s16 prm_mod, u8 shift); | |||
103 | extern int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift); | 104 | extern int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift); |
104 | extern int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift, u8 st_shift); | 105 | extern int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift, u8 st_shift); |
105 | 106 | ||
107 | extern int omap2_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst); | ||
108 | extern int omap2_pwrdm_read_next_pwrst(struct powerdomain *pwrdm); | ||
109 | extern int omap2_pwrdm_read_pwrst(struct powerdomain *pwrdm); | ||
110 | extern int omap2_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, | ||
111 | u8 pwrst); | ||
112 | extern int omap2_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, | ||
113 | u8 pwrst); | ||
114 | extern int omap2_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank); | ||
115 | extern int omap2_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank); | ||
116 | extern int omap2_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst); | ||
117 | extern int omap2_pwrdm_wait_transition(struct powerdomain *pwrdm); | ||
118 | |||
106 | #endif /* __ASSEMBLER */ | 119 | #endif /* __ASSEMBLER */ |
107 | 120 | ||
108 | /* | 121 | /* |
diff --git a/arch/arm/mach-omap2/prm33xx.c b/arch/arm/mach-omap2/prm33xx.c index e7dbb6cf1255..3417dd3a7c37 100644 --- a/arch/arm/mach-omap2/prm33xx.c +++ b/arch/arm/mach-omap2/prm33xx.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <plat/common.h> | 22 | #include <plat/common.h> |
23 | 23 | ||
24 | #include "common.h" | 24 | #include "common.h" |
25 | #include "powerdomain.h" | ||
25 | #include "prm33xx.h" | 26 | #include "prm33xx.h" |
26 | #include "prm-regbits-33xx.h" | 27 | #include "prm-regbits-33xx.h" |
27 | 28 | ||
@@ -133,3 +134,204 @@ int am33xx_prm_deassert_hardreset(u8 shift, s16 inst, | |||
133 | 134 | ||
134 | return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0; | 135 | return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0; |
135 | } | 136 | } |
137 | |||
138 | static int am33xx_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst) | ||
139 | { | ||
140 | am33xx_prm_rmw_reg_bits(OMAP_POWERSTATE_MASK, | ||
141 | (pwrst << OMAP_POWERSTATE_SHIFT), | ||
142 | pwrdm->prcm_offs, pwrdm->pwrstctrl_offs); | ||
143 | return 0; | ||
144 | } | ||
145 | |||
146 | static int am33xx_pwrdm_read_next_pwrst(struct powerdomain *pwrdm) | ||
147 | { | ||
148 | u32 v; | ||
149 | |||
150 | v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs); | ||
151 | v &= OMAP_POWERSTATE_MASK; | ||
152 | v >>= OMAP_POWERSTATE_SHIFT; | ||
153 | |||
154 | return v; | ||
155 | } | ||
156 | |||
157 | static int am33xx_pwrdm_read_pwrst(struct powerdomain *pwrdm) | ||
158 | { | ||
159 | u32 v; | ||
160 | |||
161 | v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs); | ||
162 | v &= OMAP_POWERSTATEST_MASK; | ||
163 | v >>= OMAP_POWERSTATEST_SHIFT; | ||
164 | |||
165 | return v; | ||
166 | } | ||
167 | |||
168 | static int am33xx_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm) | ||
169 | { | ||
170 | u32 v; | ||
171 | |||
172 | v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs); | ||
173 | v &= AM33XX_LASTPOWERSTATEENTERED_MASK; | ||
174 | v >>= AM33XX_LASTPOWERSTATEENTERED_SHIFT; | ||
175 | |||
176 | return v; | ||
177 | } | ||
178 | |||
179 | static int am33xx_pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm) | ||
180 | { | ||
181 | am33xx_prm_rmw_reg_bits(AM33XX_LOWPOWERSTATECHANGE_MASK, | ||
182 | (1 << AM33XX_LOWPOWERSTATECHANGE_SHIFT), | ||
183 | pwrdm->prcm_offs, pwrdm->pwrstctrl_offs); | ||
184 | return 0; | ||
185 | } | ||
186 | |||
187 | static int am33xx_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm) | ||
188 | { | ||
189 | am33xx_prm_rmw_reg_bits(AM33XX_LASTPOWERSTATEENTERED_MASK, | ||
190 | AM33XX_LASTPOWERSTATEENTERED_MASK, | ||
191 | pwrdm->prcm_offs, pwrdm->pwrstst_offs); | ||
192 | return 0; | ||
193 | } | ||
194 | |||
195 | static int am33xx_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst) | ||
196 | { | ||
197 | u32 m; | ||
198 | |||
199 | m = pwrdm->logicretstate_mask; | ||
200 | if (!m) | ||
201 | return -EINVAL; | ||
202 | |||
203 | am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)), | ||
204 | pwrdm->prcm_offs, pwrdm->pwrstctrl_offs); | ||
205 | |||
206 | return 0; | ||
207 | } | ||
208 | |||
209 | static int am33xx_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm) | ||
210 | { | ||
211 | u32 v; | ||
212 | |||
213 | v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs); | ||
214 | v &= AM33XX_LOGICSTATEST_MASK; | ||
215 | v >>= AM33XX_LOGICSTATEST_SHIFT; | ||
216 | |||
217 | return v; | ||
218 | } | ||
219 | |||
220 | static int am33xx_pwrdm_read_logic_retst(struct powerdomain *pwrdm) | ||
221 | { | ||
222 | u32 v, m; | ||
223 | |||
224 | m = pwrdm->logicretstate_mask; | ||
225 | if (!m) | ||
226 | return -EINVAL; | ||
227 | |||
228 | v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs); | ||
229 | v &= m; | ||
230 | v >>= __ffs(m); | ||
231 | |||
232 | return v; | ||
233 | } | ||
234 | |||
235 | static int am33xx_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, | ||
236 | u8 pwrst) | ||
237 | { | ||
238 | u32 m; | ||
239 | |||
240 | m = pwrdm->mem_on_mask[bank]; | ||
241 | if (!m) | ||
242 | return -EINVAL; | ||
243 | |||
244 | am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)), | ||
245 | pwrdm->prcm_offs, pwrdm->pwrstctrl_offs); | ||
246 | |||
247 | return 0; | ||
248 | } | ||
249 | |||
250 | static int am33xx_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, | ||
251 | u8 pwrst) | ||
252 | { | ||
253 | u32 m; | ||
254 | |||
255 | m = pwrdm->mem_ret_mask[bank]; | ||
256 | if (!m) | ||
257 | return -EINVAL; | ||
258 | |||
259 | am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)), | ||
260 | pwrdm->prcm_offs, pwrdm->pwrstctrl_offs); | ||
261 | |||
262 | return 0; | ||
263 | } | ||
264 | |||
265 | static int am33xx_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank) | ||
266 | { | ||
267 | u32 m, v; | ||
268 | |||
269 | m = pwrdm->mem_pwrst_mask[bank]; | ||
270 | if (!m) | ||
271 | return -EINVAL; | ||
272 | |||
273 | v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs); | ||
274 | v &= m; | ||
275 | v >>= __ffs(m); | ||
276 | |||
277 | return v; | ||
278 | } | ||
279 | |||
280 | static int am33xx_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank) | ||
281 | { | ||
282 | u32 m, v; | ||
283 | |||
284 | m = pwrdm->mem_retst_mask[bank]; | ||
285 | if (!m) | ||
286 | return -EINVAL; | ||
287 | |||
288 | v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs); | ||
289 | v &= m; | ||
290 | v >>= __ffs(m); | ||
291 | |||
292 | return v; | ||
293 | } | ||
294 | |||
295 | static int am33xx_pwrdm_wait_transition(struct powerdomain *pwrdm) | ||
296 | { | ||
297 | u32 c = 0; | ||
298 | |||
299 | /* | ||
300 | * REVISIT: pwrdm_wait_transition() may be better implemented | ||
301 | * via a callback and a periodic timer check -- how long do we expect | ||
302 | * powerdomain transitions to take? | ||
303 | */ | ||
304 | |||
305 | /* XXX Is this udelay() value meaningful? */ | ||
306 | while ((am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs) | ||
307 | & OMAP_INTRANSITION_MASK) && | ||
308 | (c++ < PWRDM_TRANSITION_BAILOUT)) | ||
309 | udelay(1); | ||
310 | |||
311 | if (c > PWRDM_TRANSITION_BAILOUT) { | ||
312 | pr_err("powerdomain: %s: waited too long to complete transition\n", | ||
313 | pwrdm->name); | ||
314 | return -EAGAIN; | ||
315 | } | ||
316 | |||
317 | pr_debug("powerdomain: completed transition in %d loops\n", c); | ||
318 | |||
319 | return 0; | ||
320 | } | ||
321 | |||
322 | struct pwrdm_ops am33xx_pwrdm_operations = { | ||
323 | .pwrdm_set_next_pwrst = am33xx_pwrdm_set_next_pwrst, | ||
324 | .pwrdm_read_next_pwrst = am33xx_pwrdm_read_next_pwrst, | ||
325 | .pwrdm_read_pwrst = am33xx_pwrdm_read_pwrst, | ||
326 | .pwrdm_read_prev_pwrst = am33xx_pwrdm_read_prev_pwrst, | ||
327 | .pwrdm_set_logic_retst = am33xx_pwrdm_set_logic_retst, | ||
328 | .pwrdm_read_logic_pwrst = am33xx_pwrdm_read_logic_pwrst, | ||
329 | .pwrdm_read_logic_retst = am33xx_pwrdm_read_logic_retst, | ||
330 | .pwrdm_clear_all_prev_pwrst = am33xx_pwrdm_clear_all_prev_pwrst, | ||
331 | .pwrdm_set_lowpwrstchange = am33xx_pwrdm_set_lowpwrstchange, | ||
332 | .pwrdm_read_mem_pwrst = am33xx_pwrdm_read_mem_pwrst, | ||
333 | .pwrdm_read_mem_retst = am33xx_pwrdm_read_mem_retst, | ||
334 | .pwrdm_set_mem_onst = am33xx_pwrdm_set_mem_onst, | ||
335 | .pwrdm_set_mem_retst = am33xx_pwrdm_set_mem_retst, | ||
336 | .pwrdm_wait_transition = am33xx_pwrdm_wait_transition, | ||
337 | }; | ||
diff --git a/arch/arm/mach-omap2/prm3xxx.c b/arch/arm/mach-omap2/prm3xxx.c index 88f7d8de7da9..e276ff270ac5 100644 --- a/arch/arm/mach-omap2/prm3xxx.c +++ b/arch/arm/mach-omap2/prm3xxx.c | |||
@@ -5,6 +5,7 @@ | |||
5 | * Copyright (C) 2010 Nokia Corporation | 5 | * Copyright (C) 2010 Nokia Corporation |
6 | * Benoît Cousson | 6 | * Benoît Cousson |
7 | * Paul Walmsley | 7 | * Paul Walmsley |
8 | * Rajendra Nayak <rnayak@ti.com> | ||
8 | * | 9 | * |
9 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License version 2 as | 11 | * it under the terms of the GNU General Public License version 2 as |
@@ -22,8 +23,9 @@ | |||
22 | #include <plat/prcm.h> | 23 | #include <plat/prcm.h> |
23 | 24 | ||
24 | #include "vp.h" | 25 | #include "vp.h" |
25 | 26 | #include "powerdomain.h" | |
26 | #include "prm3xxx.h" | 27 | #include "prm3xxx.h" |
28 | #include "prm2xxx_3xxx.h" | ||
27 | #include "cm2xxx_3xxx.h" | 29 | #include "cm2xxx_3xxx.h" |
28 | #include "prm-regbits-34xx.h" | 30 | #include "prm-regbits-34xx.h" |
29 | 31 | ||
@@ -215,6 +217,109 @@ static void __init omap3xxx_prm_enable_io_wakeup(void) | |||
215 | PM_WKEN); | 217 | PM_WKEN); |
216 | } | 218 | } |
217 | 219 | ||
220 | /* Powerdomain low-level functions */ | ||
221 | |||
222 | /* Applicable only for OMAP3. Not supported on OMAP2 */ | ||
223 | static int omap3_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm) | ||
224 | { | ||
225 | return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, | ||
226 | OMAP3430_PM_PREPWSTST, | ||
227 | OMAP3430_LASTPOWERSTATEENTERED_MASK); | ||
228 | } | ||
229 | |||
230 | static int omap3_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm) | ||
231 | { | ||
232 | return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, | ||
233 | OMAP2_PM_PWSTST, | ||
234 | OMAP3430_LOGICSTATEST_MASK); | ||
235 | } | ||
236 | |||
237 | static int omap3_pwrdm_read_logic_retst(struct powerdomain *pwrdm) | ||
238 | { | ||
239 | return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, | ||
240 | OMAP2_PM_PWSTCTRL, | ||
241 | OMAP3430_LOGICSTATEST_MASK); | ||
242 | } | ||
243 | |||
244 | static int omap3_pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm) | ||
245 | { | ||
246 | return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, | ||
247 | OMAP3430_PM_PREPWSTST, | ||
248 | OMAP3430_LASTLOGICSTATEENTERED_MASK); | ||
249 | } | ||
250 | |||
251 | static int omap3_get_mem_bank_lastmemst_mask(u8 bank) | ||
252 | { | ||
253 | switch (bank) { | ||
254 | case 0: | ||
255 | return OMAP3430_LASTMEM1STATEENTERED_MASK; | ||
256 | case 1: | ||
257 | return OMAP3430_LASTMEM2STATEENTERED_MASK; | ||
258 | case 2: | ||
259 | return OMAP3430_LASTSHAREDL2CACHEFLATSTATEENTERED_MASK; | ||
260 | case 3: | ||
261 | return OMAP3430_LASTL2FLATMEMSTATEENTERED_MASK; | ||
262 | default: | ||
263 | WARN_ON(1); /* should never happen */ | ||
264 | return -EEXIST; | ||
265 | } | ||
266 | return 0; | ||
267 | } | ||
268 | |||
269 | static int omap3_pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank) | ||
270 | { | ||
271 | u32 m; | ||
272 | |||
273 | m = omap3_get_mem_bank_lastmemst_mask(bank); | ||
274 | |||
275 | return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, | ||
276 | OMAP3430_PM_PREPWSTST, m); | ||
277 | } | ||
278 | |||
279 | static int omap3_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm) | ||
280 | { | ||
281 | omap2_prm_write_mod_reg(0, pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST); | ||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | static int omap3_pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm) | ||
286 | { | ||
287 | return omap2_prm_rmw_mod_reg_bits(0, | ||
288 | 1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT, | ||
289 | pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL); | ||
290 | } | ||
291 | |||
292 | static int omap3_pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm) | ||
293 | { | ||
294 | return omap2_prm_rmw_mod_reg_bits(1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT, | ||
295 | 0, pwrdm->prcm_offs, | ||
296 | OMAP2_PM_PWSTCTRL); | ||
297 | } | ||
298 | |||
299 | struct pwrdm_ops omap3_pwrdm_operations = { | ||
300 | .pwrdm_set_next_pwrst = omap2_pwrdm_set_next_pwrst, | ||
301 | .pwrdm_read_next_pwrst = omap2_pwrdm_read_next_pwrst, | ||
302 | .pwrdm_read_pwrst = omap2_pwrdm_read_pwrst, | ||
303 | .pwrdm_read_prev_pwrst = omap3_pwrdm_read_prev_pwrst, | ||
304 | .pwrdm_set_logic_retst = omap2_pwrdm_set_logic_retst, | ||
305 | .pwrdm_read_logic_pwrst = omap3_pwrdm_read_logic_pwrst, | ||
306 | .pwrdm_read_logic_retst = omap3_pwrdm_read_logic_retst, | ||
307 | .pwrdm_read_prev_logic_pwrst = omap3_pwrdm_read_prev_logic_pwrst, | ||
308 | .pwrdm_set_mem_onst = omap2_pwrdm_set_mem_onst, | ||
309 | .pwrdm_set_mem_retst = omap2_pwrdm_set_mem_retst, | ||
310 | .pwrdm_read_mem_pwrst = omap2_pwrdm_read_mem_pwrst, | ||
311 | .pwrdm_read_mem_retst = omap2_pwrdm_read_mem_retst, | ||
312 | .pwrdm_read_prev_mem_pwrst = omap3_pwrdm_read_prev_mem_pwrst, | ||
313 | .pwrdm_clear_all_prev_pwrst = omap3_pwrdm_clear_all_prev_pwrst, | ||
314 | .pwrdm_enable_hdwr_sar = omap3_pwrdm_enable_hdwr_sar, | ||
315 | .pwrdm_disable_hdwr_sar = omap3_pwrdm_disable_hdwr_sar, | ||
316 | .pwrdm_wait_transition = omap2_pwrdm_wait_transition, | ||
317 | }; | ||
318 | |||
319 | /* | ||
320 | * | ||
321 | */ | ||
322 | |||
218 | static int __init omap3xxx_prm_init(void) | 323 | static int __init omap3xxx_prm_init(void) |
219 | { | 324 | { |
220 | int ret; | 325 | int ret; |
diff --git a/arch/arm/mach-omap2/prm44xx.c b/arch/arm/mach-omap2/prm44xx.c index 06bb67910a31..48d91930796d 100644 --- a/arch/arm/mach-omap2/prm44xx.c +++ b/arch/arm/mach-omap2/prm44xx.c | |||
@@ -5,6 +5,7 @@ | |||
5 | * Copyright (C) 2010 Nokia Corporation | 5 | * Copyright (C) 2010 Nokia Corporation |
6 | * Benoît Cousson | 6 | * Benoît Cousson |
7 | * Paul Walmsley | 7 | * Paul Walmsley |
8 | * Rajendra Nayak <rnayak@ti.com> | ||
8 | * | 9 | * |
9 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License version 2 as | 11 | * it under the terms of the GNU General Public License version 2 as |
@@ -27,6 +28,7 @@ | |||
27 | #include "prm-regbits-44xx.h" | 28 | #include "prm-regbits-44xx.h" |
28 | #include "prcm44xx.h" | 29 | #include "prcm44xx.h" |
29 | #include "prminst44xx.h" | 30 | #include "prminst44xx.h" |
31 | #include "powerdomain.h" | ||
30 | 32 | ||
31 | static const struct omap_prcm_irq omap4_prcm_irqs[] = { | 33 | static const struct omap_prcm_irq omap4_prcm_irqs[] = { |
32 | OMAP_PRCM_IRQ("wkup", 0, 0), | 34 | OMAP_PRCM_IRQ("wkup", 0, 0), |
@@ -291,6 +293,269 @@ static void __init omap44xx_prm_enable_io_wakeup(void) | |||
291 | OMAP4_PRM_IO_PMCTRL_OFFSET); | 293 | OMAP4_PRM_IO_PMCTRL_OFFSET); |
292 | } | 294 | } |
293 | 295 | ||
296 | /* Powerdomain low-level functions */ | ||
297 | |||
298 | static int omap4_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst) | ||
299 | { | ||
300 | omap4_prminst_rmw_inst_reg_bits(OMAP_POWERSTATE_MASK, | ||
301 | (pwrst << OMAP_POWERSTATE_SHIFT), | ||
302 | pwrdm->prcm_partition, | ||
303 | pwrdm->prcm_offs, OMAP4_PM_PWSTCTRL); | ||
304 | return 0; | ||
305 | } | ||
306 | |||
307 | static int omap4_pwrdm_read_next_pwrst(struct powerdomain *pwrdm) | ||
308 | { | ||
309 | u32 v; | ||
310 | |||
311 | v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs, | ||
312 | OMAP4_PM_PWSTCTRL); | ||
313 | v &= OMAP_POWERSTATE_MASK; | ||
314 | v >>= OMAP_POWERSTATE_SHIFT; | ||
315 | |||
316 | return v; | ||
317 | } | ||
318 | |||
319 | static int omap4_pwrdm_read_pwrst(struct powerdomain *pwrdm) | ||
320 | { | ||
321 | u32 v; | ||
322 | |||
323 | v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs, | ||
324 | OMAP4_PM_PWSTST); | ||
325 | v &= OMAP_POWERSTATEST_MASK; | ||
326 | v >>= OMAP_POWERSTATEST_SHIFT; | ||
327 | |||
328 | return v; | ||
329 | } | ||
330 | |||
331 | static int omap4_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm) | ||
332 | { | ||
333 | u32 v; | ||
334 | |||
335 | v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs, | ||
336 | OMAP4_PM_PWSTST); | ||
337 | v &= OMAP4430_LASTPOWERSTATEENTERED_MASK; | ||
338 | v >>= OMAP4430_LASTPOWERSTATEENTERED_SHIFT; | ||
339 | |||
340 | return v; | ||
341 | } | ||
342 | |||
343 | static int omap4_pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm) | ||
344 | { | ||
345 | omap4_prminst_rmw_inst_reg_bits(OMAP4430_LOWPOWERSTATECHANGE_MASK, | ||
346 | (1 << OMAP4430_LOWPOWERSTATECHANGE_SHIFT), | ||
347 | pwrdm->prcm_partition, | ||
348 | pwrdm->prcm_offs, OMAP4_PM_PWSTCTRL); | ||
349 | return 0; | ||
350 | } | ||
351 | |||
352 | static int omap4_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm) | ||
353 | { | ||
354 | omap4_prminst_rmw_inst_reg_bits(OMAP4430_LASTPOWERSTATEENTERED_MASK, | ||
355 | OMAP4430_LASTPOWERSTATEENTERED_MASK, | ||
356 | pwrdm->prcm_partition, | ||
357 | pwrdm->prcm_offs, OMAP4_PM_PWSTST); | ||
358 | return 0; | ||
359 | } | ||
360 | |||
361 | static int omap4_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst) | ||
362 | { | ||
363 | u32 v; | ||
364 | |||
365 | v = pwrst << __ffs(OMAP4430_LOGICRETSTATE_MASK); | ||
366 | omap4_prminst_rmw_inst_reg_bits(OMAP4430_LOGICRETSTATE_MASK, v, | ||
367 | pwrdm->prcm_partition, pwrdm->prcm_offs, | ||
368 | OMAP4_PM_PWSTCTRL); | ||
369 | |||
370 | return 0; | ||
371 | } | ||
372 | |||
373 | static int omap4_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, | ||
374 | u8 pwrst) | ||
375 | { | ||
376 | u32 m; | ||
377 | |||
378 | m = omap2_pwrdm_get_mem_bank_onstate_mask(bank); | ||
379 | |||
380 | omap4_prminst_rmw_inst_reg_bits(m, (pwrst << __ffs(m)), | ||
381 | pwrdm->prcm_partition, pwrdm->prcm_offs, | ||
382 | OMAP4_PM_PWSTCTRL); | ||
383 | |||
384 | return 0; | ||
385 | } | ||
386 | |||
387 | static int omap4_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, | ||
388 | u8 pwrst) | ||
389 | { | ||
390 | u32 m; | ||
391 | |||
392 | m = omap2_pwrdm_get_mem_bank_retst_mask(bank); | ||
393 | |||
394 | omap4_prminst_rmw_inst_reg_bits(m, (pwrst << __ffs(m)), | ||
395 | pwrdm->prcm_partition, pwrdm->prcm_offs, | ||
396 | OMAP4_PM_PWSTCTRL); | ||
397 | |||
398 | return 0; | ||
399 | } | ||
400 | |||
401 | static int omap4_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm) | ||
402 | { | ||
403 | u32 v; | ||
404 | |||
405 | v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs, | ||
406 | OMAP4_PM_PWSTST); | ||
407 | v &= OMAP4430_LOGICSTATEST_MASK; | ||
408 | v >>= OMAP4430_LOGICSTATEST_SHIFT; | ||
409 | |||
410 | return v; | ||
411 | } | ||
412 | |||
413 | static int omap4_pwrdm_read_logic_retst(struct powerdomain *pwrdm) | ||
414 | { | ||
415 | u32 v; | ||
416 | |||
417 | v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs, | ||
418 | OMAP4_PM_PWSTCTRL); | ||
419 | v &= OMAP4430_LOGICRETSTATE_MASK; | ||
420 | v >>= OMAP4430_LOGICRETSTATE_SHIFT; | ||
421 | |||
422 | return v; | ||
423 | } | ||
424 | |||
425 | /** | ||
426 | * omap4_pwrdm_read_prev_logic_pwrst - read the previous logic powerstate | ||
427 | * @pwrdm: struct powerdomain * to read the state for | ||
428 | * | ||
429 | * Reads the previous logic powerstate for a powerdomain. This | ||
430 | * function must determine the previous logic powerstate by first | ||
431 | * checking the previous powerstate for the domain. If that was OFF, | ||
432 | * then logic has been lost. If previous state was RETENTION, the | ||
433 | * function reads the setting for the next retention logic state to | ||
434 | * see the actual value. In every other case, the logic is | ||
435 | * retained. Returns either PWRDM_POWER_OFF or PWRDM_POWER_RET | ||
436 | * depending whether the logic was retained or not. | ||
437 | */ | ||
438 | static int omap4_pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm) | ||
439 | { | ||
440 | int state; | ||
441 | |||
442 | state = omap4_pwrdm_read_prev_pwrst(pwrdm); | ||
443 | |||
444 | if (state == PWRDM_POWER_OFF) | ||
445 | return PWRDM_POWER_OFF; | ||
446 | |||
447 | if (state != PWRDM_POWER_RET) | ||
448 | return PWRDM_POWER_RET; | ||
449 | |||
450 | return omap4_pwrdm_read_logic_retst(pwrdm); | ||
451 | } | ||
452 | |||
453 | static int omap4_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank) | ||
454 | { | ||
455 | u32 m, v; | ||
456 | |||
457 | m = omap2_pwrdm_get_mem_bank_stst_mask(bank); | ||
458 | |||
459 | v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs, | ||
460 | OMAP4_PM_PWSTST); | ||
461 | v &= m; | ||
462 | v >>= __ffs(m); | ||
463 | |||
464 | return v; | ||
465 | } | ||
466 | |||
467 | static int omap4_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank) | ||
468 | { | ||
469 | u32 m, v; | ||
470 | |||
471 | m = omap2_pwrdm_get_mem_bank_retst_mask(bank); | ||
472 | |||
473 | v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs, | ||
474 | OMAP4_PM_PWSTCTRL); | ||
475 | v &= m; | ||
476 | v >>= __ffs(m); | ||
477 | |||
478 | return v; | ||
479 | } | ||
480 | |||
481 | /** | ||
482 | * omap4_pwrdm_read_prev_mem_pwrst - reads the previous memory powerstate | ||
483 | * @pwrdm: struct powerdomain * to read mem powerstate for | ||
484 | * @bank: memory bank index | ||
485 | * | ||
486 | * Reads the previous memory powerstate for a powerdomain. This | ||
487 | * function must determine the previous memory powerstate by first | ||
488 | * checking the previous powerstate for the domain. If that was OFF, | ||
489 | * then logic has been lost. If previous state was RETENTION, the | ||
490 | * function reads the setting for the next memory retention state to | ||
491 | * see the actual value. In every other case, the logic is | ||
492 | * retained. Returns either PWRDM_POWER_OFF or PWRDM_POWER_RET | ||
493 | * depending whether logic was retained or not. | ||
494 | */ | ||
495 | static int omap4_pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank) | ||
496 | { | ||
497 | int state; | ||
498 | |||
499 | state = omap4_pwrdm_read_prev_pwrst(pwrdm); | ||
500 | |||
501 | if (state == PWRDM_POWER_OFF) | ||
502 | return PWRDM_POWER_OFF; | ||
503 | |||
504 | if (state != PWRDM_POWER_RET) | ||
505 | return PWRDM_POWER_RET; | ||
506 | |||
507 | return omap4_pwrdm_read_mem_retst(pwrdm, bank); | ||
508 | } | ||
509 | |||
510 | static int omap4_pwrdm_wait_transition(struct powerdomain *pwrdm) | ||
511 | { | ||
512 | u32 c = 0; | ||
513 | |||
514 | /* | ||
515 | * REVISIT: pwrdm_wait_transition() may be better implemented | ||
516 | * via a callback and a periodic timer check -- how long do we expect | ||
517 | * powerdomain transitions to take? | ||
518 | */ | ||
519 | |||
520 | /* XXX Is this udelay() value meaningful? */ | ||
521 | while ((omap4_prminst_read_inst_reg(pwrdm->prcm_partition, | ||
522 | pwrdm->prcm_offs, | ||
523 | OMAP4_PM_PWSTST) & | ||
524 | OMAP_INTRANSITION_MASK) && | ||
525 | (c++ < PWRDM_TRANSITION_BAILOUT)) | ||
526 | udelay(1); | ||
527 | |||
528 | if (c > PWRDM_TRANSITION_BAILOUT) { | ||
529 | pr_err("powerdomain: %s: waited too long to complete transition\n", | ||
530 | pwrdm->name); | ||
531 | return -EAGAIN; | ||
532 | } | ||
533 | |||
534 | pr_debug("powerdomain: completed transition in %d loops\n", c); | ||
535 | |||
536 | return 0; | ||
537 | } | ||
538 | |||
539 | struct pwrdm_ops omap4_pwrdm_operations = { | ||
540 | .pwrdm_set_next_pwrst = omap4_pwrdm_set_next_pwrst, | ||
541 | .pwrdm_read_next_pwrst = omap4_pwrdm_read_next_pwrst, | ||
542 | .pwrdm_read_pwrst = omap4_pwrdm_read_pwrst, | ||
543 | .pwrdm_read_prev_pwrst = omap4_pwrdm_read_prev_pwrst, | ||
544 | .pwrdm_set_lowpwrstchange = omap4_pwrdm_set_lowpwrstchange, | ||
545 | .pwrdm_clear_all_prev_pwrst = omap4_pwrdm_clear_all_prev_pwrst, | ||
546 | .pwrdm_set_logic_retst = omap4_pwrdm_set_logic_retst, | ||
547 | .pwrdm_read_logic_pwrst = omap4_pwrdm_read_logic_pwrst, | ||
548 | .pwrdm_read_prev_logic_pwrst = omap4_pwrdm_read_prev_logic_pwrst, | ||
549 | .pwrdm_read_logic_retst = omap4_pwrdm_read_logic_retst, | ||
550 | .pwrdm_read_mem_pwrst = omap4_pwrdm_read_mem_pwrst, | ||
551 | .pwrdm_read_mem_retst = omap4_pwrdm_read_mem_retst, | ||
552 | .pwrdm_read_prev_mem_pwrst = omap4_pwrdm_read_prev_mem_pwrst, | ||
553 | .pwrdm_set_mem_onst = omap4_pwrdm_set_mem_onst, | ||
554 | .pwrdm_set_mem_retst = omap4_pwrdm_set_mem_retst, | ||
555 | .pwrdm_wait_transition = omap4_pwrdm_wait_transition, | ||
556 | }; | ||
557 | |||
558 | |||
294 | static int __init omap4xxx_prm_init(void) | 559 | static int __init omap4xxx_prm_init(void) |
295 | { | 560 | { |
296 | if (!cpu_is_omap44xx()) | 561 | if (!cpu_is_omap44xx()) |