/*
- * 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;
*/
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;
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;
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;
/* 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;
if (ret)
goto out_failed;
- ret = pca953x_init_gpio(chip);
+
+ ret = gpiochip_add(&chip->gpio_chip);
if (ret)
goto out_failed;
},
.probe = pca953x_probe,
.remove = pca953x_remove,
+ .id_table = pca953x_id,
};
static int __init pca953x_init(void)