| From 102bcb6ed2d1c3ffcc7269afc957c2df11942085 Mon Sep 17 00:00:00 2001 |
| From: Tony Lindgren <tony@atomide.com> |
| Date: Mon, 4 May 2015 08:54:41 -0700 |
| Subject: ARM: OMAP2+: Fix omap off idle power consumption creeping up |
| |
| From: Tony Lindgren <tony@atomide.com> |
| |
| commit 102bcb6ed2d1c3ffcc7269afc957c2df11942085 upstream. |
| |
| If we use a combination of VMODE and I2C4 for retention modes, |
| eventually the off idle power consumption will creep up by about |
| 23mW, even during off mode with I2C4 always staying enabled. |
| |
| Turns out this is because of erratum i531 "Extra Power Consumed |
| When Repeated Start Operation Mode Is Enabled on I2C Interface |
| Dedicated for Smart Reflex (I2C4)" as pointed out by Nishanth |
| Menon <nm@ti.com>. |
| |
| Let's fix the issue by adding i2c_cfg_clear_mask for the bits |
| to clear when initializing the I2C4 adapter so we can clear |
| SREN bit that drives the I2C4 lines low otherwise when there |
| is no traffic. |
| |
| Fixes: 3b8c4ebb7630 ("ARM: OMAP3: Fix idle mode signaling for |
| sys_clkreq and sys_off_mode") |
| Cc: Kevin Hilman <khilman@kernel.org> |
| Cc: Tero Kristo <t-kristo@ti.com> |
| Reviewed-by: Nishanth Menon <nm@ti.com> |
| Signed-off-by: Tony Lindgren <tony@atomide.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| arch/arm/mach-omap2/prm-regbits-34xx.h | 1 + |
| arch/arm/mach-omap2/prm-regbits-44xx.h | 1 + |
| arch/arm/mach-omap2/vc.c | 12 ++++++++++-- |
| arch/arm/mach-omap2/vc.h | 2 ++ |
| arch/arm/mach-omap2/vc3xxx_data.c | 1 + |
| arch/arm/mach-omap2/vc44xx_data.c | 1 + |
| 6 files changed, 16 insertions(+), 2 deletions(-) |
| |
| --- a/arch/arm/mach-omap2/prm-regbits-34xx.h |
| +++ b/arch/arm/mach-omap2/prm-regbits-34xx.h |
| @@ -112,6 +112,7 @@ |
| #define OMAP3430_VC_CMD_ONLP_SHIFT 16 |
| #define OMAP3430_VC_CMD_RET_SHIFT 8 |
| #define OMAP3430_VC_CMD_OFF_SHIFT 0 |
| +#define OMAP3430_SREN_MASK (1 << 4) |
| #define OMAP3430_HSEN_MASK (1 << 3) |
| #define OMAP3430_MCODE_MASK (0x7 << 0) |
| #define OMAP3430_VALID_MASK (1 << 24) |
| --- a/arch/arm/mach-omap2/prm-regbits-44xx.h |
| +++ b/arch/arm/mach-omap2/prm-regbits-44xx.h |
| @@ -35,6 +35,7 @@ |
| #define OMAP4430_GLOBAL_WARM_SW_RST_SHIFT 1 |
| #define OMAP4430_GLOBAL_WUEN_MASK (1 << 16) |
| #define OMAP4430_HSMCODE_MASK (0x7 << 0) |
| +#define OMAP4430_SRMODEEN_MASK (1 << 4) |
| #define OMAP4430_HSMODEEN_MASK (1 << 3) |
| #define OMAP4430_HSSCLL_SHIFT 24 |
| #define OMAP4430_ICEPICK_RST_SHIFT 9 |
| --- a/arch/arm/mach-omap2/vc.c |
| +++ b/arch/arm/mach-omap2/vc.c |
| @@ -316,7 +316,8 @@ static void __init omap3_vc_init_pmic_si |
| * 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. |
| + * loaded. See also omap_vc_i2c_init for comments regarding |
| + * erratum i531. |
| */ |
| val = voltdm->read(OMAP3_PRM_VOLTCTRL_OFFSET); |
| if (!(val & OMAP3430_PRM_VOLTCTRL_SEL_OFF)) { |
| @@ -704,9 +705,16 @@ static void __init omap_vc_i2c_init(stru |
| return; |
| } |
| |
| + /* |
| + * Note that for omap3 OMAP3430_SREN_MASK clears SREN to work around |
| + * erratum i531 "Extra Power Consumed When Repeated Start Operation |
| + * Mode Is Enabled on I2C Interface Dedicated for Smart Reflex (I2C4)". |
| + * Otherwise I2C4 eventually leads into about 23mW extra power being |
| + * consumed even during off idle using VMODE. |
| + */ |
| i2c_high_speed = voltdm->pmic->i2c_high_speed; |
| if (i2c_high_speed) |
| - voltdm->rmw(vc->common->i2c_cfg_hsen_mask, |
| + voltdm->rmw(vc->common->i2c_cfg_clear_mask, |
| vc->common->i2c_cfg_hsen_mask, |
| vc->common->i2c_cfg_reg); |
| |
| --- a/arch/arm/mach-omap2/vc.h |
| +++ b/arch/arm/mach-omap2/vc.h |
| @@ -34,6 +34,7 @@ struct voltagedomain; |
| * @cmd_ret_shift: RET field shift in PRM_VC_CMD_VAL_* register |
| * @cmd_off_shift: OFF field shift in PRM_VC_CMD_VAL_* register |
| * @i2c_cfg_reg: I2C configuration register offset |
| + * @i2c_cfg_clear_mask: high-speed mode bit clear mask in I2C config register |
| * @i2c_cfg_hsen_mask: high-speed mode bit field mask in I2C config register |
| * @i2c_mcode_mask: MCODE field mask for I2C config register |
| * |
| @@ -52,6 +53,7 @@ struct omap_vc_common { |
| u8 cmd_ret_shift; |
| u8 cmd_off_shift; |
| u8 i2c_cfg_reg; |
| + u8 i2c_cfg_clear_mask; |
| u8 i2c_cfg_hsen_mask; |
| u8 i2c_mcode_mask; |
| }; |
| --- a/arch/arm/mach-omap2/vc3xxx_data.c |
| +++ b/arch/arm/mach-omap2/vc3xxx_data.c |
| @@ -40,6 +40,7 @@ static struct omap_vc_common omap3_vc_co |
| .cmd_onlp_shift = OMAP3430_VC_CMD_ONLP_SHIFT, |
| .cmd_ret_shift = OMAP3430_VC_CMD_RET_SHIFT, |
| .cmd_off_shift = OMAP3430_VC_CMD_OFF_SHIFT, |
| + .i2c_cfg_clear_mask = OMAP3430_SREN_MASK | OMAP3430_HSEN_MASK, |
| .i2c_cfg_hsen_mask = OMAP3430_HSEN_MASK, |
| .i2c_cfg_reg = OMAP3_PRM_VC_I2C_CFG_OFFSET, |
| .i2c_mcode_mask = OMAP3430_MCODE_MASK, |
| --- a/arch/arm/mach-omap2/vc44xx_data.c |
| +++ b/arch/arm/mach-omap2/vc44xx_data.c |
| @@ -42,6 +42,7 @@ static const struct omap_vc_common omap4 |
| .cmd_ret_shift = OMAP4430_RET_SHIFT, |
| .cmd_off_shift = OMAP4430_OFF_SHIFT, |
| .i2c_cfg_reg = OMAP4_PRM_VC_CFG_I2C_MODE_OFFSET, |
| + .i2c_cfg_clear_mask = OMAP4430_SRMODEEN_MASK | OMAP4430_HSMODEEN_MASK, |
| .i2c_cfg_hsen_mask = OMAP4430_HSMODEEN_MASK, |
| .i2c_mcode_mask = OMAP4430_HSMCODE_MASK, |
| }; |