Re: [patch 2.6.24-rc6-mm 8/9] gpiolib: pca9539 i2c gpio expander support

2008-01-06 Thread Jean Delvare
On Sat, 5 Jan 2008 11:40:55 -0800, David Brownell wrote:
> From: eric miao <[EMAIL PROTECTED]>
> Subject: [PATCH] gpiolib: support PCA9539 GPIO expander
> 
> This adds a new-style I2C driver with basic support for the sixteen
> bit PCA9539 GPIO expanders.  These chips have multiple registers,
> push-pull output drivers, and (not supported in this patch) pin
> change interrupts.
> 
> Board-specific code must provide "pca9539_platform_data" with each
> chip's "i2c_board_info".  That provides the GPIO numbers to be used
> by that chip, and callbacks for board-specific setup/teardown logic.
> 
> Derived from drivers/i2c/chips/pca9539.c (which has no current known
> users).  This is faster and simpler; it uses 16-bit register access,
> and cache the OUTPUT and DIRECTION registers for fast access
> 
> Signed-off-by: eric miao <[EMAIL PROTECTED]>
> Signed-off-by: David Brownell <[EMAIL PROTECTED]>
> ---
> Incorporates cleanups noted by Jean Delvare.
> 
>  drivers/gpio/Kconfig|   10 +
>  drivers/gpio/Makefile   |1 
>  drivers/gpio/pca9539.c  |  271 
> 
>  include/linux/i2c/pca9539.h |   18 ++
>  4 files changed, 300 insertions(+)

Acked-by: Jean Delvare <[EMAIL PROTECTED]>

-- 
Jean Delvare
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 2.6.24-rc6-mm 8/9] gpiolib: pca9539 i2c gpio expander support

2008-01-05 Thread David Brownell
From: eric miao <[EMAIL PROTECTED]>
Subject: [PATCH] gpiolib: support PCA9539 GPIO expander

This adds a new-style I2C driver with basic support for the sixteen
bit PCA9539 GPIO expanders.  These chips have multiple registers,
push-pull output drivers, and (not supported in this patch) pin
change interrupts.

Board-specific code must provide "pca9539_platform_data" with each
chip's "i2c_board_info".  That provides the GPIO numbers to be used
by that chip, and callbacks for board-specific setup/teardown logic.

Derived from drivers/i2c/chips/pca9539.c (which has no current known
users).  This is faster and simpler; it uses 16-bit register access,
and cache the OUTPUT and DIRECTION registers for fast access

Signed-off-by: eric miao <[EMAIL PROTECTED]>
Signed-off-by: David Brownell <[EMAIL PROTECTED]>
---
Incorporates cleanups noted by Jean Delvare.

 drivers/gpio/Kconfig|   10 +
 drivers/gpio/Makefile   |1 
 drivers/gpio/pca9539.c  |  271 
 include/linux/i2c/pca9539.h |   18 ++
 4 files changed, 300 insertions(+)

--- at91.orig/drivers/gpio/Kconfig  2008-01-05 11:27:12.0 -0800
+++ at91/drivers/gpio/Kconfig   2008-01-05 11:27:12.0 -0800
@@ -27,6 +27,16 @@ config DEBUG_GPIO
 
 comment "I2C GPIO expanders:"
 
+config GPIO_PCA9539
+   tristate "PCA9539 16-bit 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.
+
+ This driver can also be built as a module.  If so, the module
+ will be called pca9539.
+
 config GPIO_PCF857X
tristate "PCF857x, PCA857x, and PCA967x I2C GPIO expanders"
depends on I2C
--- at91.orig/drivers/gpio/Makefile 2008-01-05 11:27:12.0 -0800
+++ at91/drivers/gpio/Makefile  2008-01-05 11:27:12.0 -0800
@@ -1,6 +1,7 @@
 # gpio support: dedicated expander chips, etc
 
 obj-$(CONFIG_GPIO_MCP23S08)+= mcp23s08.o
+obj-$(CONFIG_GPIO_PCA9539) += pca9539.o
 obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o
 
 ifeq ($(CONFIG_DEBUG_GPIO),y)
--- /dev/null   1970-01-01 00:00:00.0 +
+++ at91/drivers/gpio/pca9539.c 2008-01-05 11:32:06.0 -0800
@@ -0,0 +1,271 @@
+/*
+ *  pca9539.c - 16-bit I/O port with interrupt and reset
+ *
+ *  Copyright (C) 2005 Ben Gardner <[EMAIL PROTECTED]>
+ *  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 
+#include 
+#include 
+#include 
+
+#include 
+
+
+#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(>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 = 

Re: [patch 2.6.24-rc6-mm 8/9] gpiolib: pca9539 i2c gpio expander support

2008-01-05 Thread David Brownell
From: eric miao [EMAIL PROTECTED]
Subject: [PATCH] gpiolib: support PCA9539 GPIO expander

This adds a new-style I2C driver with basic support for the sixteen
bit PCA9539 GPIO expanders.  These chips have multiple registers,
push-pull output drivers, and (not supported in this patch) pin
change interrupts.

Board-specific code must provide pca9539_platform_data with each
chip's i2c_board_info.  That provides the GPIO numbers to be used
by that chip, and callbacks for board-specific setup/teardown logic.

Derived from drivers/i2c/chips/pca9539.c (which has no current known
users).  This is faster and simpler; it uses 16-bit register access,
and cache the OUTPUT and DIRECTION registers for fast access

Signed-off-by: eric miao [EMAIL PROTECTED]
Signed-off-by: David Brownell [EMAIL PROTECTED]
---
Incorporates cleanups noted by Jean Delvare.

 drivers/gpio/Kconfig|   10 +
 drivers/gpio/Makefile   |1 
 drivers/gpio/pca9539.c  |  271 
 include/linux/i2c/pca9539.h |   18 ++
 4 files changed, 300 insertions(+)

--- at91.orig/drivers/gpio/Kconfig  2008-01-05 11:27:12.0 -0800
+++ at91/drivers/gpio/Kconfig   2008-01-05 11:27:12.0 -0800
@@ -27,6 +27,16 @@ config DEBUG_GPIO
 
 comment I2C GPIO expanders:
 
+config GPIO_PCA9539
+   tristate PCA9539 16-bit 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.
+
+ This driver can also be built as a module.  If so, the module
+ will be called pca9539.
+
 config GPIO_PCF857X
tristate PCF857x, PCA857x, and PCA967x I2C GPIO expanders
depends on I2C
--- at91.orig/drivers/gpio/Makefile 2008-01-05 11:27:12.0 -0800
+++ at91/drivers/gpio/Makefile  2008-01-05 11:27:12.0 -0800
@@ -1,6 +1,7 @@
 # gpio support: dedicated expander chips, etc
 
 obj-$(CONFIG_GPIO_MCP23S08)+= mcp23s08.o
+obj-$(CONFIG_GPIO_PCA9539) += pca9539.o
 obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o
 
 ifeq ($(CONFIG_DEBUG_GPIO),y)
--- /dev/null   1970-01-01 00:00:00.0 +
+++ at91/drivers/gpio/pca9539.c 2008-01-05 11:32:06.0 -0800
@@ -0,0 +1,271 @@
+/*
+ *  pca9539.c - 16-bit I/O port with interrupt and reset
+ *
+ *  Copyright (C) 2005 Ben Gardner [EMAIL PROTECTED]
+ *  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);
+   

Re: [patch 2.6.24-rc6-mm 8/9] gpiolib: pca9539 i2c gpio expander support

2008-01-03 Thread David Brownell
Le 02 Janvier 2008, Jean Delvare a écrit:
> 
> Hi David, hi Eric,
> 
> Le 29/12/2007, "David Brownell" <[EMAIL PROTECTED]> a écrit:
> >From: eric miao <[EMAIL PROTECTED]>
> >
> >This adds a new-style I2C driver with basic support for the sixteen
> >bit PCA9539 GPIO expanders.
> >
> > ... 
> 
> Random comments:
> 
> >+static int pca9539_gpio_get_value(struct gpio_chip *gc, unsigned off)
> >+{
> >+...
> >+
> >+ret = pca9539_read_reg(chip, PCA9539_INPUT, _val);
> >+if (ret < 0) {
> >+/* NOTE:  diagnostic already omitted; that's the
> >+ * best we can do here.
> >+ */
> >+return 0;
> >+}
> 
> I guess that you really mean "emitted" here, not "omitted"?

Yeah, typo.


> More importantly, I don't agree that it's the best we can do here.
> Maybe it was already discussed before and there's a good reason to not
> report errors from "get" functions at the gpio-core level,

Yes there is.  It's by explicit request.  Expecting drivers to cope
with per-bit errors is at best unrealistic.  This was decided well
over a year ago ... nobody wants to see bit-banging code that spends
more time trying to figure out how to recover from "can't happen"
errors than getting real work done.  (None of the SOC-specific GPIO
interfaces being replaced by this generic one returned errors either.)

That said, with things like I2C there actually *could* be errors;
which are impossible with valid parameters to SOC-level GPIOs.
That might argue for gpio_{get,set}_value_cansleep() calls being
able to return fault codes that would be nonsense on the more
widely used gpio_{get,set}_value() alls.

But such a change would be for a different set of patches.  This
set does not change *any* driver programming interface.  At all.


> >+static int __devinit pca9539_probe(struct i2c_client *client)
> >+{
> >+ (...)
> >+if (pdata->setup) {
> >+ret = pdata->setup(client, chip->gpio_chip.base,
> >+chip->gpio_chip.ngpio, pdata->context);
> >+if (ret < 0)
> >+dev_dbg(>dev, "setup failed, %d\n", ret);
> 
> Should be at least dev_warn() and maybe even dev_err().

It's not treated as an error (i.e. abort the probe); warning
is right.

Hmm, I thought both this issue and the previous one had been
fixed already ... oh, it was the pcf857x driver that fixed that.
Never mind.  ;)


> >+}
> >+ (...)
> >+}
> >+
> >+static int pca9539_remove(struct i2c_client *client)
> >+{
> >+ (...)
> >+if (pdata->teardown) {
> >+ret = pdata->teardown(client, chip->gpio_chip.base,
> >+chip->gpio_chip.ngpio, pdata->context);
> >+if (ret < 0)
> >+dev_dbg(>dev, "teardown failed, %d\n", ret);
> 
> Same thing here.

That was supposed to be dev_err() then "return ret" !


> >+}
> >+
> >+ret = gpiochip_remove(>gpio_chip);
> >+if (ret) {
> >+dev_err(>dev, "failed remove gpio_chip\n");
> 
> This error message could certainly be reworded to sound better. Also, for
> consistency you should include the value of "ret" in the message.

Right.  So, pretty much like the appended.  (Which I'll merge into
refreshed version of this patch.)


--- a/drivers/gpio/pca9539.c
+++ b/drivers/gpio/pca9539.c
@@ -118,7 +118,7 @@ static int pca9539_gpio_get_value(struct
 
ret = pca9539_read_reg(chip, PCA9539_INPUT, _val);
if (ret < 0) {
-   /* NOTE:  diagnostic already omitted; that's the
+   /* NOTE:  diagnostic already emitted; that's the
 * best we can do here.
 */
return 0;
@@ -205,7 +205,7 @@ static int __devinit pca9539_probe(struc
ret = pdata->setup(client, chip->gpio_chip.base,
chip->gpio_chip.ngpio, pdata->context);
if (ret < 0)
-   dev_dbg(>dev, "setup failed, %d\n", ret);
+   dev_warn(>dev, "setup failed, %d\n", ret);
}
 
i2c_set_clientdata(client, chip);
@@ -225,13 +225,17 @@ static int pca9539_remove(struct i2c_cli
if (pdata->teardown) {
ret = pdata->teardown(client, chip->gpio_chip.base,
chip->gpio_chip.ngpio, pdata->context);
-   if (ret < 0)
-   dev_dbg(>dev, "teardown failed, %d\n", ret);
+   if (ret < 0) {
+   dev_err(>dev, "%s failed, %d\n",
+   "teardown", ret);
+   return ret;
+   }
}
 
ret = gpiochip_remove(>gpio_chip);
if (ret) {
-   dev_err(>dev, "failed remove gpio_chip\n");
+   dev_err(>dev, "%s failed, %d\n",
+   "gpiochip_remove()", ret);
return ret;
}
 

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

Re: [patch 2.6.24-rc6-mm 8/9] gpiolib: pca9539 i2c gpio expander support

2008-01-03 Thread David Brownell
Le 02 Janvier 2008, Jean Delvare a écrit:
 
 Hi David, hi Eric,
 
 Le 29/12/2007, David Brownell [EMAIL PROTECTED] a écrit:
 From: eric miao [EMAIL PROTECTED]
 
 This adds a new-style I2C driver with basic support for the sixteen
 bit PCA9539 GPIO expanders.
 
  ... 
 
 Random comments:
 
 +static int pca9539_gpio_get_value(struct gpio_chip *gc, unsigned off)
 +{
 +...
 +
 +ret = pca9539_read_reg(chip, PCA9539_INPUT, reg_val);
 +if (ret  0) {
 +/* NOTE:  diagnostic already omitted; that's the
 + * best we can do here.
 + */
 +return 0;
 +}
 
 I guess that you really mean emitted here, not omitted?

Yeah, typo.


 More importantly, I don't agree that it's the best we can do here.
 Maybe it was already discussed before and there's a good reason to not
 report errors from get functions at the gpio-core level,

Yes there is.  It's by explicit request.  Expecting drivers to cope
with per-bit errors is at best unrealistic.  This was decided well
over a year ago ... nobody wants to see bit-banging code that spends
more time trying to figure out how to recover from can't happen
errors than getting real work done.  (None of the SOC-specific GPIO
interfaces being replaced by this generic one returned errors either.)

That said, with things like I2C there actually *could* be errors;
which are impossible with valid parameters to SOC-level GPIOs.
That might argue for gpio_{get,set}_value_cansleep() calls being
able to return fault codes that would be nonsense on the more
widely used gpio_{get,set}_value() alls.

But such a change would be for a different set of patches.  This
set does not change *any* driver programming interface.  At all.


 +static int __devinit pca9539_probe(struct i2c_client *client)
 +{
 + (...)
 +if (pdata-setup) {
 +ret = pdata-setup(client, chip-gpio_chip.base,
 +chip-gpio_chip.ngpio, pdata-context);
 +if (ret  0)
 +dev_dbg(client-dev, setup failed, %d\n, ret);
 
 Should be at least dev_warn() and maybe even dev_err().

It's not treated as an error (i.e. abort the probe); warning
is right.

Hmm, I thought both this issue and the previous one had been
fixed already ... oh, it was the pcf857x driver that fixed that.
Never mind.  ;)


 +}
 + (...)
 +}
 +
 +static int pca9539_remove(struct i2c_client *client)
 +{
 + (...)
 +if (pdata-teardown) {
 +ret = pdata-teardown(client, chip-gpio_chip.base,
 +chip-gpio_chip.ngpio, pdata-context);
 +if (ret  0)
 +dev_dbg(client-dev, teardown failed, %d\n, ret);
 
 Same thing here.

That was supposed to be dev_err() then return ret !


 +}
 +
 +ret = gpiochip_remove(chip-gpio_chip);
 +if (ret) {
 +dev_err(client-dev, failed remove gpio_chip\n);
 
 This error message could certainly be reworded to sound better. Also, for
 consistency you should include the value of ret in the message.

Right.  So, pretty much like the appended.  (Which I'll merge into
refreshed version of this patch.)


--- a/drivers/gpio/pca9539.c
+++ b/drivers/gpio/pca9539.c
@@ -118,7 +118,7 @@ static int pca9539_gpio_get_value(struct
 
ret = pca9539_read_reg(chip, PCA9539_INPUT, reg_val);
if (ret  0) {
-   /* NOTE:  diagnostic already omitted; that's the
+   /* NOTE:  diagnostic already emitted; that's the
 * best we can do here.
 */
return 0;
@@ -205,7 +205,7 @@ static int __devinit pca9539_probe(struc
ret = pdata-setup(client, chip-gpio_chip.base,
chip-gpio_chip.ngpio, pdata-context);
if (ret  0)
-   dev_dbg(client-dev, setup failed, %d\n, ret);
+   dev_warn(client-dev, setup failed, %d\n, ret);
}
 
i2c_set_clientdata(client, chip);
@@ -225,13 +225,17 @@ static int pca9539_remove(struct i2c_cli
if (pdata-teardown) {
ret = pdata-teardown(client, chip-gpio_chip.base,
chip-gpio_chip.ngpio, pdata-context);
-   if (ret  0)
-   dev_dbg(client-dev, teardown failed, %d\n, ret);
+   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, failed remove gpio_chip\n);
+   dev_err(client-dev, %s failed, %d\n,
+   gpiochip_remove(), ret);
return ret;
}
 

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  

Re: [patch 2.6.24-rc6-mm 8/9] gpiolib: pca9539 i2c gpio expander support

2008-01-02 Thread Jean Delvare

Hi David, hi Eric,

Le 29/12/2007, "David Brownell" <[EMAIL PROTECTED]> a écrit:
>From: eric miao <[EMAIL PROTECTED]>
>
>This adds a new-style I2C driver with basic support for the sixteen
>bit PCA9539 GPIO expanders.  These chips have multiple registers,
>push-pull output drivers, and (not supported by this patch) pin
>change interrupts.
>
>Board-specific code must provide "pca9539_platform_data" with each
>chip's "i2c_board_info".  That provides the GPIO numbers to be used
>by that chip, and callbacks for board-specific setup/teardown logic.
>
>Derived from drivers/i2c/chips/pca9539.c (which has no current known
>users).  This is faster and simpler; it uses 16-bit register access,
>and caches the OUTPUT and DIRECTION registers for fast access.
>
>Signed-off-by: eric miao <[EMAIL PROTECTED]>
>Signed-off-by: David Brownell <[EMAIL PROTECTED]>
>---
> drivers/gpio/Kconfig|   10 +
> drivers/gpio/Makefile   |1
> drivers/gpio/pca9539.c  |  264 ++
> include/linux/i2c/pca9539.h |   18 +++
> 4 files changed, 293 insertions(+)

Random comments:

>+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 omitted; that's the
>+   * best we can do here.
>+   */
>+  return 0;
>+  }

I guess that you really mean "emitted" here, not "omitted"?

More importantly, I don't agree that it's the best we can do here.
Maybe it was already discussed before and there's a good reason to not
report errors from "get" functions at the gpio-core level, but I
can't see it. Whether a read error should be considered as "0" or
"1" (or neither) should be a decision left to the user of the GPIO
chip, rather than to each GPIO driver.

>+
>+  return (reg_val & (1u << off)) ? 1 : 0;
>+}

>+static int __devinit pca9539_probe(struct i2c_client *client)
>+{
>+ (...)
>+  if (pdata->setup) {
>+  ret = pdata->setup(client, chip->gpio_chip.base,
>+  chip->gpio_chip.ngpio, pdata->context);
>+  if (ret < 0)
>+  dev_dbg(>dev, "setup failed, %d\n", ret);

Should be at least dev_warn() and maybe even dev_err().

>+  }
>+ (...)
>+}
>+
>+static int pca9539_remove(struct i2c_client *client)
>+{
>+ (...)
>+  if (pdata->teardown) {
>+  ret = pdata->teardown(client, chip->gpio_chip.base,
>+  chip->gpio_chip.ngpio, pdata->context);
>+  if (ret < 0)
>+  dev_dbg(>dev, "teardown failed, %d\n", ret);

Same thing here.

>+  }
>+
>+  ret = gpiochip_remove(>gpio_chip);
>+  if (ret) {
>+  dev_err(>dev, "failed remove gpio_chip\n");

This error message could certainly be reworded to sound better. Also, for
consistency you should include the value of "ret" in the message.

>+  return ret;
>+  }
>+
>+  kfree(chip);
>+  return 0;
>+}

--
Jean Delvare
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 2.6.24-rc6-mm 8/9] gpiolib: pca9539 i2c gpio expander support

2008-01-02 Thread Jean Delvare

Hi David, hi Eric,

Le 29/12/2007, David Brownell [EMAIL PROTECTED] a écrit:
From: eric miao [EMAIL PROTECTED]

This adds a new-style I2C driver with basic support for the sixteen
bit PCA9539 GPIO expanders.  These chips have multiple registers,
push-pull output drivers, and (not supported by this patch) pin
change interrupts.

Board-specific code must provide pca9539_platform_data with each
chip's i2c_board_info.  That provides the GPIO numbers to be used
by that chip, and callbacks for board-specific setup/teardown logic.

Derived from drivers/i2c/chips/pca9539.c (which has no current known
users).  This is faster and simpler; it uses 16-bit register access,
and caches the OUTPUT and DIRECTION registers for fast access.

Signed-off-by: eric miao [EMAIL PROTECTED]
Signed-off-by: David Brownell [EMAIL PROTECTED]
---
 drivers/gpio/Kconfig|   10 +
 drivers/gpio/Makefile   |1
 drivers/gpio/pca9539.c  |  264 ++
 include/linux/i2c/pca9539.h |   18 +++
 4 files changed, 293 insertions(+)

Random comments:

+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, reg_val);
+  if (ret  0) {
+  /* NOTE:  diagnostic already omitted; that's the
+   * best we can do here.
+   */
+  return 0;
+  }

I guess that you really mean emitted here, not omitted?

More importantly, I don't agree that it's the best we can do here.
Maybe it was already discussed before and there's a good reason to not
report errors from get functions at the gpio-core level, but I
can't see it. Whether a read error should be considered as 0 or
1 (or neither) should be a decision left to the user of the GPIO
chip, rather than to each GPIO driver.

+
+  return (reg_val  (1u  off)) ? 1 : 0;
+}

+static int __devinit pca9539_probe(struct i2c_client *client)
+{
+ (...)
+  if (pdata-setup) {
+  ret = pdata-setup(client, chip-gpio_chip.base,
+  chip-gpio_chip.ngpio, pdata-context);
+  if (ret  0)
+  dev_dbg(client-dev, setup failed, %d\n, ret);

Should be at least dev_warn() and maybe even dev_err().

+  }
+ (...)
+}
+
+static int pca9539_remove(struct i2c_client *client)
+{
+ (...)
+  if (pdata-teardown) {
+  ret = pdata-teardown(client, chip-gpio_chip.base,
+  chip-gpio_chip.ngpio, pdata-context);
+  if (ret  0)
+  dev_dbg(client-dev, teardown failed, %d\n, ret);

Same thing here.

+  }
+
+  ret = gpiochip_remove(chip-gpio_chip);
+  if (ret) {
+  dev_err(client-dev, failed remove gpio_chip\n);

This error message could certainly be reworded to sound better. Also, for
consistency you should include the value of ret in the message.

+  return ret;
+  }
+
+  kfree(chip);
+  return 0;
+}

--
Jean Delvare
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[patch 2.6.24-rc6-mm 8/9] gpiolib: pca9539 i2c gpio expander support

2007-12-28 Thread David Brownell
From: eric miao <[EMAIL PROTECTED]>

This adds a new-style I2C driver with basic support for the sixteen
bit PCA9539 GPIO expanders.  These chips have multiple registers,
push-pull output drivers, and (not supported by this patch) pin
change interrupts.

Board-specific code must provide "pca9539_platform_data" with each
chip's "i2c_board_info".  That provides the GPIO numbers to be used
by that chip, and callbacks for board-specific setup/teardown logic.

Derived from drivers/i2c/chips/pca9539.c (which has no current known
users).  This is faster and simpler; it uses 16-bit register access,
and caches the OUTPUT and DIRECTION registers for fast access.

Signed-off-by: eric miao <[EMAIL PROTECTED]>
Signed-off-by: David Brownell <[EMAIL PROTECTED]>
---
 drivers/gpio/Kconfig|   10 +
 drivers/gpio/Makefile   |1 
 drivers/gpio/pca9539.c  |  264 
 include/linux/i2c/pca9539.h |   18 +++
 4 files changed, 293 insertions(+)

--- at91.orig/drivers/gpio/Kconfig
+++ at91/drivers/gpio/Kconfig
@@ -27,6 +27,16 @@ config DEBUG_GPIO
 
 comment "I2C GPIO expanders:"
 
+config GPIO_PCA9539
+   tristate "PCA9539 16-bit 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.
+
+ This driver can also be built as a module.  If so, the module
+ will be called pca9539.
+
 config GPIO_PCF857X
tristate "PCF857x, PCA857x, and PCA967x I2C GPIO expanders"
depends on I2C
--- at91.orig/drivers/gpio/Makefile
+++ at91/drivers/gpio/Makefile
@@ -1,6 +1,7 @@
 # gpio support: dedicated expander chips, etc
 
 obj-$(CONFIG_GPIO_MCP23S08)+= mcp23s08.o
+obj-$(CONFIG_GPIO_PCA9539) += pca9539.o
 obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o
 
 ifeq ($(CONFIG_DEBUG_GPIO),y)
--- /dev/null
+++ at91/drivers/gpio/pca9539.c
@@ -0,0 +1,264 @@
+/*
+ *  pca9539.c - 16-bit I/O port with interrupt and reset
+ *
+ *  Copyright (C) 2005 Ben Gardner <[EMAIL PROTECTED]>
+ *  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 
+#include 
+#include 
+#include 
+
+#include 
+
+
+#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(>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, 

[patch 2.6.24-rc6-mm 8/9] gpiolib: pca9539 i2c gpio expander support

2007-12-28 Thread David Brownell
From: eric miao [EMAIL PROTECTED]

This adds a new-style I2C driver with basic support for the sixteen
bit PCA9539 GPIO expanders.  These chips have multiple registers,
push-pull output drivers, and (not supported by this patch) pin
change interrupts.

Board-specific code must provide pca9539_platform_data with each
chip's i2c_board_info.  That provides the GPIO numbers to be used
by that chip, and callbacks for board-specific setup/teardown logic.

Derived from drivers/i2c/chips/pca9539.c (which has no current known
users).  This is faster and simpler; it uses 16-bit register access,
and caches the OUTPUT and DIRECTION registers for fast access.

Signed-off-by: eric miao [EMAIL PROTECTED]
Signed-off-by: David Brownell [EMAIL PROTECTED]
---
 drivers/gpio/Kconfig|   10 +
 drivers/gpio/Makefile   |1 
 drivers/gpio/pca9539.c  |  264 
 include/linux/i2c/pca9539.h |   18 +++
 4 files changed, 293 insertions(+)

--- at91.orig/drivers/gpio/Kconfig
+++ at91/drivers/gpio/Kconfig
@@ -27,6 +27,16 @@ config DEBUG_GPIO
 
 comment I2C GPIO expanders:
 
+config GPIO_PCA9539
+   tristate PCA9539 16-bit 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.
+
+ This driver can also be built as a module.  If so, the module
+ will be called pca9539.
+
 config GPIO_PCF857X
tristate PCF857x, PCA857x, and PCA967x I2C GPIO expanders
depends on I2C
--- at91.orig/drivers/gpio/Makefile
+++ at91/drivers/gpio/Makefile
@@ -1,6 +1,7 @@
 # gpio support: dedicated expander chips, etc
 
 obj-$(CONFIG_GPIO_MCP23S08)+= mcp23s08.o
+obj-$(CONFIG_GPIO_PCA9539) += pca9539.o
 obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o
 
 ifeq ($(CONFIG_DEBUG_GPIO),y)
--- /dev/null
+++ at91/drivers/gpio/pca9539.c
@@ -0,0 +1,264 @@
+/*
+ *  pca9539.c - 16-bit I/O port with interrupt and reset
+ *
+ *  Copyright (C) 2005 Ben Gardner [EMAIL PROTECTED]
+ *  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;
+
+