diff options
Diffstat (limited to 'drivers/gpio/gpio-palmas.c')
| -rw-r--r-- | drivers/gpio/gpio-palmas.c | 110 | 
1 files changed, 71 insertions, 39 deletions
diff --git a/drivers/gpio/gpio-palmas.c b/drivers/gpio/gpio-palmas.c index 8588af0f766..86bdbe36206 100644 --- a/drivers/gpio/gpio-palmas.c +++ b/drivers/gpio/gpio-palmas.c @@ -31,6 +31,10 @@ struct palmas_gpio {  	struct palmas *palmas;  }; +struct palmas_device_data { +	int ngpio; +}; +  static inline struct palmas_gpio *to_palmas_gpio(struct gpio_chip *chip)  {  	return container_of(chip, struct palmas_gpio, gpio_chip); @@ -42,23 +46,26 @@ static int palmas_gpio_get(struct gpio_chip *gc, unsigned offset)  	struct palmas *palmas = pg->palmas;  	unsigned int val;  	int ret; +	unsigned int reg; +	int gpio16 = (offset/8); + +	offset %= 8; +	reg = (gpio16) ? PALMAS_GPIO_DATA_DIR2 : PALMAS_GPIO_DATA_DIR; -	ret = palmas_read(palmas, PALMAS_GPIO_BASE, PALMAS_GPIO_DATA_DIR, &val); +	ret = palmas_read(palmas, PALMAS_GPIO_BASE, reg, &val);  	if (ret < 0) { -		dev_err(gc->dev, "GPIO_DATA_DIR read failed, err = %d\n", ret); +		dev_err(gc->dev, "Reg 0x%02x read failed, %d\n", reg, ret);  		return ret;  	} -	if (val & (1 << offset)) { -		ret = palmas_read(palmas, PALMAS_GPIO_BASE, -				  PALMAS_GPIO_DATA_OUT, &val); -	} else { -		ret = palmas_read(palmas, PALMAS_GPIO_BASE, -				  PALMAS_GPIO_DATA_IN, &val); -	} +	if (val & BIT(offset)) +		reg = (gpio16) ? PALMAS_GPIO_DATA_OUT2 : PALMAS_GPIO_DATA_OUT; +	else +		reg = (gpio16) ? PALMAS_GPIO_DATA_IN2 : PALMAS_GPIO_DATA_IN; + +	ret = palmas_read(palmas, PALMAS_GPIO_BASE, reg, &val);  	if (ret < 0) { -		dev_err(gc->dev, "GPIO_DATA_IN/OUT read failed, err = %d\n", -			ret); +		dev_err(gc->dev, "Reg 0x%02x read failed, %d\n", reg, ret);  		return ret;  	}  	return !!(val & BIT(offset)); @@ -70,17 +77,20 @@ static void palmas_gpio_set(struct gpio_chip *gc, unsigned offset,  	struct palmas_gpio *pg = to_palmas_gpio(gc);  	struct palmas *palmas = pg->palmas;  	int ret; +	unsigned int reg; +	int gpio16 = (offset/8); -	if (value) -		ret = palmas_write(palmas, PALMAS_GPIO_BASE, -				PALMAS_GPIO_SET_DATA_OUT, BIT(offset)); +	offset %= 8; +	if (gpio16) +		reg = (value) ? +			PALMAS_GPIO_SET_DATA_OUT2 : PALMAS_GPIO_CLEAR_DATA_OUT2;  	else -		ret = palmas_write(palmas, PALMAS_GPIO_BASE, -				PALMAS_GPIO_CLEAR_DATA_OUT, BIT(offset)); +		reg = (value) ? +			PALMAS_GPIO_SET_DATA_OUT : PALMAS_GPIO_CLEAR_DATA_OUT; + +	ret = palmas_write(palmas, PALMAS_GPIO_BASE, reg, BIT(offset));  	if (ret < 0) -		dev_err(gc->dev, "%s write failed, err = %d\n", -			(value) ? "GPIO_SET_DATA_OUT" : "GPIO_CLEAR_DATA_OUT", -			ret); +		dev_err(gc->dev, "Reg 0x%02x write failed, %d\n", reg, ret);  }  static int palmas_gpio_output(struct gpio_chip *gc, unsigned offset, @@ -89,14 +99,19 @@ static int palmas_gpio_output(struct gpio_chip *gc, unsigned offset,  	struct palmas_gpio *pg = to_palmas_gpio(gc);  	struct palmas *palmas = pg->palmas;  	int ret; +	unsigned int reg; +	int gpio16 = (offset/8); + +	offset %= 8; +	reg = (gpio16) ? PALMAS_GPIO_DATA_DIR2 : PALMAS_GPIO_DATA_DIR;  	/* Set the initial value */  	palmas_gpio_set(gc, offset, value); -	ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE, -		PALMAS_GPIO_DATA_DIR, BIT(offset), BIT(offset)); +	ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE, reg, +				BIT(offset), BIT(offset));  	if (ret < 0) -		dev_err(gc->dev, "GPIO_DATA_DIR write failed, err = %d\n", ret); +		dev_err(gc->dev, "Reg 0x%02x update failed, %d\n", reg, ret);  	return ret;  } @@ -105,11 +120,15 @@ static int palmas_gpio_input(struct gpio_chip *gc, unsigned offset)  	struct palmas_gpio *pg = to_palmas_gpio(gc);  	struct palmas *palmas = pg->palmas;  	int ret; +	unsigned int reg; +	int gpio16 = (offset/8); + +	offset %= 8; +	reg = (gpio16) ? PALMAS_GPIO_DATA_DIR2 : PALMAS_GPIO_DATA_DIR; -	ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE, -		PALMAS_GPIO_DATA_DIR, BIT(offset), 0); +	ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE, reg, BIT(offset), 0);  	if (ret < 0) -		dev_err(gc->dev, "GPIO_DATA_DIR write failed, err = %d\n", ret); +		dev_err(gc->dev, "Reg 0x%02x update failed, %d\n", reg, ret);  	return ret;  } @@ -121,25 +140,47 @@ static int palmas_gpio_to_irq(struct gpio_chip *gc, unsigned offset)  	return palmas_irq_get_virq(palmas, PALMAS_GPIO_0_IRQ + offset);  } +static const struct palmas_device_data palmas_dev_data = { +	.ngpio = 8, +}; + +static const struct palmas_device_data tps80036_dev_data = { +	.ngpio = 16, +}; + +static const struct of_device_id of_palmas_gpio_match[] = { +	{ .compatible = "ti,palmas-gpio", .data = &palmas_dev_data,}, +	{ .compatible = "ti,tps65913-gpio", .data = &palmas_dev_data,}, +	{ .compatible = "ti,tps65914-gpio", .data = &palmas_dev_data,}, +	{ .compatible = "ti,tps80036-gpio", .data = &tps80036_dev_data,}, +	{ }, +}; +MODULE_DEVICE_TABLE(of, of_palmas_gpio_match); +  static int palmas_gpio_probe(struct platform_device *pdev)  {  	struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);  	struct palmas_platform_data *palmas_pdata;  	struct palmas_gpio *palmas_gpio;  	int ret; +	const struct of_device_id *match; +	const struct palmas_device_data *dev_data; + +	match = of_match_device(of_palmas_gpio_match, &pdev->dev); +	dev_data = match->data; +	if (!dev_data) +		dev_data = &palmas_dev_data;  	palmas_gpio = devm_kzalloc(&pdev->dev,  				sizeof(*palmas_gpio), GFP_KERNEL); -	if (!palmas_gpio) { -		dev_err(&pdev->dev, "Could not allocate palmas_gpio\n"); +	if (!palmas_gpio)  		return -ENOMEM; -	}  	palmas_gpio->palmas = palmas;  	palmas_gpio->gpio_chip.owner = THIS_MODULE;  	palmas_gpio->gpio_chip.label = dev_name(&pdev->dev); -	palmas_gpio->gpio_chip.ngpio = 8; -	palmas_gpio->gpio_chip.can_sleep = 1; +	palmas_gpio->gpio_chip.ngpio = dev_data->ngpio; +	palmas_gpio->gpio_chip.can_sleep = true;  	palmas_gpio->gpio_chip.direction_input = palmas_gpio_input;  	palmas_gpio->gpio_chip.direction_output = palmas_gpio_output;  	palmas_gpio->gpio_chip.to_irq = palmas_gpio_to_irq; @@ -172,15 +213,6 @@ static int palmas_gpio_remove(struct platform_device *pdev)  	return gpiochip_remove(&palmas_gpio->gpio_chip);  } -static struct of_device_id of_palmas_gpio_match[] = { -	{ .compatible = "ti,palmas-gpio"}, -	{ .compatible = "ti,tps65913-gpio"}, -	{ .compatible = "ti,tps65914-gpio"}, -	{ .compatible = "ti,tps80036-gpio"}, -	{ }, -}; -MODULE_DEVICE_TABLE(of, of_palmas_gpio_match); -  static struct platform_driver palmas_gpio_driver = {  	.driver.name	= "palmas-gpio",  	.driver.owner	= THIS_MODULE,  | 
