[ARM] Feroceon: pass proper -mtune argument to gcc
[safe/jmp/linux-2.6] / drivers / gpio / pca953x.c
index 7fae4e5..9ceeb89 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  pca9539.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 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, },
+       { "max7310", 8, },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, pca953x_id);
 
-#define NR_PCA9539_GPIOS       16
-
-#define PCA9539_INPUT          0
-#define PCA9539_OUTPUT         2
-#define PCA9539_INVERT         4
-#define PCA9539_DIRECTION      6
-
-struct pca9539_chip {
+struct pca953x_chip {
        unsigned gpio_start;
        uint16_t reg_output;
        uint16_t reg_direction;
@@ -38,19 +50,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->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 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->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;
@@ -60,16 +85,16 @@ static int pca9539_read_reg(struct pca9539_chip *chip, int reg, uint16_t *val)
        return 0;
 }
 
-static int pca9539_gpio_direction_input(struct gpio_chip *gc, unsigned off)
+static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off)
 {
-       struct pca9539_chip *chip;
+       struct pca953x_chip *chip;
        uint16_t reg_val;
        int ret;
 
-       chip = container_of(gc, struct pca9539_chip, gpio_chip);
+       chip = container_of(gc, struct pca953x_chip, gpio_chip);
 
        reg_val = chip->reg_direction | (1u << off);
-       ret = pca9539_write_reg(chip, PCA9539_DIRECTION, reg_val);
+       ret = pca953x_write_reg(chip, PCA953X_DIRECTION, reg_val);
        if (ret)
                return ret;
 
@@ -77,14 +102,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 +117,7 @@ static int pca9539_gpio_direction_output(struct gpio_chip *gc,
        else
                reg_val = chip->reg_output & ~(1u << off);
 
-       ret = pca9539_write_reg(chip, PCA9539_OUTPUT, reg_val);
+       ret = pca953x_write_reg(chip, PCA953X_OUTPUT, reg_val);
        if (ret)
                return ret;
 
@@ -100,7 +125,7 @@ static int pca9539_gpio_direction_output(struct gpio_chip *gc,
 
        /* then direction */
        reg_val = chip->reg_direction & ~(1u << off);
-       ret = pca9539_write_reg(chip, PCA9539_DIRECTION, reg_val);
+       ret = pca953x_write_reg(chip, PCA953X_DIRECTION, reg_val);
        if (ret)
                return ret;
 
@@ -108,15 +133,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, &reg_val);
+       ret = pca953x_read_reg(chip, PCA953X_INPUT, &reg_val);
        if (ret < 0) {
                /* NOTE:  diagnostic already emitted; that's all we should
                 * do unless gpio_*_value_cansleep() calls become different
@@ -128,55 +153,57 @@ static int pca9539_gpio_get_value(struct gpio_chip *gc, unsigned off)
        return (reg_val & (1u << off)) ? 1 : 0;
 }
 
-static void pca9539_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
+static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
 {
-       struct pca9539_chip *chip;
+       struct pca953x_chip *chip;
        uint16_t reg_val;
        int ret;
 
-       chip = container_of(gc, struct pca9539_chip, gpio_chip);
+       chip = container_of(gc, struct pca953x_chip, gpio_chip);
 
        if (val)
                reg_val = chip->reg_output | (1u << off);
        else
                reg_val = chip->reg_output & ~(1u << off);
 
-       ret = pca9539_write_reg(chip, PCA9539_OUTPUT, reg_val);
+       ret = pca953x_write_reg(chip, PCA953X_OUTPUT, reg_val);
        if (ret)
                return;
 
        chip->reg_output = reg_val;
 }
 
-static int pca9539_init_gpio(struct pca9539_chip *chip)
+static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
 {
        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->can_sleep = 1;
 
        gc->base = chip->gpio_start;
-       gc->ngpio = NR_PCA9539_GPIOS;
-       gc->label = "pca9539";
-
-       return gpiochip_add(gc);
+       gc->ngpio = gpios;
+       gc->label = chip->client->name;
+       gc->dev = &chip->client->dev;
+       gc->owner = THIS_MODULE;
 }
 
-static int __devinit pca9539_probe(struct i2c_client *client)
+static int __devinit pca953x_probe(struct i2c_client *client,
+                                  const struct i2c_device_id *id)
 {
-       struct pca9539_platform_data *pdata;
-       struct pca9539_chip *chip;
+       struct pca953x_platform_data *pdata;
+       struct pca953x_chip *chip;
        int ret;
 
        pdata = client->dev.platform_data;
        if (pdata == NULL)
                return -ENODEV;
 
-       chip = kzalloc(sizeof(struct pca9539_chip), GFP_KERNEL);
+       chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL);
        if (chip == NULL)
                return -ENOMEM;
 
@@ -187,20 +214,23 @@ 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);
+       pca953x_setup_gpio(chip, id->driver_data);
+
+       ret = pca953x_read_reg(chip, PCA953X_OUTPUT, &chip->reg_output);
        if (ret)
                goto out_failed;
 
-       ret = pca9539_read_reg(chip, PCA9539_DIRECTION, &chip->reg_direction);
+       ret = pca953x_read_reg(chip, PCA953X_DIRECTION, &chip->reg_direction);
        if (ret)
                goto out_failed;
 
        /* set platform specific polarity inversion */
-       ret = pca9539_write_reg(chip, PCA9539_INVERT, pdata->invert);
+       ret = pca953x_write_reg(chip, PCA953X_INVERT, pdata->invert);
        if (ret)
                goto out_failed;
 
-       ret = pca9539_init_gpio(chip);
+
+       ret = gpiochip_add(&chip->gpio_chip);
        if (ret)
                goto out_failed;
 
@@ -219,10 +249,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 +276,30 @@ 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,
+       .id_table       = pca953x_id,
 };
 
-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);
+/* register after i2c postcore initcall and before
+ * subsys initcalls that may rely on these GPIOs
+ */
+subsys_initcall(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");