0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/kernel.h>
0009 #include <linux/types.h>
0010 #include <linux/errno.h>
0011 #include <linux/err.h>
0012 #include <linux/io.h>
0013
0014 #include "powerdomain.h"
0015 #include "prm33xx.h"
0016 #include "prm-regbits-33xx.h"
0017
0018 #define AM33XX_PRM_RSTCTRL_OFFSET 0x0000
0019
0020 #define AM33XX_RST_GLOBAL_WARM_SW_MASK (1 << 0)
0021
0022
0023 static u32 am33xx_prm_read_reg(s16 inst, u16 idx)
0024 {
0025 return readl_relaxed(prm_base.va + inst + idx);
0026 }
0027
0028
0029 static void am33xx_prm_write_reg(u32 val, s16 inst, u16 idx)
0030 {
0031 writel_relaxed(val, prm_base.va + inst + idx);
0032 }
0033
0034
0035 static u32 am33xx_prm_rmw_reg_bits(u32 mask, u32 bits, s16 inst, s16 idx)
0036 {
0037 u32 v;
0038
0039 v = am33xx_prm_read_reg(inst, idx);
0040 v &= ~mask;
0041 v |= bits;
0042 am33xx_prm_write_reg(v, inst, idx);
0043
0044 return v;
0045 }
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059 static int am33xx_prm_is_hardreset_asserted(u8 shift, u8 part, s16 inst,
0060 u16 rstctrl_offs)
0061 {
0062 u32 v;
0063
0064 v = am33xx_prm_read_reg(inst, rstctrl_offs);
0065 v &= 1 << shift;
0066 v >>= shift;
0067
0068 return v;
0069 }
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085 static int am33xx_prm_assert_hardreset(u8 shift, u8 part, s16 inst,
0086 u16 rstctrl_offs)
0087 {
0088 u32 mask = 1 << shift;
0089
0090 am33xx_prm_rmw_reg_bits(mask, mask, inst, rstctrl_offs);
0091
0092 return 0;
0093 }
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114 static int am33xx_prm_deassert_hardreset(u8 shift, u8 st_shift, u8 part,
0115 s16 inst, u16 rstctrl_offs,
0116 u16 rstst_offs)
0117 {
0118 int c;
0119 u32 mask = 1 << st_shift;
0120
0121
0122 if (am33xx_prm_is_hardreset_asserted(shift, 0, inst, rstctrl_offs) == 0)
0123 return -EEXIST;
0124
0125
0126 am33xx_prm_rmw_reg_bits(0xffffffff, mask, inst, rstst_offs);
0127
0128
0129 mask = 1 << shift;
0130
0131 am33xx_prm_rmw_reg_bits(mask, 0, inst, rstctrl_offs);
0132
0133
0134 omap_test_timeout(am33xx_prm_is_hardreset_asserted(st_shift, 0, inst,
0135 rstst_offs),
0136 MAX_MODULE_HARDRESET_WAIT, c);
0137
0138 return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0;
0139 }
0140
0141 static int am33xx_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
0142 {
0143 am33xx_prm_rmw_reg_bits(OMAP_POWERSTATE_MASK,
0144 (pwrst << OMAP_POWERSTATE_SHIFT),
0145 pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
0146 return 0;
0147 }
0148
0149 static int am33xx_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
0150 {
0151 u32 v;
0152
0153 v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
0154 v &= OMAP_POWERSTATE_MASK;
0155 v >>= OMAP_POWERSTATE_SHIFT;
0156
0157 return v;
0158 }
0159
0160 static int am33xx_pwrdm_read_pwrst(struct powerdomain *pwrdm)
0161 {
0162 u32 v;
0163
0164 v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
0165 v &= OMAP_POWERSTATEST_MASK;
0166 v >>= OMAP_POWERSTATEST_SHIFT;
0167
0168 return v;
0169 }
0170
0171 static int am33xx_pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)
0172 {
0173 am33xx_prm_rmw_reg_bits(AM33XX_LOWPOWERSTATECHANGE_MASK,
0174 (1 << AM33XX_LOWPOWERSTATECHANGE_SHIFT),
0175 pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
0176 return 0;
0177 }
0178
0179 static int am33xx_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
0180 {
0181 am33xx_prm_rmw_reg_bits(AM33XX_LASTPOWERSTATEENTERED_MASK,
0182 AM33XX_LASTPOWERSTATEENTERED_MASK,
0183 pwrdm->prcm_offs, pwrdm->pwrstst_offs);
0184 return 0;
0185 }
0186
0187 static int am33xx_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
0188 {
0189 u32 m;
0190
0191 m = pwrdm->logicretstate_mask;
0192 if (!m)
0193 return -EINVAL;
0194
0195 am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)),
0196 pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
0197
0198 return 0;
0199 }
0200
0201 static int am33xx_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
0202 {
0203 u32 v;
0204
0205 v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
0206 v &= AM33XX_LOGICSTATEST_MASK;
0207 v >>= AM33XX_LOGICSTATEST_SHIFT;
0208
0209 return v;
0210 }
0211
0212 static int am33xx_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
0213 {
0214 u32 v, m;
0215
0216 m = pwrdm->logicretstate_mask;
0217 if (!m)
0218 return -EINVAL;
0219
0220 v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
0221 v &= m;
0222 v >>= __ffs(m);
0223
0224 return v;
0225 }
0226
0227 static int am33xx_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank,
0228 u8 pwrst)
0229 {
0230 u32 m;
0231
0232 m = pwrdm->mem_on_mask[bank];
0233 if (!m)
0234 return -EINVAL;
0235
0236 am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)),
0237 pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
0238
0239 return 0;
0240 }
0241
0242 static int am33xx_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank,
0243 u8 pwrst)
0244 {
0245 u32 m;
0246
0247 m = pwrdm->mem_ret_mask[bank];
0248 if (!m)
0249 return -EINVAL;
0250
0251 am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)),
0252 pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
0253
0254 return 0;
0255 }
0256
0257 static int am33xx_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
0258 {
0259 u32 m, v;
0260
0261 m = pwrdm->mem_pwrst_mask[bank];
0262 if (!m)
0263 return -EINVAL;
0264
0265 v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
0266 v &= m;
0267 v >>= __ffs(m);
0268
0269 return v;
0270 }
0271
0272 static int am33xx_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
0273 {
0274 u32 m, v;
0275
0276 m = pwrdm->mem_retst_mask[bank];
0277 if (!m)
0278 return -EINVAL;
0279
0280 v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
0281 v &= m;
0282 v >>= __ffs(m);
0283
0284 return v;
0285 }
0286
0287 static int am33xx_pwrdm_wait_transition(struct powerdomain *pwrdm)
0288 {
0289 u32 c = 0;
0290
0291
0292
0293
0294
0295
0296
0297
0298 while ((am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs)
0299 & OMAP_INTRANSITION_MASK) &&
0300 (c++ < PWRDM_TRANSITION_BAILOUT))
0301 udelay(1);
0302
0303 if (c > PWRDM_TRANSITION_BAILOUT) {
0304 pr_err("powerdomain: %s: waited too long to complete transition\n",
0305 pwrdm->name);
0306 return -EAGAIN;
0307 }
0308
0309 pr_debug("powerdomain: completed transition in %d loops\n", c);
0310
0311 return 0;
0312 }
0313
0314 static int am33xx_check_vcvp(void)
0315 {
0316
0317 return 0;
0318 }
0319
0320
0321
0322
0323
0324
0325 static void am33xx_prm_global_warm_sw_reset(void)
0326 {
0327 am33xx_prm_rmw_reg_bits(AM33XX_RST_GLOBAL_WARM_SW_MASK,
0328 AM33XX_RST_GLOBAL_WARM_SW_MASK,
0329 AM33XX_PRM_DEVICE_MOD,
0330 AM33XX_PRM_RSTCTRL_OFFSET);
0331
0332
0333 (void)am33xx_prm_read_reg(AM33XX_PRM_DEVICE_MOD,
0334 AM33XX_PRM_RSTCTRL_OFFSET);
0335 }
0336
0337 static void am33xx_pwrdm_save_context(struct powerdomain *pwrdm)
0338 {
0339 pwrdm->context = am33xx_prm_read_reg(pwrdm->prcm_offs,
0340 pwrdm->pwrstctrl_offs);
0341
0342
0343
0344
0345 pwrdm->context &= ~AM33XX_LOWPOWERSTATECHANGE_MASK;
0346 }
0347
0348 static void am33xx_pwrdm_restore_context(struct powerdomain *pwrdm)
0349 {
0350 int st, ctrl;
0351
0352 st = am33xx_prm_read_reg(pwrdm->prcm_offs,
0353 pwrdm->pwrstst_offs);
0354
0355 am33xx_prm_write_reg(pwrdm->context, pwrdm->prcm_offs,
0356 pwrdm->pwrstctrl_offs);
0357
0358
0359 st &= OMAP_POWERSTATEST_MASK;
0360 ctrl = OMAP_POWERSTATEST_MASK & pwrdm->context;
0361
0362 if (st != ctrl)
0363 am33xx_pwrdm_wait_transition(pwrdm);
0364 }
0365
0366 struct pwrdm_ops am33xx_pwrdm_operations = {
0367 .pwrdm_set_next_pwrst = am33xx_pwrdm_set_next_pwrst,
0368 .pwrdm_read_next_pwrst = am33xx_pwrdm_read_next_pwrst,
0369 .pwrdm_read_pwrst = am33xx_pwrdm_read_pwrst,
0370 .pwrdm_set_logic_retst = am33xx_pwrdm_set_logic_retst,
0371 .pwrdm_read_logic_pwrst = am33xx_pwrdm_read_logic_pwrst,
0372 .pwrdm_read_logic_retst = am33xx_pwrdm_read_logic_retst,
0373 .pwrdm_clear_all_prev_pwrst = am33xx_pwrdm_clear_all_prev_pwrst,
0374 .pwrdm_set_lowpwrstchange = am33xx_pwrdm_set_lowpwrstchange,
0375 .pwrdm_read_mem_pwrst = am33xx_pwrdm_read_mem_pwrst,
0376 .pwrdm_read_mem_retst = am33xx_pwrdm_read_mem_retst,
0377 .pwrdm_set_mem_onst = am33xx_pwrdm_set_mem_onst,
0378 .pwrdm_set_mem_retst = am33xx_pwrdm_set_mem_retst,
0379 .pwrdm_wait_transition = am33xx_pwrdm_wait_transition,
0380 .pwrdm_has_voltdm = am33xx_check_vcvp,
0381 .pwrdm_save_context = am33xx_pwrdm_save_context,
0382 .pwrdm_restore_context = am33xx_pwrdm_restore_context,
0383 };
0384
0385 static struct prm_ll_data am33xx_prm_ll_data = {
0386 .assert_hardreset = am33xx_prm_assert_hardreset,
0387 .deassert_hardreset = am33xx_prm_deassert_hardreset,
0388 .is_hardreset_asserted = am33xx_prm_is_hardreset_asserted,
0389 .reset_system = am33xx_prm_global_warm_sw_reset,
0390 };
0391
0392 int __init am33xx_prm_init(const struct omap_prcm_init_data *data)
0393 {
0394 return prm_register(&am33xx_prm_ll_data);
0395 }
0396
0397 static void __exit am33xx_prm_exit(void)
0398 {
0399 prm_unregister(&am33xx_prm_ll_data);
0400 }
0401 __exitcall(am33xx_prm_exit);