diff options
author | Paul Walmsley <paul@pwsan.com> | 2012-12-28 04:10:44 -0500 |
---|---|---|
committer | Paul Walmsley <paul@pwsan.com> | 2013-01-02 14:07:16 -0500 |
commit | 7e7fff8254e318cede06a1a8c55b0d86dd4d8c5b (patch) | |
tree | 38ad0446026932ed55ae1af167dae17c0a417f3a /arch/arm/mach-omap2 | |
parent | cfef4b2723d525a6588c4c55b42f9b98be27937f (diff) |
ARM: OMAP2/3: PRM: fix bogus OMAP2xxx powerstate return values
On OMAP2xxx chips, the register bitfields for the
PM_PWSTCTRL_*.POWERSTATE and PM_PWSTST_*.LASTSTATEENTERED are
different than those used on OMAP3/4. The order is reversed. So, for
example, on OMAP2xxx, 0x0 indicates 'ON'; but on OMAP3/4, 0x0
indicates 'OFF'. Similarly, on OMAP2xxx, 0x3 indicates 'OFF', but on
OMAP3/4, 0x3 indicates 'ON'.
To fix this, we treat the OMAP3/4 values as the powerdomain API
values, and create new low-level powerdomain functions for the
OMAP2xxx chips which translate between the OMAP2xxx values and the
OMAP3/4 values.
Without this patch, the conversion of the OMAP2xxx PM code to the
functional powerstate code results in a non-booting kernel.
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Diffstat (limited to 'arch/arm/mach-omap2')
-rw-r--r-- | arch/arm/mach-omap2/prm2xxx.c | 88 | ||||
-rw-r--r-- | arch/arm/mach-omap2/prm2xxx_3xxx.c | 22 | ||||
-rw-r--r-- | arch/arm/mach-omap2/prm3xxx.c | 28 |
3 files changed, 110 insertions, 28 deletions
diff --git a/arch/arm/mach-omap2/prm2xxx.c b/arch/arm/mach-omap2/prm2xxx.c index faeab18696df..00cd4fcbda0f 100644 --- a/arch/arm/mach-omap2/prm2xxx.c +++ b/arch/arm/mach-omap2/prm2xxx.c | |||
@@ -29,6 +29,14 @@ | |||
29 | #include "prm-regbits-24xx.h" | 29 | #include "prm-regbits-24xx.h" |
30 | 30 | ||
31 | /* | 31 | /* |
32 | * OMAP24xx PM_PWSTCTRL_*.POWERSTATE and PM_PWSTST_*.LASTSTATEENTERED bits - | ||
33 | * these are reversed from the bits used on OMAP3+ | ||
34 | */ | ||
35 | #define OMAP24XX_PWRDM_POWER_ON 0x0 | ||
36 | #define OMAP24XX_PWRDM_POWER_RET 0x1 | ||
37 | #define OMAP24XX_PWRDM_POWER_OFF 0x3 | ||
38 | |||
39 | /* | ||
32 | * omap2xxx_prm_reset_src_map - map from bits in the PRM_RSTST_WKUP | 40 | * omap2xxx_prm_reset_src_map - map from bits in the PRM_RSTST_WKUP |
33 | * hardware register (which are specific to the OMAP2xxx SoCs) to | 41 | * hardware register (which are specific to the OMAP2xxx SoCs) to |
34 | * reset source ID bit shifts (which is an OMAP SoC-independent | 42 | * reset source ID bit shifts (which is an OMAP SoC-independent |
@@ -69,6 +77,34 @@ static u32 omap2xxx_prm_read_reset_sources(void) | |||
69 | } | 77 | } |
70 | 78 | ||
71 | /** | 79 | /** |
80 | * omap2xxx_pwrst_to_common_pwrst - convert OMAP2xxx pwrst to common pwrst | ||
81 | * @omap2xxx_pwrst: OMAP2xxx hardware power state to convert | ||
82 | * | ||
83 | * Return the common power state bits corresponding to the OMAP2xxx | ||
84 | * hardware power state bits @omap2xxx_pwrst, or -EINVAL upon error. | ||
85 | */ | ||
86 | static int omap2xxx_pwrst_to_common_pwrst(u8 omap2xxx_pwrst) | ||
87 | { | ||
88 | u8 pwrst; | ||
89 | |||
90 | switch (omap2xxx_pwrst) { | ||
91 | case OMAP24XX_PWRDM_POWER_OFF: | ||
92 | pwrst = PWRDM_POWER_OFF; | ||
93 | break; | ||
94 | case OMAP24XX_PWRDM_POWER_RET: | ||
95 | pwrst = PWRDM_POWER_RET; | ||
96 | break; | ||
97 | case OMAP24XX_PWRDM_POWER_ON: | ||
98 | pwrst = PWRDM_POWER_ON; | ||
99 | break; | ||
100 | default: | ||
101 | return -EINVAL; | ||
102 | } | ||
103 | |||
104 | return pwrst; | ||
105 | } | ||
106 | |||
107 | /** | ||
72 | * omap2xxx_prm_dpll_reset - use DPLL reset to reboot the OMAP SoC | 108 | * omap2xxx_prm_dpll_reset - use DPLL reset to reboot the OMAP SoC |
73 | * | 109 | * |
74 | * Set the DPLL reset bit, which should reboot the SoC. This is the | 110 | * Set the DPLL reset bit, which should reboot the SoC. This is the |
@@ -98,10 +134,56 @@ int omap2xxx_clkdm_wakeup(struct clockdomain *clkdm) | |||
98 | return 0; | 134 | return 0; |
99 | } | 135 | } |
100 | 136 | ||
137 | static int omap2xxx_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst) | ||
138 | { | ||
139 | u8 omap24xx_pwrst; | ||
140 | |||
141 | switch (pwrst) { | ||
142 | case PWRDM_POWER_OFF: | ||
143 | omap24xx_pwrst = OMAP24XX_PWRDM_POWER_OFF; | ||
144 | break; | ||
145 | case PWRDM_POWER_RET: | ||
146 | omap24xx_pwrst = OMAP24XX_PWRDM_POWER_RET; | ||
147 | break; | ||
148 | case PWRDM_POWER_ON: | ||
149 | omap24xx_pwrst = OMAP24XX_PWRDM_POWER_ON; | ||
150 | break; | ||
151 | default: | ||
152 | return -EINVAL; | ||
153 | } | ||
154 | |||
155 | omap2_prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK, | ||
156 | (omap24xx_pwrst << OMAP_POWERSTATE_SHIFT), | ||
157 | pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL); | ||
158 | return 0; | ||
159 | } | ||
160 | |||
161 | static int omap2xxx_pwrdm_read_next_pwrst(struct powerdomain *pwrdm) | ||
162 | { | ||
163 | u8 omap2xxx_pwrst; | ||
164 | |||
165 | omap2xxx_pwrst = omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, | ||
166 | OMAP2_PM_PWSTCTRL, | ||
167 | OMAP_POWERSTATE_MASK); | ||
168 | |||
169 | return omap2xxx_pwrst_to_common_pwrst(omap2xxx_pwrst); | ||
170 | } | ||
171 | |||
172 | static int omap2xxx_pwrdm_read_pwrst(struct powerdomain *pwrdm) | ||
173 | { | ||
174 | u8 omap2xxx_pwrst; | ||
175 | |||
176 | omap2xxx_pwrst = omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, | ||
177 | OMAP2_PM_PWSTST, | ||
178 | OMAP_POWERSTATEST_MASK); | ||
179 | |||
180 | return omap2xxx_pwrst_to_common_pwrst(omap2xxx_pwrst); | ||
181 | } | ||
182 | |||
101 | struct pwrdm_ops omap2_pwrdm_operations = { | 183 | struct pwrdm_ops omap2_pwrdm_operations = { |
102 | .pwrdm_set_next_pwrst = omap2_pwrdm_set_next_pwrst, | 184 | .pwrdm_set_next_pwrst = omap2xxx_pwrdm_set_next_pwrst, |
103 | .pwrdm_read_next_pwrst = omap2_pwrdm_read_next_pwrst, | 185 | .pwrdm_read_next_pwrst = omap2xxx_pwrdm_read_next_pwrst, |
104 | .pwrdm_read_pwrst = omap2_pwrdm_read_pwrst, | 186 | .pwrdm_read_pwrst = omap2xxx_pwrdm_read_pwrst, |
105 | .pwrdm_set_logic_retst = omap2_pwrdm_set_logic_retst, | 187 | .pwrdm_set_logic_retst = omap2_pwrdm_set_logic_retst, |
106 | .pwrdm_set_mem_onst = omap2_pwrdm_set_mem_onst, | 188 | .pwrdm_set_mem_onst = omap2_pwrdm_set_mem_onst, |
107 | .pwrdm_set_mem_retst = omap2_pwrdm_set_mem_retst, | 189 | .pwrdm_set_mem_retst = omap2_pwrdm_set_mem_retst, |
diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.c b/arch/arm/mach-omap2/prm2xxx_3xxx.c index 30517f5af707..a3e121f94a86 100644 --- a/arch/arm/mach-omap2/prm2xxx_3xxx.c +++ b/arch/arm/mach-omap2/prm2xxx_3xxx.c | |||
@@ -103,28 +103,6 @@ int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift, u8 st_shift) | |||
103 | /* Powerdomain low-level functions */ | 103 | /* Powerdomain low-level functions */ |
104 | 104 | ||
105 | /* Common functions across OMAP2 and OMAP3 */ | 105 | /* Common functions across OMAP2 and OMAP3 */ |
106 | int omap2_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst) | ||
107 | { | ||
108 | omap2_prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK, | ||
109 | (pwrst << OMAP_POWERSTATE_SHIFT), | ||
110 | pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL); | ||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | int omap2_pwrdm_read_next_pwrst(struct powerdomain *pwrdm) | ||
115 | { | ||
116 | return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, | ||
117 | OMAP2_PM_PWSTCTRL, | ||
118 | OMAP_POWERSTATE_MASK); | ||
119 | } | ||
120 | |||
121 | int omap2_pwrdm_read_pwrst(struct powerdomain *pwrdm) | ||
122 | { | ||
123 | return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, | ||
124 | OMAP2_PM_PWSTST, | ||
125 | OMAP_POWERSTATEST_MASK); | ||
126 | } | ||
127 | |||
128 | int omap2_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, | 106 | int omap2_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, |
129 | u8 pwrst) | 107 | u8 pwrst) |
130 | { | 108 | { |
diff --git a/arch/arm/mach-omap2/prm3xxx.c b/arch/arm/mach-omap2/prm3xxx.c index db198d058584..4d43474d7455 100644 --- a/arch/arm/mach-omap2/prm3xxx.c +++ b/arch/arm/mach-omap2/prm3xxx.c | |||
@@ -278,6 +278,28 @@ static u32 omap3xxx_prm_read_reset_sources(void) | |||
278 | 278 | ||
279 | /* Powerdomain low-level functions */ | 279 | /* Powerdomain low-level functions */ |
280 | 280 | ||
281 | static int omap3_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst) | ||
282 | { | ||
283 | omap2_prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK, | ||
284 | (pwrst << OMAP_POWERSTATE_SHIFT), | ||
285 | pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL); | ||
286 | return 0; | ||
287 | } | ||
288 | |||
289 | static int omap3_pwrdm_read_next_pwrst(struct powerdomain *pwrdm) | ||
290 | { | ||
291 | return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, | ||
292 | OMAP2_PM_PWSTCTRL, | ||
293 | OMAP_POWERSTATE_MASK); | ||
294 | } | ||
295 | |||
296 | static int omap3_pwrdm_read_pwrst(struct powerdomain *pwrdm) | ||
297 | { | ||
298 | return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, | ||
299 | OMAP2_PM_PWSTST, | ||
300 | OMAP_POWERSTATEST_MASK); | ||
301 | } | ||
302 | |||
281 | /* Applicable only for OMAP3. Not supported on OMAP2 */ | 303 | /* Applicable only for OMAP3. Not supported on OMAP2 */ |
282 | static int omap3_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm) | 304 | static int omap3_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm) |
283 | { | 305 | { |
@@ -356,9 +378,9 @@ static int omap3_pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm) | |||
356 | } | 378 | } |
357 | 379 | ||
358 | struct pwrdm_ops omap3_pwrdm_operations = { | 380 | struct pwrdm_ops omap3_pwrdm_operations = { |
359 | .pwrdm_set_next_pwrst = omap2_pwrdm_set_next_pwrst, | 381 | .pwrdm_set_next_pwrst = omap3_pwrdm_set_next_pwrst, |
360 | .pwrdm_read_next_pwrst = omap2_pwrdm_read_next_pwrst, | 382 | .pwrdm_read_next_pwrst = omap3_pwrdm_read_next_pwrst, |
361 | .pwrdm_read_pwrst = omap2_pwrdm_read_pwrst, | 383 | .pwrdm_read_pwrst = omap3_pwrdm_read_pwrst, |
362 | .pwrdm_read_prev_pwrst = omap3_pwrdm_read_prev_pwrst, | 384 | .pwrdm_read_prev_pwrst = omap3_pwrdm_read_prev_pwrst, |
363 | .pwrdm_set_logic_retst = omap2_pwrdm_set_logic_retst, | 385 | .pwrdm_set_logic_retst = omap2_pwrdm_set_logic_retst, |
364 | .pwrdm_read_logic_pwrst = omap3_pwrdm_read_logic_pwrst, | 386 | .pwrdm_read_logic_pwrst = omap3_pwrdm_read_logic_pwrst, |