Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e23efa31 authored by Phil Reid's avatar Phil Reid Committed by Linus Walleij
Browse files

gpio: pca954x: Add vcc regulator and enable it



Some i2c gpio devices are connected to a switchable power supply
which needs to be enabled prior to probing the device. This patch
allows the drive to enable the devices vcc regulator prior to probing.

Signed-off-by: default avatarPhil Reid <preid@electromag.com.au>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent 65053e1a
Loading
Loading
Loading
Loading
+32 −9
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#include <asm/unaligned.h>
#include <linux/of_platform.h>
#include <linux/acpi.h>
#include <linux/regulator/consumer.h>

#define PCA953X_INPUT		0
#define PCA953X_OUTPUT		1
@@ -113,6 +114,7 @@ struct pca953x_chip {
	const char *const *names;
	int	chip_type;
	unsigned long driver_data;
	struct regulator *regulator;
};

static int pca953x_read_single(struct pca953x_chip *chip, int reg, u32 *val,
@@ -746,6 +748,7 @@ static int pca953x_probe(struct i2c_client *client,
	int irq_base = 0;
	int ret;
	u32 invert = 0;
	struct regulator *reg;

	chip = devm_kzalloc(&client->dev,
			sizeof(struct pca953x_chip), GFP_KERNEL);
@@ -765,6 +768,20 @@ static int pca953x_probe(struct i2c_client *client,

	chip->client = client;

	reg = devm_regulator_get(&client->dev, "vcc");
	if (IS_ERR(reg)) {
		ret = PTR_ERR(reg);
		if (ret != -EPROBE_DEFER)
			dev_err(&client->dev, "reg get err: %d\n", ret);
		return ret;
	}
	ret = regulator_enable(reg);
	if (ret) {
		dev_err(&client->dev, "reg en err: %d\n", ret);
		return ret;
	}
	chip->regulator = reg;

	if (id) {
		chip->driver_data = id->driver_data;
	} else {
@@ -776,8 +793,10 @@ static int pca953x_probe(struct i2c_client *client,
			chip->driver_data = (int)(uintptr_t)match->data;
		} else {
			id = acpi_match_device(pca953x_acpi_ids, &client->dev);
			if (!id)
				return -ENODEV;
			if (!id) {
				ret = -ENODEV;
				goto err_exit;
			}

			chip->driver_data = id->driver_data;
		}
@@ -797,15 +816,15 @@ static int pca953x_probe(struct i2c_client *client,
	else
		ret = device_pca957x_init(chip, invert);
	if (ret)
		return ret;
		goto err_exit;

	ret = devm_gpiochip_add_data(&client->dev, &chip->gpio_chip, chip);
	if (ret)
		return ret;
		goto err_exit;

	ret = pca953x_irq_setup(chip, irq_base);
	if (ret)
		return ret;
		goto err_exit;

	if (pdata && pdata->setup) {
		ret = pdata->setup(client, chip->gpio_chip.base,
@@ -816,6 +835,10 @@ static int pca953x_probe(struct i2c_client *client,

	i2c_set_clientdata(client, chip);
	return 0;

err_exit:
	regulator_disable(chip->regulator);
	return ret;
}

static int pca953x_remove(struct i2c_client *client)
@@ -827,14 +850,14 @@ static int pca953x_remove(struct i2c_client *client)
	if (pdata && pdata->teardown) {
		ret = pdata->teardown(client, chip->gpio_chip.base,
				chip->gpio_chip.ngpio, pdata->context);
		if (ret < 0) {
		if (ret < 0)
			dev_err(&client->dev, "%s failed, %d\n",
					"teardown", ret);
			return ret;
		}
	}

	return 0;
	regulator_disable(chip->regulator);

	return ret;
}

/* convenience to stop overlong match-table lines */