Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

regulator: twl6030: workaround the VMMC reset behavior

During reset the VMMC regulator doesn't reach 0V and only drops to
1.8V, furthermore the pulse width is under 200us whereas the SD
specification expect 1ms.

The WR_S bit allows the TWL6030 to no reset at all the VMMC during warm
reset and keep the current voltage. Thanks to this workaround the SD
card doesn't reach a undefined reset stage.

Actually this behavior is available for all the LDO regulator, so the
driver will also allow to use it with any of these regulator.

Signed-off-by: Gregory CLEMENT <gregory.clement@bootlin.com>
Link: https://lore.kernel.org/r/20190725094542.16547-4-gregory.clement@bootlin.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Gregory CLEMENT and committed by
Mark Brown
d9df0187 621d3ce8

+14 -1
+14 -1
drivers/regulator/twl6030-regulator.c
··· 57 57 #define VREG_BC_PROC 3 58 58 #define VREG_BC_CLK_RST 4 59 59 60 + /* TWL6030 LDO register values for VREG_VOLTAGE */ 61 + #define TWL6030_VREG_VOLTAGE_WR_S BIT(7) 62 + 60 63 /* TWL6030 LDO register values for CFG_STATE */ 61 64 #define TWL6030_CFG_STATE_OFF 0x00 62 65 #define TWL6030_CFG_STATE_ON 0x01 ··· 71 68 #define TWL6030_CFG_STATE_APP(v) (((v) & TWL6030_CFG_STATE_APP_MASK) >>\ 72 69 TWL6030_CFG_STATE_APP_SHIFT) 73 70 74 - /* Flags for SMPS Voltage reading */ 71 + /* Flags for SMPS Voltage reading and LDO reading*/ 75 72 #define SMPS_OFFSET_EN BIT(0) 76 73 #define SMPS_EXTENDED_EN BIT(1) 74 + #define TWL_6030_WARM_RESET BIT(3) 77 75 78 76 /* twl6032 SMPS EPROM values */ 79 77 #define TWL6030_SMPS_OFFSET 0xB0 ··· 254 250 { 255 251 struct twlreg_info *info = rdev_get_drvdata(rdev); 256 252 253 + if (info->flags & TWL_6030_WARM_RESET) 254 + selector |= TWL6030_VREG_VOLTAGE_WR_S; 255 + 257 256 return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE, 258 257 selector); 259 258 } ··· 265 258 { 266 259 struct twlreg_info *info = rdev_get_drvdata(rdev); 267 260 int vsel = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE); 261 + 262 + if (info->flags & TWL_6030_WARM_RESET) 263 + vsel &= ~TWL6030_VREG_VOLTAGE_WR_S; 268 264 269 265 return vsel; 270 266 } ··· 719 709 info->flags |= SMPS_OFFSET_EN; 720 710 break; 721 711 } 712 + 713 + if (of_get_property(np, "ti,retain-on-reset", NULL)) 714 + info->flags |= TWL_6030_WARM_RESET; 722 715 723 716 config.dev = &pdev->dev; 724 717 config.init_data = initdata;