0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/cpu_pm.h>
0013 #include <linux/kernel.h>
0014 #include <linux/delay.h>
0015 #include <linux/errno.h>
0016 #include <linux/err.h>
0017 #include <linux/io.h>
0018 #include <linux/of_irq.h>
0019 #include <linux/of.h>
0020
0021 #include "soc.h"
0022 #include "iomap.h"
0023 #include "common.h"
0024 #include "vp.h"
0025 #include "prm44xx.h"
0026 #include "prcm43xx.h"
0027 #include "prm-regbits-44xx.h"
0028 #include "prcm44xx.h"
0029 #include "prminst44xx.h"
0030 #include "powerdomain.h"
0031 #include "pm.h"
0032
0033
0034
0035 static void omap44xx_prm_read_pending_irqs(unsigned long *events);
0036 static void omap44xx_prm_ocp_barrier(void);
0037 static void omap44xx_prm_save_and_clear_irqen(u32 *saved_mask);
0038 static void omap44xx_prm_restore_irqen(u32 *saved_mask);
0039 static void omap44xx_prm_reconfigure_io_chain(void);
0040
0041 static const struct omap_prcm_irq omap4_prcm_irqs[] = {
0042 OMAP_PRCM_IRQ("io", 9, 1),
0043 };
0044
0045 static struct omap_prcm_irq_setup omap4_prcm_irq_setup = {
0046 .ack = OMAP4_PRM_IRQSTATUS_MPU_OFFSET,
0047 .mask = OMAP4_PRM_IRQENABLE_MPU_OFFSET,
0048 .pm_ctrl = OMAP4_PRM_IO_PMCTRL_OFFSET,
0049 .nr_regs = 2,
0050 .irqs = omap4_prcm_irqs,
0051 .nr_irqs = ARRAY_SIZE(omap4_prcm_irqs),
0052 .read_pending_irqs = &omap44xx_prm_read_pending_irqs,
0053 .ocp_barrier = &omap44xx_prm_ocp_barrier,
0054 .save_and_clear_irqen = &omap44xx_prm_save_and_clear_irqen,
0055 .restore_irqen = &omap44xx_prm_restore_irqen,
0056 .reconfigure_io_chain = &omap44xx_prm_reconfigure_io_chain,
0057 };
0058
0059 struct omap_prm_irq_context {
0060 unsigned long irq_enable;
0061 unsigned long pm_ctrl;
0062 };
0063
0064 static struct omap_prm_irq_context omap_prm_context;
0065
0066
0067
0068
0069
0070
0071
0072 static struct prm_reset_src_map omap44xx_prm_reset_src_map[] = {
0073 { OMAP4430_GLOBAL_WARM_SW_RST_SHIFT,
0074 OMAP_GLOBAL_WARM_RST_SRC_ID_SHIFT },
0075 { OMAP4430_GLOBAL_COLD_RST_SHIFT,
0076 OMAP_GLOBAL_COLD_RST_SRC_ID_SHIFT },
0077 { OMAP4430_MPU_SECURITY_VIOL_RST_SHIFT,
0078 OMAP_SECU_VIOL_RST_SRC_ID_SHIFT },
0079 { OMAP4430_MPU_WDT_RST_SHIFT, OMAP_MPU_WD_RST_SRC_ID_SHIFT },
0080 { OMAP4430_SECURE_WDT_RST_SHIFT, OMAP_SECU_WD_RST_SRC_ID_SHIFT },
0081 { OMAP4430_EXTERNAL_WARM_RST_SHIFT, OMAP_EXTWARM_RST_SRC_ID_SHIFT },
0082 { OMAP4430_VDD_MPU_VOLT_MGR_RST_SHIFT,
0083 OMAP_VDD_MPU_VM_RST_SRC_ID_SHIFT },
0084 { OMAP4430_VDD_IVA_VOLT_MGR_RST_SHIFT,
0085 OMAP_VDD_IVA_VM_RST_SRC_ID_SHIFT },
0086 { OMAP4430_VDD_CORE_VOLT_MGR_RST_SHIFT,
0087 OMAP_VDD_CORE_VM_RST_SRC_ID_SHIFT },
0088 { OMAP4430_ICEPICK_RST_SHIFT, OMAP_ICEPICK_RST_SRC_ID_SHIFT },
0089 { OMAP4430_C2C_RST_SHIFT, OMAP_C2C_RST_SRC_ID_SHIFT },
0090 { -1, -1 },
0091 };
0092
0093
0094
0095
0096 static u32 omap4_prm_read_inst_reg(s16 inst, u16 reg)
0097 {
0098 return readl_relaxed(prm_base.va + inst + reg);
0099 }
0100
0101
0102 static void omap4_prm_write_inst_reg(u32 val, s16 inst, u16 reg)
0103 {
0104 writel_relaxed(val, prm_base.va + inst + reg);
0105 }
0106
0107
0108 static u32 omap4_prm_rmw_inst_reg_bits(u32 mask, u32 bits, s16 inst, s16 reg)
0109 {
0110 u32 v;
0111
0112 v = omap4_prm_read_inst_reg(inst, reg);
0113 v &= ~mask;
0114 v |= bits;
0115 omap4_prm_write_inst_reg(v, inst, reg);
0116
0117 return v;
0118 }
0119
0120
0121
0122
0123
0124
0125
0126
0127 struct omap4_vp {
0128 u32 irqstatus_mpu;
0129 u32 tranxdone_status;
0130 };
0131
0132 static struct omap4_vp omap4_vp[] = {
0133 [OMAP4_VP_VDD_MPU_ID] = {
0134 .irqstatus_mpu = OMAP4_PRM_IRQSTATUS_MPU_2_OFFSET,
0135 .tranxdone_status = OMAP4430_VP_MPU_TRANXDONE_ST_MASK,
0136 },
0137 [OMAP4_VP_VDD_IVA_ID] = {
0138 .irqstatus_mpu = OMAP4_PRM_IRQSTATUS_MPU_OFFSET,
0139 .tranxdone_status = OMAP4430_VP_IVA_TRANXDONE_ST_MASK,
0140 },
0141 [OMAP4_VP_VDD_CORE_ID] = {
0142 .irqstatus_mpu = OMAP4_PRM_IRQSTATUS_MPU_OFFSET,
0143 .tranxdone_status = OMAP4430_VP_CORE_TRANXDONE_ST_MASK,
0144 },
0145 };
0146
0147 static u32 omap4_prm_vp_check_txdone(u8 vp_id)
0148 {
0149 struct omap4_vp *vp = &omap4_vp[vp_id];
0150 u32 irqstatus;
0151
0152 irqstatus = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
0153 OMAP4430_PRM_OCP_SOCKET_INST,
0154 vp->irqstatus_mpu);
0155 return irqstatus & vp->tranxdone_status;
0156 }
0157
0158 static void omap4_prm_vp_clear_txdone(u8 vp_id)
0159 {
0160 struct omap4_vp *vp = &omap4_vp[vp_id];
0161
0162 omap4_prminst_write_inst_reg(vp->tranxdone_status,
0163 OMAP4430_PRM_PARTITION,
0164 OMAP4430_PRM_OCP_SOCKET_INST,
0165 vp->irqstatus_mpu);
0166 };
0167
0168 u32 omap4_prm_vcvp_read(u8 offset)
0169 {
0170 s32 inst = omap4_prmst_get_prm_dev_inst();
0171
0172 if (inst == PRM_INSTANCE_UNKNOWN)
0173 return 0;
0174
0175 return omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
0176 inst, offset);
0177 }
0178
0179 void omap4_prm_vcvp_write(u32 val, u8 offset)
0180 {
0181 s32 inst = omap4_prmst_get_prm_dev_inst();
0182
0183 if (inst == PRM_INSTANCE_UNKNOWN)
0184 return;
0185
0186 omap4_prminst_write_inst_reg(val, OMAP4430_PRM_PARTITION,
0187 inst, offset);
0188 }
0189
0190 u32 omap4_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset)
0191 {
0192 s32 inst = omap4_prmst_get_prm_dev_inst();
0193
0194 if (inst == PRM_INSTANCE_UNKNOWN)
0195 return 0;
0196
0197 return omap4_prminst_rmw_inst_reg_bits(mask, bits,
0198 OMAP4430_PRM_PARTITION,
0199 inst,
0200 offset);
0201 }
0202
0203 static inline u32 _read_pending_irq_reg(u16 irqen_offs, u16 irqst_offs)
0204 {
0205 u32 mask, st;
0206
0207
0208 mask = omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
0209 irqen_offs);
0210 st = omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST, irqst_offs);
0211
0212 return mask & st;
0213 }
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223 static void omap44xx_prm_read_pending_irqs(unsigned long *events)
0224 {
0225 int i;
0226
0227 for (i = 0; i < omap4_prcm_irq_setup.nr_regs; i++)
0228 events[i] = _read_pending_irq_reg(omap4_prcm_irq_setup.mask +
0229 i * 4, omap4_prcm_irq_setup.ack + i * 4);
0230 }
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240 static void omap44xx_prm_ocp_barrier(void)
0241 {
0242 omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
0243 OMAP4_REVISION_PRM_OFFSET);
0244 }
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257 static void omap44xx_prm_save_and_clear_irqen(u32 *saved_mask)
0258 {
0259 int i;
0260 u16 reg;
0261
0262 for (i = 0; i < omap4_prcm_irq_setup.nr_regs; i++) {
0263 reg = omap4_prcm_irq_setup.mask + i * 4;
0264
0265 saved_mask[i] =
0266 omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
0267 reg);
0268 omap4_prm_write_inst_reg(0, OMAP4430_PRM_OCP_SOCKET_INST, reg);
0269 }
0270
0271
0272 omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
0273 OMAP4_REVISION_PRM_OFFSET);
0274 }
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286 static void omap44xx_prm_restore_irqen(u32 *saved_mask)
0287 {
0288 int i;
0289
0290 for (i = 0; i < omap4_prcm_irq_setup.nr_regs; i++)
0291 omap4_prm_write_inst_reg(saved_mask[i],
0292 OMAP4430_PRM_OCP_SOCKET_INST,
0293 omap4_prcm_irq_setup.mask + i * 4);
0294 }
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305 static void omap44xx_prm_reconfigure_io_chain(void)
0306 {
0307 int i = 0;
0308 s32 inst = omap4_prmst_get_prm_dev_inst();
0309
0310 if (inst == PRM_INSTANCE_UNKNOWN)
0311 return;
0312
0313
0314 omap4_prm_rmw_inst_reg_bits(OMAP4430_WUCLK_CTRL_MASK,
0315 OMAP4430_WUCLK_CTRL_MASK,
0316 inst,
0317 omap4_prcm_irq_setup.pm_ctrl);
0318 omap_test_timeout(
0319 (((omap4_prm_read_inst_reg(inst,
0320 omap4_prcm_irq_setup.pm_ctrl) &
0321 OMAP4430_WUCLK_STATUS_MASK) >>
0322 OMAP4430_WUCLK_STATUS_SHIFT) == 1),
0323 MAX_IOPAD_LATCH_TIME, i);
0324 if (i == MAX_IOPAD_LATCH_TIME)
0325 pr_warn("PRM: I/O chain clock line assertion timed out\n");
0326
0327
0328 omap4_prm_rmw_inst_reg_bits(OMAP4430_WUCLK_CTRL_MASK, 0x0,
0329 inst,
0330 omap4_prcm_irq_setup.pm_ctrl);
0331 omap_test_timeout(
0332 (((omap4_prm_read_inst_reg(inst,
0333 omap4_prcm_irq_setup.pm_ctrl) &
0334 OMAP4430_WUCLK_STATUS_MASK) >>
0335 OMAP4430_WUCLK_STATUS_SHIFT) == 0),
0336 MAX_IOPAD_LATCH_TIME, i);
0337 if (i == MAX_IOPAD_LATCH_TIME)
0338 pr_warn("PRM: I/O chain clock line deassertion timed out\n");
0339
0340 return;
0341 }
0342
0343
0344
0345
0346
0347
0348
0349
0350
0351 static void omap44xx_prm_enable_io_wakeup(void)
0352 {
0353 s32 inst = omap4_prmst_get_prm_dev_inst();
0354
0355 if (inst == PRM_INSTANCE_UNKNOWN)
0356 return;
0357
0358 omap4_prm_rmw_inst_reg_bits(OMAP4430_GLOBAL_WUEN_MASK,
0359 OMAP4430_GLOBAL_WUEN_MASK,
0360 inst,
0361 omap4_prcm_irq_setup.pm_ctrl);
0362 }
0363
0364
0365
0366
0367
0368
0369
0370 static u32 omap44xx_prm_read_reset_sources(void)
0371 {
0372 struct prm_reset_src_map *p;
0373 u32 r = 0;
0374 u32 v;
0375 s32 inst = omap4_prmst_get_prm_dev_inst();
0376
0377 if (inst == PRM_INSTANCE_UNKNOWN)
0378 return 0;
0379
0380
0381 v = omap4_prm_read_inst_reg(inst,
0382 OMAP4_RM_RSTST);
0383
0384 p = omap44xx_prm_reset_src_map;
0385 while (p->reg_shift >= 0 && p->std_shift >= 0) {
0386 if (v & (1 << p->reg_shift))
0387 r |= 1 << p->std_shift;
0388 p++;
0389 }
0390
0391 return r;
0392 }
0393
0394
0395
0396
0397
0398
0399
0400
0401
0402
0403
0404 static bool omap44xx_prm_was_any_context_lost_old(u8 part, s16 inst, u16 idx)
0405 {
0406 return (omap4_prminst_read_inst_reg(part, inst, idx)) ? 1 : 0;
0407 }
0408
0409
0410
0411
0412
0413
0414
0415
0416
0417
0418
0419 static void omap44xx_prm_clear_context_loss_flags_old(u8 part, s16 inst,
0420 u16 idx)
0421 {
0422 omap4_prminst_write_inst_reg(0xffffffff, part, inst, idx);
0423 }
0424
0425
0426
0427 static int omap4_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
0428 {
0429 omap4_prminst_rmw_inst_reg_bits(OMAP_POWERSTATE_MASK,
0430 (pwrst << OMAP_POWERSTATE_SHIFT),
0431 pwrdm->prcm_partition,
0432 pwrdm->prcm_offs, OMAP4_PM_PWSTCTRL);
0433 return 0;
0434 }
0435
0436 static int omap4_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
0437 {
0438 u32 v;
0439
0440 v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
0441 OMAP4_PM_PWSTCTRL);
0442 v &= OMAP_POWERSTATE_MASK;
0443 v >>= OMAP_POWERSTATE_SHIFT;
0444
0445 return v;
0446 }
0447
0448 static int omap4_pwrdm_read_pwrst(struct powerdomain *pwrdm)
0449 {
0450 u32 v;
0451
0452 v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
0453 OMAP4_PM_PWSTST);
0454 v &= OMAP_POWERSTATEST_MASK;
0455 v >>= OMAP_POWERSTATEST_SHIFT;
0456
0457 return v;
0458 }
0459
0460 static int omap4_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
0461 {
0462 u32 v;
0463
0464 v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
0465 OMAP4_PM_PWSTST);
0466 v &= OMAP4430_LASTPOWERSTATEENTERED_MASK;
0467 v >>= OMAP4430_LASTPOWERSTATEENTERED_SHIFT;
0468
0469 return v;
0470 }
0471
0472 static int omap4_pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)
0473 {
0474 omap4_prminst_rmw_inst_reg_bits(OMAP4430_LOWPOWERSTATECHANGE_MASK,
0475 (1 << OMAP4430_LOWPOWERSTATECHANGE_SHIFT),
0476 pwrdm->prcm_partition,
0477 pwrdm->prcm_offs, OMAP4_PM_PWSTCTRL);
0478 return 0;
0479 }
0480
0481 static int omap4_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
0482 {
0483 omap4_prminst_rmw_inst_reg_bits(OMAP4430_LASTPOWERSTATEENTERED_MASK,
0484 OMAP4430_LASTPOWERSTATEENTERED_MASK,
0485 pwrdm->prcm_partition,
0486 pwrdm->prcm_offs, OMAP4_PM_PWSTST);
0487 return 0;
0488 }
0489
0490 static int omap4_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
0491 {
0492 u32 v;
0493
0494 v = pwrst << __ffs(OMAP4430_LOGICRETSTATE_MASK);
0495 omap4_prminst_rmw_inst_reg_bits(OMAP4430_LOGICRETSTATE_MASK, v,
0496 pwrdm->prcm_partition, pwrdm->prcm_offs,
0497 OMAP4_PM_PWSTCTRL);
0498
0499 return 0;
0500 }
0501
0502 static int omap4_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank,
0503 u8 pwrst)
0504 {
0505 u32 m;
0506
0507 m = omap2_pwrdm_get_mem_bank_onstate_mask(bank);
0508
0509 omap4_prminst_rmw_inst_reg_bits(m, (pwrst << __ffs(m)),
0510 pwrdm->prcm_partition, pwrdm->prcm_offs,
0511 OMAP4_PM_PWSTCTRL);
0512
0513 return 0;
0514 }
0515
0516 static int omap4_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank,
0517 u8 pwrst)
0518 {
0519 u32 m;
0520
0521 m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
0522
0523 omap4_prminst_rmw_inst_reg_bits(m, (pwrst << __ffs(m)),
0524 pwrdm->prcm_partition, pwrdm->prcm_offs,
0525 OMAP4_PM_PWSTCTRL);
0526
0527 return 0;
0528 }
0529
0530 static int omap4_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
0531 {
0532 u32 v;
0533
0534 v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
0535 OMAP4_PM_PWSTST);
0536 v &= OMAP4430_LOGICSTATEST_MASK;
0537 v >>= OMAP4430_LOGICSTATEST_SHIFT;
0538
0539 return v;
0540 }
0541
0542 static int omap4_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
0543 {
0544 u32 v;
0545
0546 v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
0547 OMAP4_PM_PWSTCTRL);
0548 v &= OMAP4430_LOGICRETSTATE_MASK;
0549 v >>= OMAP4430_LOGICRETSTATE_SHIFT;
0550
0551 return v;
0552 }
0553
0554
0555
0556
0557
0558
0559
0560
0561
0562
0563
0564
0565
0566
0567 static int omap4_pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm)
0568 {
0569 int state;
0570
0571 state = omap4_pwrdm_read_prev_pwrst(pwrdm);
0572
0573 if (state == PWRDM_POWER_OFF)
0574 return PWRDM_POWER_OFF;
0575
0576 if (state != PWRDM_POWER_RET)
0577 return PWRDM_POWER_RET;
0578
0579 return omap4_pwrdm_read_logic_retst(pwrdm);
0580 }
0581
0582 static int omap4_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
0583 {
0584 u32 m, v;
0585
0586 m = omap2_pwrdm_get_mem_bank_stst_mask(bank);
0587
0588 v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
0589 OMAP4_PM_PWSTST);
0590 v &= m;
0591 v >>= __ffs(m);
0592
0593 return v;
0594 }
0595
0596 static int omap4_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
0597 {
0598 u32 m, v;
0599
0600 m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
0601
0602 v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
0603 OMAP4_PM_PWSTCTRL);
0604 v &= m;
0605 v >>= __ffs(m);
0606
0607 return v;
0608 }
0609
0610
0611
0612
0613
0614
0615
0616
0617
0618
0619
0620
0621
0622
0623
0624 static int omap4_pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
0625 {
0626 int state;
0627
0628 state = omap4_pwrdm_read_prev_pwrst(pwrdm);
0629
0630 if (state == PWRDM_POWER_OFF)
0631 return PWRDM_POWER_OFF;
0632
0633 if (state != PWRDM_POWER_RET)
0634 return PWRDM_POWER_RET;
0635
0636 return omap4_pwrdm_read_mem_retst(pwrdm, bank);
0637 }
0638
0639 static int omap4_pwrdm_wait_transition(struct powerdomain *pwrdm)
0640 {
0641 u32 c = 0;
0642
0643
0644
0645
0646
0647
0648
0649
0650 while ((omap4_prminst_read_inst_reg(pwrdm->prcm_partition,
0651 pwrdm->prcm_offs,
0652 OMAP4_PM_PWSTST) &
0653 OMAP_INTRANSITION_MASK) &&
0654 (c++ < PWRDM_TRANSITION_BAILOUT))
0655 udelay(1);
0656
0657 if (c > PWRDM_TRANSITION_BAILOUT) {
0658 pr_err("powerdomain: %s: waited too long to complete transition\n",
0659 pwrdm->name);
0660 return -EAGAIN;
0661 }
0662
0663 pr_debug("powerdomain: completed transition in %d loops\n", c);
0664
0665 return 0;
0666 }
0667
0668 static int omap4_check_vcvp(void)
0669 {
0670 if (prm_features & PRM_HAS_VOLTAGE)
0671 return 1;
0672
0673 return 0;
0674 }
0675
0676
0677
0678
0679
0680
0681
0682
0683 static void omap4_pwrdm_save_context(struct powerdomain *pwrdm)
0684 {
0685 pwrdm->context = omap4_prminst_read_inst_reg(pwrdm->prcm_partition,
0686 pwrdm->prcm_offs,
0687 pwrdm->pwrstctrl_offs);
0688
0689
0690
0691
0692
0693 pwrdm->context &= ~OMAP4430_LOWPOWERSTATECHANGE_MASK;
0694 }
0695
0696
0697
0698
0699
0700
0701
0702
0703 static void omap4_pwrdm_restore_context(struct powerdomain *pwrdm)
0704 {
0705 int st, ctrl;
0706
0707 st = omap4_prminst_read_inst_reg(pwrdm->prcm_partition,
0708 pwrdm->prcm_offs,
0709 pwrdm->pwrstctrl_offs);
0710
0711 omap4_prminst_write_inst_reg(pwrdm->context,
0712 pwrdm->prcm_partition,
0713 pwrdm->prcm_offs,
0714 pwrdm->pwrstctrl_offs);
0715
0716
0717 st &= OMAP_POWERSTATEST_MASK;
0718 ctrl = OMAP_POWERSTATEST_MASK & pwrdm->context;
0719
0720 if (st != ctrl)
0721 omap4_pwrdm_wait_transition(pwrdm);
0722 }
0723
0724 struct pwrdm_ops omap4_pwrdm_operations = {
0725 .pwrdm_set_next_pwrst = omap4_pwrdm_set_next_pwrst,
0726 .pwrdm_read_next_pwrst = omap4_pwrdm_read_next_pwrst,
0727 .pwrdm_read_pwrst = omap4_pwrdm_read_pwrst,
0728 .pwrdm_read_prev_pwrst = omap4_pwrdm_read_prev_pwrst,
0729 .pwrdm_set_lowpwrstchange = omap4_pwrdm_set_lowpwrstchange,
0730 .pwrdm_clear_all_prev_pwrst = omap4_pwrdm_clear_all_prev_pwrst,
0731 .pwrdm_set_logic_retst = omap4_pwrdm_set_logic_retst,
0732 .pwrdm_read_logic_pwrst = omap4_pwrdm_read_logic_pwrst,
0733 .pwrdm_read_prev_logic_pwrst = omap4_pwrdm_read_prev_logic_pwrst,
0734 .pwrdm_read_logic_retst = omap4_pwrdm_read_logic_retst,
0735 .pwrdm_read_mem_pwrst = omap4_pwrdm_read_mem_pwrst,
0736 .pwrdm_read_mem_retst = omap4_pwrdm_read_mem_retst,
0737 .pwrdm_read_prev_mem_pwrst = omap4_pwrdm_read_prev_mem_pwrst,
0738 .pwrdm_set_mem_onst = omap4_pwrdm_set_mem_onst,
0739 .pwrdm_set_mem_retst = omap4_pwrdm_set_mem_retst,
0740 .pwrdm_wait_transition = omap4_pwrdm_wait_transition,
0741 .pwrdm_has_voltdm = omap4_check_vcvp,
0742 .pwrdm_save_context = omap4_pwrdm_save_context,
0743 .pwrdm_restore_context = omap4_pwrdm_restore_context,
0744 };
0745
0746 static int omap44xx_prm_late_init(void);
0747
0748 static void prm_save_context(void)
0749 {
0750 omap_prm_context.irq_enable =
0751 omap4_prm_read_inst_reg(AM43XX_PRM_OCP_SOCKET_INST,
0752 omap4_prcm_irq_setup.mask);
0753
0754 omap_prm_context.pm_ctrl =
0755 omap4_prm_read_inst_reg(AM43XX_PRM_DEVICE_INST,
0756 omap4_prcm_irq_setup.pm_ctrl);
0757 }
0758
0759 static void prm_restore_context(void)
0760 {
0761 omap4_prm_write_inst_reg(omap_prm_context.irq_enable,
0762 OMAP4430_PRM_OCP_SOCKET_INST,
0763 omap4_prcm_irq_setup.mask);
0764
0765 omap4_prm_write_inst_reg(omap_prm_context.pm_ctrl,
0766 AM43XX_PRM_DEVICE_INST,
0767 omap4_prcm_irq_setup.pm_ctrl);
0768 }
0769
0770 static int cpu_notifier(struct notifier_block *nb, unsigned long cmd, void *v)
0771 {
0772 switch (cmd) {
0773 case CPU_CLUSTER_PM_ENTER:
0774 if (enable_off_mode)
0775 prm_save_context();
0776 break;
0777 case CPU_CLUSTER_PM_EXIT:
0778 if (enable_off_mode)
0779 prm_restore_context();
0780 break;
0781 }
0782
0783 return NOTIFY_OK;
0784 }
0785
0786
0787
0788
0789 static struct prm_ll_data omap44xx_prm_ll_data = {
0790 .read_reset_sources = &omap44xx_prm_read_reset_sources,
0791 .was_any_context_lost_old = &omap44xx_prm_was_any_context_lost_old,
0792 .clear_context_loss_flags_old = &omap44xx_prm_clear_context_loss_flags_old,
0793 .late_init = &omap44xx_prm_late_init,
0794 .assert_hardreset = omap4_prminst_assert_hardreset,
0795 .deassert_hardreset = omap4_prminst_deassert_hardreset,
0796 .is_hardreset_asserted = omap4_prminst_is_hardreset_asserted,
0797 .reset_system = omap4_prminst_global_warm_sw_reset,
0798 .vp_check_txdone = omap4_prm_vp_check_txdone,
0799 .vp_clear_txdone = omap4_prm_vp_clear_txdone,
0800 };
0801
0802 static const struct omap_prcm_init_data *prm_init_data;
0803
0804 int __init omap44xx_prm_init(const struct omap_prcm_init_data *data)
0805 {
0806 static struct notifier_block nb;
0807 omap_prm_base_init();
0808
0809 prm_init_data = data;
0810
0811 if (data->flags & PRM_HAS_IO_WAKEUP)
0812 prm_features |= PRM_HAS_IO_WAKEUP;
0813
0814 if (data->flags & PRM_HAS_VOLTAGE)
0815 prm_features |= PRM_HAS_VOLTAGE;
0816
0817 omap4_prminst_set_prm_dev_inst(data->device_inst_offset);
0818
0819
0820 if (of_device_is_compatible(data->np, "ti,am4-prcm")) {
0821 omap4_prcm_irq_setup.nr_irqs = 1;
0822 omap4_prcm_irq_setup.nr_regs = 1;
0823 omap4_prcm_irq_setup.pm_ctrl = AM43XX_PRM_IO_PMCTRL_OFFSET;
0824 omap4_prcm_irq_setup.ack = AM43XX_PRM_IRQSTATUS_MPU_OFFSET;
0825 omap4_prcm_irq_setup.mask = AM43XX_PRM_IRQENABLE_MPU_OFFSET;
0826 }
0827
0828
0829 if (soc_is_am43xx()) {
0830 nb.notifier_call = cpu_notifier;
0831 cpu_pm_register_notifier(&nb);
0832 }
0833
0834 return prm_register(&omap44xx_prm_ll_data);
0835 }
0836
0837 static int omap44xx_prm_late_init(void)
0838 {
0839 int irq_num;
0840
0841 if (!(prm_features & PRM_HAS_IO_WAKEUP))
0842 return 0;
0843
0844 irq_num = of_irq_get(prm_init_data->np, 0);
0845 if (irq_num == -EPROBE_DEFER)
0846 return irq_num;
0847
0848 omap4_prcm_irq_setup.irq = irq_num;
0849
0850 omap44xx_prm_enable_io_wakeup();
0851
0852 return omap_prcm_register_chain_handler(&omap4_prcm_irq_setup);
0853 }
0854
0855 static void __exit omap44xx_prm_exit(void)
0856 {
0857 prm_unregister(&omap44xx_prm_ll_data);
0858 }
0859 __exitcall(omap44xx_prm_exit);