aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio/gpio-pca953x.c
diff options
context:
space:
mode:
authorAndreas Schallenberg <Andreas.Schallenberg@3alitytechnica.com>2012-05-09 03:46:17 -0400
committerGrant Likely <grant.likely@secretlab.ca>2012-05-18 18:48:34 -0400
commitae79c19049b75af476adcbcfda6fc29bd93fc6f8 (patch)
tree8fef28f94ddf49b8c0679ec7de0ae9680b0fb90b /drivers/gpio/gpio-pca953x.c
parent453007cf472a2b4c1034e850c3004ee9027005f6 (diff)
Add support for TCA6424A
This patch extends the PCA953x driver to support TI's TCA6424A 24 bit I2C I/O expander. The patch is based on code by Michele Bevilacqua. Changes in v2: - Compare ngpio against 24 in both places, not >16 - Larger datatype now u32 instead of uint. Bit fields not used for struct members since their address is taken. - Be precise: TCA6424A (untested for older TCA6424) Signed-off-by: Andreas Schallenberg<Andreas.Schallenberg@3alitytechnica.com> Acked-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers/gpio/gpio-pca953x.c')
-rw-r--r--drivers/gpio/gpio-pca953x.c43
1 files changed, 30 insertions, 13 deletions
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
index d3f3e8f54561..1c313c710be3 100644
--- a/drivers/gpio/gpio-pca953x.c
+++ b/drivers/gpio/gpio-pca953x.c
@@ -28,6 +28,8 @@
28#define PCA953X_INVERT 2 28#define PCA953X_INVERT 2
29#define PCA953X_DIRECTION 3 29#define PCA953X_DIRECTION 3
30 30
31#define REG_ADDR_AI 0x80
32
31#define PCA957X_IN 0 33#define PCA957X_IN 0
32#define PCA957X_INVRT 1 34#define PCA957X_INVRT 1
33#define PCA957X_BKEN 2 35#define PCA957X_BKEN 2
@@ -63,15 +65,15 @@ static const struct i2c_device_id pca953x_id[] = {
63 { "pca6107", 8 | PCA953X_TYPE | PCA_INT, }, 65 { "pca6107", 8 | PCA953X_TYPE | PCA_INT, },
64 { "tca6408", 8 | PCA953X_TYPE | PCA_INT, }, 66 { "tca6408", 8 | PCA953X_TYPE | PCA_INT, },
65 { "tca6416", 16 | PCA953X_TYPE | PCA_INT, }, 67 { "tca6416", 16 | PCA953X_TYPE | PCA_INT, },
66 /* NYET: { "tca6424", 24, }, */ 68 { "tca6424", 24 | PCA953X_TYPE | PCA_INT, },
67 { } 69 { }
68}; 70};
69MODULE_DEVICE_TABLE(i2c, pca953x_id); 71MODULE_DEVICE_TABLE(i2c, pca953x_id);
70 72
71struct pca953x_chip { 73struct pca953x_chip {
72 unsigned gpio_start; 74 unsigned gpio_start;
73 uint16_t reg_output; 75 u32 reg_output;
74 uint16_t reg_direction; 76 u32 reg_direction;
75 struct mutex i2c_lock; 77 struct mutex i2c_lock;
76 78
77#ifdef CONFIG_GPIO_PCA953X_IRQ 79#ifdef CONFIG_GPIO_PCA953X_IRQ
@@ -89,12 +91,20 @@ struct pca953x_chip {
89 int chip_type; 91 int chip_type;
90}; 92};
91 93
92static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val) 94static int pca953x_write_reg(struct pca953x_chip *chip, int reg, u32 val)
93{ 95{
94 int ret = 0; 96 int ret = 0;
95 97
96 if (chip->gpio_chip.ngpio <= 8) 98 if (chip->gpio_chip.ngpio <= 8)
97 ret = i2c_smbus_write_byte_data(chip->client, reg, val); 99 ret = i2c_smbus_write_byte_data(chip->client, reg, val);
100 else if (chip->gpio_chip.ngpio == 24) {
101 ret = i2c_smbus_write_word_data(chip->client,
102 (reg << 2) | REG_ADDR_AI,
103 val & 0xffff);
104 ret = i2c_smbus_write_byte_data(chip->client,
105 (reg << 2) + 2,
106 (val & 0xff0000) >> 16);
107 }
98 else { 108 else {
99 switch (chip->chip_type) { 109 switch (chip->chip_type) {
100 case PCA953X_TYPE: 110 case PCA953X_TYPE:
@@ -121,12 +131,17 @@ static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val)
121 return 0; 131 return 0;
122} 132}
123 133
124static int pca953x_read_reg(struct pca953x_chip *chip, int reg, uint16_t *val) 134static int pca953x_read_reg(struct pca953x_chip *chip, int reg, u32 *val)
125{ 135{
126 int ret; 136 int ret;
127 137
128 if (chip->gpio_chip.ngpio <= 8) 138 if (chip->gpio_chip.ngpio <= 8)
129 ret = i2c_smbus_read_byte_data(chip->client, reg); 139 ret = i2c_smbus_read_byte_data(chip->client, reg);
140 else if (chip->gpio_chip.ngpio == 24) {
141 ret = i2c_smbus_read_word_data(chip->client, reg << 2);
142 ret |= (i2c_smbus_read_byte_data(chip->client,
143 (reg << 2) + 2)<<16);
144 }
130 else 145 else
131 ret = i2c_smbus_read_word_data(chip->client, reg << 1); 146 ret = i2c_smbus_read_word_data(chip->client, reg << 1);
132 147
@@ -135,14 +150,14 @@ static int pca953x_read_reg(struct pca953x_chip *chip, int reg, uint16_t *val)
135 return ret; 150 return ret;
136 } 151 }
137 152
138 *val = (uint16_t)ret; 153 *val = (u32)ret;
139 return 0; 154 return 0;
140} 155}
141 156
142static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off) 157static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off)
143{ 158{
144 struct pca953x_chip *chip; 159 struct pca953x_chip *chip;
145 uint16_t reg_val; 160 uint reg_val;
146 int ret, offset = 0; 161 int ret, offset = 0;
147 162
148 chip = container_of(gc, struct pca953x_chip, gpio_chip); 163 chip = container_of(gc, struct pca953x_chip, gpio_chip);
@@ -173,7 +188,7 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc,
173 unsigned off, int val) 188 unsigned off, int val)
174{ 189{
175 struct pca953x_chip *chip; 190 struct pca953x_chip *chip;
176 uint16_t reg_val; 191 uint reg_val;
177 int ret, offset = 0; 192 int ret, offset = 0;
178 193
179 chip = container_of(gc, struct pca953x_chip, gpio_chip); 194 chip = container_of(gc, struct pca953x_chip, gpio_chip);
@@ -223,7 +238,7 @@ exit:
223static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off) 238static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
224{ 239{
225 struct pca953x_chip *chip; 240 struct pca953x_chip *chip;
226 uint16_t reg_val; 241 u32 reg_val;
227 int ret, offset = 0; 242 int ret, offset = 0;
228 243
229 chip = container_of(gc, struct pca953x_chip, gpio_chip); 244 chip = container_of(gc, struct pca953x_chip, gpio_chip);
@@ -253,7 +268,7 @@ static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
253static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val) 268static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
254{ 269{
255 struct pca953x_chip *chip; 270 struct pca953x_chip *chip;
256 uint16_t reg_val; 271 u32 reg_val;
257 int ret, offset = 0; 272 int ret, offset = 0;
258 273
259 chip = container_of(gc, struct pca953x_chip, gpio_chip); 274 chip = container_of(gc, struct pca953x_chip, gpio_chip);
@@ -386,7 +401,7 @@ static struct irq_chip pca953x_irq_chip = {
386 401
387static uint16_t pca953x_irq_pending(struct pca953x_chip *chip) 402static uint16_t pca953x_irq_pending(struct pca953x_chip *chip)
388{ 403{
389 uint16_t cur_stat; 404 u32 cur_stat;
390 uint16_t old_stat; 405 uint16_t old_stat;
391 uint16_t pending; 406 uint16_t pending;
392 uint16_t trigger; 407 uint16_t trigger;
@@ -449,6 +464,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
449{ 464{
450 struct i2c_client *client = chip->client; 465 struct i2c_client *client = chip->client;
451 int ret, offset = 0; 466 int ret, offset = 0;
467 u32 temporary;
452 468
453 if (irq_base != -1 469 if (irq_base != -1
454 && (id->driver_data & PCA_INT)) { 470 && (id->driver_data & PCA_INT)) {
@@ -462,7 +478,8 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
462 offset = PCA957X_IN; 478 offset = PCA957X_IN;
463 break; 479 break;
464 } 480 }
465 ret = pca953x_read_reg(chip, offset, &chip->irq_stat); 481 ret = pca953x_read_reg(chip, offset, &temporary);
482 chip->irq_stat = temporary;
466 if (ret) 483 if (ret)
467 goto out_failed; 484 goto out_failed;
468 485
@@ -603,7 +620,7 @@ out:
603static int __devinit device_pca957x_init(struct pca953x_chip *chip, int invert) 620static int __devinit device_pca957x_init(struct pca953x_chip *chip, int invert)
604{ 621{
605 int ret; 622 int ret;
606 uint16_t val = 0; 623 u32 val = 0;
607 624
608 /* Let every port in proper state, that could save power */ 625 /* Let every port in proper state, that could save power */
609 pca953x_write_reg(chip, PCA957X_PUPD, 0x0); 626 pca953x_write_reg(chip, PCA957X_PUPD, 0x0);