|
@@ -512,3 +512,161 @@ static void __init prcm_setup_regs(void)
|
|
|
OMAP3430_DSS_MOD, PM_WKEN);
|
|
|
|
|
|
/* Enable wakeups in PER */
|
|
|
+ omap2_prm_write_mod_reg(omap3630_en_uart4_mask |
|
|
|
+ OMAP3430_EN_GPIO2_MASK | OMAP3430_EN_GPIO3_MASK |
|
|
|
+ OMAP3430_EN_GPIO4_MASK | OMAP3430_EN_GPIO5_MASK |
|
|
|
+ OMAP3430_EN_GPIO6_MASK | OMAP3430_EN_UART3_MASK |
|
|
|
+ OMAP3430_EN_MCBSP2_MASK | OMAP3430_EN_MCBSP3_MASK |
|
|
|
+ OMAP3430_EN_MCBSP4_MASK,
|
|
|
+ OMAP3430_PER_MOD, PM_WKEN);
|
|
|
+ /* and allow them to wake up MPU */
|
|
|
+ omap2_prm_write_mod_reg(omap3630_grpsel_uart4_mask |
|
|
|
+ OMAP3430_GRPSEL_GPIO2_MASK |
|
|
|
+ OMAP3430_GRPSEL_GPIO3_MASK |
|
|
|
+ OMAP3430_GRPSEL_GPIO4_MASK |
|
|
|
+ OMAP3430_GRPSEL_GPIO5_MASK |
|
|
|
+ OMAP3430_GRPSEL_GPIO6_MASK |
|
|
|
+ OMAP3430_GRPSEL_UART3_MASK |
|
|
|
+ OMAP3430_GRPSEL_MCBSP2_MASK |
|
|
|
+ OMAP3430_GRPSEL_MCBSP3_MASK |
|
|
|
+ OMAP3430_GRPSEL_MCBSP4_MASK,
|
|
|
+ OMAP3430_PER_MOD, OMAP3430_PM_MPUGRPSEL);
|
|
|
+
|
|
|
+ /* Don't attach IVA interrupts */
|
|
|
+ if (omap3_has_iva()) {
|
|
|
+ omap2_prm_write_mod_reg(0, WKUP_MOD, OMAP3430_PM_IVAGRPSEL);
|
|
|
+ omap2_prm_write_mod_reg(0, CORE_MOD, OMAP3430_PM_IVAGRPSEL1);
|
|
|
+ omap2_prm_write_mod_reg(0, CORE_MOD, OMAP3430ES2_PM_IVAGRPSEL3);
|
|
|
+ omap2_prm_write_mod_reg(0, OMAP3430_PER_MOD,
|
|
|
+ OMAP3430_PM_IVAGRPSEL);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Clear any pending 'reset' flags */
|
|
|
+ omap2_prm_write_mod_reg(0xffffffff, MPU_MOD, OMAP2_RM_RSTST);
|
|
|
+ omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP2_RM_RSTST);
|
|
|
+ omap2_prm_write_mod_reg(0xffffffff, OMAP3430_PER_MOD, OMAP2_RM_RSTST);
|
|
|
+ omap2_prm_write_mod_reg(0xffffffff, OMAP3430_EMU_MOD, OMAP2_RM_RSTST);
|
|
|
+ omap2_prm_write_mod_reg(0xffffffff, OMAP3430_NEON_MOD, OMAP2_RM_RSTST);
|
|
|
+ omap2_prm_write_mod_reg(0xffffffff, OMAP3430_DSS_MOD, OMAP2_RM_RSTST);
|
|
|
+ omap2_prm_write_mod_reg(0xffffffff, OMAP3430ES2_USBHOST_MOD, OMAP2_RM_RSTST);
|
|
|
+
|
|
|
+ /* Clear any pending PRCM interrupts */
|
|
|
+ omap2_prm_write_mod_reg(0, OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
|
|
|
+
|
|
|
+ if (omap3_has_iva())
|
|
|
+ omap3_iva_idle();
|
|
|
+
|
|
|
+ omap3_d2d_idle();
|
|
|
+}
|
|
|
+
|
|
|
+void omap3_pm_off_mode_enable(int enable)
|
|
|
+{
|
|
|
+ struct power_state *pwrst;
|
|
|
+ u32 state;
|
|
|
+
|
|
|
+ if (enable)
|
|
|
+ state = PWRDM_POWER_OFF;
|
|
|
+ else
|
|
|
+ state = PWRDM_POWER_RET;
|
|
|
+
|
|
|
+ list_for_each_entry(pwrst, &pwrst_list, node) {
|
|
|
+ if (IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583) &&
|
|
|
+ pwrst->pwrdm == core_pwrdm &&
|
|
|
+ state == PWRDM_POWER_OFF) {
|
|
|
+ pwrst->next_state = PWRDM_POWER_RET;
|
|
|
+ pr_warn("%s: Core OFF disabled due to errata i583\n",
|
|
|
+ __func__);
|
|
|
+ } else {
|
|
|
+ pwrst->next_state = state;
|
|
|
+ }
|
|
|
+ omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+int omap3_pm_get_suspend_state(struct powerdomain *pwrdm)
|
|
|
+{
|
|
|
+ struct power_state *pwrst;
|
|
|
+
|
|
|
+ list_for_each_entry(pwrst, &pwrst_list, node) {
|
|
|
+ if (pwrst->pwrdm == pwrdm)
|
|
|
+ return pwrst->next_state;
|
|
|
+ }
|
|
|
+ return -EINVAL;
|
|
|
+}
|
|
|
+
|
|
|
+int omap3_pm_set_suspend_state(struct powerdomain *pwrdm, int state)
|
|
|
+{
|
|
|
+ struct power_state *pwrst;
|
|
|
+
|
|
|
+ list_for_each_entry(pwrst, &pwrst_list, node) {
|
|
|
+ if (pwrst->pwrdm == pwrdm) {
|
|
|
+ pwrst->next_state = state;
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return -EINVAL;
|
|
|
+}
|
|
|
+
|
|
|
+static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
|
|
|
+{
|
|
|
+ struct power_state *pwrst;
|
|
|
+
|
|
|
+ if (!pwrdm->pwrsts)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ pwrst = kmalloc(sizeof(struct power_state), GFP_ATOMIC);
|
|
|
+ if (!pwrst)
|
|
|
+ return -ENOMEM;
|
|
|
+ pwrst->pwrdm = pwrdm;
|
|
|
+ pwrst->next_state = PWRDM_POWER_RET;
|
|
|
+ list_add(&pwrst->node, &pwrst_list);
|
|
|
+
|
|
|
+ if (pwrdm_has_hdwr_sar(pwrdm))
|
|
|
+ pwrdm_enable_hdwr_sar(pwrdm);
|
|
|
+
|
|
|
+ return omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Push functions to SRAM
|
|
|
+ *
|
|
|
+ * The minimum set of functions is pushed to SRAM for execution:
|
|
|
+ * - omap3_do_wfi for erratum i581 WA,
|
|
|
+ * - save_secure_ram_context for security extensions.
|
|
|
+ */
|
|
|
+void omap_push_sram_idle(void)
|
|
|
+{
|
|
|
+ omap3_do_wfi_sram = omap_sram_push(omap3_do_wfi, omap3_do_wfi_sz);
|
|
|
+
|
|
|
+ if (omap_type() != OMAP2_DEVICE_TYPE_GP)
|
|
|
+ _omap_save_secure_sram = omap_sram_push(save_secure_ram_context,
|
|
|
+ save_secure_ram_context_sz);
|
|
|
+}
|
|
|
+
|
|
|
+static void __init pm_errata_configure(void)
|
|
|
+{
|
|
|
+ if (cpu_is_omap3630()) {
|
|
|
+ pm34xx_errata |= PM_RTA_ERRATUM_i608;
|
|
|
+ /* Enable the l2 cache toggling in sleep logic */
|
|
|
+ enable_omap3630_toggle_l2_on_restore();
|
|
|
+ if (omap_rev() < OMAP3630_REV_ES1_2)
|
|
|
+ pm34xx_errata |= (PM_SDRC_WAKEUP_ERRATUM_i583 |
|
|
|
+ PM_PER_MEMORIES_ERRATUM_i582);
|
|
|
+ } else if (cpu_is_omap34xx()) {
|
|
|
+ pm34xx_errata |= PM_PER_MEMORIES_ERRATUM_i582;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+int __init omap3_pm_init(void)
|
|
|
+{
|
|
|
+ struct power_state *pwrst, *tmp;
|
|
|
+ struct clockdomain *neon_clkdm, *mpu_clkdm, *per_clkdm, *wkup_clkdm;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ if (!omap3_has_io_chain_ctrl())
|
|
|
+ pr_warning("PM: no software I/O chain control; some wakeups may be lost\n");
|
|
|
+
|
|
|
+ pm_errata_configure();
|
|
|
+
|
|
|
+ /* XXX prcm_setup_regs needs to be before enabling hw
|
|
|
+ * supervised mode for powerdomains */
|