|
@@ -128,3 +128,188 @@ u32 omap3_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset)
|
|
* return value.
|
|
* return value.
|
|
*/
|
|
*/
|
|
void omap3xxx_prm_dpll3_reset(void)
|
|
void omap3xxx_prm_dpll3_reset(void)
|
|
|
|
+{
|
|
|
|
+ omap2_prm_set_mod_reg_bits(OMAP_RST_DPLL3_MASK, OMAP3430_GR_MOD,
|
|
|
|
+ OMAP2_RM_RSTCTRL);
|
|
|
|
+ /* OCP barrier */
|
|
|
|
+ omap2_prm_read_mod_reg(OMAP3430_GR_MOD, OMAP2_RM_RSTCTRL);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * omap3xxx_prm_read_pending_irqs - read pending PRM MPU IRQs into @events
|
|
|
|
+ * @events: ptr to a u32, preallocated by caller
|
|
|
|
+ *
|
|
|
|
+ * Read PRM_IRQSTATUS_MPU bits, AND'ed with the currently-enabled PRM
|
|
|
|
+ * MPU IRQs, and store the result into the u32 pointed to by @events.
|
|
|
|
+ * No return value.
|
|
|
|
+ */
|
|
|
|
+void omap3xxx_prm_read_pending_irqs(unsigned long *events)
|
|
|
|
+{
|
|
|
|
+ u32 mask, st;
|
|
|
|
+
|
|
|
|
+ /* XXX Can the mask read be avoided (e.g., can it come from RAM?) */
|
|
|
|
+ mask = omap2_prm_read_mod_reg(OCP_MOD, OMAP3_PRM_IRQENABLE_MPU_OFFSET);
|
|
|
|
+ st = omap2_prm_read_mod_reg(OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
|
|
|
|
+
|
|
|
|
+ events[0] = mask & st;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * omap3xxx_prm_ocp_barrier - force buffered MPU writes to the PRM to complete
|
|
|
|
+ *
|
|
|
|
+ * Force any buffered writes to the PRM IP block to complete. Needed
|
|
|
|
+ * by the PRM IRQ handler, which reads and writes directly to the IP
|
|
|
|
+ * block, to avoid race conditions after acknowledging or clearing IRQ
|
|
|
|
+ * bits. No return value.
|
|
|
|
+ */
|
|
|
|
+void omap3xxx_prm_ocp_barrier(void)
|
|
|
|
+{
|
|
|
|
+ omap2_prm_read_mod_reg(OCP_MOD, OMAP3_PRM_REVISION_OFFSET);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * omap3xxx_prm_save_and_clear_irqen - save/clear PRM_IRQENABLE_MPU reg
|
|
|
|
+ * @saved_mask: ptr to a u32 array to save IRQENABLE bits
|
|
|
|
+ *
|
|
|
|
+ * Save the PRM_IRQENABLE_MPU register to @saved_mask. @saved_mask
|
|
|
|
+ * must be allocated by the caller. Intended to be used in the PRM
|
|
|
|
+ * interrupt handler suspend callback. The OCP barrier is needed to
|
|
|
|
+ * ensure the write to disable PRM interrupts reaches the PRM before
|
|
|
|
+ * returning; otherwise, spurious interrupts might occur. No return
|
|
|
|
+ * value.
|
|
|
|
+ */
|
|
|
|
+void omap3xxx_prm_save_and_clear_irqen(u32 *saved_mask)
|
|
|
|
+{
|
|
|
|
+ saved_mask[0] = omap2_prm_read_mod_reg(OCP_MOD,
|
|
|
|
+ OMAP3_PRM_IRQENABLE_MPU_OFFSET);
|
|
|
|
+ omap2_prm_write_mod_reg(0, OCP_MOD, OMAP3_PRM_IRQENABLE_MPU_OFFSET);
|
|
|
|
+
|
|
|
|
+ /* OCP barrier */
|
|
|
|
+ omap2_prm_read_mod_reg(OCP_MOD, OMAP3_PRM_REVISION_OFFSET);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * omap3xxx_prm_restore_irqen - set PRM_IRQENABLE_MPU register from args
|
|
|
|
+ * @saved_mask: ptr to a u32 array of IRQENABLE bits saved previously
|
|
|
|
+ *
|
|
|
|
+ * Restore the PRM_IRQENABLE_MPU register from @saved_mask. Intended
|
|
|
|
+ * to be used in the PRM interrupt handler resume callback to restore
|
|
|
|
+ * values saved by omap3xxx_prm_save_and_clear_irqen(). No OCP
|
|
|
|
+ * barrier should be needed here; any pending PRM interrupts will fire
|
|
|
|
+ * once the writes reach the PRM. No return value.
|
|
|
|
+ */
|
|
|
|
+void omap3xxx_prm_restore_irqen(u32 *saved_mask)
|
|
|
|
+{
|
|
|
|
+ omap2_prm_write_mod_reg(saved_mask[0], OCP_MOD,
|
|
|
|
+ OMAP3_PRM_IRQENABLE_MPU_OFFSET);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * omap3xxx_prm_reconfigure_io_chain - clear latches and reconfigure I/O chain
|
|
|
|
+ *
|
|
|
|
+ * Clear any previously-latched I/O wakeup events and ensure that the
|
|
|
|
+ * I/O wakeup gates are aligned with the current mux settings. Works
|
|
|
|
+ * by asserting WUCLKIN, waiting for WUCLKOUT to be asserted, and then
|
|
|
|
+ * deasserting WUCLKIN and clearing the ST_IO_CHAIN WKST bit. No
|
|
|
|
+ * return value.
|
|
|
|
+ */
|
|
|
|
+void omap3xxx_prm_reconfigure_io_chain(void)
|
|
|
|
+{
|
|
|
|
+ int i = 0;
|
|
|
|
+
|
|
|
|
+ omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
|
|
|
|
+ PM_WKEN);
|
|
|
|
+
|
|
|
|
+ omap_test_timeout(omap2_prm_read_mod_reg(WKUP_MOD, PM_WKST) &
|
|
|
|
+ OMAP3430_ST_IO_CHAIN_MASK,
|
|
|
|
+ MAX_IOPAD_LATCH_TIME, i);
|
|
|
|
+ if (i == MAX_IOPAD_LATCH_TIME)
|
|
|
|
+ pr_warn("PRM: I/O chain clock line assertion timed out\n");
|
|
|
|
+
|
|
|
|
+ omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
|
|
|
|
+ PM_WKEN);
|
|
|
|
+
|
|
|
|
+ omap2_prm_set_mod_reg_bits(OMAP3430_ST_IO_CHAIN_MASK, WKUP_MOD,
|
|
|
|
+ PM_WKST);
|
|
|
|
+
|
|
|
|
+ omap2_prm_read_mod_reg(WKUP_MOD, PM_WKST);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * omap3xxx_prm_enable_io_wakeup - enable wakeup events from I/O wakeup latches
|
|
|
|
+ *
|
|
|
|
+ * Activates the I/O wakeup event latches and allows events logged by
|
|
|
|
+ * those latches to signal a wakeup event to the PRCM. For I/O
|
|
|
|
+ * wakeups to occur, WAKEUPENABLE bits must be set in the pad mux
|
|
|
|
+ * registers, and omap3xxx_prm_reconfigure_io_chain() must be called.
|
|
|
|
+ * No return value.
|
|
|
|
+ */
|
|
|
|
+static void __init omap3xxx_prm_enable_io_wakeup(void)
|
|
|
|
+{
|
|
|
|
+ if (omap3_has_io_wakeup())
|
|
|
|
+ omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD,
|
|
|
|
+ PM_WKEN);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * omap3xxx_prm_read_reset_sources - return the last SoC reset source
|
|
|
|
+ *
|
|
|
|
+ * Return a u32 representing the last reset sources of the SoC. The
|
|
|
|
+ * returned reset source bits are standardized across OMAP SoCs.
|
|
|
|
+ */
|
|
|
|
+static u32 omap3xxx_prm_read_reset_sources(void)
|
|
|
|
+{
|
|
|
|
+ struct prm_reset_src_map *p;
|
|
|
|
+ u32 r = 0;
|
|
|
|
+ u32 v;
|
|
|
|
+
|
|
|
|
+ v = omap2_prm_read_mod_reg(WKUP_MOD, OMAP2_RM_RSTST);
|
|
|
|
+
|
|
|
|
+ p = omap3xxx_prm_reset_src_map;
|
|
|
|
+ while (p->reg_shift >= 0 && p->std_shift >= 0) {
|
|
|
|
+ if (v & (1 << p->reg_shift))
|
|
|
|
+ r |= 1 << p->std_shift;
|
|
|
|
+ p++;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return r;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* Powerdomain low-level functions */
|
|
|
|
+
|
|
|
|
+static int omap3_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
|
|
|
|
+{
|
|
|
|
+ omap2_prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
|
|
|
|
+ (pwrst << OMAP_POWERSTATE_SHIFT),
|
|
|
|
+ pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL);
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int omap3_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
|
|
|
|
+{
|
|
|
|
+ return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
|
|
|
|
+ OMAP2_PM_PWSTCTRL,
|
|
|
|
+ OMAP_POWERSTATE_MASK);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int omap3_pwrdm_read_pwrst(struct powerdomain *pwrdm)
|
|
|
|
+{
|
|
|
|
+ return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
|
|
|
|
+ OMAP2_PM_PWSTST,
|
|
|
|
+ OMAP_POWERSTATEST_MASK);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* Applicable only for OMAP3. Not supported on OMAP2 */
|
|
|
|
+static int omap3_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
|
|
|
|
+{
|
|
|
|
+ return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
|
|
|
|
+ OMAP3430_PM_PREPWSTST,
|
|
|
|
+ OMAP3430_LASTPOWERSTATEENTERED_MASK);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int omap3_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
|
|
|
|
+{
|
|
|
|
+ return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
|
|
|
|
+ OMAP2_PM_PWSTST,
|
|
|
|
+ OMAP3430_LOGICSTATEST_MASK);
|
|
|
|
+}
|