]> git.karo-electronics.de Git - karo-tx-uboot.git/commitdiff
pca953x: support 16-pin devices
authorChris Packham <judge.packham@gmail.com>
Sun, 19 Dec 2010 10:12:13 +0000 (10:12 +0000)
committerHeiko Schocher <hs@denx.de>
Mon, 10 Jan 2011 06:53:00 +0000 (07:53 +0100)
This adds support for for the PCA9535/PCA9539 family of gpio devices which
have 16 output pins.

To let the driver know which devices are 16-pin it is necessary to define
CONFIG_SYS_I2C_PCA953X_WIDTH in your board config file. This is used to
create an array of {chip, ngpio} tuples that are used to determine the
width of a particular chip. For backwards compatibility it is assumed that
any chip not defined in CONFIG_SYS_I2C_PCA953X_WIDTH has 8 pins.

Acked-by: Peter Tyser <ptyser@xes-inc.com>
Tested-by: Peter Tyser <ptyser@xes-inc.com>
Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz>
README
drivers/gpio/pca953x.c

diff --git a/README b/README
index 68f5fb09180ec39b4f87306a75e9902347e48cec..831c5af15c302e9cf63cf6bf2af3f4257c726503 100644 (file)
--- a/README
+++ b/README
@@ -746,6 +746,10 @@ The following options need to be configured:
                CONFIG_PCA953X          - use NXP's PCA953X series I2C GPIO
                CONFIG_PCA953X_INFO     - enable pca953x info command
 
                CONFIG_PCA953X          - use NXP's PCA953X series I2C GPIO
                CONFIG_PCA953X_INFO     - enable pca953x info command
 
+               The CONFIG_SYS_I2C_PCA953X_WIDTH option specifies a list of
+               chip-ngpio pairs that tell the PCA953X driver the number of
+               pins supported by a particular chip.
+
                Note that if the GPIO device uses I2C, then the I2C interface
                must also be configured. See I2C Support, below.
 
                Note that if the GPIO device uses I2C, then the I2C interface
                must also be configured. See I2C Support, below.
 
index 6e82bd66afbd0eca41b9368b5641b8a73bf39f42..359fdeea23246b8285a5382b50b5e8885bd826af 100644 (file)
@@ -17,8 +17,8 @@
  */
 
 /*
  */
 
 /*
- * Driver for NXP's 4 and 8 bit I2C gpio expanders (eg pca9537, pca9557, etc)
- * TODO: support additional devices with more than 8-bits GPIO
+ * Driver for NXP's 4, 8 and 16 bit I2C gpio expanders (eg pca9537, pca9557,
+ * pca9539, etc)
  */
 
 #include <common.h>
  */
 
 #include <common.h>
@@ -38,20 +38,81 @@ enum {
        PCA953X_CMD_INVERT,
 };
 
        PCA953X_CMD_INVERT,
 };
 
+#ifdef CONFIG_SYS_I2C_PCA953X_WIDTH
+struct pca953x_chip_ngpio {
+       uint8_t chip;
+       uint8_t ngpio;
+};
+
+static struct pca953x_chip_ngpio pca953x_chip_ngpios[] =
+    CONFIG_SYS_I2C_PCA953X_WIDTH;
+
+#define NUM_CHIP_GPIOS (sizeof(pca953x_chip_ngpios) / \
+                       sizeof(struct pca953x_chip_ngpio))
+
+/*
+ * Determine the number of GPIO pins supported. If we don't know we assume
+ * 8 pins.
+ */
+static int pca953x_ngpio(uint8_t chip)
+{
+       int i;
+
+       for (i = 0; i < NUM_CHIP_GPIOS; i++)
+               if (pca953x_chip_ngpios[i].chip == chip)
+                       return pca953x_chip_ngpios[i].ngpio;
+
+       return 8;
+}
+#else
+static int pca953x_ngpio(uint8_t chip)
+{
+       return 8;
+}
+#endif
+
 /*
  * Modify masked bits in register
  */
 static int pca953x_reg_write(uint8_t chip, uint addr, uint mask, uint data)
 {
 /*
  * Modify masked bits in register
  */
 static int pca953x_reg_write(uint8_t chip, uint addr, uint mask, uint data)
 {
-       uint8_t val;
+       uint8_t valb;
+       uint16_t valw;
 
 
-       if (i2c_read(chip, addr, 1, &val, 1))
-               return -1;
+       if (pca953x_ngpio(chip) <= 8) {
+               if (i2c_read(chip, addr, 1, &valb, 1))
+                       return -1;
+
+               valb &= ~mask;
+               valb |= data;
+
+               return i2c_write(chip, addr, 1, &valb, 1);
+       } else {
+               if (i2c_read(chip, addr << 1, 1, (u8*)&valw, 2))
+                       return -1;
 
 
-       val &= ~mask;
-       val |= data;
+               valw &= ~mask;
+               valw |= data;
 
 
-       return i2c_write(chip, addr, 1, &val, 1);
+               return i2c_write(chip, addr << 1, 1, (u8*)&valw, 2);
+       }
+}
+
+static int pca953x_reg_read(uint8_t chip, uint addr, uint *data)
+{
+       uint8_t valb;
+       uint16_t valw;
+
+       if (pca953x_ngpio(chip) <= 8) {
+               if (i2c_read(chip, addr, 1, &valb, 1))
+                       return -1;
+               *data = (int)valb;
+       } else {
+               if (i2c_read(chip, addr << 1, 1, (u8*)&valw, 2))
+                       return -1;
+               *data = (int)valw;
+       }
+       return 0;
 }
 
 /*
 }
 
 /*
@@ -86,9 +147,9 @@ int pca953x_set_dir(uint8_t chip, uint mask, uint data)
  */
 int pca953x_get_val(uint8_t chip)
 {
  */
 int pca953x_get_val(uint8_t chip)
 {
-       uint8_t val;
+       uint val;
 
 
-       if (i2c_read(chip, 0, 1, &val, 1))
+       if (pca953x_reg_read(chip, PCA953X_IN, &val) < 0)
                return -1;
 
        return (int)val;
                return -1;
 
        return (int)val;
@@ -102,37 +163,44 @@ int pca953x_get_val(uint8_t chip)
 static int pca953x_info(uint8_t chip)
 {
        int i;
 static int pca953x_info(uint8_t chip)
 {
        int i;
-       uint8_t data;
+       uint data;
+       int nr_gpio = pca953x_ngpio(chip);
+       int msb = nr_gpio - 1;
 
 
-       printf("pca953x@ 0x%x:\n\n", chip);
-       printf("gpio pins: 76543210\n");
-       printf("-------------------\n");
+       printf("pca953x@ 0x%x (%d pins):\n\n", chip, nr_gpio);
+       printf("gpio pins: ");
+       for (i = msb; i >= 0; i--)
+               printf("%x", i);
+       printf("\n");
+       for (i = 11 + nr_gpio; i > 0; i--)
+               printf("-");
+       printf("\n");
 
 
-       if (i2c_read(chip, PCA953X_CONF, 1, &data, 1))
+       if (pca953x_reg_read(chip, PCA953X_CONF, &data) < 0)
                return -1;
        printf("conf:      ");
                return -1;
        printf("conf:      ");
-       for (i = 7; i >= 0; i--)
+       for (i = msb; i >= 0; i--)
                printf("%c", data & (1 << i) ? 'i' : 'o');
        printf("\n");
 
                printf("%c", data & (1 << i) ? 'i' : 'o');
        printf("\n");
 
-       if (i2c_read(chip, PCA953X_POL, 1, &data, 1))
+       if (pca953x_reg_read(chip, PCA953X_POL, &data) < 0)
                return -1;
        printf("invert:    ");
                return -1;
        printf("invert:    ");
-       for (i = 7; i >= 0; i--)
+       for (i = msb; i >= 0; i--)
                printf("%c", data & (1 << i) ? '1' : '0');
        printf("\n");
 
                printf("%c", data & (1 << i) ? '1' : '0');
        printf("\n");
 
-       if (i2c_read(chip, PCA953X_IN, 1, &data, 1))
+       if (pca953x_reg_read(chip, PCA953X_IN, &data) < 0)
                return -1;
        printf("input:     ");
                return -1;
        printf("input:     ");
-       for (i = 7; i >= 0; i--)
+       for (i = msb; i >= 0; i--)
                printf("%c", data & (1 << i) ? '1' : '0');
        printf("\n");
 
                printf("%c", data & (1 << i) ? '1' : '0');
        printf("\n");
 
-       if (i2c_read(chip, PCA953X_OUT, 1, &data, 1))
+       if (pca953x_reg_read(chip, PCA953X_OUT, &data) < 0)
                return -1;
        printf("output:    ");
                return -1;
        printf("output:    ");
-       for (i = 7; i >= 0; i--)
+       for (i = msb; i >= 0; i--)
                printf("%c", data & (1 << i) ? '1' : '0');
        printf("\n");
 
                printf("%c", data & (1 << i) ? '1' : '0');
        printf("\n");