* [PATCH 1/3] Prepare to extend pca9539 to support more chips - rename files
@ 2008-01-31 14:04 Guennadi Liakhovetski
2008-01-31 14:04 ` [PATCH 3/3] Add support for PCA953[4-8] I2C GPIO extenders to the pca953x driver Guennadi Liakhovetski
[not found] ` <Pine.LNX.4.64.0801311453470.8478-0199iw4Nj15frtckUFj5Ag@public.gmane.org>
0 siblings, 2 replies; 11+ messages in thread
From: Guennadi Liakhovetski @ 2008-01-31 14:04 UTC (permalink / raw)
To: video4linux-list, i2c; +Cc: David Brownell, Jean Delvare
First stage of the extension, letting pca9539 also support
pca9536, pca9537, and pca9538. Split to make review easier.
Here only rename the files and modify the Makefile.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@pengutronix.de>
---
This is a git-style rename patch. If desired, I can produce a complete GNU
patch instead.
drivers/gpio/Makefile | 2 +-
drivers/gpio/{pca9539.c => pca953x.c} | 2 +-
include/linux/i2c/{pca9539.h => pca953x.h} | 0
3 files changed, 2 insertions(+), 2 deletions(-)
rename drivers/gpio/{pca9539.c => pca953x.c} (99%)
rename include/linux/i2c/{pca9539.h => pca953x.h} (100%)
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 470ecd6..16dda77 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -5,5 +5,5 @@ ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG
obj-$(CONFIG_HAVE_GPIO_LIB) += gpiolib.o
obj-$(CONFIG_GPIO_MCP23S08) += mcp23s08.o
-obj-$(CONFIG_GPIO_PCA9539) += pca9539.o
+obj-$(CONFIG_GPIO_PCA9539) += pca953x.o
obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o
diff --git a/drivers/gpio/pca9539.c b/drivers/gpio/pca953x.c
similarity index 99%
rename from drivers/gpio/pca9539.c
rename to drivers/gpio/pca953x.c
index 3e85c92..7fae4e5 100644
--- a/drivers/gpio/pca9539.c
+++ b/drivers/gpio/pca953x.c
@@ -14,7 +14,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/i2c.h>
-#include <linux/i2c/pca9539.h>
+#include <linux/i2c/pca953x.h>
#include <asm/gpio.h>
diff --git a/include/linux/i2c/pca9539.h b/include/linux/i2c/pca953x.h
similarity index 100%
rename from include/linux/i2c/pca9539.h
rename to include/linux/i2c/pca953x.h
--
1.5.3.4
--
video4linux-list mailing list
Unsubscribe mailto:video4linux-list-request@redhat.com?subject=unsubscribe
https://www.redhat.com/mailman/listinfo/video4linux-list
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 3/3] Add support for PCA953[4-8] I2C GPIO extenders to the pca953x driver 2008-01-31 14:04 [PATCH 1/3] Prepare to extend pca9539 to support more chips - rename files Guennadi Liakhovetski @ 2008-01-31 14:04 ` Guennadi Liakhovetski [not found] ` <Pine.LNX.4.64.0801311500240.8478-0199iw4Nj15frtckUFj5Ag@public.gmane.org> [not found] ` <Pine.LNX.4.64.0801311453470.8478-0199iw4Nj15frtckUFj5Ag@public.gmane.org> 1 sibling, 1 reply; 11+ messages in thread From: Guennadi Liakhovetski @ 2008-01-31 14:04 UTC (permalink / raw) To: video4linux-list, i2c; +Cc: David Brownell, Jean Delvare Last stage in adding more chips to the pca953x gpio driver. As long as we don't implement their interrupt and reset functionality, they are identical except for the numbers of GPIOs and register size. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@pengutronix.de> --- drivers/gpio/pca953x.c | 114 +++++++++++++++++++++++++++++++++++------------- 1 files changed, 84 insertions(+), 30 deletions(-) diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c index 51adbaa..a7d3ae2 100644 --- a/drivers/gpio/pca953x.c +++ b/drivers/gpio/pca953x.c @@ -1,5 +1,5 @@ /* - * pca953x.c - 16-bit I/O port with interrupt and reset + * pca953x.c - I/O ports with interrupt and reset * * Copyright (C) 2005 Ben Gardner <bgardner@wabtec.com> * Copyright (C) 2007 Marvell International Ltd. @@ -18,16 +18,43 @@ #include <asm/gpio.h> +#define PCA953X_INPUT 0 +#define PCA953X_OUTPUT 1 +#define PCA953X_INVERT 2 +#define PCA953X_DIRECTION 3 -#define NR_PCA953X_GPIOS 16 +/* This is only temporary - should go with 2.6.26. Only introduced now + * to avoid a sequence of strcmp() calls and just compare in a loop */ +struct pca953x_desc { + unsigned int gpios; + char *name; +}; -#define PCA953X_INPUT 0 -#define PCA953X_OUTPUT 2 -#define PCA953X_INVERT 4 -#define PCA953X_DIRECTION 6 +static const struct pca953x_desc pca953x_descs[] = { + { + .gpios = 8, + .name = "pca9534", + }, { + .gpios = 16, + .name = "pca9535", + }, { + .gpios = 4, + .name = "pca9536", + }, { + .gpios = 4, + .name = "pca9537", + }, { + .gpios = 8, + .name = "pca9538", + }, { + .gpios = 16, + .name = "pca9539", + }, +}; struct pca953x_chip { unsigned gpio_start; + unsigned reg_shift; uint16_t reg_output; uint16_t reg_direction; @@ -40,17 +67,30 @@ struct pca953x_chip { */ static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val) { - if (i2c_smbus_write_word_data(chip->client, reg, val) < 0) - return -EIO; + int ret; + + if (chip->gpio_chip.ngpio <= 8) + ret = i2c_smbus_write_byte_data(chip->client, reg, val); else - return 0; + ret = i2c_smbus_write_word_data(chip->client, reg, val); + + if (ret < 0) { + dev_err(&chip->client->dev, "failed writing register\n"); + return -EIO; + } + + return 0; } static int pca953x_read_reg(struct pca953x_chip *chip, int reg, uint16_t *val) { int ret; - ret = i2c_smbus_read_word_data(chip->client, reg); + if (chip->gpio_chip.ngpio <= 8) + ret = i2c_smbus_read_byte_data(chip->client, reg); + else + ret = i2c_smbus_read_word_data(chip->client, reg); + if (ret < 0) { dev_err(&chip->client->dev, "failed reading register\n"); return -EIO; @@ -64,12 +104,13 @@ static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off) { struct pca953x_chip *chip; uint16_t reg_val; - int ret; + int ret, reg; chip = container_of(gc, struct pca953x_chip, gpio_chip); reg_val = chip->reg_direction | (1u << off); - ret = pca953x_write_reg(chip, PCA953X_DIRECTION, reg_val); + reg = PCA953X_DIRECTION << chip->reg_shift; + ret = pca953x_write_reg(chip, reg, reg_val); if (ret) return ret; @@ -82,7 +123,7 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc, { struct pca953x_chip *chip; uint16_t reg_val; - int ret; + int ret, reg; chip = container_of(gc, struct pca953x_chip, gpio_chip); @@ -92,7 +133,8 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc, else reg_val = chip->reg_output & ~(1u << off); - ret = pca953x_write_reg(chip, PCA953X_OUTPUT, reg_val); + reg = PCA953X_OUTPUT << chip->reg_shift; + ret = pca953x_write_reg(chip, reg, reg_val); if (ret) return ret; @@ -100,7 +142,8 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc, /* then direction */ reg_val = chip->reg_direction & ~(1u << off); - ret = pca953x_write_reg(chip, PCA953X_DIRECTION, reg_val); + reg = PCA953X_DIRECTION << chip->reg_shift; + ret = pca953x_write_reg(chip, reg, reg_val); if (ret) return ret; @@ -112,11 +155,12 @@ static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off) { struct pca953x_chip *chip; uint16_t reg_val; - int ret; + int ret, reg; chip = container_of(gc, struct pca953x_chip, gpio_chip); - ret = pca953x_read_reg(chip, PCA953X_INPUT, ®_val); + reg = PCA953X_INPUT << chip->reg_shift; + ret = pca953x_read_reg(chip, reg, ®_val); if (ret < 0) { /* NOTE: diagnostic already emitted; that's all we should * do unless gpio_*_value_cansleep() calls become different @@ -132,7 +176,7 @@ static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val) { struct pca953x_chip *chip; uint16_t reg_val; - int ret; + int ret, reg; chip = container_of(gc, struct pca953x_chip, gpio_chip); @@ -141,14 +185,15 @@ static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val) else reg_val = chip->reg_output & ~(1u << off); - ret = pca953x_write_reg(chip, PCA953X_OUTPUT, reg_val); + reg = PCA953X_OUTPUT << chip->reg_shift; + ret = pca953x_write_reg(chip, reg, reg_val); if (ret) return; chip->reg_output = reg_val; } -static int pca953x_init_gpio(struct pca953x_chip *chip) +static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios) { struct gpio_chip *gc; @@ -160,22 +205,26 @@ static int pca953x_init_gpio(struct pca953x_chip *chip) gc->set = pca953x_gpio_set_value; gc->base = chip->gpio_start; - gc->ngpio = NR_PCA953X_GPIOS; - gc->label = "pca953x"; - - return gpiochip_add(gc); + gc->ngpio = gpios; + gc->label = chip->client->name; } static int __devinit pca953x_probe(struct i2c_client *client) { struct pca953x_platform_data *pdata; struct pca953x_chip *chip; - int ret; + int ret, i; pdata = client->dev.platform_data; if (pdata == NULL) return -ENODEV; + for (i = 0; i < ARRAY_SIZE(pca953x_descs); i++) + if (!strcmp(pca953x_descs[i].name, client->name)) + break; + if (i == ARRAY_SIZE(pca953x_descs)) + return -ENODEV; + chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL); if (chip == NULL) return -ENOMEM; @@ -187,20 +236,25 @@ static int __devinit pca953x_probe(struct i2c_client *client) /* initialize cached registers from their original values. * we can't share this chip with another i2c master. */ - ret = pca953x_read_reg(chip, PCA953X_OUTPUT, &chip->reg_output); + chip->reg_shift = (pca953x_descs[i].gpios - 1) >> 3; + + pca953x_setup_gpio(chip, pca953x_descs[i].gpios); + + ret = pca953x_read_reg(chip, PCA953X_OUTPUT << chip->reg_shift, &chip->reg_output); if (ret) goto out_failed; - ret = pca953x_read_reg(chip, PCA953X_DIRECTION, &chip->reg_direction); + ret = pca953x_read_reg(chip, PCA953X_DIRECTION << chip->reg_shift, &chip->reg_direction); if (ret) goto out_failed; /* set platform specific polarity inversion */ - ret = pca953x_write_reg(chip, PCA953X_INVERT, pdata->invert); + ret = pca953x_write_reg(chip, PCA953X_INVERT << chip->reg_shift, pdata->invert); if (ret) goto out_failed; - ret = pca953x_init_gpio(chip); + + ret = gpiochip_add(&chip->gpio_chip); if (ret) goto out_failed; @@ -267,5 +321,5 @@ static void __exit pca953x_exit(void) module_exit(pca953x_exit); MODULE_AUTHOR("eric miao <eric.miao@marvell.com>"); -MODULE_DESCRIPTION("GPIO expander driver for PCA9536...PCA9539"); +MODULE_DESCRIPTION("GPIO expander driver for PCA953X"); MODULE_LICENSE("GPL"); -- 1.5.3.4 -- video4linux-list mailing list Unsubscribe mailto:video4linux-list-request@redhat.com?subject=unsubscribe https://www.redhat.com/mailman/listinfo/video4linux-list ^ permalink raw reply related [flat|nested] 11+ messages in thread
[parent not found: <Pine.LNX.4.64.0801311500240.8478-0199iw4Nj15frtckUFj5Ag@public.gmane.org>]
* Re: [PATCH 3/3] Add support for PCA953[4-8] I2C GPIO extenders to the pca953x driver [not found] ` <Pine.LNX.4.64.0801311500240.8478-0199iw4Nj15frtckUFj5Ag@public.gmane.org> @ 2008-01-31 21:20 ` David Brownell 2008-01-31 22:13 ` Guennadi Liakhovetski 0 siblings, 1 reply; 11+ messages in thread From: David Brownell @ 2008-01-31 21:20 UTC (permalink / raw) To: Guennadi Liakhovetski Cc: video4linux-list-H+wXaHxf7aLQT0dZR+AlfA, i2c-GZX6beZjE8VD60Wz+7aTrA On Thursday 31 January 2008, Guennadi Liakhovetski wrote: > +/* This is only temporary - should go with 2.6.26. Only introduced now > + * to avoid a sequence of strcmp() calls and just compare in a loop */ > +struct pca953x_desc { > + unsigned int gpios; > + char *name; > +}; This is a bit sub-optimal; if it were the same as i2c_device_id then less code would need to change later. So I'll probably tweak that bit before sending it on. Otherwise, fine ... thanks! - Dave _______________________________________________ i2c mailing list i2c-GZX6beZjE8VD60Wz+7aTrA@public.gmane.org http://lists.lm-sensors.org/mailman/listinfo/i2c ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 3/3] Add support for PCA953[4-8] I2C GPIO extenders to the pca953x driver 2008-01-31 21:20 ` David Brownell @ 2008-01-31 22:13 ` Guennadi Liakhovetski [not found] ` <Pine.LNX.4.64.0801312308110.3704-0199iw4Nj15frtckUFj5Ag@public.gmane.org> 0 siblings, 1 reply; 11+ messages in thread From: Guennadi Liakhovetski @ 2008-01-31 22:13 UTC (permalink / raw) To: David Brownell; +Cc: Jean Delvare, video4linux-list, i2c On Thu, 31 Jan 2008, David Brownell wrote: > On Thursday 31 January 2008, Guennadi Liakhovetski wrote: > > +/* This is only temporary - should go with 2.6.26. Only introduced now > > + * to avoid a sequence of strcmp() calls and just compare in a loop */ > > +struct pca953x_desc { > > + unsigned int gpios; > > + char *name; > > +}; > > This is a bit sub-optimal; if it were the same as i2c_device_id then > less code would need to change later. So I'll probably tweak that bit > before sending it on. Well, you said i2c_device_id is going to look like struct i2c_device_id { char name[I2C_NAME_SIZE]; kernel_ulong_t driver_data; /* Data private to the driver */ }; And I only have a (const) statically initialized array of such structs. So, what would be the difference? Thanks Guennadi --- Guennadi Liakhovetski -- video4linux-list mailing list Unsubscribe mailto:video4linux-list-request@redhat.com?subject=unsubscribe https://www.redhat.com/mailman/listinfo/video4linux-list ^ permalink raw reply [flat|nested] 11+ messages in thread
[parent not found: <Pine.LNX.4.64.0801312308110.3704-0199iw4Nj15frtckUFj5Ag@public.gmane.org>]
* Re: [PATCH 3/3] Add support for PCA953[4-8] I2C GPIO extenders to the pca953x driver [not found] ` <Pine.LNX.4.64.0801312308110.3704-0199iw4Nj15frtckUFj5Ag@public.gmane.org> @ 2008-01-31 23:35 ` David Brownell 2008-02-01 10:57 ` Guennadi Liakhovetski 0 siblings, 1 reply; 11+ messages in thread From: David Brownell @ 2008-01-31 23:35 UTC (permalink / raw) To: Guennadi Liakhovetski Cc: video4linux-list-H+wXaHxf7aLQT0dZR+AlfA, i2c-GZX6beZjE8VD60Wz+7aTrA On Thursday 31 January 2008, Guennadi Liakhovetski wrote: > On Thu, 31 Jan 2008, David Brownell wrote: > > > On Thursday 31 January 2008, Guennadi Liakhovetski wrote: > > > +/* This is only temporary - should go with 2.6.26. Only introduced now > > > + * to avoid a sequence of strcmp() calls and just compare in a loop */ > > > +struct pca953x_desc { > > > + unsigned int gpios; > > > + char *name; > > > +}; > > > > This is a bit sub-optimal; if it were the same as i2c_device_id then > > less code would need to change later. So I'll probably tweak that bit > > before sending it on. > > Well, you said i2c_device_id is going to look like > > struct i2c_device_id { > char name[I2C_NAME_SIZE]; > kernel_ulong_t driver_data; /* Data private to the driver */ > }; > > And I only have a (const) statically initialized array of such structs. > So, what would be the difference? Compare to this cleaned up version of your patch 3/3 ... which is a bit smaller since it removes reg_shift. (Tell me I didn't break anything!) When 2.6.26 merges i2c_device_id, then "pca953x_desc" will be replaced by "i2c_device_id" and some code will vanish from probe(). No other changes needed. - Dave =========== CUT HERE From: Guennadi Liakhovetski <g.liakhovetski-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org> This third part of the extension to support more pca953x chips updates the logic to handle the smaller register widths used by the 4-bit and 8-bit parts, and to use the chip type to determine how many GPIOs it provides. As long as we don't support interrupt and reset capabilities, those size issues are the only software-visible differences between these parts. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org> Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> --- drivers/gpio/pca953x.c | 73 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 55 insertions(+), 18 deletions(-) --- g26.orig/drivers/gpio/pca953x.c 2008-01-31 14:41:19.000000000 -0800 +++ g26/drivers/gpio/pca953x.c 2008-01-31 15:20:28.000000000 -0800 @@ -1,5 +1,5 @@ /* - * pca953x.c - 16-bit I/O port with interrupt and reset + * pca953x.c - 4/8/16 bit I/O ports * * Copyright (C) 2005 Ben Gardner <bgardner-ohtLXRgXiI/QT0dZR+AlfA@public.gmane.org> * Copyright (C) 2007 Marvell International Ltd. @@ -18,13 +18,26 @@ #include <asm/gpio.h> +#define PCA953X_INPUT 0 +#define PCA953X_OUTPUT 1 +#define PCA953X_INVERT 2 +#define PCA953X_DIRECTION 3 + +/* This is temporary - in 2.6.26 i2c_driver_data should replace it. */ +struct pca953x_desc { + char name[I2C_NAME_SIZE]; + unsigned long driver_data; +}; -#define NR_PCA953X_GPIOS 16 - -#define PCA953X_INPUT 0 -#define PCA953X_OUTPUT 2 -#define PCA953X_INVERT 4 -#define PCA953X_DIRECTION 6 +static const struct pca953x_desc pca953x_descs[] = { + { "pca9534", 8, }, + { "pca9535", 16, }, + { "pca9536", 4, }, + { "pca9537", 4, }, + { "pca9538", 8, }, + { "pca9539", 16, }, + /* REVISIT several pca955x parts should work here too */ +}; struct pca953x_chip { unsigned gpio_start; @@ -40,17 +53,30 @@ struct pca953x_chip { */ static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val) { - if (i2c_smbus_write_word_data(chip->client, reg, val) < 0) - return -EIO; + int ret; + + if (chip->gpio_chip.ngpio <= 8) + ret = i2c_smbus_write_byte_data(chip->client, reg, val); else - return 0; + ret = i2c_smbus_write_word_data(chip->client, reg << 1, val); + + if (ret < 0) { + dev_err(&chip->client->dev, "failed writing register\n"); + return -EIO; + } + + return 0; } static int pca953x_read_reg(struct pca953x_chip *chip, int reg, uint16_t *val) { int ret; - ret = i2c_smbus_read_word_data(chip->client, reg); + if (chip->gpio_chip.ngpio <= 8) + ret = i2c_smbus_read_byte_data(chip->client, reg); + else + ret = i2c_smbus_read_word_data(chip->client, reg << 1); + if (ret < 0) { dev_err(&chip->client->dev, "failed reading register\n"); return -EIO; @@ -148,7 +174,7 @@ static void pca953x_gpio_set_value(struc chip->reg_output = reg_val; } -static int pca953x_init_gpio(struct pca953x_chip *chip) +static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios) { struct gpio_chip *gc; @@ -160,22 +186,30 @@ static int pca953x_init_gpio(struct pca9 gc->set = pca953x_gpio_set_value; gc->base = chip->gpio_start; - gc->ngpio = NR_PCA953X_GPIOS; - gc->label = "pca953x"; - - return gpiochip_add(gc); + gc->ngpio = gpios; + gc->label = chip->client->name; } static int __devinit pca953x_probe(struct i2c_client *client) { struct pca953x_platform_data *pdata; struct pca953x_chip *chip; - int ret; + int ret, i; + const struct pca953x_desc *id = NULL; pdata = client->dev.platform_data; if (pdata == NULL) return -ENODEV; + /* this loop vanishes when we get i2c_device_id */ + for (i = 0; i < ARRAY_SIZE(pca953x_descs); i++) + if (!strcmp(pca953x_descs[i].name, client->name)) { + id = pca953x_descs + i; + break; + } + if (!id) + return -ENODEV; + chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL); if (chip == NULL) return -ENOMEM; @@ -187,6 +221,8 @@ static int __devinit pca953x_probe(struc /* initialize cached registers from their original values. * we can't share this chip with another i2c master. */ + pca953x_setup_gpio(chip, id->driver_data); + ret = pca953x_read_reg(chip, PCA953X_OUTPUT, &chip->reg_output); if (ret) goto out_failed; @@ -200,7 +236,8 @@ static int __devinit pca953x_probe(struc if (ret) goto out_failed; - ret = pca953x_init_gpio(chip); + + ret = gpiochip_add(&chip->gpio_chip); if (ret) goto out_failed; _______________________________________________ i2c mailing list i2c-GZX6beZjE8VD60Wz+7aTrA@public.gmane.org http://lists.lm-sensors.org/mailman/listinfo/i2c ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 3/3] Add support for PCA953[4-8] I2C GPIO extenders to the pca953x driver 2008-01-31 23:35 ` David Brownell @ 2008-02-01 10:57 ` Guennadi Liakhovetski 0 siblings, 0 replies; 11+ messages in thread From: Guennadi Liakhovetski @ 2008-02-01 10:57 UTC (permalink / raw) To: David Brownell; +Cc: Jean Delvare, video4linux-list, i2c On Thu, 31 Jan 2008, David Brownell wrote: > Compare to this cleaned up version of your patch 3/3 ... which is a bit > smaller since it removes reg_shift. (Tell me I didn't break anything!) You didn't:-) It still works. Thanks Guennadi --- Guennadi Liakhovetski -- video4linux-list mailing list Unsubscribe mailto:video4linux-list-request@redhat.com?subject=unsubscribe https://www.redhat.com/mailman/listinfo/video4linux-list ^ permalink raw reply [flat|nested] 11+ messages in thread
[parent not found: <Pine.LNX.4.64.0801311453470.8478-0199iw4Nj15frtckUFj5Ag@public.gmane.org>]
* [PATCH 2/3] Second stage extending the pca953x GPIO driver - change Kconfig, "sed" files [not found] ` <Pine.LNX.4.64.0801311453470.8478-0199iw4Nj15frtckUFj5Ag@public.gmane.org> @ 2008-01-31 14:04 ` Guennadi Liakhovetski [not found] ` <Pine.LNX.4.64.0801311456280.8478-0199iw4Nj15frtckUFj5Ag@public.gmane.org> 2008-01-31 21:01 ` [PATCH 1/3] Prepare to extend pca9539 to support more chips - rename files David Brownell 1 sibling, 1 reply; 11+ messages in thread From: Guennadi Liakhovetski @ 2008-01-31 14:04 UTC (permalink / raw) To: video4linux-list-H+wXaHxf7aLQT0dZR+AlfA, i2c-GZX6beZjE8VD60Wz+7aTrA Cc: David Brownell All affected files have been passed through sed, except for a couple of obvious exception places. Also extended Kconfig help. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org> --- drivers/gpio/Kconfig | 11 ++-- drivers/gpio/Makefile | 2 +- drivers/gpio/pca953x.c | 110 +++++++++++++++++++++--------------------- include/linux/i2c/pca953x.h | 2 +- 4 files changed, 63 insertions(+), 62 deletions(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 74fac0f..a122d85 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -27,15 +27,16 @@ config DEBUG_GPIO comment "I2C GPIO expanders:" -config GPIO_PCA9539 - tristate "PCA9539 16-bit I/O port" +config GPIO_PCA953X + tristate "PCA953X I/O ports" depends on I2C help - Say yes here to support the PCA9539 16-bit I/O port. These - parts are made by NXP and TI. + Say yes here to support the PCA9534 (8-bit), PCA9535 (16-bit), + PCA9536 (4-bit), PCA9537 (4-bit), PCA9538 (8-bit), and PCA9539 + (16-bit) I/O ports. These parts are made by NXP and TI. This driver can also be built as a module. If so, the module - will be called pca9539. + will be called pca953x. config GPIO_PCF857X tristate "PCF857x, PCA857x, and PCA967x I2C GPIO expanders" diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 16dda77..fdde992 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -5,5 +5,5 @@ ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG obj-$(CONFIG_HAVE_GPIO_LIB) += gpiolib.o obj-$(CONFIG_GPIO_MCP23S08) += mcp23s08.o -obj-$(CONFIG_GPIO_PCA9539) += pca953x.o +obj-$(CONFIG_GPIO_PCA953X) += pca953x.o obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c index 7fae4e5..51adbaa 100644 --- a/drivers/gpio/pca953x.c +++ b/drivers/gpio/pca953x.c @@ -1,5 +1,5 @@ /* - * pca9539.c - 16-bit I/O port with interrupt and reset + * pca953x.c - 16-bit I/O port with interrupt and reset * * Copyright (C) 2005 Ben Gardner <bgardner-ohtLXRgXiI/QT0dZR+AlfA@public.gmane.org> * Copyright (C) 2007 Marvell International Ltd. @@ -19,14 +19,14 @@ #include <asm/gpio.h> -#define NR_PCA9539_GPIOS 16 +#define NR_PCA953X_GPIOS 16 -#define PCA9539_INPUT 0 -#define PCA9539_OUTPUT 2 -#define PCA9539_INVERT 4 -#define PCA9539_DIRECTION 6 +#define PCA953X_INPUT 0 +#define PCA953X_OUTPUT 2 +#define PCA953X_INVERT 4 +#define PCA953X_DIRECTION 6 -struct pca9539_chip { +struct pca953x_chip { unsigned gpio_start; uint16_t reg_output; uint16_t reg_direction; @@ -38,7 +38,7 @@ struct pca9539_chip { /* NOTE: we can't currently rely on fault codes to come from SMBus * calls, so we map all errors to EIO here and return zero otherwise. */ -static int pca9539_write_reg(struct pca9539_chip *chip, int reg, uint16_t val) +static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val) { if (i2c_smbus_write_word_data(chip->client, reg, val) < 0) return -EIO; @@ -46,7 +46,7 @@ static int pca9539_write_reg(struct pca9539_chip *chip, int reg, uint16_t val) return 0; } -static int pca9539_read_reg(struct pca9539_chip *chip, int reg, uint16_t *val) +static int pca953x_read_reg(struct pca953x_chip *chip, int reg, uint16_t *val) { int ret; @@ -60,16 +60,16 @@ static int pca9539_read_reg(struct pca9539_chip *chip, int reg, uint16_t *val) return 0; } -static int pca9539_gpio_direction_input(struct gpio_chip *gc, unsigned off) +static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off) { - struct pca9539_chip *chip; + struct pca953x_chip *chip; uint16_t reg_val; int ret; - chip = container_of(gc, struct pca9539_chip, gpio_chip); + chip = container_of(gc, struct pca953x_chip, gpio_chip); reg_val = chip->reg_direction | (1u << off); - ret = pca9539_write_reg(chip, PCA9539_DIRECTION, reg_val); + ret = pca953x_write_reg(chip, PCA953X_DIRECTION, reg_val); if (ret) return ret; @@ -77,14 +77,14 @@ static int pca9539_gpio_direction_input(struct gpio_chip *gc, unsigned off) return 0; } -static int pca9539_gpio_direction_output(struct gpio_chip *gc, +static int pca953x_gpio_direction_output(struct gpio_chip *gc, unsigned off, int val) { - struct pca9539_chip *chip; + struct pca953x_chip *chip; uint16_t reg_val; int ret; - chip = container_of(gc, struct pca9539_chip, gpio_chip); + chip = container_of(gc, struct pca953x_chip, gpio_chip); /* set output level */ if (val) @@ -92,7 +92,7 @@ static int pca9539_gpio_direction_output(struct gpio_chip *gc, else reg_val = chip->reg_output & ~(1u << off); - ret = pca9539_write_reg(chip, PCA9539_OUTPUT, reg_val); + ret = pca953x_write_reg(chip, PCA953X_OUTPUT, reg_val); if (ret) return ret; @@ -100,7 +100,7 @@ static int pca9539_gpio_direction_output(struct gpio_chip *gc, /* then direction */ reg_val = chip->reg_direction & ~(1u << off); - ret = pca9539_write_reg(chip, PCA9539_DIRECTION, reg_val); + ret = pca953x_write_reg(chip, PCA953X_DIRECTION, reg_val); if (ret) return ret; @@ -108,15 +108,15 @@ static int pca9539_gpio_direction_output(struct gpio_chip *gc, return 0; } -static int pca9539_gpio_get_value(struct gpio_chip *gc, unsigned off) +static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off) { - struct pca9539_chip *chip; + struct pca953x_chip *chip; uint16_t reg_val; int ret; - chip = container_of(gc, struct pca9539_chip, gpio_chip); + chip = container_of(gc, struct pca953x_chip, gpio_chip); - ret = pca9539_read_reg(chip, PCA9539_INPUT, ®_val); + ret = pca953x_read_reg(chip, PCA953X_INPUT, ®_val); if (ret < 0) { /* NOTE: diagnostic already emitted; that's all we should * do unless gpio_*_value_cansleep() calls become different @@ -128,55 +128,55 @@ static int pca9539_gpio_get_value(struct gpio_chip *gc, unsigned off) return (reg_val & (1u << off)) ? 1 : 0; } -static void pca9539_gpio_set_value(struct gpio_chip *gc, unsigned off, int val) +static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val) { - struct pca9539_chip *chip; + struct pca953x_chip *chip; uint16_t reg_val; int ret; - chip = container_of(gc, struct pca9539_chip, gpio_chip); + chip = container_of(gc, struct pca953x_chip, gpio_chip); if (val) reg_val = chip->reg_output | (1u << off); else reg_val = chip->reg_output & ~(1u << off); - ret = pca9539_write_reg(chip, PCA9539_OUTPUT, reg_val); + ret = pca953x_write_reg(chip, PCA953X_OUTPUT, reg_val); if (ret) return; chip->reg_output = reg_val; } -static int pca9539_init_gpio(struct pca9539_chip *chip) +static int pca953x_init_gpio(struct pca953x_chip *chip) { struct gpio_chip *gc; gc = &chip->gpio_chip; - gc->direction_input = pca9539_gpio_direction_input; - gc->direction_output = pca9539_gpio_direction_output; - gc->get = pca9539_gpio_get_value; - gc->set = pca9539_gpio_set_value; + gc->direction_input = pca953x_gpio_direction_input; + gc->direction_output = pca953x_gpio_direction_output; + gc->get = pca953x_gpio_get_value; + gc->set = pca953x_gpio_set_value; gc->base = chip->gpio_start; - gc->ngpio = NR_PCA9539_GPIOS; - gc->label = "pca9539"; + gc->ngpio = NR_PCA953X_GPIOS; + gc->label = "pca953x"; return gpiochip_add(gc); } -static int __devinit pca9539_probe(struct i2c_client *client) +static int __devinit pca953x_probe(struct i2c_client *client) { - struct pca9539_platform_data *pdata; - struct pca9539_chip *chip; + struct pca953x_platform_data *pdata; + struct pca953x_chip *chip; int ret; pdata = client->dev.platform_data; if (pdata == NULL) return -ENODEV; - chip = kzalloc(sizeof(struct pca9539_chip), GFP_KERNEL); + chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL); if (chip == NULL) return -ENOMEM; @@ -187,20 +187,20 @@ static int __devinit pca9539_probe(struct i2c_client *client) /* initialize cached registers from their original values. * we can't share this chip with another i2c master. */ - ret = pca9539_read_reg(chip, PCA9539_OUTPUT, &chip->reg_output); + ret = pca953x_read_reg(chip, PCA953X_OUTPUT, &chip->reg_output); if (ret) goto out_failed; - ret = pca9539_read_reg(chip, PCA9539_DIRECTION, &chip->reg_direction); + ret = pca953x_read_reg(chip, PCA953X_DIRECTION, &chip->reg_direction); if (ret) goto out_failed; /* set platform specific polarity inversion */ - ret = pca9539_write_reg(chip, PCA9539_INVERT, pdata->invert); + ret = pca953x_write_reg(chip, PCA953X_INVERT, pdata->invert); if (ret) goto out_failed; - ret = pca9539_init_gpio(chip); + ret = pca953x_init_gpio(chip); if (ret) goto out_failed; @@ -219,10 +219,10 @@ out_failed: return ret; } -static int pca9539_remove(struct i2c_client *client) +static int pca953x_remove(struct i2c_client *client) { - struct pca9539_platform_data *pdata = client->dev.platform_data; - struct pca9539_chip *chip = i2c_get_clientdata(client); + struct pca953x_platform_data *pdata = client->dev.platform_data; + struct pca953x_chip *chip = i2c_get_clientdata(client); int ret = 0; if (pdata->teardown) { @@ -246,26 +246,26 @@ static int pca9539_remove(struct i2c_client *client) return 0; } -static struct i2c_driver pca9539_driver = { +static struct i2c_driver pca953x_driver = { .driver = { - .name = "pca9539", + .name = "pca953x", }, - .probe = pca9539_probe, - .remove = pca9539_remove, + .probe = pca953x_probe, + .remove = pca953x_remove, }; -static int __init pca9539_init(void) +static int __init pca953x_init(void) { - return i2c_add_driver(&pca9539_driver); + return i2c_add_driver(&pca953x_driver); } -module_init(pca9539_init); +module_init(pca953x_init); -static void __exit pca9539_exit(void) +static void __exit pca953x_exit(void) { - i2c_del_driver(&pca9539_driver); + i2c_del_driver(&pca953x_driver); } -module_exit(pca9539_exit); +module_exit(pca953x_exit); MODULE_AUTHOR("eric miao <eric.miao-eYqpPyKDWXRBDgjK7y7TUQ@public.gmane.org>"); -MODULE_DESCRIPTION("GPIO expander driver for PCA9539"); +MODULE_DESCRIPTION("GPIO expander driver for PCA9536...PCA9539"); MODULE_LICENSE("GPL"); diff --git a/include/linux/i2c/pca953x.h b/include/linux/i2c/pca953x.h index 611d84a..3c73612 100644 --- a/include/linux/i2c/pca953x.h +++ b/include/linux/i2c/pca953x.h @@ -1,6 +1,6 @@ /* platform data for the PCA9539 16-bit I/O expander driver */ -struct pca9539_platform_data { +struct pca953x_platform_data { /* number of the first GPIO */ unsigned gpio_base; -- 1.5.3.4 _______________________________________________ i2c mailing list i2c-GZX6beZjE8VD60Wz+7aTrA@public.gmane.org http://lists.lm-sensors.org/mailman/listinfo/i2c ^ permalink raw reply related [flat|nested] 11+ messages in thread
[parent not found: <Pine.LNX.4.64.0801311456280.8478-0199iw4Nj15frtckUFj5Ag@public.gmane.org>]
* Re: [PATCH 2/3] Second stage extending the pca953x GPIO driver - change Kconfig, "sed" files [not found] ` <Pine.LNX.4.64.0801311456280.8478-0199iw4Nj15frtckUFj5Ag@public.gmane.org> @ 2008-01-31 21:25 ` David Brownell 0 siblings, 0 replies; 11+ messages in thread From: David Brownell @ 2008-01-31 21:25 UTC (permalink / raw) To: Guennadi Liakhovetski Cc: video4linux-list-H+wXaHxf7aLQT0dZR+AlfA, i2c-GZX6beZjE8VD60Wz+7aTrA On Thursday 31 January 2008, Guennadi Liakhovetski wrote: > + Say yes here to support the PCA9534 (8-bit), PCA9535 (16-bit), > + PCA9536 (4-bit), PCA9537 (4-bit), PCA9538 (8-bit), and PCA9539 > + (16-bit) I/O ports. These parts are made by NXP and TI. Yeah, let's ignore the pca9554/55/56/57/58 for now. Even though this driver should handle those too. ;) _______________________________________________ i2c mailing list i2c-GZX6beZjE8VD60Wz+7aTrA@public.gmane.org http://lists.lm-sensors.org/mailman/listinfo/i2c ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 1/3] Prepare to extend pca9539 to support more chips - rename files [not found] ` <Pine.LNX.4.64.0801311453470.8478-0199iw4Nj15frtckUFj5Ag@public.gmane.org> 2008-01-31 14:04 ` [PATCH 2/3] Second stage extending the pca953x GPIO driver - change Kconfig, "sed" files Guennadi Liakhovetski @ 2008-01-31 21:01 ` David Brownell 2008-01-31 22:06 ` Guennadi Liakhovetski 1 sibling, 1 reply; 11+ messages in thread From: David Brownell @ 2008-01-31 21:01 UTC (permalink / raw) To: Guennadi Liakhovetski Cc: video4linux-list-H+wXaHxf7aLQT0dZR+AlfA, i2c-GZX6beZjE8VD60Wz+7aTrA On Thursday 31 January 2008, Guennadi Liakhovetski wrote: > This is a git-style rename patch. If desired, I can produce a complete GNU > patch instead. Yes, please. This goes through Andrew's tree, using Quilt. _______________________________________________ i2c mailing list i2c-GZX6beZjE8VD60Wz+7aTrA@public.gmane.org http://lists.lm-sensors.org/mailman/listinfo/i2c ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 1/3] Prepare to extend pca9539 to support more chips - rename files 2008-01-31 21:01 ` [PATCH 1/3] Prepare to extend pca9539 to support more chips - rename files David Brownell @ 2008-01-31 22:06 ` Guennadi Liakhovetski [not found] ` <Pine.LNX.4.64.0801312303270.3704-0199iw4Nj15frtckUFj5Ag@public.gmane.org> 0 siblings, 1 reply; 11+ messages in thread From: Guennadi Liakhovetski @ 2008-01-31 22:06 UTC (permalink / raw) To: David Brownell; +Cc: Jean Delvare, video4linux-list, i2c First stage of the extension, letting pca9539 also support pca9536, pca9537, and pca9538. Split to make review easier. Here only rename the files and modify the Makefile. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@pengutronix.de> --- On Thu, 31 Jan 2008, David Brownell wrote: > On Thursday 31 January 2008, Guennadi Liakhovetski wrote: > > This is a git-style rename patch. If desired, I can produce a complete GNU > > patch instead. > > Yes, please. This goes through Andrew's tree, using Quilt. Below. Are you expecting your gpiolib, and, respectively, this patch to be pushed to Linus for 2.6.25 or more likely later? Thanks Guennadi diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 470ecd6..16dda77 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -5,5 +5,5 @@ ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG obj-$(CONFIG_HAVE_GPIO_LIB) += gpiolib.o obj-$(CONFIG_GPIO_MCP23S08) += mcp23s08.o -obj-$(CONFIG_GPIO_PCA9539) += pca9539.o +obj-$(CONFIG_GPIO_PCA9539) += pca953x.o obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o diff --git a/drivers/gpio/pca9539.c b/drivers/gpio/pca9539.c deleted file mode 100644 index 3e85c92..0000000 --- a/drivers/gpio/pca9539.c +++ /dev/null @@ -1,271 +0,0 @@ -/* - * pca9539.c - 16-bit I/O port with interrupt and reset - * - * Copyright (C) 2005 Ben Gardner <bgardner@wabtec.com> - * Copyright (C) 2007 Marvell International Ltd. - * - * Derived from drivers/i2c/chips/pca9539.c - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/i2c.h> -#include <linux/i2c/pca9539.h> - -#include <asm/gpio.h> - - -#define NR_PCA9539_GPIOS 16 - -#define PCA9539_INPUT 0 -#define PCA9539_OUTPUT 2 -#define PCA9539_INVERT 4 -#define PCA9539_DIRECTION 6 - -struct pca9539_chip { - unsigned gpio_start; - uint16_t reg_output; - uint16_t reg_direction; - - struct i2c_client *client; - struct gpio_chip gpio_chip; -}; - -/* NOTE: we can't currently rely on fault codes to come from SMBus - * calls, so we map all errors to EIO here and return zero otherwise. - */ -static int pca9539_write_reg(struct pca9539_chip *chip, int reg, uint16_t val) -{ - if (i2c_smbus_write_word_data(chip->client, reg, val) < 0) - return -EIO; - else - return 0; -} - -static int pca9539_read_reg(struct pca9539_chip *chip, int reg, uint16_t *val) -{ - int ret; - - ret = i2c_smbus_read_word_data(chip->client, reg); - if (ret < 0) { - dev_err(&chip->client->dev, "failed reading register\n"); - return -EIO; - } - - *val = (uint16_t)ret; - return 0; -} - -static int pca9539_gpio_direction_input(struct gpio_chip *gc, unsigned off) -{ - struct pca9539_chip *chip; - uint16_t reg_val; - int ret; - - chip = container_of(gc, struct pca9539_chip, gpio_chip); - - reg_val = chip->reg_direction | (1u << off); - ret = pca9539_write_reg(chip, PCA9539_DIRECTION, reg_val); - if (ret) - return ret; - - chip->reg_direction = reg_val; - return 0; -} - -static int pca9539_gpio_direction_output(struct gpio_chip *gc, - unsigned off, int val) -{ - struct pca9539_chip *chip; - uint16_t reg_val; - int ret; - - chip = container_of(gc, struct pca9539_chip, gpio_chip); - - /* set output level */ - if (val) - reg_val = chip->reg_output | (1u << off); - else - reg_val = chip->reg_output & ~(1u << off); - - ret = pca9539_write_reg(chip, PCA9539_OUTPUT, reg_val); - if (ret) - return ret; - - chip->reg_output = reg_val; - - /* then direction */ - reg_val = chip->reg_direction & ~(1u << off); - ret = pca9539_write_reg(chip, PCA9539_DIRECTION, reg_val); - if (ret) - return ret; - - chip->reg_direction = reg_val; - return 0; -} - -static int pca9539_gpio_get_value(struct gpio_chip *gc, unsigned off) -{ - struct pca9539_chip *chip; - uint16_t reg_val; - int ret; - - chip = container_of(gc, struct pca9539_chip, gpio_chip); - - ret = pca9539_read_reg(chip, PCA9539_INPUT, ®_val); - if (ret < 0) { - /* NOTE: diagnostic already emitted; that's all we should - * do unless gpio_*_value_cansleep() calls become different - * from their nonsleeping siblings (and report faults). - */ - return 0; - } - - return (reg_val & (1u << off)) ? 1 : 0; -} - -static void pca9539_gpio_set_value(struct gpio_chip *gc, unsigned off, int val) -{ - struct pca9539_chip *chip; - uint16_t reg_val; - int ret; - - chip = container_of(gc, struct pca9539_chip, gpio_chip); - - if (val) - reg_val = chip->reg_output | (1u << off); - else - reg_val = chip->reg_output & ~(1u << off); - - ret = pca9539_write_reg(chip, PCA9539_OUTPUT, reg_val); - if (ret) - return; - - chip->reg_output = reg_val; -} - -static int pca9539_init_gpio(struct pca9539_chip *chip) -{ - struct gpio_chip *gc; - - gc = &chip->gpio_chip; - - gc->direction_input = pca9539_gpio_direction_input; - gc->direction_output = pca9539_gpio_direction_output; - gc->get = pca9539_gpio_get_value; - gc->set = pca9539_gpio_set_value; - - gc->base = chip->gpio_start; - gc->ngpio = NR_PCA9539_GPIOS; - gc->label = "pca9539"; - - return gpiochip_add(gc); -} - -static int __devinit pca9539_probe(struct i2c_client *client) -{ - struct pca9539_platform_data *pdata; - struct pca9539_chip *chip; - int ret; - - pdata = client->dev.platform_data; - if (pdata == NULL) - return -ENODEV; - - chip = kzalloc(sizeof(struct pca9539_chip), GFP_KERNEL); - if (chip == NULL) - return -ENOMEM; - - chip->client = client; - - chip->gpio_start = pdata->gpio_base; - - /* initialize cached registers from their original values. - * we can't share this chip with another i2c master. - */ - ret = pca9539_read_reg(chip, PCA9539_OUTPUT, &chip->reg_output); - if (ret) - goto out_failed; - - ret = pca9539_read_reg(chip, PCA9539_DIRECTION, &chip->reg_direction); - if (ret) - goto out_failed; - - /* set platform specific polarity inversion */ - ret = pca9539_write_reg(chip, PCA9539_INVERT, pdata->invert); - if (ret) - goto out_failed; - - ret = pca9539_init_gpio(chip); - if (ret) - goto out_failed; - - if (pdata->setup) { - ret = pdata->setup(client, chip->gpio_chip.base, - chip->gpio_chip.ngpio, pdata->context); - if (ret < 0) - dev_warn(&client->dev, "setup failed, %d\n", ret); - } - - i2c_set_clientdata(client, chip); - return 0; - -out_failed: - kfree(chip); - return ret; -} - -static int pca9539_remove(struct i2c_client *client) -{ - struct pca9539_platform_data *pdata = client->dev.platform_data; - struct pca9539_chip *chip = i2c_get_clientdata(client); - int ret = 0; - - if (pdata->teardown) { - ret = pdata->teardown(client, chip->gpio_chip.base, - chip->gpio_chip.ngpio, pdata->context); - if (ret < 0) { - dev_err(&client->dev, "%s failed, %d\n", - "teardown", ret); - return ret; - } - } - - ret = gpiochip_remove(&chip->gpio_chip); - if (ret) { - dev_err(&client->dev, "%s failed, %d\n", - "gpiochip_remove()", ret); - return ret; - } - - kfree(chip); - return 0; -} - -static struct i2c_driver pca9539_driver = { - .driver = { - .name = "pca9539", - }, - .probe = pca9539_probe, - .remove = pca9539_remove, -}; - -static int __init pca9539_init(void) -{ - return i2c_add_driver(&pca9539_driver); -} -module_init(pca9539_init); - -static void __exit pca9539_exit(void) -{ - i2c_del_driver(&pca9539_driver); -} -module_exit(pca9539_exit); - -MODULE_AUTHOR("eric miao <eric.miao@marvell.com>"); -MODULE_DESCRIPTION("GPIO expander driver for PCA9539"); -MODULE_LICENSE("GPL"); diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c new file mode 100644 index 0000000..7fae4e5 --- /dev/null +++ b/drivers/gpio/pca953x.c @@ -0,0 +1,271 @@ +/* + * pca9539.c - 16-bit I/O port with interrupt and reset + * + * Copyright (C) 2005 Ben Gardner <bgardner@wabtec.com> + * Copyright (C) 2007 Marvell International Ltd. + * + * Derived from drivers/i2c/chips/pca9539.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/i2c.h> +#include <linux/i2c/pca953x.h> + +#include <asm/gpio.h> + + +#define NR_PCA9539_GPIOS 16 + +#define PCA9539_INPUT 0 +#define PCA9539_OUTPUT 2 +#define PCA9539_INVERT 4 +#define PCA9539_DIRECTION 6 + +struct pca9539_chip { + unsigned gpio_start; + uint16_t reg_output; + uint16_t reg_direction; + + struct i2c_client *client; + struct gpio_chip gpio_chip; +}; + +/* NOTE: we can't currently rely on fault codes to come from SMBus + * calls, so we map all errors to EIO here and return zero otherwise. + */ +static int pca9539_write_reg(struct pca9539_chip *chip, int reg, uint16_t val) +{ + if (i2c_smbus_write_word_data(chip->client, reg, val) < 0) + return -EIO; + else + return 0; +} + +static int pca9539_read_reg(struct pca9539_chip *chip, int reg, uint16_t *val) +{ + int ret; + + ret = i2c_smbus_read_word_data(chip->client, reg); + if (ret < 0) { + dev_err(&chip->client->dev, "failed reading register\n"); + return -EIO; + } + + *val = (uint16_t)ret; + return 0; +} + +static int pca9539_gpio_direction_input(struct gpio_chip *gc, unsigned off) +{ + struct pca9539_chip *chip; + uint16_t reg_val; + int ret; + + chip = container_of(gc, struct pca9539_chip, gpio_chip); + + reg_val = chip->reg_direction | (1u << off); + ret = pca9539_write_reg(chip, PCA9539_DIRECTION, reg_val); + if (ret) + return ret; + + chip->reg_direction = reg_val; + return 0; +} + +static int pca9539_gpio_direction_output(struct gpio_chip *gc, + unsigned off, int val) +{ + struct pca9539_chip *chip; + uint16_t reg_val; + int ret; + + chip = container_of(gc, struct pca9539_chip, gpio_chip); + + /* set output level */ + if (val) + reg_val = chip->reg_output | (1u << off); + else + reg_val = chip->reg_output & ~(1u << off); + + ret = pca9539_write_reg(chip, PCA9539_OUTPUT, reg_val); + if (ret) + return ret; + + chip->reg_output = reg_val; + + /* then direction */ + reg_val = chip->reg_direction & ~(1u << off); + ret = pca9539_write_reg(chip, PCA9539_DIRECTION, reg_val); + if (ret) + return ret; + + chip->reg_direction = reg_val; + return 0; +} + +static int pca9539_gpio_get_value(struct gpio_chip *gc, unsigned off) +{ + struct pca9539_chip *chip; + uint16_t reg_val; + int ret; + + chip = container_of(gc, struct pca9539_chip, gpio_chip); + + ret = pca9539_read_reg(chip, PCA9539_INPUT, ®_val); + if (ret < 0) { + /* NOTE: diagnostic already emitted; that's all we should + * do unless gpio_*_value_cansleep() calls become different + * from their nonsleeping siblings (and report faults). + */ + return 0; + } + + return (reg_val & (1u << off)) ? 1 : 0; +} + +static void pca9539_gpio_set_value(struct gpio_chip *gc, unsigned off, int val) +{ + struct pca9539_chip *chip; + uint16_t reg_val; + int ret; + + chip = container_of(gc, struct pca9539_chip, gpio_chip); + + if (val) + reg_val = chip->reg_output | (1u << off); + else + reg_val = chip->reg_output & ~(1u << off); + + ret = pca9539_write_reg(chip, PCA9539_OUTPUT, reg_val); + if (ret) + return; + + chip->reg_output = reg_val; +} + +static int pca9539_init_gpio(struct pca9539_chip *chip) +{ + struct gpio_chip *gc; + + gc = &chip->gpio_chip; + + gc->direction_input = pca9539_gpio_direction_input; + gc->direction_output = pca9539_gpio_direction_output; + gc->get = pca9539_gpio_get_value; + gc->set = pca9539_gpio_set_value; + + gc->base = chip->gpio_start; + gc->ngpio = NR_PCA9539_GPIOS; + gc->label = "pca9539"; + + return gpiochip_add(gc); +} + +static int __devinit pca9539_probe(struct i2c_client *client) +{ + struct pca9539_platform_data *pdata; + struct pca9539_chip *chip; + int ret; + + pdata = client->dev.platform_data; + if (pdata == NULL) + return -ENODEV; + + chip = kzalloc(sizeof(struct pca9539_chip), GFP_KERNEL); + if (chip == NULL) + return -ENOMEM; + + chip->client = client; + + chip->gpio_start = pdata->gpio_base; + + /* initialize cached registers from their original values. + * we can't share this chip with another i2c master. + */ + ret = pca9539_read_reg(chip, PCA9539_OUTPUT, &chip->reg_output); + if (ret) + goto out_failed; + + ret = pca9539_read_reg(chip, PCA9539_DIRECTION, &chip->reg_direction); + if (ret) + goto out_failed; + + /* set platform specific polarity inversion */ + ret = pca9539_write_reg(chip, PCA9539_INVERT, pdata->invert); + if (ret) + goto out_failed; + + ret = pca9539_init_gpio(chip); + if (ret) + goto out_failed; + + if (pdata->setup) { + ret = pdata->setup(client, chip->gpio_chip.base, + chip->gpio_chip.ngpio, pdata->context); + if (ret < 0) + dev_warn(&client->dev, "setup failed, %d\n", ret); + } + + i2c_set_clientdata(client, chip); + return 0; + +out_failed: + kfree(chip); + return ret; +} + +static int pca9539_remove(struct i2c_client *client) +{ + struct pca9539_platform_data *pdata = client->dev.platform_data; + struct pca9539_chip *chip = i2c_get_clientdata(client); + int ret = 0; + + if (pdata->teardown) { + ret = pdata->teardown(client, chip->gpio_chip.base, + chip->gpio_chip.ngpio, pdata->context); + if (ret < 0) { + dev_err(&client->dev, "%s failed, %d\n", + "teardown", ret); + return ret; + } + } + + ret = gpiochip_remove(&chip->gpio_chip); + if (ret) { + dev_err(&client->dev, "%s failed, %d\n", + "gpiochip_remove()", ret); + return ret; + } + + kfree(chip); + return 0; +} + +static struct i2c_driver pca9539_driver = { + .driver = { + .name = "pca9539", + }, + .probe = pca9539_probe, + .remove = pca9539_remove, +}; + +static int __init pca9539_init(void) +{ + return i2c_add_driver(&pca9539_driver); +} +module_init(pca9539_init); + +static void __exit pca9539_exit(void) +{ + i2c_del_driver(&pca9539_driver); +} +module_exit(pca9539_exit); + +MODULE_AUTHOR("eric miao <eric.miao@marvell.com>"); +MODULE_DESCRIPTION("GPIO expander driver for PCA9539"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/i2c/pca9539.h b/include/linux/i2c/pca9539.h deleted file mode 100644 index 611d84a..0000000 --- a/include/linux/i2c/pca9539.h +++ /dev/null @@ -1,18 +0,0 @@ -/* platform data for the PCA9539 16-bit I/O expander driver */ - -struct pca9539_platform_data { - /* number of the first GPIO */ - unsigned gpio_base; - - /* initial polarity inversion setting */ - uint16_t invert; - - void *context; /* param to setup/teardown */ - - int (*setup)(struct i2c_client *client, - unsigned gpio, unsigned ngpio, - void *context); - int (*teardown)(struct i2c_client *client, - unsigned gpio, unsigned ngpio, - void *context); -}; diff --git a/include/linux/i2c/pca953x.h b/include/linux/i2c/pca953x.h new file mode 100644 index 0000000..611d84a --- /dev/null +++ b/include/linux/i2c/pca953x.h @@ -0,0 +1,18 @@ +/* platform data for the PCA9539 16-bit I/O expander driver */ + +struct pca9539_platform_data { + /* number of the first GPIO */ + unsigned gpio_base; + + /* initial polarity inversion setting */ + uint16_t invert; + + void *context; /* param to setup/teardown */ + + int (*setup)(struct i2c_client *client, + unsigned gpio, unsigned ngpio, + void *context); + int (*teardown)(struct i2c_client *client, + unsigned gpio, unsigned ngpio, + void *context); +}; -- video4linux-list mailing list Unsubscribe mailto:video4linux-list-request@redhat.com?subject=unsubscribe https://www.redhat.com/mailman/listinfo/video4linux-list ^ permalink raw reply related [flat|nested] 11+ messages in thread
[parent not found: <Pine.LNX.4.64.0801312303270.3704-0199iw4Nj15frtckUFj5Ag@public.gmane.org>]
* Re: [PATCH 1/3] Prepare to extend pca9539 to support more chips - rename files [not found] ` <Pine.LNX.4.64.0801312303270.3704-0199iw4Nj15frtckUFj5Ag@public.gmane.org> @ 2008-01-31 23:50 ` David Brownell 0 siblings, 0 replies; 11+ messages in thread From: David Brownell @ 2008-01-31 23:50 UTC (permalink / raw) To: Guennadi Liakhovetski Cc: video4linux-list-H+wXaHxf7aLQT0dZR+AlfA, i2c-GZX6beZjE8VD60Wz+7aTrA On Thursday 31 January 2008, Guennadi Liakhovetski wrote: > Are you expecting your gpiolib, and, respectively, this patch to > be pushed to Linus for 2.6.25 or more likely later? 2.6.25 ... I see no reason to hold these three patches back. In fact I'll probably submit them to Andrew later today. - Dave _______________________________________________ i2c mailing list i2c-GZX6beZjE8VD60Wz+7aTrA@public.gmane.org http://lists.lm-sensors.org/mailman/listinfo/i2c ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2008-02-01 10:57 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-01-31 14:04 [PATCH 1/3] Prepare to extend pca9539 to support more chips - rename files Guennadi Liakhovetski
2008-01-31 14:04 ` [PATCH 3/3] Add support for PCA953[4-8] I2C GPIO extenders to the pca953x driver Guennadi Liakhovetski
[not found] ` <Pine.LNX.4.64.0801311500240.8478-0199iw4Nj15frtckUFj5Ag@public.gmane.org>
2008-01-31 21:20 ` David Brownell
2008-01-31 22:13 ` Guennadi Liakhovetski
[not found] ` <Pine.LNX.4.64.0801312308110.3704-0199iw4Nj15frtckUFj5Ag@public.gmane.org>
2008-01-31 23:35 ` David Brownell
2008-02-01 10:57 ` Guennadi Liakhovetski
[not found] ` <Pine.LNX.4.64.0801311453470.8478-0199iw4Nj15frtckUFj5Ag@public.gmane.org>
2008-01-31 14:04 ` [PATCH 2/3] Second stage extending the pca953x GPIO driver - change Kconfig, "sed" files Guennadi Liakhovetski
[not found] ` <Pine.LNX.4.64.0801311456280.8478-0199iw4Nj15frtckUFj5Ag@public.gmane.org>
2008-01-31 21:25 ` David Brownell
2008-01-31 21:01 ` [PATCH 1/3] Prepare to extend pca9539 to support more chips - rename files David Brownell
2008-01-31 22:06 ` Guennadi Liakhovetski
[not found] ` <Pine.LNX.4.64.0801312303270.3704-0199iw4Nj15frtckUFj5Ag@public.gmane.org>
2008-01-31 23:50 ` David Brownell
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox