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>
---
drivers/i2c/muxes/i2c-mux-pca954x.c | 35 ++++++++++++++++++++++++-----
1 file changed, 30 insertions(+), 5 deletions(-)
diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c
index 39f313658b18..0d966a55b727 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>
@@ -101,6 +102,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 */
@@ -440,6 +442,9 @@ static void pca954x_cleanup(struct i2c_mux_core *muxc)
struct pca954x *data = i2c_mux_priv(muxc);
int c, irq;
+ if (data->supply)
+ regulator_disable(data->supply);
+
if (data->irq) {
for (c = 0; c < data->chip->nchans; c++) {
irq = irq_find_mapping(data->irq, c);
@@ -492,10 +497,28 @@ static int pca954x_probe(struct i2c_client *client)
i2c_set_clientdata(client, muxc);
data->client = client;
+ data->supply = devm_regulator_get_optional(dev, "vdd");
+ if (IS_ERR(data->supply)) {
+ ret = PTR_ERR(data->supply);
+ if (ret != -ENODEV)
+ return dev_err_probe(dev, ret,
+ "Failed to request regulator\n");
+ else
+ data->supply = NULL;
+ } else {
+ 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);
@@ -512,7 +535,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 ||
@@ -520,7 +543,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;
}
}
@@ -539,7 +563,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.39.2
On Fri, Apr 14, 2023 at 01:01:36PM +0200, Patrick Rudolph wrote:
> + data->supply = devm_regulator_get_optional(dev, "vdd");
> + if (IS_ERR(data->supply)) {
> + ret = PTR_ERR(data->supply);
Unless the device can work without power it should be using a normal
regulator_get().
Hi Mark,
It was using the normal regulator_get() in the last revision, but
Sergey requested to make it optional.
Please advise me what to do here? Who is right?
Regards,
Patrick
On Fri, Apr 14, 2023 at 1:47 PM Mark Brown <broonie@kernel.org> wrote:
>
> On Fri, Apr 14, 2023 at 01:01:36PM +0200, Patrick Rudolph wrote:
>
> > + data->supply = devm_regulator_get_optional(dev, "vdd");
> > + if (IS_ERR(data->supply)) {
> > + ret = PTR_ERR(data->supply);
>
> Unless the device can work without power it should be using a normal
> regulator_get().
On Fri, Apr 14, 2023 at 02:01:09PM +0200, Patrick Rudolph wrote: > It was using the normal regulator_get() in the last revision, but > Sergey requested to make it optional. > Please advise me what to do here? Who is right? As I said regulator_get_optional() is strictly for the case where the supply may be physically absent and shouldn not be used in any other situation. Using the wrong variant will break error handling. > > Regards, > Patrick > > On Fri, Apr 14, 2023 at 1:47 PM Mark Brown <broonie@kernel.org> wrote: Please don't top post, reply in line with needed context. This allows readers to readily follow the flow of conversation and understand what you are talking about and also helps ensure that everything in the discussion is being addressed.
© 2016 - 2025 Red Hat, Inc.