diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c index dff120a38e40..38e8122c4b09 100644 --- a/drivers/regulator/anatop-regulator.c +++ b/drivers/regulator/anatop-regulator.c @@ -35,6 +35,7 @@ #define LDO_RAMP_UP_FREQ_IN_MHZ 24 /* cycle based on 24M OSC */ #define LDO_POWER_GATE 0x00 +#define LDO_FET_FULL_ON 0x1f struct anatop_regulator { const char *name; @@ -50,6 +51,7 @@ struct anatop_regulator { int max_voltage; struct regulator_desc rdesc; struct regulator_init_data *initdata; + bool bypass; int sel; }; @@ -103,8 +105,10 @@ static int anatop_regmap_get_voltage_sel(struct regulator_dev *reg) static int anatop_regmap_enable(struct regulator_dev *reg) { struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg); + int sel; - return regulator_set_voltage_sel_regmap(reg, anatop_reg->sel); + sel = anatop_reg->bypass ? LDO_FET_FULL_ON : anatop_reg->sel; + return regulator_set_voltage_sel_regmap(reg, sel); } static int anatop_regmap_disable(struct regulator_dev *reg) @@ -123,7 +127,7 @@ static int anatop_regmap_core_set_voltage_sel(struct regulator_dev *reg, struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg); int ret; - if (!anatop_regmap_is_enabled(reg)) { + if (anatop_reg->bypass || !anatop_regmap_is_enabled(reg)) { anatop_reg->sel = selector; return 0; } @@ -138,12 +142,41 @@ static int anatop_regmap_core_get_voltage_sel(struct regulator_dev *reg) { struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg); - if (!anatop_regmap_is_enabled(reg)) + if (anatop_reg->bypass || !anatop_regmap_is_enabled(reg)) return anatop_reg->sel; return regulator_get_voltage_sel_regmap(reg); } +static int anatop_regmap_get_bypass(struct regulator_dev *reg, bool *enable) +{ + struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg); + int sel; + + sel = regulator_get_voltage_sel_regmap(reg); + if (sel == LDO_FET_FULL_ON) + WARN_ON(!anatop_reg->bypass); + else if (sel != LDO_POWER_GATE) + WARN_ON(anatop_reg->bypass); + + *enable = anatop_reg->bypass; + return 0; +} + +static int anatop_regmap_set_bypass(struct regulator_dev *reg, bool enable) +{ + struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg); + int sel; + + if (enable == anatop_reg->bypass) + return 0; + + sel = enable ? LDO_FET_FULL_ON : anatop_reg->sel; + anatop_reg->bypass = enable; + + return regulator_set_voltage_sel_regmap(reg, sel); +} + static struct regulator_ops anatop_rops = { .set_voltage_sel = anatop_regmap_set_voltage_sel, .get_voltage_sel = anatop_regmap_get_voltage_sel, @@ -160,6 +193,8 @@ static struct regulator_ops anatop_core_rops = { .get_voltage_sel = anatop_regmap_core_get_voltage_sel, .list_voltage = regulator_list_voltage_linear, .map_voltage = regulator_map_voltage_linear, + .get_bypass = anatop_regmap_get_bypass, + .set_bypass = anatop_regmap_set_bypass, }; static int anatop_regulator_probe(struct platform_device *pdev) @@ -265,6 +300,10 @@ static int anatop_regulator_probe(struct platform_device *pdev) } sreg->sel = (val & rdesc->vsel_mask) >> sreg->vol_bit_shift; + if (sreg->sel == LDO_FET_FULL_ON) { + sreg->sel = 0; + sreg->bypass = true; + } } else { rdesc->ops = &anatop_rops; }