On Sat, Apr 23, 2022 at 08:14:19PM +0200, Krzysztof Kozlowski wrote: > The driver duplicated regulator core feature of controlling > regulators with GPIOs (of_parse_cb + ena_gpiod) and created its own > enable-gpios property with multiple GPIOs. > > The core already does it. Keep old method for backwards compatibility. > > Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@xxxxxxxxxx> > --- > drivers/regulator/rt4801-regulator.c | 68 ++++++++++++++++++++++++---- > 1 file changed, 58 insertions(+), 10 deletions(-) > > diff --git a/drivers/regulator/rt4801-regulator.c b/drivers/regulator/rt4801-regulator.c > index 7a87788d3f09..22efe44cd3a0 100644 > --- a/drivers/regulator/rt4801-regulator.c > +++ b/drivers/regulator/rt4801-regulator.c > @@ -29,17 +29,71 @@ > > struct rt4801_priv { > struct device *dev; > + /* > + * Driver supports enable GPIOs in two ways: > + * 1. Legacy enable-gpios property with multiple entries and enable > + * control handled by the driver. > + * 2. Per-regulator enable-gpios property with enable control handled by > + * the regulator core. > + * > + * The enable_gpios and enable_flag properties are for the (1) case. > + */ > struct gpio_descs *enable_gpios; > unsigned int enable_flag; > unsigned int volt_sel[DSV_OUT_MAX]; > }; > > +static int rt4801_of_parse_cb(struct device_node *np, > + const struct regulator_desc *desc, > + struct regulator_config *config) > +{ > + struct rt4801_priv *priv = config->driver_data; > + > + if (priv->enable_gpios) { > + dev_warn(priv->dev, "duplicated enable-gpios property\n"); > + return 0; > + } > + config->ena_gpiod = fwnode_gpiod_get_index(of_fwnode_handle(np), > + "enable-gpios", 'enable' only, gpiod API will automatically concat it to 'enable-gpios'. > + 0, > + GPIOD_OUT_HIGH | > + GPIOD_FLAGS_BIT_NONEXCLUSIVE, > + "rt4801"); > + if (IS_ERR(config->ena_gpiod)) > + config->ena_gpiod = NULL; > + > + return 0; > +} > + > +/* > + * regulator_ops->is_enabled() implementation > + */ > +static int rt4801_is_enabled(struct regulator_dev *rdev) > +{ > + struct rt4801_priv *priv = rdev_get_drvdata(rdev); > + int id = rdev_get_id(rdev); > + > + return !!(priv->enable_flag & BIT(id)); > +} > + > +/* > + * Internally used only is_enabled() implementation using also ena_pin from > + * regulator core. > + */ > +static bool rt4801_is_enabled_ena_pin(struct regulator_dev *rdev) > +{ > + if (rdev->ena_pin) > + return rdev->ena_gpio_state; > + > + return rt4801_is_enabled(rdev); > +} > + > static int rt4801_set_voltage_sel(struct regulator_dev *rdev, unsigned int selector) > { > struct rt4801_priv *priv = rdev_get_drvdata(rdev); > int id = rdev_get_id(rdev), ret; > > - if (priv->enable_flag & BIT(id)) { > + if (rt4801_is_enabled_ena_pin(rdev)) { > ret = regulator_set_voltage_sel_regmap(rdev, selector); > if (ret) > return ret; > @@ -54,7 +108,7 @@ static int rt4801_get_voltage_sel(struct regulator_dev *rdev) > struct rt4801_priv *priv = rdev_get_drvdata(rdev); > int id = rdev_get_id(rdev); > > - if (priv->enable_flag & BIT(id)) > + if (rt4801_is_enabled_ena_pin(rdev)) > return regulator_get_voltage_sel_regmap(rdev); > > return priv->volt_sel[id]; > @@ -100,14 +154,6 @@ static int rt4801_disable(struct regulator_dev *rdev) > return 0; > } > > -static int rt4801_is_enabled(struct regulator_dev *rdev) > -{ > - struct rt4801_priv *priv = rdev_get_drvdata(rdev); > - int id = rdev_get_id(rdev); > - > - return !!(priv->enable_flag & BIT(id)); > -} > - > static const struct regulator_ops rt4801_regulator_ops = { > .list_voltage = regulator_list_voltage_linear, > .set_voltage_sel = rt4801_set_voltage_sel, > @@ -122,6 +168,7 @@ static const struct regulator_desc rt4801_regulator_descs[] = { > .name = "DSVP", > .ops = &rt4801_regulator_ops, > .of_match = of_match_ptr("DSVP"), > + .of_parse_cb = rt4801_of_parse_cb, > .type = REGULATOR_VOLTAGE, > .id = DSV_OUT_POS, > .min_uV = MIN_UV, > @@ -135,6 +182,7 @@ static const struct regulator_desc rt4801_regulator_descs[] = { > .name = "DSVN", > .ops = &rt4801_regulator_ops, > .of_match = of_match_ptr("DSVN"), > + .of_parse_cb = rt4801_of_parse_cb, > .type = REGULATOR_VOLTAGE, > .id = DSV_OUT_NEG, > .min_uV = MIN_UV, There's one problem. If 'ena_gpiod' is specified, it cannot be conexisted with ops 'enable/disable/is_enabled' by regulator framework. It will cause no one to recover the voltage back. You can check the original 'enable' ops. How about to only parse gpio in 'of_parse_cb' and put it all into the driver data, not to use regulator framework 'ena_gpiod'? Best regards, ChiYuan Huang. > -- > 2.32.0 >