|
@@ -548,3 +548,132 @@ static int omap4_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
|
|
return v;
|
|
return v;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int omap4_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
|
|
|
|
+{
|
|
|
|
+ u32 m, v;
|
|
|
|
+
|
|
|
|
+ m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
|
|
|
|
+
|
|
|
|
+ v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
|
|
|
|
+ OMAP4_PM_PWSTCTRL);
|
|
|
|
+ v &= m;
|
|
|
|
+ v >>= __ffs(m);
|
|
|
|
+
|
|
|
|
+ return v;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * omap4_pwrdm_read_prev_mem_pwrst - reads the previous memory powerstate
|
|
|
|
+ * @pwrdm: struct powerdomain * to read mem powerstate for
|
|
|
|
+ * @bank: memory bank index
|
|
|
|
+ *
|
|
|
|
+ * Reads the previous memory powerstate for a powerdomain. This
|
|
|
|
+ * function must determine the previous memory powerstate by first
|
|
|
|
+ * checking the previous powerstate for the domain. If that was OFF,
|
|
|
|
+ * then logic has been lost. If previous state was RETENTION, the
|
|
|
|
+ * function reads the setting for the next memory retention state to
|
|
|
|
+ * see the actual value. In every other case, the logic is
|
|
|
|
+ * retained. Returns either PWRDM_POWER_OFF or PWRDM_POWER_RET
|
|
|
|
+ * depending whether logic was retained or not.
|
|
|
|
+ */
|
|
|
|
+static int omap4_pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
|
|
|
|
+{
|
|
|
|
+ int state;
|
|
|
|
+
|
|
|
|
+ state = omap4_pwrdm_read_prev_pwrst(pwrdm);
|
|
|
|
+
|
|
|
|
+ if (state == PWRDM_POWER_OFF)
|
|
|
|
+ return PWRDM_POWER_OFF;
|
|
|
|
+
|
|
|
|
+ if (state != PWRDM_POWER_RET)
|
|
|
|
+ return PWRDM_POWER_RET;
|
|
|
|
+
|
|
|
|
+ return omap4_pwrdm_read_mem_retst(pwrdm, bank);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int omap4_pwrdm_wait_transition(struct powerdomain *pwrdm)
|
|
|
|
+{
|
|
|
|
+ u32 c = 0;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * REVISIT: pwrdm_wait_transition() may be better implemented
|
|
|
|
+ * via a callback and a periodic timer check -- how long do we expect
|
|
|
|
+ * powerdomain transitions to take?
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+ /* XXX Is this udelay() value meaningful? */
|
|
|
|
+ while ((omap4_prminst_read_inst_reg(pwrdm->prcm_partition,
|
|
|
|
+ pwrdm->prcm_offs,
|
|
|
|
+ OMAP4_PM_PWSTST) &
|
|
|
|
+ OMAP_INTRANSITION_MASK) &&
|
|
|
|
+ (c++ < PWRDM_TRANSITION_BAILOUT))
|
|
|
|
+ udelay(1);
|
|
|
|
+
|
|
|
|
+ if (c > PWRDM_TRANSITION_BAILOUT) {
|
|
|
|
+ pr_err("powerdomain: %s: waited too long to complete transition\n",
|
|
|
|
+ pwrdm->name);
|
|
|
|
+ return -EAGAIN;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ pr_debug("powerdomain: completed transition in %d loops\n", c);
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+struct pwrdm_ops omap4_pwrdm_operations = {
|
|
|
|
+ .pwrdm_set_next_pwrst = omap4_pwrdm_set_next_pwrst,
|
|
|
|
+ .pwrdm_read_next_pwrst = omap4_pwrdm_read_next_pwrst,
|
|
|
|
+ .pwrdm_read_pwrst = omap4_pwrdm_read_pwrst,
|
|
|
|
+ .pwrdm_read_prev_pwrst = omap4_pwrdm_read_prev_pwrst,
|
|
|
|
+ .pwrdm_set_lowpwrstchange = omap4_pwrdm_set_lowpwrstchange,
|
|
|
|
+ .pwrdm_clear_all_prev_pwrst = omap4_pwrdm_clear_all_prev_pwrst,
|
|
|
|
+ .pwrdm_set_logic_retst = omap4_pwrdm_set_logic_retst,
|
|
|
|
+ .pwrdm_read_logic_pwrst = omap4_pwrdm_read_logic_pwrst,
|
|
|
|
+ .pwrdm_read_prev_logic_pwrst = omap4_pwrdm_read_prev_logic_pwrst,
|
|
|
|
+ .pwrdm_read_logic_retst = omap4_pwrdm_read_logic_retst,
|
|
|
|
+ .pwrdm_read_mem_pwrst = omap4_pwrdm_read_mem_pwrst,
|
|
|
|
+ .pwrdm_read_mem_retst = omap4_pwrdm_read_mem_retst,
|
|
|
|
+ .pwrdm_read_prev_mem_pwrst = omap4_pwrdm_read_prev_mem_pwrst,
|
|
|
|
+ .pwrdm_set_mem_onst = omap4_pwrdm_set_mem_onst,
|
|
|
|
+ .pwrdm_set_mem_retst = omap4_pwrdm_set_mem_retst,
|
|
|
|
+ .pwrdm_wait_transition = omap4_pwrdm_wait_transition,
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * XXX document
|
|
|
|
+ */
|
|
|
|
+static struct prm_ll_data omap44xx_prm_ll_data = {
|
|
|
|
+ .read_reset_sources = &omap44xx_prm_read_reset_sources,
|
|
|
|
+ .was_any_context_lost_old = &omap44xx_prm_was_any_context_lost_old,
|
|
|
|
+ .clear_context_loss_flags_old = &omap44xx_prm_clear_context_loss_flags_old,
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+int __init omap44xx_prm_init(void)
|
|
|
|
+{
|
|
|
|
+ if (!cpu_is_omap44xx())
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ return prm_register(&omap44xx_prm_ll_data);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int __init omap44xx_prm_late_init(void)
|
|
|
|
+{
|
|
|
|
+ if (!cpu_is_omap44xx())
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ omap44xx_prm_enable_io_wakeup();
|
|
|
|
+
|
|
|
|
+ return omap_prcm_register_chain_handler(&omap4_prcm_irq_setup);
|
|
|
|
+}
|
|
|
|
+subsys_initcall(omap44xx_prm_late_init);
|
|
|
|
+
|
|
|
|
+static void __exit omap44xx_prm_exit(void)
|
|
|
|
+{
|
|
|
|
+ if (!cpu_is_omap44xx())
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ /* Should never happen */
|
|
|
|
+ WARN(prm_unregister(&omap44xx_prm_ll_data),
|
|
|
|
+ "%s: prm_ll_data function pointer mismatch\n", __func__);
|
|
|
|
+}
|
|
|
|
+__exitcall(omap44xx_prm_exit);
|