Re: [PATCH v2 2/2] regulator: richtek,rt4801: use existing ena_gpiod feature

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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
> 



[Index of Archives]     [Device Tree Compilter]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux PCI Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Yosemite Backpacking]


  Powered by Linux