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 <asm/unaligned.h>
 | 
				
			||||||
#include <linux/of_platform.h>
 | 
					#include <linux/of_platform.h>
 | 
				
			||||||
#include <linux/acpi.h>
 | 
					#include <linux/acpi.h>
 | 
				
			||||||
 | 
					#include <linux/regulator/consumer.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define PCA953X_INPUT		0
 | 
					#define PCA953X_INPUT		0
 | 
				
			||||||
#define PCA953X_OUTPUT		1
 | 
					#define PCA953X_OUTPUT		1
 | 
				
			||||||
| 
						 | 
					@ -113,6 +114,7 @@ struct pca953x_chip {
 | 
				
			||||||
	const char *const *names;
 | 
						const char *const *names;
 | 
				
			||||||
	int	chip_type;
 | 
						int	chip_type;
 | 
				
			||||||
	unsigned long driver_data;
 | 
						unsigned long driver_data;
 | 
				
			||||||
 | 
						struct regulator *regulator;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int pca953x_read_single(struct pca953x_chip *chip, int reg, u32 *val,
 | 
					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 irq_base = 0;
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
	u32 invert = 0;
 | 
						u32 invert = 0;
 | 
				
			||||||
 | 
						struct regulator *reg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	chip = devm_kzalloc(&client->dev,
 | 
						chip = devm_kzalloc(&client->dev,
 | 
				
			||||||
			sizeof(struct pca953x_chip), GFP_KERNEL);
 | 
								sizeof(struct pca953x_chip), GFP_KERNEL);
 | 
				
			||||||
| 
						 | 
					@ -765,6 +768,20 @@ static int pca953x_probe(struct i2c_client *client,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	chip->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) {
 | 
						if (id) {
 | 
				
			||||||
		chip->driver_data = id->driver_data;
 | 
							chip->driver_data = id->driver_data;
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
| 
						 | 
					@ -776,8 +793,10 @@ static int pca953x_probe(struct i2c_client *client,
 | 
				
			||||||
			chip->driver_data = (int)(uintptr_t)match->data;
 | 
								chip->driver_data = (int)(uintptr_t)match->data;
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			id = acpi_match_device(pca953x_acpi_ids, &client->dev);
 | 
								id = acpi_match_device(pca953x_acpi_ids, &client->dev);
 | 
				
			||||||
			if (!id)
 | 
								if (!id) {
 | 
				
			||||||
				return -ENODEV;
 | 
									ret = -ENODEV;
 | 
				
			||||||
 | 
									goto err_exit;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			chip->driver_data = id->driver_data;
 | 
								chip->driver_data = id->driver_data;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -797,15 +816,15 @@ static int pca953x_probe(struct i2c_client *client,
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		ret = device_pca957x_init(chip, invert);
 | 
							ret = device_pca957x_init(chip, invert);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		return ret;
 | 
							goto err_exit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = devm_gpiochip_add_data(&client->dev, &chip->gpio_chip, chip);
 | 
						ret = devm_gpiochip_add_data(&client->dev, &chip->gpio_chip, chip);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		return ret;
 | 
							goto err_exit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = pca953x_irq_setup(chip, irq_base);
 | 
						ret = pca953x_irq_setup(chip, irq_base);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		return ret;
 | 
							goto err_exit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (pdata && pdata->setup) {
 | 
						if (pdata && pdata->setup) {
 | 
				
			||||||
		ret = pdata->setup(client, chip->gpio_chip.base,
 | 
							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);
 | 
						i2c_set_clientdata(client, chip);
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					err_exit:
 | 
				
			||||||
 | 
						regulator_disable(chip->regulator);
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int pca953x_remove(struct i2c_client *client)
 | 
					static int pca953x_remove(struct i2c_client *client)
 | 
				
			||||||
| 
						 | 
					@ -827,14 +850,14 @@ static int pca953x_remove(struct i2c_client *client)
 | 
				
			||||||
	if (pdata && pdata->teardown) {
 | 
						if (pdata && pdata->teardown) {
 | 
				
			||||||
		ret = pdata->teardown(client, chip->gpio_chip.base,
 | 
							ret = pdata->teardown(client, chip->gpio_chip.base,
 | 
				
			||||||
				chip->gpio_chip.ngpio, pdata->context);
 | 
									chip->gpio_chip.ngpio, pdata->context);
 | 
				
			||||||
		if (ret < 0) {
 | 
							if (ret < 0)
 | 
				
			||||||
			dev_err(&client->dev, "%s failed, %d\n",
 | 
								dev_err(&client->dev, "%s failed, %d\n",
 | 
				
			||||||
					"teardown", ret);
 | 
										"teardown", ret);
 | 
				
			||||||
			return ret;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						regulator_disable(chip->regulator);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* convenience to stop overlong match-table lines */
 | 
					/* convenience to stop overlong match-table lines */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue