* [RFC PATCH 3/8] Philips PCA9536 4 bit I2C GPIO extender driver [not found] <Pine.LNX.4.64.0801231646090.4932@axis700.grange> @ 2008-01-23 17:41 ` Guennadi Liakhovetski [not found] ` <Pine.LNX.4.64.0801231820060.4932-0199iw4Nj15frtckUFj5Ag@public.gmane.org> 0 siblings, 1 reply; 14+ messages in thread From: Guennadi Liakhovetski @ 2008-01-23 17:41 UTC (permalink / raw) To: video4linux-list; +Cc: i2c This driver will be used by the mt9m001 and the mt9v022 camera drivers, that can use a pca9536 to switch between 8 and 10 bit modes. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@pengutronix.de> --- drivers/i2c/chips/Kconfig | 10 +++ drivers/i2c/chips/Makefile | 1 + drivers/i2c/chips/pca9536.c | 153 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 164 insertions(+), 0 deletions(-) create mode 100644 drivers/i2c/chips/pca9536.c diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig index 2e1c24f..6f492f1 100644 --- a/drivers/i2c/chips/Kconfig +++ b/drivers/i2c/chips/Kconfig @@ -65,6 +65,16 @@ config SENSORS_PCF8574 These devices are hard to detect and rarely found on mainstream hardware. If unsure, say N. +config SENSORS_PCA9536 + tristate "Philips PCA9536 4-bit I/O port" + depends on EXPERIMENTAL + help + If you say yes here you get support for the Philips PCA9539 + 4-bit I/O port. + + This driver can also be built as a module. If so, the module + will be called pca9536. + config SENSORS_PCA9539 tristate "Philips PCA9539 16-bit I/O port" depends on EXPERIMENTAL diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile index ca924e1..e24c582 100644 --- a/drivers/i2c/chips/Makefile +++ b/drivers/i2c/chips/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_DS1682) += ds1682.o obj-$(CONFIG_SENSORS_EEPROM) += eeprom.o obj-$(CONFIG_SENSORS_MAX6875) += max6875.o obj-$(CONFIG_SENSORS_M41T00) += m41t00.o +obj-$(CONFIG_SENSORS_PCA9536) += pca9536.o obj-$(CONFIG_SENSORS_PCA9539) += pca9539.o obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o diff --git a/drivers/i2c/chips/pca9536.c b/drivers/i2c/chips/pca9536.c new file mode 100644 index 0000000..08e5d8b --- /dev/null +++ b/drivers/i2c/chips/pca9536.c @@ -0,0 +1,152 @@ +/* + * Driver for PCA9536 I/O Expander + * + * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/videodev.h> +#include <linux/slab.h> +#include <linux/i2c.h> +#include <linux/hwmon-sysfs.h> + +#include <media/v4l2-common.h> +#include <media/v4l2-chip-ident.h> + +#define PCA9536_INPUT 0 +#define PCA9536_OUTPUT 1 +#define PCA9536_INVERT 2 +#define PCA9536_DIRECTION 3 + +/* following are the sysfs callback functions */ +static ssize_t pca9536_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct sensor_device_attribute *psa = to_sensor_dev_attr(attr); + struct i2c_client *client = to_i2c_client(dev); + + return sprintf(buf, "%d\n", i2c_smbus_read_byte_data(client, + psa->index)); +} + +static ssize_t pca9536_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *psa = to_sensor_dev_attr(attr); + struct i2c_client *client = to_i2c_client(dev); + unsigned long val = simple_strtoul(buf, NULL, 0); + + if (val > 0xff) + return -EINVAL; + + i2c_smbus_write_byte_data(client, psa->index, val); + return count; +} + +int pca9536_set_level(struct i2c_client *client, u8 pin, u8 level) +{ + s32 data; + + if (pin > 3) + return -EINVAL; + + /* Switch to output */ + data = i2c_smbus_read_byte_data(client, PCA9536_DIRECTION); + if (data < 0) + return data; + data = i2c_smbus_write_byte_data(client, PCA9536_DIRECTION, + data & ~(1 << pin)); + if (data < 0) + return data; + + /* Set level */ + data = i2c_smbus_read_byte_data(client, PCA9536_OUTPUT); + if (data < 0) + return data; + if (level) + data |= (1 << pin); + else + data &= ~(1 << pin); + data = i2c_smbus_write_byte_data(client, PCA9536_OUTPUT, data); + + return data; +} +EXPORT_SYMBOL(pca9536_set_level); + +/* Define the device attributes */ + +#define PCA9536_ENTRY_RO(name, reg) \ + static SENSOR_DEVICE_ATTR(name, S_IRUGO, pca9536_show, NULL, reg) + +#define PCA9536_ENTRY_RW(name, reg) \ + static SENSOR_DEVICE_ATTR(name, S_IRUGO | S_IWUSR, pca9536_show, \ + pca9536_store, reg) + +PCA9536_ENTRY_RO(input, PCA9536_INPUT); +PCA9536_ENTRY_RW(output, PCA9536_OUTPUT); +PCA9536_ENTRY_RW(invert, PCA9536_INVERT); +PCA9536_ENTRY_RW(direction, PCA9536_DIRECTION); + +static struct attribute *pca9536_attributes[] = { + &sensor_dev_attr_input.dev_attr.attr, + &sensor_dev_attr_output.dev_attr.attr, + &sensor_dev_attr_invert.dev_attr.attr, + &sensor_dev_attr_direction.dev_attr.attr, + NULL +}; + +static struct attribute_group pca9536_defattr_group = { + .attrs = pca9536_attributes, +}; + +static int pca9536_probe(struct i2c_client *client) +{ + struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + pr_debug("%s: I2C-Adapter doesn't support I2C_FUNC_SMBUS_BYTE\n", __FUNCTION__); + return -EIO; + } + + if (client->dev.platform_data) + /* This chip is going to be used from the kernel */ + *(struct i2c_client **)client->dev.platform_data = client; + + /* Register sysfs hooks */ + return sysfs_create_group(&client->dev.kobj, + &pca9536_defattr_group); +} + +static int pca9536_remove(struct i2c_client *client) +{ + sysfs_remove_group(&client->dev.kobj, &pca9536_defattr_group); + return 0; +} + +static struct i2c_driver pca9536_i2c_driver = { + .driver = { + .name = "pca9536", + }, + .probe = pca9536_probe, + .remove = pca9536_remove, +}; + +static int __init pca9536_mod_init(void) +{ + return i2c_add_driver(&pca9536_i2c_driver); +} + +static void __exit pca9536_mod_exit(void) +{ + i2c_del_driver(&pca9536_i2c_driver); +} + +module_init(pca9536_mod_init); +module_exit(pca9536_mod_exit); + +MODULE_DESCRIPTION("PCA9536 driver"); +MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>"); +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] 14+ messages in thread
[parent not found: <Pine.LNX.4.64.0801231820060.4932-0199iw4Nj15frtckUFj5Ag@public.gmane.org>]
* Re: [RFC PATCH 3/8] Philips PCA9536 4 bit I2C GPIO extender driver [not found] ` <Pine.LNX.4.64.0801231820060.4932-0199iw4Nj15frtckUFj5Ag@public.gmane.org> @ 2008-01-27 21:45 ` Jean Delvare 2008-01-27 22:27 ` [i2c] " Guennadi Liakhovetski [not found] ` <20080127224559.4eed7cea-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org> 0 siblings, 2 replies; 14+ messages in thread From: Jean Delvare @ 2008-01-27 21:45 UTC (permalink / raw) To: Guennadi Liakhovetski Cc: David Brownell, video4linux-list-H+wXaHxf7aLQT0dZR+AlfA, i2c-GZX6beZjE8VD60Wz+7aTrA Hi Guennadi, On Wed, 23 Jan 2008 18:41:39 +0100 (CET), Guennadi Liakhovetski wrote: > This driver will be used by the mt9m001 and the mt9v022 camera drivers, > that can use a pca9536 to switch between 8 and 10 bit modes. > > Signed-off-by: Guennadi Liakhovetski <g.liakhovetski-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org> > --- > drivers/i2c/chips/Kconfig | 10 +++ > drivers/i2c/chips/Makefile | 1 + > drivers/i2c/chips/pca9536.c | 153 +++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 164 insertions(+), 0 deletions(-) > create mode 100644 drivers/i2c/chips/pca9536.c There is a new GPIO subsystem (under driver/gpio), that's where you should add this driver. > > diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig > index 2e1c24f..6f492f1 100644 > --- a/drivers/i2c/chips/Kconfig > +++ b/drivers/i2c/chips/Kconfig > @@ -65,6 +65,16 @@ config SENSORS_PCF8574 > These devices are hard to detect and rarely found on mainstream > hardware. If unsure, say N. > > +config SENSORS_PCA9536 > + tristate "Philips PCA9536 4-bit I/O port" > + depends on EXPERIMENTAL > + help > + If you say yes here you get support for the Philips PCA9539 > + 4-bit I/O port. > + > + This driver can also be built as a module. If so, the module > + will be called pca9536. > + > config SENSORS_PCA9539 > tristate "Philips PCA9539 16-bit I/O port" > depends on EXPERIMENTAL > diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile > index ca924e1..e24c582 100644 > --- a/drivers/i2c/chips/Makefile > +++ b/drivers/i2c/chips/Makefile > @@ -8,6 +8,7 @@ obj-$(CONFIG_DS1682) += ds1682.o > obj-$(CONFIG_SENSORS_EEPROM) += eeprom.o > obj-$(CONFIG_SENSORS_MAX6875) += max6875.o > obj-$(CONFIG_SENSORS_M41T00) += m41t00.o > +obj-$(CONFIG_SENSORS_PCA9536) += pca9536.o > obj-$(CONFIG_SENSORS_PCA9539) += pca9539.o > obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o > obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o > diff --git a/drivers/i2c/chips/pca9536.c b/drivers/i2c/chips/pca9536.c > new file mode 100644 > index 0000000..08e5d8b > --- /dev/null > +++ b/drivers/i2c/chips/pca9536.c > @@ -0,0 +1,152 @@ > +/* > + * Driver for PCA9536 I/O Expander > + * > + * Copyright (C) 2008, Guennadi Liakhovetski <kernel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org> > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + */ > + > +#include <linux/videodev.h> > +#include <linux/slab.h> I don't think you need slab.h. > +#include <linux/i2c.h> > +#include <linux/hwmon-sysfs.h> > + > +#include <media/v4l2-common.h> > +#include <media/v4l2-chip-ident.h> A GPIO driver shouldn't include video-specific header files. > + > +#define PCA9536_INPUT 0 > +#define PCA9536_OUTPUT 1 > +#define PCA9536_INVERT 2 > +#define PCA9536_DIRECTION 3 > + > +/* following are the sysfs callback functions */ > +static ssize_t pca9536_show(struct device *dev, struct device_attribute *attr, > + char *buf) > +{ > + struct sensor_device_attribute *psa = to_sensor_dev_attr(attr); > + struct i2c_client *client = to_i2c_client(dev); > + > + return sprintf(buf, "%d\n", i2c_smbus_read_byte_data(client, > + psa->index)); > +} > + > +static ssize_t pca9536_store(struct device *dev, struct device_attribute *attr, > + const char *buf, size_t count) > +{ > + struct sensor_device_attribute *psa = to_sensor_dev_attr(attr); > + struct i2c_client *client = to_i2c_client(dev); > + unsigned long val = simple_strtoul(buf, NULL, 0); > + > + if (val > 0xff) > + return -EINVAL; > + > + i2c_smbus_write_byte_data(client, psa->index, val); > + return count; > +} > + > +int pca9536_set_level(struct i2c_client *client, u8 pin, u8 level) > +{ > + s32 data; > + > + if (pin > 3) > + return -EINVAL; > + > + /* Switch to output */ > + data = i2c_smbus_read_byte_data(client, PCA9536_DIRECTION); > + if (data < 0) > + return data; > + data = i2c_smbus_write_byte_data(client, PCA9536_DIRECTION, > + data & ~(1 << pin)); > + if (data < 0) > + return data; > + > + /* Set level */ > + data = i2c_smbus_read_byte_data(client, PCA9536_OUTPUT); > + if (data < 0) > + return data; > + if (level) > + data |= (1 << pin); > + else > + data &= ~(1 << pin); > + data = i2c_smbus_write_byte_data(client, PCA9536_OUTPUT, data); > + > + return data; > +} > +EXPORT_SYMBOL(pca9536_set_level); > + > +/* Define the device attributes */ > + > +#define PCA9536_ENTRY_RO(name, reg) \ > + static SENSOR_DEVICE_ATTR(name, S_IRUGO, pca9536_show, NULL, reg) > + > +#define PCA9536_ENTRY_RW(name, reg) \ > + static SENSOR_DEVICE_ATTR(name, S_IRUGO | S_IWUSR, pca9536_show, \ > + pca9536_store, reg) > + > +PCA9536_ENTRY_RO(input, PCA9536_INPUT); > +PCA9536_ENTRY_RW(output, PCA9536_OUTPUT); > +PCA9536_ENTRY_RW(invert, PCA9536_INVERT); > +PCA9536_ENTRY_RW(direction, PCA9536_DIRECTION); > + > +static struct attribute *pca9536_attributes[] = { > + &sensor_dev_attr_input.dev_attr.attr, > + &sensor_dev_attr_output.dev_attr.attr, > + &sensor_dev_attr_invert.dev_attr.attr, > + &sensor_dev_attr_direction.dev_attr.attr, > + NULL > +}; > + > +static struct attribute_group pca9536_defattr_group = { > + .attrs = pca9536_attributes, > +}; I'm not sure what this sysfs interface is good for given the use case of this driver. It might even be dangerous to have, users may damage their hardware? > + > +static int pca9536_probe(struct i2c_client *client) > +{ > + struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); > + > + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { > + pr_debug("%s: I2C-Adapter doesn't support I2C_FUNC_SMBUS_BYTE\n", __FUNCTION__); Please use dev_dbg(). > + return -EIO; > + } > + > + if (client->dev.platform_data) > + /* This chip is going to be used from the kernel */ > + *(struct i2c_client **)client->dev.platform_data = client; This doesn't make any sense to me - what are you doing? > + > + /* Register sysfs hooks */ > + return sysfs_create_group(&client->dev.kobj, > + &pca9536_defattr_group); > +} > + > +static int pca9536_remove(struct i2c_client *client) > +{ > + sysfs_remove_group(&client->dev.kobj, &pca9536_defattr_group); > + return 0; > +} > + > +static struct i2c_driver pca9536_i2c_driver = { > + .driver = { > + .name = "pca9536", > + }, > + .probe = pca9536_probe, > + .remove = pca9536_remove, > +}; > + > +static int __init pca9536_mod_init(void) > +{ > + return i2c_add_driver(&pca9536_i2c_driver); > +} > + > +static void __exit pca9536_mod_exit(void) > +{ > + i2c_del_driver(&pca9536_i2c_driver); > +} > + > +module_init(pca9536_mod_init); > +module_exit(pca9536_mod_exit); > + > +MODULE_DESCRIPTION("PCA9536 driver"); > +MODULE_AUTHOR("Guennadi Liakhovetski <kernel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>"); > +MODULE_LICENSE("GPL"); -- Jean Delvare _______________________________________________ i2c mailing list i2c-GZX6beZjE8VD60Wz+7aTrA@public.gmane.org http://lists.lm-sensors.org/mailman/listinfo/i2c ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [i2c] [RFC PATCH 3/8] Philips PCA9536 4 bit I2C GPIO extender driver 2008-01-27 21:45 ` Jean Delvare @ 2008-01-27 22:27 ` Guennadi Liakhovetski [not found] ` <20080127224559.4eed7cea-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org> 1 sibling, 0 replies; 14+ messages in thread From: Guennadi Liakhovetski @ 2008-01-27 22:27 UTC (permalink / raw) To: Jean Delvare; +Cc: David Brownell, video4linux-list, i2c On Sun, 27 Jan 2008, Jean Delvare wrote: > Hi Guennadi, > > On Wed, 23 Jan 2008 18:41:39 +0100 (CET), Guennadi Liakhovetski wrote: > > This driver will be used by the mt9m001 and the mt9v022 camera drivers, > > that can use a pca9536 to switch between 8 and 10 bit modes. > > > > Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@pengutronix.de> > > --- > > drivers/i2c/chips/Kconfig | 10 +++ > > drivers/i2c/chips/Makefile | 1 + > > drivers/i2c/chips/pca9536.c | 153 +++++++++++++++++++++++++++++++++++++++++++ > > 3 files changed, 164 insertions(+), 0 deletions(-) > > create mode 100644 drivers/i2c/chips/pca9536.c > > There is a new GPIO subsystem (under driver/gpio), that's where you > should add this driver. Right, thanks, will move there, as well as will fix all your clean up suggestions - unneeded headers, dev_dbg, actually, might even remove sysfs attributes - they were there only for debugging. > > + if (client->dev.platform_data) > > + /* This chip is going to be used from the kernel */ > > + *(struct i2c_client **)client->dev.platform_data = client; > > This doesn't make any sense to me - what are you doing? This was my way to call int pca9536_set_level(struct i2c_client *client, u8 pin, u8 level) { ... } EXPORT_SYMBOL(pca9536_set_level); from video drivers. But, if I make it a GPIO driver, I'll get a gpio API too, so, will not have to export a new function, right (haven't looked at gpio API yet)? But, probably, I still will need to somehow pass a handle to this gpio-controller to the video driver. The idea is: in platform file we know, that a specific GPIO controller is attached to a specific camera. So, I do static struct i2c_client *camera_data_bus_switch; static struct soc_camera_link iclink[] = { { .bus_id = 0, /* Must match with the camera ID above */ .extender = &camera_data_bus_switch, }, { .bus_id = 0, /* Must match with the camera ID above */ } }; /* Board I2C devices. */ static struct i2c_board_info __initdata pcm027_i2c_devices[] = { { /* Must initialize before the camera(s) */ I2C_BOARD_INFO("pca9536", 0x41), .type = "pca9536", .platform_data = &camera_data_bus_switch, }, { I2C_BOARD_INFO("mt9v022", 0x48), .type = "mt9v022", .platform_data = &iclink[0], /* With extender */ }, { I2C_BOARD_INFO("mt9m001", 0x5d), .type = "mt9m001", .platform_data = &iclink[0], /* With extender */ }, }; this way I tell, that the pca9536 extender with i2c address 0x41 is used to switch both cameras. And in the pca9536 driver I fill in the camera_data_bus_switch variable, so that cameras can later find and use the switch. Well, I haven't find a better way to do this. 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] 14+ messages in thread
[parent not found: <20080127224559.4eed7cea-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>]
* Re: [RFC PATCH 3/8] Philips PCA9536 4 bit I2C GPIO extender driver [not found] ` <20080127224559.4eed7cea-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org> @ 2008-01-28 6:18 ` David Brownell 2008-01-30 16:48 ` [i2c] [RFC PATCH 3/8] Add PCA9536 4 bit I2C GPIO extender support to the pca9539 GPIO driver Guennadi Liakhovetski 0 siblings, 1 reply; 14+ messages in thread From: David Brownell @ 2008-01-28 6:18 UTC (permalink / raw) To: Guennadi Liakhovetski Cc: video4linux-list-H+wXaHxf7aLQT0dZR+AlfA, i2c-GZX6beZjE8VD60Wz+7aTrA On Sunday 27 January 2008, Jean Delvare wrote: > > There is a new GPIO subsystem (under driver/gpio), that's where you > should add this driver. That should merge soonish into kernel GIT -- Linus is merging up a storm before LCA starts, but Andrew's not sent it yet -- but it's easy to grab from current MM. There's a pca9539 driver there, and ISTR the 9536 is very similar except it has no IRQ support and only has 8-bit registers. You should be able to reuse its platform_data structure. It has a registration callback that should let you establish the linkage to the camera(s) you want to control. I suspect you'll come across one other issue... one potential fix being to add a mechanism matching a NOTE in the gpiolib sources. I think you should consider making one driver that can handle three chips: the 4-bit pca9536 (8 pins) and pca9537 (10 pins -- add irq and reset), plus their 8-bit pca9538 sibling (16 pins -- four more GPIOs, and two address bits). Their register model is *identical* ... all that would mean is understanding that for some chips the high nibble is actually valid. (And eventually, maybe, that some chips support input-changed IRQs that can help avoid synchronous register reads. If the i2c_client doesn't list an IRQ that's of course not an issue.) - Dave _______________________________________________ i2c mailing list i2c-GZX6beZjE8VD60Wz+7aTrA@public.gmane.org http://lists.lm-sensors.org/mailman/listinfo/i2c ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [i2c] [RFC PATCH 3/8] Add PCA9536 4 bit I2C GPIO extender support to the pca9539 GPIO driver 2008-01-28 6:18 ` David Brownell @ 2008-01-30 16:48 ` Guennadi Liakhovetski 2008-01-31 1:31 ` eric miao 0 siblings, 1 reply; 14+ messages in thread From: Guennadi Liakhovetski @ 2008-01-30 16:48 UTC (permalink / raw) To: David Brownell; +Cc: Jean Delvare, video4linux-list, i2c PCA9539 and PCA9536 have identical register layout, and differ only in the number of GPIOs and, respectively, register size. Extend the pca9539 driver to also support PCA9536. The driver can further be extended in the future to also support PCA953[4578] chips. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@pengutronix.de> --- On Sun, 27 Jan 2008, David Brownell wrote: > On Sunday 27 January 2008, Jean Delvare wrote: > > > > There is a new GPIO subsystem (under driver/gpio), that's where you > > should add this driver. > > That should merge soonish into kernel GIT -- Linus is merging up a > storm before LCA starts, but Andrew's not sent it yet -- but it's > easy to grab from current MM. Hope it does, as now my video patches depend on those. > There's a pca9539 driver there, and ISTR the 9536 is very similar > except it has no IRQ support and only has 8-bit registers. You > should be able to reuse its platform_data structure. It has a > registration callback that should let you establish the linkage to > the camera(s) you want to control. I didn't need anything like that. I just used the platform knowledge of the GPIO number. This way the camera driver just obtains the GPIO, requests and uses it. > I suspect you'll come across one other issue... one potential fix > being to add a mechanism matching a NOTE in the gpiolib sources. You mean gpio numbers? See above - platform code knows, that it's GPIO 1 on the extender, that the cameras need. > I think you should consider making one driver that can handle three > chips: the 4-bit pca9536 (8 pins) and pca9537 (10 pins -- add irq and > reset), plus their 8-bit pca9538 sibling (16 pins -- four more GPIOs, > and two address bits). Their register model is *identical* ... all > that would mean is understanding that for some chips the high nibble > is actually valid. (And eventually, maybe, that some chips support > input-changed IRQs that can help avoid synchronous register reads. > If the i2c_client doesn't list an IRQ that's of course not an issue.) I think, there are more than 3. But I'd prefer staying with the two at the moment - others can be added later. And I haven't found in the driver support for IRQ and reset pins, so, no differentiation is made for those either. Note, the patch below uses git-specific "renamed from/to" tags, so, it won't work with GNU patch. But it is easier to review it this way. Thanks Guennadi diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 74fac0f..713c0fe 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -27,15 +27,15 @@ config DEBUG_GPIO comment "I2C GPIO expanders:" -config GPIO_PCA9539 - tristate "PCA9539 16-bit I/O port" +config GPIO_PCA953X + tristate "PCA953X I/O port" 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 PCA9539 16-bit and PCA9536 4-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 470ecd6..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) += pca9539.o +obj-$(CONFIG_GPIO_PCA953X) += pca953x.o obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o diff --git a/drivers/gpio/pca9539.c b/drivers/gpio/pca953x.c similarity index 67% rename from drivers/gpio/pca9539.c rename to drivers/gpio/pca953x.c index 3e85c92..3e9d650 100644 @@ -1,5 +1,5 @@ /* - * pca9539.c - 16-bit I/O port with interrupt and reset + * pca953x.c - I/O port with interrupt and reset * * Copyright (C) 2005 Ben Gardner <bgardner@wabtec.com> * Copyright (C) 2007 Marvell International Ltd. @@ -14,19 +14,42 @@ #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> +enum { + PCA9536, + PCA9539, +}; -#define NR_PCA9539_GPIOS 16 +struct pca953x_desc { + unsigned int gpios; + unsigned int input; + unsigned int output; + unsigned int invert; + unsigned int direction; +}; -#define PCA9539_INPUT 0 -#define PCA9539_OUTPUT 2 -#define PCA9539_INVERT 4 -#define PCA9539_DIRECTION 6 +static const struct pca953x_desc pca953x_descs[] = { + [PCA9536] = { + .gpios = 4, + .input = 0, + .output = 1, + .invert = 2, + .direction = 3, + }, + [PCA9539] = { + .gpios = 16, + .input = 0, + .output = 2, + .invert = 4, + .direction = 6, + }, +}; -struct pca9539_chip { +struct pca953x_chip { + struct pca953x_desc const *desc; unsigned gpio_start; uint16_t reg_output; uint16_t reg_direction; @@ -38,19 +61,32 @@ 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; + int ret; + + if (chip->desc->gpios <= 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 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; - ret = i2c_smbus_read_word_data(chip->client, reg); + if (chip->desc->gpios <= 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; @@ -60,16 +96,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, chip->desc->direction, reg_val); if (ret) return ret; @@ -77,14 +113,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 +128,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, chip->desc->output, reg_val); if (ret) return ret; @@ -100,7 +136,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, chip->desc->direction, reg_val); if (ret) return ret; @@ -108,15 +144,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, chip->desc->input, ®_val); if (ret < 0) { /* NOTE: diagnostic already emitted; that's all we should * do unless gpio_*_value_cansleep() calls become different @@ -128,58 +164,67 @@ 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, chip->desc->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 = chip->desc->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; + int variant; pdata = client->dev.platform_data; if (pdata == NULL) return -ENODEV; - chip = kzalloc(sizeof(struct pca9539_chip), GFP_KERNEL); + if (!strcmp("pca9539", pdata->name)) + variant = PCA9539; + else if (!strcmp("pca9536", pdata->name)) + variant = PCA9536; + else + return -ENODEV; + + chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL); if (chip == NULL) return -ENOMEM; + chip->desc = &pca953x_descs[variant]; chip->client = client; chip->gpio_start = pdata->gpio_base; @@ -187,20 +232,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, chip->desc->output, &chip->reg_output); if (ret) goto out_failed; - ret = pca9539_read_reg(chip, PCA9539_DIRECTION, &chip->reg_direction); + ret = pca953x_read_reg(chip, chip->desc->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, chip->desc->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 +264,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 +291,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@marvell.com>"); -MODULE_DESCRIPTION("GPIO expander driver for PCA9539"); +MODULE_DESCRIPTION("GPIO expander driver for PCA953X"); MODULE_LICENSE("GPL"); diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index f29a502..806b86c 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h @@ -16,6 +16,10 @@ #define ARCH_NR_GPIOS 256 #endif +#ifndef NO_GPIO +#define NO_GPIO ((unsigned int)-1) +#endif + struct seq_file; /** diff --git a/include/linux/i2c/pca9539.h b/include/linux/i2c/pca953x.h similarity index 67% rename from include/linux/i2c/pca9539.h rename to include/linux/i2c/pca953x.h index 611d84a..8977e57 100644 --- a/include/linux/i2c/pca9539.h +++ b/include/linux/i2c/pca953x.h @@ -1,9 +1,12 @@ -/* platform data for the PCA9539 16-bit I/O expander driver */ +/* platform data for the PCA953x I/O expander driver */ -struct pca9539_platform_data { +struct pca953x_platform_data { /* number of the first GPIO */ unsigned gpio_base; + /* chip variant. Currently supported "pca9536" and "pca9539" */ + const char *name; + /* initial polarity inversion setting */ uint16_t invert; -- 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] 14+ messages in thread
* Re: [i2c] [RFC PATCH 3/8] Add PCA9536 4 bit I2C GPIO extender support to the pca9539 GPIO driver 2008-01-30 16:48 ` [i2c] [RFC PATCH 3/8] Add PCA9536 4 bit I2C GPIO extender support to the pca9539 GPIO driver Guennadi Liakhovetski @ 2008-01-31 1:31 ` eric miao [not found] ` <f17812d70801301731n62597f12kc151d01c320e3dec-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 0 siblings, 1 reply; 14+ messages in thread From: eric miao @ 2008-01-31 1:31 UTC (permalink / raw) To: Guennadi Liakhovetski; +Cc: David Brownell, Jean Delvare, video4linux-list, i2c I like this patch, overall looks ok. See my comments below. On Jan 31, 2008 12:48 AM, Guennadi Liakhovetski <g.liakhovetski@pengutronix.de> wrote: > PCA9539 and PCA9536 have identical register layout, and differ only in the > number of GPIOs and, respectively, register size. Extend the pca9539 > driver to also support PCA9536. The driver can further be extended in the > future to also support PCA953[4578] chips. > > Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@pengutronix.de> > > --- > > On Sun, 27 Jan 2008, David Brownell wrote: > > > On Sunday 27 January 2008, Jean Delvare wrote: > > > > > > There is a new GPIO subsystem (under driver/gpio), that's where you > > > should add this driver. > > > > That should merge soonish into kernel GIT -- Linus is merging up a > > storm before LCA starts, but Andrew's not sent it yet -- but it's > > easy to grab from current MM. > > Hope it does, as now my video patches depend on those. > > > There's a pca9539 driver there, and ISTR the 9536 is very similar > > except it has no IRQ support and only has 8-bit registers. You > > should be able to reuse its platform_data structure. It has a > > registration callback that should let you establish the linkage to > > the camera(s) you want to control. > > I didn't need anything like that. I just used the platform knowledge of > the GPIO number. This way the camera driver just obtains the GPIO, > requests and uses it. > > > I suspect you'll come across one other issue... one potential fix > > being to add a mechanism matching a NOTE in the gpiolib sources. > > You mean gpio numbers? See above - platform code knows, that it's GPIO 1 > on the extender, that the cameras need. > > > I think you should consider making one driver that can handle three > > chips: the 4-bit pca9536 (8 pins) and pca9537 (10 pins -- add irq and > > reset), plus their 8-bit pca9538 sibling (16 pins -- four more GPIOs, > > and two address bits). Their register model is *identical* ... all > > that would mean is understanding that for some chips the high nibble > > is actually valid. (And eventually, maybe, that some chips support > > input-changed IRQs that can help avoid synchronous register reads. > > If the i2c_client doesn't list an IRQ that's of course not an issue.) > > I think, there are more than 3. But I'd prefer staying with the two at the > moment - others can be added later. And I haven't found in the driver > support for IRQ and reset pins, so, no differentiation is made for those > either. > > Note, the patch below uses git-specific "renamed from/to" tags, so, it > won't work with GNU patch. But it is easier to review it this way. > > Thanks > Guennadi > > > diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig > index 74fac0f..713c0fe 100644 > --- a/drivers/gpio/Kconfig > +++ b/drivers/gpio/Kconfig > @@ -27,15 +27,15 @@ config DEBUG_GPIO > > comment "I2C GPIO expanders:" > > -config GPIO_PCA9539 > - tristate "PCA9539 16-bit I/O port" > +config GPIO_PCA953X > + tristate "PCA953X I/O port" > 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 PCA9539 16-bit and PCA9536 4-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 470ecd6..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) += pca9539.o > +obj-$(CONFIG_GPIO_PCA953X) += pca953x.o > obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o > diff --git a/drivers/gpio/pca9539.c b/drivers/gpio/pca953x.c > similarity index 67% > rename from drivers/gpio/pca9539.c > rename to drivers/gpio/pca953x.c > index 3e85c92..3e9d650 100644 > @@ -1,5 +1,5 @@ > /* > - * pca9539.c - 16-bit I/O port with interrupt and reset > + * pca953x.c - I/O port with interrupt and reset > * > * Copyright (C) 2005 Ben Gardner <bgardner@wabtec.com> > * Copyright (C) 2007 Marvell International Ltd. > @@ -14,19 +14,42 @@ > #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> > > +enum { > + PCA9536, > + PCA9539, > +}; > > -#define NR_PCA9539_GPIOS 16 > +struct pca953x_desc { > + unsigned int gpios; > + unsigned int input; > + unsigned int output; > + unsigned int invert; > + unsigned int direction; > +}; I guess the register address can be inferred either from the number of GPIOs or a single member field of "shift" may be sufficient. > > -#define PCA9539_INPUT 0 > -#define PCA9539_OUTPUT 2 > -#define PCA9539_INVERT 4 > -#define PCA9539_DIRECTION 6 > +static const struct pca953x_desc pca953x_descs[] = { > + [PCA9536] = { > + .gpios = 4, > + .input = 0, > + .output = 1, > + .invert = 2, > + .direction = 3, > + }, > + [PCA9539] = { > + .gpios = 16, > + .input = 0, > + .output = 2, > + .invert = 4, > + .direction = 6, > + }, > +}; > > -struct pca9539_chip { > +struct pca953x_chip { > + struct pca953x_desc const *desc; > unsigned gpio_start; > uint16_t reg_output; > uint16_t reg_direction; > @@ -38,19 +61,32 @@ 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; > + int ret; > + > + if (chip->desc->gpios <= 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 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; > > - ret = i2c_smbus_read_word_data(chip->client, reg); > + if (chip->desc->gpios <= 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; > @@ -60,16 +96,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, chip->desc->direction, reg_val); > if (ret) > return ret; > > @@ -77,14 +113,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 +128,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, chip->desc->output, reg_val); > if (ret) > return ret; > > @@ -100,7 +136,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, chip->desc->direction, reg_val); > if (ret) > return ret; > > @@ -108,15 +144,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, chip->desc->input, ®_val); > if (ret < 0) { > /* NOTE: diagnostic already emitted; that's all we should > * do unless gpio_*_value_cansleep() calls become different > @@ -128,58 +164,67 @@ 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, chip->desc->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 = chip->desc->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; > + int variant; > > pdata = client->dev.platform_data; > if (pdata == NULL) > return -ENODEV; > > - chip = kzalloc(sizeof(struct pca9539_chip), GFP_KERNEL); > + if (!strcmp("pca9539", pdata->name)) > + variant = PCA9539; > + else if (!strcmp("pca9536", pdata->name)) > + variant = PCA9536; > + else > + return -ENODEV; > + I prefer integer here more than string, for simplicity and efficiency. What about: switch (pdata->model) { case 9536: chip->num_gpio = 8; case 9539: chip->num_gpio = 16; default: warning - not supported. } And maybe the chip->num_gpio can serve as the "shift" to calculate the register offset, thus avoiding the introducing of "pca953x_desc" structure at all. > + chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL); > if (chip == NULL) > return -ENOMEM; > > + chip->desc = &pca953x_descs[variant]; > chip->client = client; > > chip->gpio_start = pdata->gpio_base; > @@ -187,20 +232,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, chip->desc->output, &chip->reg_output); > if (ret) > goto out_failed; > > - ret = pca9539_read_reg(chip, PCA9539_DIRECTION, &chip->reg_direction); > + ret = pca953x_read_reg(chip, chip->desc->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, chip->desc->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 +264,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 +291,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@marvell.com>"); > -MODULE_DESCRIPTION("GPIO expander driver for PCA9539"); > +MODULE_DESCRIPTION("GPIO expander driver for PCA953X"); > MODULE_LICENSE("GPL"); > diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h > index f29a502..806b86c 100644 > --- a/include/asm-generic/gpio.h > +++ b/include/asm-generic/gpio.h > @@ -16,6 +16,10 @@ > #define ARCH_NR_GPIOS 256 > #endif > > +#ifndef NO_GPIO > +#define NO_GPIO ((unsigned int)-1) > +#endif > + I don't understand this. > struct seq_file; > > /** > diff --git a/include/linux/i2c/pca9539.h b/include/linux/i2c/pca953x.h > similarity index 67% > rename from include/linux/i2c/pca9539.h > rename to include/linux/i2c/pca953x.h > index 611d84a..8977e57 100644 > --- a/include/linux/i2c/pca9539.h > +++ b/include/linux/i2c/pca953x.h > @@ -1,9 +1,12 @@ > -/* platform data for the PCA9539 16-bit I/O expander driver */ > +/* platform data for the PCA953x I/O expander driver */ > > -struct pca9539_platform_data { > +struct pca953x_platform_data { > /* number of the first GPIO */ > unsigned gpio_base; > > + /* chip variant. Currently supported "pca9536" and "pca9539" */ > + const char *name; > + > /* initial polarity inversion setting */ > uint16_t invert; > > -- > video4linux-list mailing list > Unsubscribe mailto:video4linux-list-request@redhat.com?subject=unsubscribe > https://www.redhat.com/mailman/listinfo/video4linux-list > -- Cheers - eric -- 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] 14+ messages in thread
[parent not found: <f17812d70801301731n62597f12kc151d01c320e3dec-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>]
* Re: [RFC PATCH 3/8] Add PCA9536 4 bit I2C GPIO extender support to the pca9539 GPIO driver [not found] ` <f17812d70801301731n62597f12kc151d01c320e3dec-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> @ 2008-01-31 4:52 ` David Brownell 2008-01-31 10:13 ` [i2c] " Guennadi Liakhovetski 0 siblings, 1 reply; 14+ messages in thread From: David Brownell @ 2008-01-31 4:52 UTC (permalink / raw) To: eric miao, Guennadi Liakhovetski Cc: video4linux-list-H+wXaHxf7aLQT0dZR+AlfA, i2c-GZX6beZjE8VD60Wz+7aTrA On Wednesday 30 January 2008, eric miao wrote: > I like this patch, overall looks ok. See my comments below. I basically like it, but I'd still like to see some changes. :) I'd split this patch into two parts (feature addition, and renaming), and use simpler chip type handling. Re that latter, in 2.6.26 there will be an i2c_device_id struct: struct i2c_device_id { char name[I2C_NAME_SIZE]; kernel_ulong_t driver_data; /* Data private to the driver */ }; A little planning done now will make it easy to use that scheme. First, don't add a type field to the platform_data; that's what the i2c_client.name is for. Then just map those strings to the number of GPIOs (eventually just use driver_data), and everything else follows from there. > > --- a/drivers/gpio/Kconfig > > +++ b/drivers/gpio/Kconfig > > @@ -27,15 +27,15 @@ config DEBUG_GPIO > > > > comment "I2C GPIO expanders:" > > > > -config GPIO_PCA9539 > > - tristate "PCA9539 16-bit I/O port" > > +config GPIO_PCA953X > > + tristate "PCA953X I/O port" "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 PCA9539 16-bit and PCA9536 4-bit I/O ports. This should IMO list the '38 (8-bit) and '37 (4-bit) parts too. Same register layout as the '36 (4-bit). Otherwise the "x" seems misleading... > > diff --git a/drivers/gpio/pca9539.c b/drivers/gpio/pca953x.c > > similarity index 67% > > rename from drivers/gpio/pca9539.c > > rename to drivers/gpio/pca953x.c I'd prefer to see the new feature and the renaming be separate patches. > > -#define NR_PCA9539_GPIOS 16 > > +struct pca953x_desc { > > + unsigned int gpios; > > + unsigned int input; > > + unsigned int output; > > + unsigned int invert; > > + unsigned int direction; > > +}; > > I guess the register address can be inferred either from the number > of GPIOs or a single member field of "shift" may be sufficient. Yes, inferring that would be simpler. The number of GPIOs is a function of the particular chip, and register offsets are 0/1/2/3 except for the 16-GPIO part where they're twice that. What I'd do is save those four offsets directly in pca953x_chip, initialized near when gpio_chip.ngpio is set up and with no need for a separate "desc" type or table. Eventually there'd be: struct i2c_device_id chips [] = { { "pca9536", 4, }, { "pca9537", 4, }, { "pca9538", 8, }, { "pca9539", 16, }, }; MODULE_DEVICE_TABLE(i2c, chips); Meanwhile, the equivalent of that table can come from a few strcmp() tests in the probe() logic -- like what you already have, except not using a "desc" type. > > -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 = chip->desc->gpios; I'd expect "desc" to vanish, and ngpio to be an input to this function (see below). Then ngpio could be used to choose the values to stuff into chip->{input,output,invert,direction} register offsets. > > + gc->label = "pca953x"; Why not just set gc->label to be chip->client->name? Might as well have /sys/kernel/debug/gpio output be that little bit more useful. And save the space that would otherwise be wasted by that string. :) > > > > 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; > > + int variant; > > > > pdata = client->dev.platform_data; > > if (pdata == NULL) > > return -ENODEV; > > > > - chip = kzalloc(sizeof(struct pca9539_chip), GFP_KERNEL); > > + if (!strcmp("pca9539", pdata->name)) Use client->name instead; there's no need to change pdata. > > + variant = PCA9539; > > + else if (!strcmp("pca9536", pdata->name)) > > + variant = PCA9536; > > + else > > + return -ENODEV; > > + > > I prefer integer here more than string, for simplicity and efficiency. Actually I'd use strings right now, and not change pdata at all. But compare client->name, using that to figure out how many GPIOs. When, later, an i2c_device_id is passed in, the driver can get the number of GPIOs handed to it directly ... and won't need to worry about that ENODEV case. > > --- a/include/asm-generic/gpio.h > > +++ b/include/asm-generic/gpio.h > > @@ -16,6 +16,10 @@ > > #define ARCH_NR_GPIOS 256 > > #endif > > > > +#ifndef NO_GPIO > > +#define NO_GPIO ((unsigned int)-1) > > +#endif > > + > > I don't understand this. Me either; *ANY* negative number is invalid as a GPIO number, not just "-1"... > > --- a/include/linux/i2c/pca9539.h > > +++ b/include/linux/i2c/pca953x.h > > @@ -1,9 +1,12 @@ > > -/* platform data for the PCA9539 16-bit I/O expander driver */ > > +/* platform data for the PCA953x I/O expander driver */ > > > > -struct pca9539_platform_data { > > +struct pca953x_platform_data { > > /* number of the first GPIO */ > > unsigned gpio_base; > > > > + /* chip variant. Currently supported "pca9536" and "pca9539" */ > > + const char *name; > > + That's not needed; i2c_client.name should identify the chip. > > /* initial polarity inversion setting */ > > uint16_t invert; > > > > _______________________________________________ i2c mailing list i2c-GZX6beZjE8VD60Wz+7aTrA@public.gmane.org http://lists.lm-sensors.org/mailman/listinfo/i2c ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [i2c] [RFC PATCH 3/8] Add PCA9536 4 bit I2C GPIO extender support to the pca9539 GPIO driver 2008-01-31 4:52 ` David Brownell @ 2008-01-31 10:13 ` Guennadi Liakhovetski [not found] ` <Pine.LNX.4.64.0801311025210.6494-0199iw4Nj15frtckUFj5Ag@public.gmane.org> 0 siblings, 1 reply; 14+ messages in thread From: Guennadi Liakhovetski @ 2008-01-31 10:13 UTC (permalink / raw) To: David Brownell; +Cc: Jean Delvare, video4linux-list, i2c Thanks for all the comments, I'm going to address them in the next version of the patch. A couple of small clarifications first: On Wed, 30 Jan 2008, David Brownell wrote: > I'd split this patch into two parts (feature addition, and renaming), Would you prefer patch-1: git-mv && sed -e "s/pca9539/pca953x/" patch-2: add pca953[678] or patch-1: git-mv patch-2: sed -e "s/pca9539/pca953x/" && pca953[678] or even patch-1: git-mv patch-2: sed -e "s/pca9539/pca953x/" patch-3: pca953[678] ? > > > 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 PCA9539 16-bit and PCA9536 4-bit I/O ports. > > This should IMO list the '38 (8-bit) and '37 (4-bit) parts too. > Same register layout as the '36 (4-bit). Otherwise the "x" seems > misleading... Ok, I don't want to look through all datasheets ATM, so, I'll just trust you, ok? > > > -#define NR_PCA9539_GPIOS 16 > > > +struct pca953x_desc { > > > + unsigned int gpios; > > > + unsigned int input; > > > + unsigned int output; > > > + unsigned int invert; > > > + unsigned int direction; > > > +}; > > > > I guess the register address can be inferred either from the number > > of GPIOs or a single member field of "shift" may be sufficient. > > Yes, inferring that would be simpler. The number of GPIOs is a > function of the particular chip, and register offsets are 0/1/2/3 > except for the 16-GPIO part where they're twice that. > > What I'd do is save those four offsets directly in pca953x_chip, > initialized near when gpio_chip.ngpio is set up and with no need > for a separate "desc" type or table. Eventually there'd be: > > struct i2c_device_id chips [] = { > { "pca9536", 4, }, > { "pca9537", 4, }, > { "pca9538", 8, }, > { "pca9539", 16, }, > }; > MODULE_DEVICE_TABLE(i2c, chips); > > Meanwhile, the equivalent of that table can come from a few strcmp() > tests in the probe() logic -- like what you already have, except > not using a "desc" type. I introduced the descriptor array, to contain _constant_ chip descriptions, much like your "struct i2c_device_id chips []" array above. So, actually, using my descriptor array is nearer to what it eventually should become, I think. Under 2.6.26 you'd also, probably, just have a "struct i2c_device_id *" member in your pca953x_chip. I can change the descriptor table to look exactly like the i2c_device_id, and then in probe just walk it in a loop, comparing the name? Or would you be getting a pointer to "struct i2c_device_id" in the probe()? > > > -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 = chip->desc->gpios; > > I'd expect "desc" to vanish, and ngpio to be an input to this function > (see below). Then ngpio could be used to choose the values to stuff > into chip->{input,output,invert,direction} register offsets. > > > > > + gc->label = "pca953x"; > > Why not just set gc->label to be chip->client->name? See above. I didn't invent it - just a result of "sed". But I can change it I guess. > > > --- a/include/asm-generic/gpio.h > > > +++ b/include/asm-generic/gpio.h > > > @@ -16,6 +16,10 @@ > > > #define ARCH_NR_GPIOS 256 > > > #endif > > > > > > +#ifndef NO_GPIO > > > +#define NO_GPIO ((unsigned int)-1) > > > +#endif > > > + > > > > I don't understand this. > > Me either; *ANY* negative number is invalid as a GPIO number, > not just "-1"... Ok, this one should rather go into a separate patch. I'd like to have such a macro to check whether the platform is using a GPIO with this specific camera or not. Similar to NO_IRQ. 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] 14+ messages in thread
[parent not found: <Pine.LNX.4.64.0801311025210.6494-0199iw4Nj15frtckUFj5Ag@public.gmane.org>]
* Re: [RFC PATCH 3/8] Add PCA9536 4 bit I2C GPIO extender support to the pca9539 GPIO driver [not found] ` <Pine.LNX.4.64.0801311025210.6494-0199iw4Nj15frtckUFj5Ag@public.gmane.org> @ 2008-01-31 10:48 ` David Brownell 2008-01-31 11:30 ` [i2c] " Guennadi Liakhovetski 2008-01-31 13:30 ` [i2c] " Guennadi Liakhovetski 0 siblings, 2 replies; 14+ messages in thread From: David Brownell @ 2008-01-31 10:48 UTC (permalink / raw) To: Guennadi Liakhovetski Cc: video4linux-list-H+wXaHxf7aLQT0dZR+AlfA, i2c-GZX6beZjE8VD60Wz+7aTrA On Thursday 31 January 2008, Guennadi Liakhovetski wrote: > Thanks for all the comments, I'm going to address them in the next version > of the patch. A couple of small clarifications first: > > On Wed, 30 Jan 2008, David Brownell wrote: > > > I'd split this patch into two parts (feature addition, and renaming), > > Would you prefer > > ... > > patch-1: git-mv > patch-2: sed -e "s/pca9539/pca953x/" > patch-3: pca953[678] > > ? I think that last would be clearest in terms of GIT history and patch reviewability... that's why you listed it, right? :) So that one, given my druthers. > > > > > 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 PCA9539 16-bit and PCA9536 4-bit I/O ports. > > > > This should IMO list the '38 (8-bit) and '37 (4-bit) parts too. > > Same register layout as the '36 (4-bit). Otherwise the "x" seems > > misleading... > > Ok, I don't want to look through all datasheets ATM, so, I'll just trust > you, ok? OK by me. The NXP website makes them easy enough to find, but it's another one of those sites that tries to be too clever by overusing JavaScript. > > What I'd do is save those four offsets directly in pca953x_chip, > > initialized near when gpio_chip.ngpio is set up and with no need > > for a separate "desc" type or table. Eventually there'd be: > > > > struct i2c_device_id chips [] = { > > { "pca9536", 4, }, > > { "pca9537", 4, }, > > { "pca9538", 8, }, > > { "pca9539", 16, }, > > }; > > MODULE_DEVICE_TABLE(i2c, chips); > > > > Meanwhile, the equivalent of that table can come from a few strcmp() > > tests in the probe() logic -- like what you already have, except > > not using a "desc" type. > > I introduced the descriptor array, to contain _constant_ chip > descriptions, much like your "struct i2c_device_id chips []" array above. > So, actually, using my descriptor array is nearer to what it eventually > should become, I think. Under 2.6.26 you'd also, probably, just have a > "struct i2c_device_id *" member in your pca953x_chip. Well, I was also pointing out that all you need is the number of GPIOs; no need to save any ID struct at all. These chips are VERY similar. > I can change the > descriptor table to look exactly like the i2c_device_id, and then in probe > just walk it in a loop, comparing the name? Or would you be getting a > pointer to "struct i2c_device_id" in the probe()? The probe() would get handed the ID, not unlike how USB or PCI work: http://marc.info/?l=i2c&m=120091221712826&w=2 > > > > +#ifndef NO_GPIO > > > > +#define NO_GPIO ((unsigned int)-1) > > > > +#endif > > > > + > > > > > > I don't understand this. > > > > Me either; *ANY* negative number is invalid as a GPIO number, > > not just "-1"... > > Ok, this one should rather go into a separate patch. I'd like to have such > a macro to check whether the platform is using a GPIO with this specific > camera or not. Similar to NO_IRQ. Then maybe there should be an is_valid_gpio() predicate. Anything not between 0..MAX_INT would fail. And there should be a Documentation/gpio.txt update to match. - Dave _______________________________________________ i2c mailing list i2c-GZX6beZjE8VD60Wz+7aTrA@public.gmane.org http://lists.lm-sensors.org/mailman/listinfo/i2c ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [i2c] [RFC PATCH 3/8] Add PCA9536 4 bit I2C GPIO extender support to the pca9539 GPIO driver 2008-01-31 10:48 ` David Brownell @ 2008-01-31 11:30 ` Guennadi Liakhovetski [not found] ` <Pine.LNX.4.64.0801311204280.6494-0199iw4Nj15frtckUFj5Ag@public.gmane.org> 2008-01-31 13:30 ` [i2c] " Guennadi Liakhovetski 1 sibling, 1 reply; 14+ messages in thread From: Guennadi Liakhovetski @ 2008-01-31 11:30 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: > > patch-1: git-mv > > patch-2: sed -e "s/pca9539/pca953x/" > > patch-3: pca953[678] > > > > ? > > I think that last would be clearest in terms of GIT history > and patch reviewability... that's why you listed it, right? :) > So that one, given my druthers. Was my preference too. > > > > > 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 PCA9539 16-bit and PCA9536 4-bit I/O ports. > > > > > > This should IMO list the '38 (8-bit) and '37 (4-bit) parts too. > > > Same register layout as the '36 (4-bit). Otherwise the "x" seems > > > misleading... > > > > Ok, I don't want to look through all datasheets ATM, so, I'll just trust > > you, ok? > > OK by me. The NXP website makes them easy enough to find, but > it's another one of those sites that tries to be too clever by > overusing JavaScript. I'm actually adding 9534 (8-bit) and 9535 (16-bit) too atm, if you don't mind:-) > > > What I'd do is save those four offsets directly in pca953x_chip, > > > initialized near when gpio_chip.ngpio is set up and with no need > > > for a separate "desc" type or table. Eventually there'd be: > > > > > > struct i2c_device_id chips [] = { > > > { "pca9536", 4, }, > > > { "pca9537", 4, }, > > > { "pca9538", 8, }, > > > { "pca9539", 16, }, > > > }; > > > MODULE_DEVICE_TABLE(i2c, chips); > > > > > > Meanwhile, the equivalent of that table can come from a few strcmp() > > > tests in the probe() logic -- like what you already have, except > > > not using a "desc" type. > > > > I introduced the descriptor array, to contain _constant_ chip > > descriptions, much like your "struct i2c_device_id chips []" array above. > > So, actually, using my descriptor array is nearer to what it eventually > > should become, I think. Under 2.6.26 you'd also, probably, just have a > > "struct i2c_device_id *" member in your pca953x_chip. > > Well, I was also pointing out that all you need is the number of GPIOs; > no need to save any ID struct at all. These chips are VERY similar. Ok, agreed, let's remove it then. For now I just use an array of structs similar to i2c_device_id only to avoid a long sequence of strcmp calls in probe() and compare the name in a loop. Is this alright? > > > > > +#ifndef NO_GPIO > > > > > +#define NO_GPIO ((unsigned int)-1) > > > > > +#endif > > > > > + > > > > > > > > I don't understand this. > > > > > > Me either; *ANY* negative number is invalid as a GPIO number, > > > not just "-1"... > > > > Ok, this one should rather go into a separate patch. I'd like to have such > > a macro to check whether the platform is using a GPIO with this specific > > camera or not. Similar to NO_IRQ. > > Then maybe there should be an is_valid_gpio() predicate. > Anything not between 0..MAX_INT would fail. And there > should be a Documentation/gpio.txt update to match. Good, will do that. 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] 14+ messages in thread
[parent not found: <Pine.LNX.4.64.0801311204280.6494-0199iw4Nj15frtckUFj5Ag@public.gmane.org>]
* Re: [RFC PATCH 3/8] Add PCA9536 4 bit I2C GPIO extender support to the pca9539 GPIO driver [not found] ` <Pine.LNX.4.64.0801311204280.6494-0199iw4Nj15frtckUFj5Ag@public.gmane.org> @ 2008-01-31 11:46 ` David Brownell 2008-01-31 11:49 ` David Brownell 1 sibling, 0 replies; 14+ messages in thread From: David Brownell @ 2008-01-31 11:46 UTC (permalink / raw) To: Guennadi Liakhovetski Cc: video4linux-list-H+wXaHxf7aLQT0dZR+AlfA, i2c-GZX6beZjE8VD60Wz+7aTrA On Thursday 31 January 2008, Guennadi Liakhovetski wrote: > > > > > This should IMO list the '38 (8-bit) and '37 (4-bit) parts too. > > > > Same register layout as the '36 (4-bit). Otherwise the "x" seems > > > > misleading... > > > > > > Ok, I don't want to look through all datasheets ATM, so, I'll just trust > > > you, ok? > > > > OK by me. The NXP website makes them easy enough to find, but > > it's another one of those sites that tries to be too clever by > > overusing JavaScript. > > I'm actually adding 9534 (8-bit) and 9535 (16-bit) too atm, if you don't > mind:-) Do they have the same register interfaces? I looked at them a long time ago, and don't recall. If they have the same interface, then more power to you! _______________________________________________ i2c mailing list i2c-GZX6beZjE8VD60Wz+7aTrA@public.gmane.org http://lists.lm-sensors.org/mailman/listinfo/i2c ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH 3/8] Add PCA9536 4 bit I2C GPIO extender support to the pca9539 GPIO driver [not found] ` <Pine.LNX.4.64.0801311204280.6494-0199iw4Nj15frtckUFj5Ag@public.gmane.org> 2008-01-31 11:46 ` David Brownell @ 2008-01-31 11:49 ` David Brownell 1 sibling, 0 replies; 14+ messages in thread From: David Brownell @ 2008-01-31 11:49 UTC (permalink / raw) To: Guennadi Liakhovetski Cc: video4linux-list-H+wXaHxf7aLQT0dZR+AlfA, i2c-GZX6beZjE8VD60Wz+7aTrA On Thursday 31 January 2008, Guennadi Liakhovetski wrote: > > > > So, actually, using my descriptor array is nearer to what it eventually > > > should become, I think. Under 2.6.26 you'd also, probably, just have a > > > "struct i2c_device_id *" member in your pca953x_chip. > > > > Well, I was also pointing out that all you need is the number of GPIOs; > > no need to save any ID struct at all. These chips are VERY similar. > > Ok, agreed, let's remove it then. For now I just use an array of structs > similar to i2c_device_id only to avoid a long sequence of strcmp calls in > probe() and compare the name in a loop. Is this alright? Sure; it's your call on most such details, I just wanted clean patches. _______________________________________________ i2c mailing list i2c-GZX6beZjE8VD60Wz+7aTrA@public.gmane.org http://lists.lm-sensors.org/mailman/listinfo/i2c ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [i2c] [RFC PATCH 3/8] Add PCA9536 4 bit I2C GPIO extender support to the pca9539 GPIO driver 2008-01-31 10:48 ` David Brownell 2008-01-31 11:30 ` [i2c] " Guennadi Liakhovetski @ 2008-01-31 13:30 ` Guennadi Liakhovetski [not found] ` <Pine.LNX.4.64.0801311425300.6494-0199iw4Nj15frtckUFj5Ag@public.gmane.org> 1 sibling, 1 reply; 14+ messages in thread From: Guennadi Liakhovetski @ 2008-01-31 13:30 UTC (permalink / raw) To: David Brownell; +Cc: Jean Delvare, video4linux-list, i2c On Thu, 31 Jan 2008, David Brownell wrote: > > > > > +#ifndef NO_GPIO > > > > > +#define NO_GPIO ((unsigned int)-1) > > > > > +#endif > > > > > + > > > > > > > > I don't understand this. > > > > > > Me either; *ANY* negative number is invalid as a GPIO number, > > > not just "-1"... > > > > Ok, this one should rather go into a separate patch. I'd like to have such > > a macro to check whether the platform is using a GPIO with this specific > > camera or not. Similar to NO_IRQ. > > Then maybe there should be an is_valid_gpio() predicate. > Anything not between 0..MAX_INT would fail. And there > should be a Documentation/gpio.txt update to match. hm, but if you deliberately want an invalid gpio number? 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] 14+ messages in thread
[parent not found: <Pine.LNX.4.64.0801311425300.6494-0199iw4Nj15frtckUFj5Ag@public.gmane.org>]
* Re: [RFC PATCH 3/8] Add PCA9536 4 bit I2C GPIO extender support to the pca9539 GPIO driver [not found] ` <Pine.LNX.4.64.0801311425300.6494-0199iw4Nj15frtckUFj5Ag@public.gmane.org> @ 2008-01-31 23:56 ` David Brownell 0 siblings, 0 replies; 14+ messages in thread From: David Brownell @ 2008-01-31 23:56 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: > > > > > > > +#ifndef NO_GPIO > > > > > > +#define NO_GPIO ((unsigned int)-1) > > > > > > +#endif > > > > > > + > > > > > > > > > > I don't understand this. > > > > > > > > Me either; *ANY* negative number is invalid as a GPIO number, > > > > not just "-1"... > > > > > > Ok, this one should rather go into a separate patch. I'd like to have such > > > a macro to check whether the platform is using a GPIO with this specific > > > camera or not. Similar to NO_IRQ. > > > > Then maybe there should be an is_valid_gpio() predicate. > > Anything not between 0..MAX_INT would fail. And there > > should be a Documentation/gpio.txt update to match. > > hm, but if you deliberately want an invalid gpio number? Any negative number suffices -- like "-EINVAL". But that's a separate problem from the one you said you wanted to solve... - Dave _______________________________________________ i2c mailing list i2c-GZX6beZjE8VD60Wz+7aTrA@public.gmane.org http://lists.lm-sensors.org/mailman/listinfo/i2c ^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2008-01-31 23:56 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <Pine.LNX.4.64.0801231646090.4932@axis700.grange>
2008-01-23 17:41 ` [RFC PATCH 3/8] Philips PCA9536 4 bit I2C GPIO extender driver Guennadi Liakhovetski
[not found] ` <Pine.LNX.4.64.0801231820060.4932-0199iw4Nj15frtckUFj5Ag@public.gmane.org>
2008-01-27 21:45 ` Jean Delvare
2008-01-27 22:27 ` [i2c] " Guennadi Liakhovetski
[not found] ` <20080127224559.4eed7cea-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
2008-01-28 6:18 ` David Brownell
2008-01-30 16:48 ` [i2c] [RFC PATCH 3/8] Add PCA9536 4 bit I2C GPIO extender support to the pca9539 GPIO driver Guennadi Liakhovetski
2008-01-31 1:31 ` eric miao
[not found] ` <f17812d70801301731n62597f12kc151d01c320e3dec-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2008-01-31 4:52 ` David Brownell
2008-01-31 10:13 ` [i2c] " Guennadi Liakhovetski
[not found] ` <Pine.LNX.4.64.0801311025210.6494-0199iw4Nj15frtckUFj5Ag@public.gmane.org>
2008-01-31 10:48 ` David Brownell
2008-01-31 11:30 ` [i2c] " Guennadi Liakhovetski
[not found] ` <Pine.LNX.4.64.0801311204280.6494-0199iw4Nj15frtckUFj5Ag@public.gmane.org>
2008-01-31 11:46 ` David Brownell
2008-01-31 11:49 ` David Brownell
2008-01-31 13:30 ` [i2c] " Guennadi Liakhovetski
[not found] ` <Pine.LNX.4.64.0801311425300.6494-0199iw4Nj15frtckUFj5Ag@public.gmane.org>
2008-01-31 23:56 ` David Brownell
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox