|
@@ -220,6 +220,87 @@ static inline u32 omap_usec_to_32k(u32 usec)
|
|
return DIV_ROUND_UP_ULL(32768ULL * (u64)usec, 1000000ULL);
|
|
return DIV_ROUND_UP_ULL(32768ULL * (u64)usec, 1000000ULL);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+struct omap3_vc {
|
|
|
|
+ struct voltagedomain *vd;
|
|
|
|
+ u32 voltctrl;
|
|
|
|
+};
|
|
|
|
+static struct omap3_vc vc;
|
|
|
|
+
|
|
|
|
+void omap3_vc_set_pmic_signaling(int core_next_state)
|
|
|
|
+{
|
|
|
|
+ struct voltagedomain *vd = vc.vd;
|
|
|
|
+ u32 voltctrl;
|
|
|
|
+
|
|
|
|
+ voltctrl = vc.voltctrl;
|
|
|
|
+ switch (core_next_state) {
|
|
|
|
+ case PWRDM_POWER_OFF:
|
|
|
|
+ voltctrl &= ~(OMAP3430_PRM_VOLTCTRL_AUTO_RET |
|
|
|
|
+ OMAP3430_PRM_VOLTCTRL_AUTO_SLEEP);
|
|
|
|
+ voltctrl |= OMAP3430_PRM_VOLTCTRL_AUTO_OFF;
|
|
|
|
+ break;
|
|
|
|
+ case PWRDM_POWER_RET:
|
|
|
|
+ default:
|
|
|
|
+ voltctrl &= ~(OMAP3430_PRM_VOLTCTRL_AUTO_OFF |
|
|
|
|
+ OMAP3430_PRM_VOLTCTRL_AUTO_SLEEP);
|
|
|
|
+ voltctrl |= OMAP3430_PRM_VOLTCTRL_AUTO_RET;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ if (voltctrl != vc.voltctrl) {
|
|
|
|
+ vd->write(voltctrl, OMAP3_PRM_VOLTCTRL_OFFSET);
|
|
|
|
+ vc.voltctrl = voltctrl;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+#define PRM_POLCTRL_TWL_MASK (OMAP3430_PRM_POLCTRL_CLKREQ_POL | \
|
|
|
|
+ OMAP3430_PRM_POLCTRL_CLKREQ_POL)
|
|
|
|
+#define PRM_POLCTRL_TWL_VAL OMAP3430_PRM_POLCTRL_CLKREQ_POL
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * Configure signal polarity for sys_clkreq and sys_off_mode pins
|
|
|
|
+ * as the default values are wrong and can cause the system to hang
|
|
|
|
+ * if any twl4030 scripts are loaded.
|
|
|
|
+ */
|
|
|
|
+static void __init omap3_vc_init_pmic_signaling(struct voltagedomain *voltdm)
|
|
|
|
+{
|
|
|
|
+ u32 val;
|
|
|
|
+
|
|
|
|
+ if (vc.vd)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ vc.vd = voltdm;
|
|
|
|
+
|
|
|
|
+ val = voltdm->read(OMAP3_PRM_POLCTRL_OFFSET);
|
|
|
|
+ if (!(val & OMAP3430_PRM_POLCTRL_CLKREQ_POL) ||
|
|
|
|
+ (val & OMAP3430_PRM_POLCTRL_CLKREQ_POL)) {
|
|
|
|
+ val |= OMAP3430_PRM_POLCTRL_CLKREQ_POL;
|
|
|
|
+ val &= ~OMAP3430_PRM_POLCTRL_OFFMODE_POL;
|
|
|
|
+ pr_debug("PM: fixing sys_clkreq and sys_off_mode polarity to 0x%x\n",
|
|
|
|
+ val);
|
|
|
|
+ voltdm->write(val, OMAP3_PRM_POLCTRL_OFFSET);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * By default let's use I2C4 signaling for retention idle
|
|
|
|
+ * and sys_off_mode pin signaling for off idle. This way we
|
|
|
|
+ * have sys_clk_req pin go down for retention and both
|
|
|
|
+ * sys_clk_req and sys_off_mode pins will go down for off
|
|
|
|
+ * idle. And we can also scale voltages to zero for off-idle.
|
|
|
|
+ * Note that no actual voltage scaling during off-idle will
|
|
|
|
+ * happen unless the board specific twl4030 PMIC scripts are
|
|
|
|
+ * loaded.
|
|
|
|
+ */
|
|
|
|
+ val = voltdm->read(OMAP3_PRM_VOLTCTRL_OFFSET);
|
|
|
|
+ if (!(val & OMAP3430_PRM_VOLTCTRL_SEL_OFF)) {
|
|
|
|
+ val |= OMAP3430_PRM_VOLTCTRL_SEL_OFF;
|
|
|
|
+ pr_debug("PM: setting voltctrl sys_off_mode signaling to 0x%x\n",
|
|
|
|
+ val);
|
|
|
|
+ voltdm->write(val, OMAP3_PRM_VOLTCTRL_OFFSET);
|
|
|
|
+ }
|
|
|
|
+ vc.voltctrl = val;
|
|
|
|
+
|
|
|
|
+ omap3_vc_set_pmic_signaling(PWRDM_POWER_ON);
|
|
|
|
+}
|
|
|
|
+
|
|
/* Set oscillator setup time for omap3 */
|
|
/* Set oscillator setup time for omap3 */
|
|
static void omap3_set_clksetup(u32 usec, struct voltagedomain *voltdm)
|
|
static void omap3_set_clksetup(u32 usec, struct voltagedomain *voltdm)
|
|
{
|
|
{
|
|
@@ -292,7 +373,7 @@ static void omap3_set_off_timings(struct voltagedomain *voltdm)
|
|
|
|
|
|
/* check if sys_off_mode is used to control off-mode voltages */
|
|
/* check if sys_off_mode is used to control off-mode voltages */
|
|
val = voltdm->read(OMAP3_PRM_VOLTCTRL_OFFSET);
|
|
val = voltdm->read(OMAP3_PRM_VOLTCTRL_OFFSET);
|
|
- if (!(val & OMAP3430_SEL_OFF_MASK)) {
|
|
|
|
|
|
+ if (!(val & OMAP3430_PRM_VOLTCTRL_SEL_OFF)) {
|
|
/* No, omap is controlling them over I2C */
|
|
/* No, omap is controlling them over I2C */
|
|
omap3_set_i2c_timings(voltdm, true);
|
|
omap3_set_i2c_timings(voltdm, true);
|
|
return;
|
|
return;
|
|
@@ -337,6 +418,7 @@ static void omap3_set_off_timings(struct voltagedomain *voltdm)
|
|
|
|
|
|
static void __init omap3_vc_init_channel(struct voltagedomain *voltdm)
|
|
static void __init omap3_vc_init_channel(struct voltagedomain *voltdm)
|
|
{
|
|
{
|
|
|
|
+ omap3_vc_init_pmic_signaling(voltdm);
|
|
omap3_set_off_timings(voltdm);
|
|
omap3_set_off_timings(voltdm);
|
|
}
|
|
}
|
|
|
|
|