]> err.no Git - linux-2.6/blobdiff - drivers/gpio/pca953x.c
gpio: pca953x driver handles pca9554 too
[linux-2.6] / drivers / gpio / pca953x.c
index ef1fe24bcbafbd035d05f10f23f4bfb784e234b5..7e40e8a55edf247968690de9cb5348969df5c75b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  pca953x.c - 16-bit I/O port with interrupt and reset
+ *  pca953x.c - 4/8/16 bit I/O ports
  *
  *  Copyright (C) 2005 Ben Gardner <bgardner@wabtec.com>
  *  Copyright (C) 2007 Marvell International Ltd.
 
 #include <asm/gpio.h>
 
-
-#define NR_PCA953X_GPIOS       16
-
-#define PCA953X_INPUT          0
-#define PCA953X_OUTPUT         2
-#define PCA953X_INVERT         4
-#define PCA953X_DIRECTION      6
+#define PCA953X_INPUT          0
+#define PCA953X_OUTPUT         1
+#define PCA953X_INVERT         2
+#define PCA953X_DIRECTION      3
+
+static const struct i2c_device_id pca953x_id[] = {
+       { "pca9534", 8, },
+       { "pca9535", 16, },
+       { "pca9536", 4, },
+       { "pca9537", 4, },
+       { "pca9538", 8, },
+       { "pca9539", 16, },
+       { "pca9554", 8, },
+       { "pca9555", 16, },
+       { "pca9557", 8, },
+       /* REVISIT several pca955x parts should work here too */
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, pca953x_id);
 
 struct pca953x_chip {
        unsigned gpio_start;
@@ -40,17 +52,30 @@ struct pca953x_chip {
  */
 static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val)
 {
-       if (i2c_smbus_write_word_data(chip->client, reg, val) < 0)
-               return -EIO;
+       int ret;
+
+       if (chip->gpio_chip.ngpio <= 8)
+               ret = i2c_smbus_write_byte_data(chip->client, reg, val);
        else
-               return 0;
+               ret = i2c_smbus_write_word_data(chip->client, reg << 1, val);
+
+       if (ret < 0) {
+               dev_err(&chip->client->dev, "failed writing register\n");
+               return -EIO;
+       }
+
+       return 0;
 }
 
 static int pca953x_read_reg(struct pca953x_chip *chip, int reg, uint16_t *val)
 {
        int ret;
 
-       ret = i2c_smbus_read_word_data(chip->client, reg);
+       if (chip->gpio_chip.ngpio <= 8)
+               ret = i2c_smbus_read_byte_data(chip->client, reg);
+       else
+               ret = i2c_smbus_read_word_data(chip->client, reg << 1);
+
        if (ret < 0) {
                dev_err(&chip->client->dev, "failed reading register\n");
                return -EIO;
@@ -148,7 +173,7 @@ static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
        chip->reg_output = reg_val;
 }
 
-static int pca953x_init_gpio(struct pca953x_chip *chip)
+static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
 {
        struct gpio_chip *gc;
 
@@ -158,15 +183,16 @@ static int pca953x_init_gpio(struct pca953x_chip *chip)
        gc->direction_output = pca953x_gpio_direction_output;
        gc->get = pca953x_gpio_get_value;
        gc->set = pca953x_gpio_set_value;
+       gc->can_sleep = 1;
 
        gc->base = chip->gpio_start;
-       gc->ngpio = NR_PCA953X_GPIOS;
-       gc->label = "pca953x";
-
-       return gpiochip_add(gc);
+       gc->ngpio = gpios;
+       gc->label = chip->client->name;
+       gc->owner = THIS_MODULE;
 }
 
-static int __devinit pca953x_probe(struct i2c_client *client)
+static int __devinit pca953x_probe(struct i2c_client *client,
+                                  const struct i2c_device_id *id)
 {
        struct pca953x_platform_data *pdata;
        struct pca953x_chip *chip;
@@ -187,6 +213,8 @@ static int __devinit pca953x_probe(struct i2c_client *client)
        /* initialize cached registers from their original values.
         * we can't share this chip with another i2c master.
         */
+       pca953x_setup_gpio(chip, id->driver_data);
+
        ret = pca953x_read_reg(chip, PCA953X_OUTPUT, &chip->reg_output);
        if (ret)
                goto out_failed;
@@ -200,7 +228,8 @@ static int __devinit pca953x_probe(struct i2c_client *client)
        if (ret)
                goto out_failed;
 
-       ret = pca953x_init_gpio(chip);
+
+       ret = gpiochip_add(&chip->gpio_chip);
        if (ret)
                goto out_failed;
 
@@ -252,6 +281,7 @@ static struct i2c_driver pca953x_driver = {
        },
        .probe          = pca953x_probe,
        .remove         = pca953x_remove,
+       .id_table       = pca953x_id,
 };
 
 static int __init pca953x_init(void)