aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-omap2/pm44xx.c61
1 files changed, 50 insertions, 11 deletions
diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
index 837025bb6d2..9e50e1db8e5 100644
--- a/arch/arm/mach-omap2/pm44xx.c
+++ b/arch/arm/mach-omap2/pm44xx.c
@@ -105,10 +105,50 @@ static struct clockdomain *emif_clkdm, *mpuss_clkdm;
*/
#define OMAP4_PM_ERRATUM_MPU_EMIF_NO_DYNDEP_IDLE_iXXX BIT(4)
+/*
+ * There is a HW bug in CMD PHY which gives ISO signals as same for both
+ * PADn and PADp on differential IO pad, because of which IO leaks higher
+ * as pull controls are differential internally and pull value does not
+ * match A value.
+ * Though there is no functionality impact due to this bug, it is seen
+ * that by disabling the pulls there is a savings ~500uA in OSWR, but draws
+ * ~300uA more during OFF mode.
+ * To save power during both idle/suspend following approach taken:
+ * 1) Enable WA during boot-up.
+ * 2) Disable WA while attempting suspend and enable during resume.
+ *
+ * CDDS no: OMAP4460-1.0BUG00291 (OMAP official errata ID yet to be available).
+ */
+#define OMAP4_PM_ERRATUM_LPDDR_CLK_IO_iXXX BIT(5)
+#define LPDDR_WD_PULL_DOWN 0x02
+
u8 pm44xx_errata;
#define is_pm44xx_erratum(erratum) (pm44xx_errata & OMAP4_PM_ERRATUM_##erratum)
#define MAX_IOPAD_LATCH_TIME 1000
+
+void syscontrol_lpddr_clk_io_errata(bool enable)
+{
+ u32 v = 0;
+
+ if (!is_pm44xx_erratum(LPDDR_CLK_IO_iXXX))
+ return;
+
+ v = omap4_ctrl_pad_readl(OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO1_2);
+ if (enable)
+ v &= ~OMAP4_LPDDR2IO1_GR10_WD_MASK;
+ else
+ v |= LPDDR_WD_PULL_DOWN << OMAP4_LPDDR2IO1_GR10_WD_SHIFT;
+ omap4_ctrl_pad_writel(v, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO1_2);
+
+ v = omap4_ctrl_pad_readl(OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO2_2);
+ if (enable)
+ v &= ~OMAP4_LPDDR2IO2_GR10_WD_MASK;
+ else
+ v |= LPDDR_WD_PULL_DOWN << OMAP4_LPDDR2IO1_GR10_WD_SHIFT;
+ omap4_ctrl_pad_writel(v, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO2_2);
+}
+
void omap4_trigger_ioctrl(void)
{
int i = 0;
@@ -258,8 +298,14 @@ void omap4_enter_sleep(unsigned int cpu, unsigned int power_state, bool suspend)
OMAP4430_PRM_DEVICE_INST, OMAP4_PRM_IO_PMCTRL_OFFSET);
}
+ if (suspend)
+ syscontrol_lpddr_clk_io_errata(false);
+
omap4_enter_lowpower(cpu, power_state);
+ if (suspend)
+ syscontrol_lpddr_clk_io_errata(true);
+
if (omap4_device_prev_state_off()) {
/* Reconfigure the trim settings as well */
omap4_ldo_trim_configure();
@@ -946,16 +992,7 @@ static void __init syscontrol_setup_regs(void)
v |= OMAP4_LPDDR21_VREF_AUTO_EN_CA_MASK | OMAP4_LPDDR21_VREF_AUTO_EN_DQ_MASK;
omap4_ctrl_pad_writel(v, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO2_3);
- /*
- * Workaround for CK differential IO PADn, PADp values due to bug in
- * EMIF CMD phy.
- */
- v = omap4_ctrl_pad_readl(OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO1_2);
- v &= ~OMAP4_LPDDR2IO1_GR10_WD_MASK;
- omap4_ctrl_pad_writel(v, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO1_2);
- v = omap4_ctrl_pad_readl(OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO2_2);
- v &= ~OMAP4_LPDDR2IO2_GR10_WD_MASK;
- omap4_ctrl_pad_writel(v, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO2_2);
+ syscontrol_lpddr_clk_io_errata(true);
}
static void __init prcm_setup_regs(void)
@@ -1265,7 +1302,9 @@ static void __init omap4_pm_setup_errata(void)
*/
if (cpu_is_omap44xx())
pm44xx_errata |= OMAP4_PM_ERRATUM_IVA_AUTO_RET_iXXX |
- OMAP4_PM_ERRATUM_HSI_SWAKEUP_iXXX;
+ OMAP4_PM_ERRATUM_HSI_SWAKEUP_iXXX |
+ OMAP4_PM_ERRATUM_LPDDR_CLK_IO_iXXX;
+
/* Dynamic Dependency errata for all silicon !=443x */
if (cpu_is_omap443x())
pm44xx_errata |= OMAP4_PM_ERRATUM_MPU_EMIF_NO_DYNDEP_i688;