aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarek Vasut <marex@denx.de>2018-04-30 21:50:45 -0400
committerMark Brown <broonie@kernel.org>2018-05-01 17:00:20 -0400
commitd2a66ddfe8acd91aca81af2ef39abd5813d5dc65 (patch)
tree1a275d92fb523f3b0b0ac5cf541385da0df5605b
parente241e3f2bf975788a1b70dff2eb5180ca395b28e (diff)
regulator: ltc3676: Assure PGOOD mask is set before changing voltage
Make sure the DVBxB bit 5, PGOOD mask, is set before changing voltage on the buck converters. If the PGOOD mask bit is not set, the PMIC may deassert the PGOOD signal during the voltage transition. On systems that use the PGOOD signal as a power OK indication for the board or SoC, which should be the case on correct designs, deasserting the PGOOD signal will lead to system reset or shutdown, which is not the expected behavior when changing PMIC buck converter voltage. Signed-off-by: Marek Vasut <marex@denx.de> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--drivers/regulator/ltc3676.c20
1 files changed, 19 insertions, 1 deletions
diff --git a/drivers/regulator/ltc3676.c b/drivers/regulator/ltc3676.c
index 662ee05ea44d..9dec1609ff66 100644
--- a/drivers/regulator/ltc3676.c
+++ b/drivers/regulator/ltc3676.c
@@ -52,6 +52,7 @@
52#define LTC3676_CLIRQ 0x1F 52#define LTC3676_CLIRQ 0x1F
53 53
54#define LTC3676_DVBxA_REF_SELECT BIT(5) 54#define LTC3676_DVBxA_REF_SELECT BIT(5)
55#define LTC3676_DVBxB_PGOOD_MASK BIT(5)
55 56
56#define LTC3676_IRQSTAT_PGOOD_TIMEOUT BIT(3) 57#define LTC3676_IRQSTAT_PGOOD_TIMEOUT BIT(3)
57#define LTC3676_IRQSTAT_UNDERVOLT_WARN BIT(4) 58#define LTC3676_IRQSTAT_UNDERVOLT_WARN BIT(4)
@@ -123,6 +124,23 @@ static int ltc3676_set_suspend_mode(struct regulator_dev *rdev,
123 mask, val); 124 mask, val);
124} 125}
125 126
127static int ltc3676_set_voltage_sel(struct regulator_dev *rdev, unsigned selector)
128{
129 struct ltc3676 *ltc3676 = rdev_get_drvdata(rdev);
130 struct device *dev = ltc3676->dev;
131 int ret, dcdc = rdev_get_id(rdev);
132
133 dev_dbg(dev, "%s id=%d selector=%d\n", __func__, dcdc, selector);
134
135 ret = regmap_update_bits(ltc3676->regmap, rdev->desc->vsel_reg + 1,
136 LTC3676_DVBxB_PGOOD_MASK,
137 LTC3676_DVBxB_PGOOD_MASK);
138 if (ret)
139 return ret;
140
141 return regulator_set_voltage_sel_regmap(rdev, selector);
142}
143
126static inline unsigned int ltc3676_scale(unsigned int uV, u32 r1, u32 r2) 144static inline unsigned int ltc3676_scale(unsigned int uV, u32 r1, u32 r2)
127{ 145{
128 uint64_t tmp; 146 uint64_t tmp;
@@ -166,7 +184,7 @@ static const struct regulator_ops ltc3676_linear_regulator_ops = {
166 .disable = regulator_disable_regmap, 184 .disable = regulator_disable_regmap,
167 .is_enabled = regulator_is_enabled_regmap, 185 .is_enabled = regulator_is_enabled_regmap,
168 .list_voltage = regulator_list_voltage_linear, 186 .list_voltage = regulator_list_voltage_linear,
169 .set_voltage_sel = regulator_set_voltage_sel_regmap, 187 .set_voltage_sel = ltc3676_set_voltage_sel,
170 .get_voltage_sel = regulator_get_voltage_sel_regmap, 188 .get_voltage_sel = regulator_get_voltage_sel_regmap,
171 .set_suspend_voltage = ltc3676_set_suspend_voltage, 189 .set_suspend_voltage = ltc3676_set_suspend_voltage,
172 .set_suspend_mode = ltc3676_set_suspend_mode, 190 .set_suspend_mode = ltc3676_set_suspend_mode,