forked from mirrors/linux
		
	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: Phil Reid <preid@electromag.com.au> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
		
							parent
							
								
									65053e1a77
								
							
						
					
					
						commit
						e23efa3111
					
				
					 1 changed files with 32 additions and 9 deletions
				
			
		| 
						 | 
				
			
			@ -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 */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue