Blame view
drivers/gpio/gpio-pca953x.c
17 KB
9e60fdcf0 gpiolib: pca9539 ... |
1 |
/* |
c103de240 gpio: reorganize ... |
2 |
* PCA953x 4/8/16 bit I/O ports |
9e60fdcf0 gpiolib: pca9539 ... |
3 4 5 6 7 8 9 10 11 12 13 14 15 |
* * Copyright (C) 2005 Ben Gardner <bgardner@wabtec.com> * Copyright (C) 2007 Marvell International Ltd. * * Derived from drivers/i2c/chips/pca9539.c * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. */ #include <linux/module.h> #include <linux/init.h> |
d120c17fa gpio: include <li... |
16 |
#include <linux/gpio.h> |
89ea8bbe9 gpio: pca953x.c: ... |
17 18 |
#include <linux/interrupt.h> #include <linux/irq.h> |
9e60fdcf0 gpiolib: pca9539 ... |
19 |
#include <linux/i2c.h> |
d1c057e31 gpio: rename pca9... |
20 |
#include <linux/i2c/pca953x.h> |
5a0e3ad6a include cleanup: ... |
21 |
#include <linux/slab.h> |
1965d3035 gpio: pca953x: Ge... |
22 23 |
#ifdef CONFIG_OF_GPIO #include <linux/of_platform.h> |
1965d3035 gpio: pca953x: Ge... |
24 |
#endif |
9e60fdcf0 gpiolib: pca9539 ... |
25 |
|
33226ffd0 gpio/pca953x: Add... |
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
#define PCA953X_INPUT 0 #define PCA953X_OUTPUT 1 #define PCA953X_INVERT 2 #define PCA953X_DIRECTION 3 #define PCA957X_IN 0 #define PCA957X_INVRT 1 #define PCA957X_BKEN 2 #define PCA957X_PUPD 3 #define PCA957X_CFG 4 #define PCA957X_OUT 5 #define PCA957X_MSK 6 #define PCA957X_INTS 7 #define PCA_GPIO_MASK 0x00FF #define PCA_INT 0x0100 #define PCA953X_TYPE 0x1000 #define PCA957X_TYPE 0x2000 |
89ea8bbe9 gpio: pca953x.c: ... |
44 |
|
3760f7367 i2c: Convert most... |
45 |
static const struct i2c_device_id pca953x_id[] = { |
33226ffd0 gpio/pca953x: Add... |
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
{ "pca9534", 8 | PCA953X_TYPE | PCA_INT, }, { "pca9535", 16 | PCA953X_TYPE | PCA_INT, }, { "pca9536", 4 | PCA953X_TYPE, }, { "pca9537", 4 | PCA953X_TYPE | PCA_INT, }, { "pca9538", 8 | PCA953X_TYPE | PCA_INT, }, { "pca9539", 16 | PCA953X_TYPE | PCA_INT, }, { "pca9554", 8 | PCA953X_TYPE | PCA_INT, }, { "pca9555", 16 | PCA953X_TYPE | PCA_INT, }, { "pca9556", 8 | PCA953X_TYPE, }, { "pca9557", 8 | PCA953X_TYPE, }, { "pca9574", 8 | PCA957X_TYPE | PCA_INT, }, { "pca9575", 16 | PCA957X_TYPE | PCA_INT, }, { "max7310", 8 | PCA953X_TYPE, }, { "max7312", 16 | PCA953X_TYPE | PCA_INT, }, { "max7313", 16 | PCA953X_TYPE | PCA_INT, }, { "max7315", 8 | PCA953X_TYPE | PCA_INT, }, { "pca6107", 8 | PCA953X_TYPE | PCA_INT, }, { "tca6408", 8 | PCA953X_TYPE | PCA_INT, }, { "tca6416", 16 | PCA953X_TYPE | PCA_INT, }, |
ab5dc3720 gpio: pca953x han... |
66 |
/* NYET: { "tca6424", 24, }, */ |
3760f7367 i2c: Convert most... |
67 |
{ } |
f5e8ff483 gpio: handle pca9... |
68 |
}; |
3760f7367 i2c: Convert most... |
69 |
MODULE_DEVICE_TABLE(i2c, pca953x_id); |
9e60fdcf0 gpiolib: pca9539 ... |
70 |
|
f3dc3630f gpio: rename pca9... |
71 |
struct pca953x_chip { |
9e60fdcf0 gpiolib: pca9539 ... |
72 73 74 |
unsigned gpio_start; uint16_t reg_output; uint16_t reg_direction; |
6e20fb180 drivers/gpio/pca9... |
75 |
struct mutex i2c_lock; |
9e60fdcf0 gpiolib: pca9539 ... |
76 |
|
89ea8bbe9 gpio: pca953x.c: ... |
77 78 79 80 81 82 83 84 |
#ifdef CONFIG_GPIO_PCA953X_IRQ struct mutex irq_lock; uint16_t irq_mask; uint16_t irq_stat; uint16_t irq_trig_raise; uint16_t irq_trig_fall; int irq_base; #endif |
9e60fdcf0 gpiolib: pca9539 ... |
85 86 |
struct i2c_client *client; struct gpio_chip gpio_chip; |
62154991a gpiolib: make nam... |
87 |
const char *const *names; |
33226ffd0 gpio/pca953x: Add... |
88 |
int chip_type; |
9e60fdcf0 gpiolib: pca9539 ... |
89 |
}; |
f3dc3630f gpio: rename pca9... |
90 |
static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val) |
9e60fdcf0 gpiolib: pca9539 ... |
91 |
{ |
33226ffd0 gpio/pca953x: Add... |
92 |
int ret = 0; |
f5e8ff483 gpio: handle pca9... |
93 94 95 |
if (chip->gpio_chip.ngpio <= 8) ret = i2c_smbus_write_byte_data(chip->client, reg, val); |
33226ffd0 gpio/pca953x: Add... |
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
else { switch (chip->chip_type) { case PCA953X_TYPE: ret = i2c_smbus_write_word_data(chip->client, reg << 1, val); break; case PCA957X_TYPE: ret = i2c_smbus_write_byte_data(chip->client, reg << 1, val & 0xff); if (ret < 0) break; ret = i2c_smbus_write_byte_data(chip->client, (reg << 1) + 1, (val & 0xff00) >> 8); break; } } |
f5e8ff483 gpio: handle pca9... |
113 114 115 116 |
if (ret < 0) { dev_err(&chip->client->dev, "failed writing register "); |
ab5dc3720 gpio: pca953x han... |
117 |
return ret; |
f5e8ff483 gpio: handle pca9... |
118 119 120 |
} return 0; |
9e60fdcf0 gpiolib: pca9539 ... |
121 |
} |
f3dc3630f gpio: rename pca9... |
122 |
static int pca953x_read_reg(struct pca953x_chip *chip, int reg, uint16_t *val) |
9e60fdcf0 gpiolib: pca9539 ... |
123 124 |
{ int ret; |
f5e8ff483 gpio: handle pca9... |
125 126 127 128 |
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); |
9e60fdcf0 gpiolib: pca9539 ... |
129 130 131 |
if (ret < 0) { dev_err(&chip->client->dev, "failed reading register "); |
ab5dc3720 gpio: pca953x han... |
132 |
return ret; |
9e60fdcf0 gpiolib: pca9539 ... |
133 134 135 136 137 |
} *val = (uint16_t)ret; return 0; } |
f3dc3630f gpio: rename pca9... |
138 |
static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off) |
9e60fdcf0 gpiolib: pca9539 ... |
139 |
{ |
f3dc3630f gpio: rename pca9... |
140 |
struct pca953x_chip *chip; |
9e60fdcf0 gpiolib: pca9539 ... |
141 |
uint16_t reg_val; |
33226ffd0 gpio/pca953x: Add... |
142 |
int ret, offset = 0; |
9e60fdcf0 gpiolib: pca9539 ... |
143 |
|
f3dc3630f gpio: rename pca9... |
144 |
chip = container_of(gc, struct pca953x_chip, gpio_chip); |
9e60fdcf0 gpiolib: pca9539 ... |
145 |
|
6e20fb180 drivers/gpio/pca9... |
146 |
mutex_lock(&chip->i2c_lock); |
9e60fdcf0 gpiolib: pca9539 ... |
147 |
reg_val = chip->reg_direction | (1u << off); |
33226ffd0 gpio/pca953x: Add... |
148 149 150 151 152 153 154 155 156 157 |
switch (chip->chip_type) { case PCA953X_TYPE: offset = PCA953X_DIRECTION; break; case PCA957X_TYPE: offset = PCA957X_CFG; break; } ret = pca953x_write_reg(chip, offset, reg_val); |
9e60fdcf0 gpiolib: pca9539 ... |
158 |
if (ret) |
6e20fb180 drivers/gpio/pca9... |
159 |
goto exit; |
9e60fdcf0 gpiolib: pca9539 ... |
160 161 |
chip->reg_direction = reg_val; |
6e20fb180 drivers/gpio/pca9... |
162 163 164 165 |
ret = 0; exit: mutex_unlock(&chip->i2c_lock); return ret; |
9e60fdcf0 gpiolib: pca9539 ... |
166 |
} |
f3dc3630f gpio: rename pca9... |
167 |
static int pca953x_gpio_direction_output(struct gpio_chip *gc, |
9e60fdcf0 gpiolib: pca9539 ... |
168 169 |
unsigned off, int val) { |
f3dc3630f gpio: rename pca9... |
170 |
struct pca953x_chip *chip; |
9e60fdcf0 gpiolib: pca9539 ... |
171 |
uint16_t reg_val; |
33226ffd0 gpio/pca953x: Add... |
172 |
int ret, offset = 0; |
9e60fdcf0 gpiolib: pca9539 ... |
173 |
|
f3dc3630f gpio: rename pca9... |
174 |
chip = container_of(gc, struct pca953x_chip, gpio_chip); |
9e60fdcf0 gpiolib: pca9539 ... |
175 |
|
6e20fb180 drivers/gpio/pca9... |
176 |
mutex_lock(&chip->i2c_lock); |
9e60fdcf0 gpiolib: pca9539 ... |
177 178 179 180 181 |
/* set output level */ if (val) reg_val = chip->reg_output | (1u << off); else reg_val = chip->reg_output & ~(1u << off); |
33226ffd0 gpio/pca953x: Add... |
182 183 184 185 186 187 188 189 190 |
switch (chip->chip_type) { case PCA953X_TYPE: offset = PCA953X_OUTPUT; break; case PCA957X_TYPE: offset = PCA957X_OUT; break; } ret = pca953x_write_reg(chip, offset, reg_val); |
9e60fdcf0 gpiolib: pca9539 ... |
191 |
if (ret) |
6e20fb180 drivers/gpio/pca9... |
192 |
goto exit; |
9e60fdcf0 gpiolib: pca9539 ... |
193 194 195 196 197 |
chip->reg_output = reg_val; /* then direction */ reg_val = chip->reg_direction & ~(1u << off); |
33226ffd0 gpio/pca953x: Add... |
198 199 200 201 202 203 204 205 206 |
switch (chip->chip_type) { case PCA953X_TYPE: offset = PCA953X_DIRECTION; break; case PCA957X_TYPE: offset = PCA957X_CFG; break; } ret = pca953x_write_reg(chip, offset, reg_val); |
9e60fdcf0 gpiolib: pca9539 ... |
207 |
if (ret) |
6e20fb180 drivers/gpio/pca9... |
208 |
goto exit; |
9e60fdcf0 gpiolib: pca9539 ... |
209 210 |
chip->reg_direction = reg_val; |
6e20fb180 drivers/gpio/pca9... |
211 212 213 214 |
ret = 0; exit: mutex_unlock(&chip->i2c_lock); return ret; |
9e60fdcf0 gpiolib: pca9539 ... |
215 |
} |
f3dc3630f gpio: rename pca9... |
216 |
static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off) |
9e60fdcf0 gpiolib: pca9539 ... |
217 |
{ |
f3dc3630f gpio: rename pca9... |
218 |
struct pca953x_chip *chip; |
9e60fdcf0 gpiolib: pca9539 ... |
219 |
uint16_t reg_val; |
33226ffd0 gpio/pca953x: Add... |
220 |
int ret, offset = 0; |
9e60fdcf0 gpiolib: pca9539 ... |
221 |
|
f3dc3630f gpio: rename pca9... |
222 |
chip = container_of(gc, struct pca953x_chip, gpio_chip); |
9e60fdcf0 gpiolib: pca9539 ... |
223 |
|
6e20fb180 drivers/gpio/pca9... |
224 |
mutex_lock(&chip->i2c_lock); |
33226ffd0 gpio/pca953x: Add... |
225 226 227 228 229 230 231 232 233 |
switch (chip->chip_type) { case PCA953X_TYPE: offset = PCA953X_INPUT; break; case PCA957X_TYPE: offset = PCA957X_IN; break; } ret = pca953x_read_reg(chip, offset, ®_val); |
6e20fb180 drivers/gpio/pca9... |
234 |
mutex_unlock(&chip->i2c_lock); |
9e60fdcf0 gpiolib: pca9539 ... |
235 236 237 238 239 240 241 242 243 244 |
if (ret < 0) { /* NOTE: diagnostic already emitted; that's all we should * do unless gpio_*_value_cansleep() calls become different * from their nonsleeping siblings (and report faults). */ return 0; } return (reg_val & (1u << off)) ? 1 : 0; } |
f3dc3630f gpio: rename pca9... |
245 |
static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val) |
9e60fdcf0 gpiolib: pca9539 ... |
246 |
{ |
f3dc3630f gpio: rename pca9... |
247 |
struct pca953x_chip *chip; |
9e60fdcf0 gpiolib: pca9539 ... |
248 |
uint16_t reg_val; |
33226ffd0 gpio/pca953x: Add... |
249 |
int ret, offset = 0; |
9e60fdcf0 gpiolib: pca9539 ... |
250 |
|
f3dc3630f gpio: rename pca9... |
251 |
chip = container_of(gc, struct pca953x_chip, gpio_chip); |
9e60fdcf0 gpiolib: pca9539 ... |
252 |
|
6e20fb180 drivers/gpio/pca9... |
253 |
mutex_lock(&chip->i2c_lock); |
9e60fdcf0 gpiolib: pca9539 ... |
254 255 256 257 |
if (val) reg_val = chip->reg_output | (1u << off); else reg_val = chip->reg_output & ~(1u << off); |
33226ffd0 gpio/pca953x: Add... |
258 259 260 261 262 263 264 265 266 |
switch (chip->chip_type) { case PCA953X_TYPE: offset = PCA953X_OUTPUT; break; case PCA957X_TYPE: offset = PCA957X_OUT; break; } ret = pca953x_write_reg(chip, offset, reg_val); |
9e60fdcf0 gpiolib: pca9539 ... |
267 |
if (ret) |
6e20fb180 drivers/gpio/pca9... |
268 |
goto exit; |
9e60fdcf0 gpiolib: pca9539 ... |
269 270 |
chip->reg_output = reg_val; |
6e20fb180 drivers/gpio/pca9... |
271 272 |
exit: mutex_unlock(&chip->i2c_lock); |
9e60fdcf0 gpiolib: pca9539 ... |
273 |
} |
f5e8ff483 gpio: handle pca9... |
274 |
static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios) |
9e60fdcf0 gpiolib: pca9539 ... |
275 276 277 278 |
{ struct gpio_chip *gc; gc = &chip->gpio_chip; |
f3dc3630f gpio: rename pca9... |
279 280 281 282 |
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; |
842078054 gpio/pca953x bugf... |
283 |
gc->can_sleep = 1; |
9e60fdcf0 gpiolib: pca9539 ... |
284 285 |
gc->base = chip->gpio_start; |
f5e8ff483 gpio: handle pca9... |
286 287 |
gc->ngpio = gpios; gc->label = chip->client->name; |
d8f388d8d gpio: sysfs inter... |
288 |
gc->dev = &chip->client->dev; |
d72cbed0c gpiolib: i2c/spi ... |
289 |
gc->owner = THIS_MODULE; |
77906a546 pca953x: support ... |
290 |
gc->names = chip->names; |
9e60fdcf0 gpiolib: pca9539 ... |
291 |
} |
89ea8bbe9 gpio: pca953x.c: ... |
292 293 294 295 296 297 298 299 |
#ifdef CONFIG_GPIO_PCA953X_IRQ static int pca953x_gpio_to_irq(struct gpio_chip *gc, unsigned off) { struct pca953x_chip *chip; chip = container_of(gc, struct pca953x_chip, gpio_chip); return chip->irq_base + off; } |
6f5cfc0e2 gpio: pca953x: ir... |
300 |
static void pca953x_irq_mask(struct irq_data *d) |
89ea8bbe9 gpio: pca953x.c: ... |
301 |
{ |
6f5cfc0e2 gpio: pca953x: ir... |
302 |
struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); |
89ea8bbe9 gpio: pca953x.c: ... |
303 |
|
6f5cfc0e2 gpio: pca953x: ir... |
304 |
chip->irq_mask &= ~(1 << (d->irq - chip->irq_base)); |
89ea8bbe9 gpio: pca953x.c: ... |
305 |
} |
6f5cfc0e2 gpio: pca953x: ir... |
306 |
static void pca953x_irq_unmask(struct irq_data *d) |
89ea8bbe9 gpio: pca953x.c: ... |
307 |
{ |
6f5cfc0e2 gpio: pca953x: ir... |
308 |
struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); |
89ea8bbe9 gpio: pca953x.c: ... |
309 |
|
6f5cfc0e2 gpio: pca953x: ir... |
310 |
chip->irq_mask |= 1 << (d->irq - chip->irq_base); |
89ea8bbe9 gpio: pca953x.c: ... |
311 |
} |
6f5cfc0e2 gpio: pca953x: ir... |
312 |
static void pca953x_irq_bus_lock(struct irq_data *d) |
89ea8bbe9 gpio: pca953x.c: ... |
313 |
{ |
6f5cfc0e2 gpio: pca953x: ir... |
314 |
struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); |
89ea8bbe9 gpio: pca953x.c: ... |
315 316 317 |
mutex_lock(&chip->irq_lock); } |
6f5cfc0e2 gpio: pca953x: ir... |
318 |
static void pca953x_irq_bus_sync_unlock(struct irq_data *d) |
89ea8bbe9 gpio: pca953x.c: ... |
319 |
{ |
6f5cfc0e2 gpio: pca953x: ir... |
320 |
struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); |
a2cb9aeb3 gpio: fix pca953x... |
321 322 323 324 325 326 327 328 329 330 331 332 |
uint16_t new_irqs; uint16_t level; /* Look for any newly setup interrupt */ new_irqs = chip->irq_trig_fall | chip->irq_trig_raise; new_irqs &= ~chip->reg_direction; while (new_irqs) { level = __ffs(new_irqs); pca953x_gpio_direction_input(&chip->gpio_chip, level); new_irqs &= ~(1 << level); } |
89ea8bbe9 gpio: pca953x.c: ... |
333 334 335 |
mutex_unlock(&chip->irq_lock); } |
6f5cfc0e2 gpio: pca953x: ir... |
336 |
static int pca953x_irq_set_type(struct irq_data *d, unsigned int type) |
89ea8bbe9 gpio: pca953x.c: ... |
337 |
{ |
6f5cfc0e2 gpio: pca953x: ir... |
338 339 |
struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); uint16_t level = d->irq - chip->irq_base; |
89ea8bbe9 gpio: pca953x.c: ... |
340 341 342 343 344 |
uint16_t mask = 1 << level; if (!(type & IRQ_TYPE_EDGE_BOTH)) { dev_err(&chip->client->dev, "irq %d: unsupported type %d ", |
6f5cfc0e2 gpio: pca953x: ir... |
345 |
d->irq, type); |
89ea8bbe9 gpio: pca953x.c: ... |
346 347 348 349 350 351 352 353 354 355 356 357 |
return -EINVAL; } if (type & IRQ_TYPE_EDGE_FALLING) chip->irq_trig_fall |= mask; else chip->irq_trig_fall &= ~mask; if (type & IRQ_TYPE_EDGE_RISING) chip->irq_trig_raise |= mask; else chip->irq_trig_raise &= ~mask; |
a2cb9aeb3 gpio: fix pca953x... |
358 |
return 0; |
89ea8bbe9 gpio: pca953x.c: ... |
359 360 361 362 |
} static struct irq_chip pca953x_irq_chip = { .name = "pca953x", |
6f5cfc0e2 gpio: pca953x: ir... |
363 364 365 366 367 |
.irq_mask = pca953x_irq_mask, .irq_unmask = pca953x_irq_unmask, .irq_bus_lock = pca953x_irq_bus_lock, .irq_bus_sync_unlock = pca953x_irq_bus_sync_unlock, .irq_set_type = pca953x_irq_set_type, |
89ea8bbe9 gpio: pca953x.c: ... |
368 369 370 371 372 373 374 375 |
}; static uint16_t pca953x_irq_pending(struct pca953x_chip *chip) { uint16_t cur_stat; uint16_t old_stat; uint16_t pending; uint16_t trigger; |
33226ffd0 gpio/pca953x: Add... |
376 377 378 379 380 381 382 383 384 385 386 |
int ret, offset = 0; switch (chip->chip_type) { case PCA953X_TYPE: offset = PCA953X_INPUT; break; case PCA957X_TYPE: offset = PCA957X_IN; break; } ret = pca953x_read_reg(chip, offset, &cur_stat); |
89ea8bbe9 gpio: pca953x.c: ... |
387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 |
if (ret) return 0; /* Remove output pins from the equation */ cur_stat &= chip->reg_direction; old_stat = chip->irq_stat; trigger = (cur_stat ^ old_stat) & chip->irq_mask; if (!trigger) return 0; chip->irq_stat = cur_stat; pending = (old_stat & chip->irq_trig_fall) | (cur_stat & chip->irq_trig_raise); pending &= trigger; return pending; } static irqreturn_t pca953x_irq_handler(int irq, void *devid) { struct pca953x_chip *chip = devid; uint16_t pending; uint16_t level; pending = pca953x_irq_pending(chip); if (!pending) return IRQ_HANDLED; do { level = __ffs(pending); |
6dd599f8a gpio/pca953x: Fix... |
421 |
handle_nested_irq(level + chip->irq_base); |
89ea8bbe9 gpio: pca953x.c: ... |
422 423 424 425 426 427 428 429 |
pending &= ~(1 << level); } while (pending); return IRQ_HANDLED; } static int pca953x_irq_setup(struct pca953x_chip *chip, |
c6dcf5924 gpio/pca953x: Rem... |
430 431 |
const struct i2c_device_id *id, int irq_base) |
89ea8bbe9 gpio: pca953x.c: ... |
432 433 |
{ struct i2c_client *client = chip->client; |
33226ffd0 gpio/pca953x: Add... |
434 |
int ret, offset = 0; |
89ea8bbe9 gpio: pca953x.c: ... |
435 |
|
c6dcf5924 gpio/pca953x: Rem... |
436 |
if (irq_base != -1 |
33226ffd0 gpio/pca953x: Add... |
437 |
&& (id->driver_data & PCA_INT)) { |
89ea8bbe9 gpio: pca953x.c: ... |
438 |
int lvl; |
33226ffd0 gpio/pca953x: Add... |
439 440 441 442 443 444 445 446 447 |
switch (chip->chip_type) { case PCA953X_TYPE: offset = PCA953X_INPUT; break; case PCA957X_TYPE: offset = PCA957X_IN; break; } ret = pca953x_read_reg(chip, offset, &chip->irq_stat); |
89ea8bbe9 gpio: pca953x.c: ... |
448 449 450 451 452 453 454 455 456 |
if (ret) goto out_failed; /* * There is no way to know which GPIO line generated the * interrupt. We have to rely on the previous read for * this purpose. */ chip->irq_stat &= chip->reg_direction; |
89ea8bbe9 gpio: pca953x.c: ... |
457 |
mutex_init(&chip->irq_lock); |
c6dcf5924 gpio/pca953x: Rem... |
458 |
chip->irq_base = irq_alloc_descs(-1, irq_base, chip->gpio_chip.ngpio, -1); |
910c8fb6b gpio/pca953x: Fix... |
459 460 |
if (chip->irq_base < 0) goto out_failed; |
89ea8bbe9 gpio: pca953x.c: ... |
461 462 |
for (lvl = 0; lvl < chip->gpio_chip.ngpio; lvl++) { int irq = lvl + chip->irq_base; |
910c8fb6b gpio/pca953x: Fix... |
463 |
irq_clear_status_flags(irq, IRQ_NOREQUEST); |
b51804bcf gpio: Cleanup gen... |
464 |
irq_set_chip_data(irq, chip); |
6dd599f8a gpio/pca953x: Fix... |
465 466 |
irq_set_chip(irq, &pca953x_irq_chip); irq_set_nested_thread(irq, true); |
89ea8bbe9 gpio: pca953x.c: ... |
467 468 469 |
#ifdef CONFIG_ARM set_irq_flags(irq, IRQF_VALID); #else |
b51804bcf gpio: Cleanup gen... |
470 |
irq_set_noprobe(irq); |
89ea8bbe9 gpio: pca953x.c: ... |
471 472 473 474 475 476 |
#endif } ret = request_threaded_irq(client->irq, NULL, pca953x_irq_handler, |
17e8b42c1 gpio/pca953x: Int... |
477 |
IRQF_TRIGGER_LOW | IRQF_ONESHOT, |
89ea8bbe9 gpio: pca953x.c: ... |
478 479 480 481 482 483 484 485 486 487 488 489 490 491 |
dev_name(&client->dev), chip); if (ret) { dev_err(&client->dev, "failed to request irq %d ", client->irq); goto out_failed; } chip->gpio_chip.to_irq = pca953x_gpio_to_irq; } return 0; out_failed: |
8a233f01b pca953x: pca953x ... |
492 |
chip->irq_base = -1; |
89ea8bbe9 gpio: pca953x.c: ... |
493 494 495 496 497 |
return ret; } static void pca953x_irq_teardown(struct pca953x_chip *chip) { |
c609c05db gpio/pca953x: Fix... |
498 499 |
if (chip->irq_base != -1) { irq_free_descs(chip->irq_base, chip->gpio_chip.ngpio); |
89ea8bbe9 gpio: pca953x.c: ... |
500 |
free_irq(chip->client->irq, chip); |
c609c05db gpio/pca953x: Fix... |
501 |
} |
89ea8bbe9 gpio: pca953x.c: ... |
502 503 504 |
} #else /* CONFIG_GPIO_PCA953X_IRQ */ static int pca953x_irq_setup(struct pca953x_chip *chip, |
c6dcf5924 gpio/pca953x: Rem... |
505 506 |
const struct i2c_device_id *id, int irq_base) |
89ea8bbe9 gpio: pca953x.c: ... |
507 508 |
{ struct i2c_client *client = chip->client; |
89ea8bbe9 gpio: pca953x.c: ... |
509 |
|
c6dcf5924 gpio/pca953x: Rem... |
510 |
if (irq_base != -1 && (id->driver_data & PCA_INT)) |
89ea8bbe9 gpio: pca953x.c: ... |
511 512 513 514 515 516 517 518 519 520 |
dev_warn(&client->dev, "interrupt support not compiled in "); return 0; } static void pca953x_irq_teardown(struct pca953x_chip *chip) { } #endif |
1965d3035 gpio: pca953x: Ge... |
521 522 523 524 525 526 |
/* * Handlers for alternative sources of platform_data */ #ifdef CONFIG_OF_GPIO /* * Translate OpenFirmware node properties into platform_data |
a57339b4b gpio/pca953x: Dep... |
527 |
* WARNING: This is DEPRECATED and will be removed eventually! |
1965d3035 gpio: pca953x: Ge... |
528 |
*/ |
404ba2b8f gpio: pca953x: St... |
529 |
static void |
c6dcf5924 gpio/pca953x: Rem... |
530 |
pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, int *invert) |
1965d3035 gpio: pca953x: Ge... |
531 |
{ |
1965d3035 gpio: pca953x: Ge... |
532 |
struct device_node *node; |
1648237dc gpio/pca953x: Fix... |
533 534 |
const __be32 *val; int size; |
1965d3035 gpio: pca953x: Ge... |
535 |
|
61c7a080a of: Always use 's... |
536 |
node = client->dev.of_node; |
1965d3035 gpio: pca953x: Ge... |
537 |
if (node == NULL) |
c6dcf5924 gpio/pca953x: Rem... |
538 |
return; |
1965d3035 gpio: pca953x: Ge... |
539 |
|
c6dcf5924 gpio/pca953x: Rem... |
540 |
*gpio_base = -1; |
1648237dc gpio/pca953x: Fix... |
541 |
val = of_get_property(node, "linux,gpio-base", &size); |
a57339b4b gpio/pca953x: Dep... |
542 |
WARN(val, "%s: device-tree property 'linux,gpio-base' is deprecated!", __func__); |
1965d3035 gpio: pca953x: Ge... |
543 |
if (val) { |
1648237dc gpio/pca953x: Fix... |
544 545 546 547 |
if (size != sizeof(*val)) dev_warn(&client->dev, "%s: wrong linux,gpio-base ", node->full_name); |
1965d3035 gpio: pca953x: Ge... |
548 |
else |
c6dcf5924 gpio/pca953x: Rem... |
549 |
*gpio_base = be32_to_cpup(val); |
1965d3035 gpio: pca953x: Ge... |
550 551 552 |
} val = of_get_property(node, "polarity", NULL); |
a57339b4b gpio/pca953x: Dep... |
553 |
WARN(val, "%s: device-tree property 'polarity' is deprecated!", __func__); |
1965d3035 gpio: pca953x: Ge... |
554 |
if (val) |
c6dcf5924 gpio/pca953x: Rem... |
555 |
*invert = *val; |
1965d3035 gpio: pca953x: Ge... |
556 557 |
} #else |
404ba2b8f gpio: pca953x: St... |
558 |
static void |
c6dcf5924 gpio/pca953x: Rem... |
559 |
pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, int *invert) |
1965d3035 gpio: pca953x: Ge... |
560 |
{ |
25fcf2b7f gpio-pca953x: fix... |
561 |
*gpio_base = -1; |
1965d3035 gpio: pca953x: Ge... |
562 563 |
} #endif |
33226ffd0 gpio/pca953x: Add... |
564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 |
static int __devinit device_pca953x_init(struct pca953x_chip *chip, int invert) { int ret; ret = pca953x_read_reg(chip, PCA953X_OUTPUT, &chip->reg_output); if (ret) goto out; ret = pca953x_read_reg(chip, PCA953X_DIRECTION, &chip->reg_direction); if (ret) goto out; /* set platform specific polarity inversion */ ret = pca953x_write_reg(chip, PCA953X_INVERT, invert); |
33226ffd0 gpio/pca953x: Add... |
579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 |
out: return ret; } static int __devinit device_pca957x_init(struct pca953x_chip *chip, int invert) { int ret; uint16_t val = 0; /* Let every port in proper state, that could save power */ pca953x_write_reg(chip, PCA957X_PUPD, 0x0); pca953x_write_reg(chip, PCA957X_CFG, 0xffff); pca953x_write_reg(chip, PCA957X_OUT, 0x0); ret = pca953x_read_reg(chip, PCA957X_IN, &val); if (ret) goto out; ret = pca953x_read_reg(chip, PCA957X_OUT, &chip->reg_output); if (ret) goto out; ret = pca953x_read_reg(chip, PCA957X_CFG, &chip->reg_direction); if (ret) goto out; /* set platform specific polarity inversion */ pca953x_write_reg(chip, PCA957X_INVRT, invert); /* To enable register 6, 7 to controll pull up and pull down */ pca953x_write_reg(chip, PCA957X_BKEN, 0x202); return 0; out: return ret; } |
d2653e927 i2c: Add support ... |
613 |
static int __devinit pca953x_probe(struct i2c_client *client, |
3760f7367 i2c: Convert most... |
614 |
const struct i2c_device_id *id) |
9e60fdcf0 gpiolib: pca9539 ... |
615 |
{ |
f3dc3630f gpio: rename pca9... |
616 617 |
struct pca953x_platform_data *pdata; struct pca953x_chip *chip; |
a57339b4b gpio/pca953x: Dep... |
618 |
int irq_base=0, invert=0; |
7ea2aa204 gpio: pca953x: pr... |
619 |
int ret; |
9e60fdcf0 gpiolib: pca9539 ... |
620 |
|
1965d3035 gpio: pca953x: Ge... |
621 622 623 |
chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL); if (chip == NULL) return -ENOMEM; |
9e60fdcf0 gpiolib: pca9539 ... |
624 |
pdata = client->dev.platform_data; |
c6dcf5924 gpio/pca953x: Rem... |
625 626 627 628 629 630 631 |
if (pdata) { irq_base = pdata->irq_base; chip->gpio_start = pdata->gpio_base; invert = pdata->invert; chip->names = pdata->names; } else { pca953x_get_alt_pdata(client, &chip->gpio_start, &invert); |
a57339b4b gpio/pca953x: Dep... |
632 633 634 635 636 |
#ifdef CONFIG_OF_GPIO /* If I2C node has no interrupts property, disable GPIO interrupts */ if (of_find_property(client->dev.of_node, "interrupts", NULL) == NULL) irq_base = -1; #endif |
1965d3035 gpio: pca953x: Ge... |
637 |
} |
9e60fdcf0 gpiolib: pca9539 ... |
638 639 |
chip->client = client; |
33226ffd0 gpio/pca953x: Add... |
640 |
chip->chip_type = id->driver_data & (PCA953X_TYPE | PCA957X_TYPE); |
77906a546 pca953x: support ... |
641 |
|
6e20fb180 drivers/gpio/pca9... |
642 |
mutex_init(&chip->i2c_lock); |
9e60fdcf0 gpiolib: pca9539 ... |
643 644 645 |
/* initialize cached registers from their original values. * we can't share this chip with another i2c master. */ |
33226ffd0 gpio/pca953x: Add... |
646 |
pca953x_setup_gpio(chip, id->driver_data & PCA_GPIO_MASK); |
f5e8ff483 gpio: handle pca9... |
647 |
|
33226ffd0 gpio/pca953x: Add... |
648 |
if (chip->chip_type == PCA953X_TYPE) |
7ea2aa204 gpio: pca953x: pr... |
649 |
ret = device_pca953x_init(chip, invert); |
33226ffd0 gpio/pca953x: Add... |
650 |
else |
7ea2aa204 gpio: pca953x: pr... |
651 652 |
ret = device_pca957x_init(chip, invert); if (ret) |
9e60fdcf0 gpiolib: pca9539 ... |
653 |
goto out_failed; |
c6dcf5924 gpio/pca953x: Rem... |
654 |
ret = pca953x_irq_setup(chip, id, irq_base); |
89ea8bbe9 gpio: pca953x.c: ... |
655 656 |
if (ret) goto out_failed; |
f5e8ff483 gpio: handle pca9... |
657 658 |
ret = gpiochip_add(&chip->gpio_chip); |
9e60fdcf0 gpiolib: pca9539 ... |
659 |
if (ret) |
272df502b gpio/pca953x: fix... |
660 |
goto out_failed_irq; |
9e60fdcf0 gpiolib: pca9539 ... |
661 |
|
c6dcf5924 gpio/pca953x: Rem... |
662 |
if (pdata && pdata->setup) { |
9e60fdcf0 gpiolib: pca9539 ... |
663 664 665 666 667 668 669 670 671 |
ret = pdata->setup(client, chip->gpio_chip.base, chip->gpio_chip.ngpio, pdata->context); if (ret < 0) dev_warn(&client->dev, "setup failed, %d ", ret); } i2c_set_clientdata(client, chip); return 0; |
272df502b gpio/pca953x: fix... |
672 |
out_failed_irq: |
89ea8bbe9 gpio: pca953x.c: ... |
673 |
pca953x_irq_teardown(chip); |
272df502b gpio/pca953x: fix... |
674 |
out_failed: |
9e60fdcf0 gpiolib: pca9539 ... |
675 676 677 |
kfree(chip); return ret; } |
f3dc3630f gpio: rename pca9... |
678 |
static int pca953x_remove(struct i2c_client *client) |
9e60fdcf0 gpiolib: pca9539 ... |
679 |
{ |
f3dc3630f gpio: rename pca9... |
680 681 |
struct pca953x_platform_data *pdata = client->dev.platform_data; struct pca953x_chip *chip = i2c_get_clientdata(client); |
9e60fdcf0 gpiolib: pca9539 ... |
682 |
int ret = 0; |
c6dcf5924 gpio/pca953x: Rem... |
683 |
if (pdata && pdata->teardown) { |
9e60fdcf0 gpiolib: pca9539 ... |
684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 |
ret = pdata->teardown(client, chip->gpio_chip.base, chip->gpio_chip.ngpio, pdata->context); if (ret < 0) { dev_err(&client->dev, "%s failed, %d ", "teardown", ret); return ret; } } ret = gpiochip_remove(&chip->gpio_chip); if (ret) { dev_err(&client->dev, "%s failed, %d ", "gpiochip_remove()", ret); return ret; } |
89ea8bbe9 gpio: pca953x.c: ... |
701 |
pca953x_irq_teardown(chip); |
9e60fdcf0 gpiolib: pca9539 ... |
702 703 704 |
kfree(chip); return 0; } |
f3dc3630f gpio: rename pca9... |
705 |
static struct i2c_driver pca953x_driver = { |
9e60fdcf0 gpiolib: pca9539 ... |
706 |
.driver = { |
f3dc3630f gpio: rename pca9... |
707 |
.name = "pca953x", |
9e60fdcf0 gpiolib: pca9539 ... |
708 |
}, |
f3dc3630f gpio: rename pca9... |
709 710 |
.probe = pca953x_probe, .remove = pca953x_remove, |
3760f7367 i2c: Convert most... |
711 |
.id_table = pca953x_id, |
9e60fdcf0 gpiolib: pca9539 ... |
712 |
}; |
f3dc3630f gpio: rename pca9... |
713 |
static int __init pca953x_init(void) |
9e60fdcf0 gpiolib: pca9539 ... |
714 |
{ |
f3dc3630f gpio: rename pca9... |
715 |
return i2c_add_driver(&pca953x_driver); |
9e60fdcf0 gpiolib: pca9539 ... |
716 |
} |
2f8d11971 gpio: i2c expande... |
717 718 719 720 |
/* register after i2c postcore initcall and before * subsys initcalls that may rely on these GPIOs */ subsys_initcall(pca953x_init); |
9e60fdcf0 gpiolib: pca9539 ... |
721 |
|
f3dc3630f gpio: rename pca9... |
722 |
static void __exit pca953x_exit(void) |
9e60fdcf0 gpiolib: pca9539 ... |
723 |
{ |
f3dc3630f gpio: rename pca9... |
724 |
i2c_del_driver(&pca953x_driver); |
9e60fdcf0 gpiolib: pca9539 ... |
725 |
} |
f3dc3630f gpio: rename pca9... |
726 |
module_exit(pca953x_exit); |
9e60fdcf0 gpiolib: pca9539 ... |
727 728 |
MODULE_AUTHOR("eric miao <eric.miao@marvell.com>"); |
f3dc3630f gpio: rename pca9... |
729 |
MODULE_DESCRIPTION("GPIO expander driver for PCA953x"); |
9e60fdcf0 gpiolib: pca9539 ... |
730 |
MODULE_LICENSE("GPL"); |