Message ID | 20221007075354.568752-5-patrick.rudolph@9elements.com |
---|---|
State | New |
Headers | show |
Series | Add support for Maxim MAX735x/MAX736x variants | expand |
On Fri, Oct 07, 2022 at 09:53:53AM +0200, 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@9elements.com> > Reviewed-by: Peter Rosin <peda@axentia.se> > --- > 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 992976fa6798..857a4ec387be 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> > @@ -133,6 +134,7 @@ struct pca954x { > struct irq_domain *irq; > unsigned int irq_mask; > raw_spinlock_t lock; > + struct regulator *supply; > }; > > /* Provide specs for the MAX735x, PCA954x and PCA984x types we know about */ > @@ -473,6 +475,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)) First of all AFAICS the data->supply pointer will never be null on the pca954x_cleanup() invocations in your current implementation. So IS_ERR() would be enough here. Second in the next comment I'll suggest to you to implement the optional regulator semantic, which implies initializing the data->supply pointer with NULL if the get-regulator function returns -ENODEV. That shall look easier than the IS_ERR() macro. So checking the data->supply pointer for being not-null would be enough here. > + regulator_disable(data->supply); > + > if (data->irq) { > for (c = 0; c < data->chip->nchans; c++) { > irq = irq_find_mapping(data->irq, c); > @@ -531,15 +536,32 @@ static int pca954x_probe(struct i2c_client *client, > pca954x_select_chan, pca954x_deselect_mux); > if (!muxc) > return -ENOMEM; > + unrelated change... > 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)) { Judging by the DT-bindings the power-supply is supposed to be optional. Isn't it? AFAICS from the _regulator_get() semantic if no vdd-supply is specified and a regulator request method with the non-optional semantic is called an ugly warning will be printed to the system log. Most of the users of the driver don't have the power-supply specified for the device. You don't want to have their logs polluted with the false warning, do you? If so you should use the devm_regulator_get_optional() method here. If it returns the -ENODEV error just overwrite the data->supply with NULL. In case of any other error halt the device probe procedure. > + ret = PTR_ERR(data->supply); > + if (ret != -EPROBE_DEFER) > + dev_err(dev, "Failed to request regulator: %d\n", ret); > + return ret; dev_err_probe() ? -Sergey > + } > + > + 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); > @@ -556,7 +578,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 || > @@ -564,7 +586,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; > } > } > > @@ -583,7 +606,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); > -- > 2.37.3 >
diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c index 992976fa6798..857a4ec387be 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> @@ -133,6 +134,7 @@ struct pca954x { struct irq_domain *irq; unsigned int irq_mask; raw_spinlock_t lock; + struct regulator *supply; }; /* Provide specs for the MAX735x, PCA954x and PCA984x types we know about */ @@ -473,6 +475,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)) + regulator_disable(data->supply); + if (data->irq) { for (c = 0; c < data->chip->nchans; c++) { irq = irq_find_mapping(data->irq, c); @@ -531,15 +536,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; + } + + 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); @@ -556,7 +578,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 || @@ -564,7 +586,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; } } @@ -583,7 +606,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);