Re: [v6 3/3] i2c: muxes: pca954x: Add regulator support

From: Peter Rosin
Date: Sat Mar 19 2022 - 12:11:52 EST


On 2022-03-19 15:41, Peter Rosin wrote:
> On 2022-02-16 08:46, Patrick Rudolph wrote:
>> Add a vdd regulator and enable it for boards that have the
>> mux powered off by default.
>>
>> Signed-off-by: Patrick Rudolph <patrick.rudolph@xxxxxxxxxxxxx>
>> ---
>> drivers/i2c/muxes/i2c-mux-pca954x.c | 34 ++++++++++++++++++++++++-----
>> 1 file changed, 29 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c
>> index 33b9a6a1fffa..e25383752616 100644
>> --- a/drivers/i2c/muxes/i2c-mux-pca954x.c
>> +++ b/drivers/i2c/muxes/i2c-mux-pca954x.c
>> @@ -49,6 +49,7 @@
>> #include <linux/module.h>
>> #include <linux/pm.h>
>> #include <linux/property.h>
>> +#include <linux/regulator/consumer.h>
>> #include <linux/slab.h>
>> #include <linux/spinlock.h>
>> #include <dt-bindings/mux/mux.h>
>> @@ -119,6 +120,7 @@ struct pca954x {
>> struct irq_domain *irq;
>> unsigned int irq_mask;
>> raw_spinlock_t lock;
>> + struct regulator *supply;
>> };
>>
>> /* Provide specs for the PCA954x and MAX735x types we know about */
>> @@ -459,6 +461,9 @@ static void pca954x_cleanup(struct i2c_mux_core *muxc)
>> struct pca954x *data = i2c_mux_priv(muxc);
>> int c, irq;
>>
>> + if (!IS_ERR_OR_NULL(data->supply))

Hmm, this is a bit confusing, but I guess it's fine since the
cleanup function is then ok even if it at some point in the future
is called before data->supply has been filled in. But this is
what confused me into the below comment...

>> + regulator_disable(data->supply);
>> +
>> if (data->irq) {
>> for (c = 0; c < data->chip->nchans; c++) {
>> irq = irq_find_mapping(data->irq, c);
>> @@ -513,15 +518,32 @@ static int pca954x_probe(struct i2c_client *client,
>> pca954x_select_chan, pca954x_deselect_mux);
>> if (!muxc)
>> return -ENOMEM;
>> +
>> data = i2c_mux_priv(muxc);
>>
>> i2c_set_clientdata(client, muxc);
>> data->client = client;
>>
>> + data->supply = devm_regulator_get(dev, "vdd");
>> + if (IS_ERR(data->supply)) {
>> + ret = PTR_ERR(data->supply);
>> + if (ret != -EPROBE_DEFER)
>> + dev_err(dev, "Failed to request regulator: %d\n", ret);
>> + return ret;
>> + }
>> +
>
> I think you need enclose the below in "if (data->supply)"

I just realized that no, you don't, because it falls back to the
dummy regulator. But then, data->supply cannot be NULL, but see
above for why it's a good thing to check for it either way when
cleaning up.

All is fine as-is.

Reviewed-by: Peter Rosin <peda@xxxxxxxxxx>

Cheers,
Peter

>> + ret = regulator_enable(data->supply);
>> + if (ret) {
>> + dev_err(dev, "Failed to enable regulator: %d\n", ret);
>> + return ret;
>> + }
>> +
>> /* Reset the mux if a reset GPIO is specified. */
>> gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
>> - if (IS_ERR(gpio))
>> - return PTR_ERR(gpio);
>> + if (IS_ERR(gpio)) {
>> + ret = PTR_ERR(gpio);
>> + goto fail_cleanup;
>> + }
>> if (gpio) {
>> udelay(1);
>> gpiod_set_value_cansleep(gpio, 0);
>> @@ -538,7 +560,7 @@ static int pca954x_probe(struct i2c_client *client,
>>
>> ret = i2c_get_device_id(client, &id);
>> if (ret && ret != -EOPNOTSUPP)
>> - return ret;
>> + goto fail_cleanup;
>>
>> if (!ret &&
>> (id.manufacturer_id != data->chip->id.manufacturer_id ||
>> @@ -546,7 +568,8 @@ static int pca954x_probe(struct i2c_client *client,
>> dev_warn(dev, "unexpected device id %03x-%03x-%x\n",
>> id.manufacturer_id, id.part_id,
>> id.die_revision);
>> - return -ENODEV;
>> + ret = -ENODEV;
>> + goto fail_cleanup;
>> }
>> }
>>
>> @@ -565,7 +588,8 @@ static int pca954x_probe(struct i2c_client *client,
>> ret = pca954x_init(client, data);
>> if (ret < 0) {
>> dev_warn(dev, "probe failed\n");
>> - return -ENODEV;
>> + ret = -ENODEV;
>> + goto fail_cleanup;
>> }
>>
>> ret = pca954x_irq_setup(muxc);