Blame view
drivers/gpio/gpio-pca953x.c
24.1 KB
9e60fdcf0 gpiolib: pca9539 ... |
1 |
/* |
1e1916950 gpio: pca953x: Ad... |
2 |
* PCA953x 4/8/16/24/40 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 |
#include <linux/interrupt.h> |
9e60fdcf0 gpiolib: pca9539 ... |
18 |
#include <linux/i2c.h> |
5877457a9 gpio: (gpio-pca95... |
19 |
#include <linux/platform_data/pca953x.h> |
bab58491c MLK-11293: gpio: ... |
20 |
#include <linux/reset.h> |
5a0e3ad6a include cleanup: ... |
21 |
#include <linux/slab.h> |
9b8e3ec34 gpio: pca953x: Us... |
22 |
#include <asm/unaligned.h> |
1965d3035 gpio: pca953x: Ge... |
23 |
#include <linux/of_platform.h> |
f32517bf1 gpio: pca953x: su... |
24 |
#include <linux/acpi.h> |
e23efa311 gpio: pca954x: Ad... |
25 |
#include <linux/regulator/consumer.h> |
9e60fdcf0 gpiolib: pca9539 ... |
26 |
|
33226ffd0 gpio/pca953x: Add... |
27 28 29 30 |
#define PCA953X_INPUT 0 #define PCA953X_OUTPUT 1 #define PCA953X_INVERT 2 #define PCA953X_DIRECTION 3 |
ae79c1904 Add support for T... |
31 |
#define REG_ADDR_AI 0x80 |
33226ffd0 gpio/pca953x: Add... |
32 33 34 35 36 37 38 39 |
#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 |
44896beae gpio: pca953x: ad... |
40 41 42 |
#define PCAL953X_IN_LATCH 34 #define PCAL953X_INT_MASK 37 #define PCAL953X_INT_STAT 38 |
33226ffd0 gpio/pca953x: Add... |
43 44 |
#define PCA_GPIO_MASK 0x00FF #define PCA_INT 0x0100 |
8c7a92dad gpio: pca953x: re... |
45 |
#define PCA_PCAL 0x0200 |
33226ffd0 gpio/pca953x: Add... |
46 47 |
#define PCA953X_TYPE 0x1000 #define PCA957X_TYPE 0x2000 |
c6664149a gpio: pca953x: st... |
48 49 50 |
#define PCA_TYPE_MASK 0xF000 #define PCA_CHIP_TYPE(x) ((x) & PCA_TYPE_MASK) |
89ea8bbe9 gpio: pca953x.c: ... |
51 |
|
3760f7367 i2c: Convert most... |
52 |
static const struct i2c_device_id pca953x_id[] = { |
89f5df01c gpio: pca953x: ad... |
53 |
{ "pca9505", 40 | PCA953X_TYPE | PCA_INT, }, |
33226ffd0 gpio/pca953x: Add... |
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, }, |
eb32b5aae gpio: pca953x: Ad... |
66 |
{ "pca9698", 40 | PCA953X_TYPE, }, |
33226ffd0 gpio/pca953x: Add... |
67 |
|
747e42a1c gpio: pca953x: en... |
68 |
{ "pcal9555a", 16 | PCA953X_TYPE | PCA_INT | PCA_PCAL, }, |
33226ffd0 gpio/pca953x: Add... |
69 70 71 72 73 74 75 |
{ "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, }, |
ae79c1904 Add support for T... |
76 |
{ "tca6424", 24 | PCA953X_TYPE | PCA_INT, }, |
2db8aba86 gpio: pca953x: Ad... |
77 |
{ "tca9539", 16 | PCA953X_TYPE | PCA_INT, }, |
e73760a60 gpio: pca953x: Ad... |
78 |
{ "xra1202", 8 | PCA953X_TYPE }, |
3760f7367 i2c: Convert most... |
79 |
{ } |
f5e8ff483 gpio: handle pca9... |
80 |
}; |
3760f7367 i2c: Convert most... |
81 |
MODULE_DEVICE_TABLE(i2c, pca953x_id); |
9e60fdcf0 gpiolib: pca9539 ... |
82 |
|
f32517bf1 gpio: pca953x: su... |
83 |
static const struct acpi_device_id pca953x_acpi_ids[] = { |
44896beae gpio: pca953x: ad... |
84 |
{ "INT3491", 16 | PCA953X_TYPE | PCA_INT | PCA_PCAL, }, |
f32517bf1 gpio: pca953x: su... |
85 86 87 |
{ } }; MODULE_DEVICE_TABLE(acpi, pca953x_acpi_ids); |
f5f0b7aa8 gpio: pca953x: ma... |
88 89 |
#define MAX_BANK 5 #define BANK_SZ 8 |
a246b8198 gpio: pca953x: Fi... |
90 |
#define NBANK(chip) DIV_ROUND_UP(chip->gpio_chip.ngpio, BANK_SZ) |
f5f0b7aa8 gpio: pca953x: ma... |
91 |
|
53661f3bc gpio: pca953x: co... |
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
struct pca953x_reg_config { int direction; int output; int input; }; static const struct pca953x_reg_config pca953x_regs = { .direction = PCA953X_DIRECTION, .output = PCA953X_OUTPUT, .input = PCA953X_INPUT, }; static const struct pca953x_reg_config pca957x_regs = { .direction = PCA957X_CFG, .output = PCA957X_OUT, .input = PCA957X_IN, }; |
f3dc3630f gpio: rename pca9... |
109 |
struct pca953x_chip { |
9e60fdcf0 gpiolib: pca9539 ... |
110 |
unsigned gpio_start; |
f5f0b7aa8 gpio: pca953x: ma... |
111 112 |
u8 reg_output[MAX_BANK]; u8 reg_direction[MAX_BANK]; |
6e20fb180 drivers/gpio/pca9... |
113 |
struct mutex i2c_lock; |
9e60fdcf0 gpiolib: pca9539 ... |
114 |
|
89ea8bbe9 gpio: pca953x.c: ... |
115 116 |
#ifdef CONFIG_GPIO_PCA953X_IRQ struct mutex irq_lock; |
f5f0b7aa8 gpio: pca953x: ma... |
117 118 119 120 |
u8 irq_mask[MAX_BANK]; u8 irq_stat[MAX_BANK]; u8 irq_trig_raise[MAX_BANK]; u8 irq_trig_fall[MAX_BANK]; |
89ea8bbe9 gpio: pca953x.c: ... |
121 |
#endif |
9e60fdcf0 gpiolib: pca9539 ... |
122 123 |
struct i2c_client *client; struct gpio_chip gpio_chip; |
62154991a gpiolib: make nam... |
124 |
const char *const *names; |
c6664149a gpio: pca953x: st... |
125 |
unsigned long driver_data; |
e23efa311 gpio: pca954x: Ad... |
126 |
struct regulator *regulator; |
53661f3bc gpio: pca953x: co... |
127 128 |
const struct pca953x_reg_config *regs; |
7acc66e37 gpio: pca953x: re... |
129 130 |
int (*write_regs)(struct pca953x_chip *, int, u8 *); |
c6e3cf01d gpio: pca953x: re... |
131 |
int (*read_regs)(struct pca953x_chip *, int, u8 *); |
9e60fdcf0 gpiolib: pca9539 ... |
132 |
}; |
f5f0b7aa8 gpio: pca953x: ma... |
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
static int pca953x_read_single(struct pca953x_chip *chip, int reg, u32 *val, int off) { int ret; int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ); int offset = off / BANK_SZ; ret = i2c_smbus_read_byte_data(chip->client, (reg << bank_shift) + offset); *val = ret; if (ret < 0) { dev_err(&chip->client->dev, "failed reading register "); return ret; } return 0; } static int pca953x_write_single(struct pca953x_chip *chip, int reg, u32 val, int off) { |
8c7a92dad gpio: pca953x: re... |
156 |
int ret; |
f5f0b7aa8 gpio: pca953x: ma... |
157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ); int offset = off / BANK_SZ; ret = i2c_smbus_write_byte_data(chip->client, (reg << bank_shift) + offset, val); if (ret < 0) { dev_err(&chip->client->dev, "failed writing register "); return ret; } return 0; } |
7acc66e37 gpio: pca953x: re... |
171 |
static int pca953x_write_regs_8(struct pca953x_chip *chip, int reg, u8 *val) |
9e60fdcf0 gpiolib: pca9539 ... |
172 |
{ |
7acc66e37 gpio: pca953x: re... |
173 174 |
return i2c_smbus_write_byte_data(chip->client, reg, *val); } |
f5e8ff483 gpio: handle pca9... |
175 |
|
7acc66e37 gpio: pca953x: re... |
176 177 178 |
static int pca953x_write_regs_16(struct pca953x_chip *chip, int reg, u8 *val) { __le16 word = cpu_to_le16(get_unaligned((u16 *)val)); |
c4d1cbd7c gpio: pca953x: en... |
179 |
|
7acc66e37 gpio: pca953x: re... |
180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
return i2c_smbus_write_word_data(chip->client, reg << 1, (__force u16)word); } static int pca957x_write_regs_16(struct pca953x_chip *chip, int reg, u8 *val) { int ret; ret = i2c_smbus_write_byte_data(chip->client, reg << 1, val[0]); if (ret < 0) return ret; return i2c_smbus_write_byte_data(chip->client, (reg << 1) + 1, val[1]); } |
f5e8ff483 gpio: handle pca9... |
194 |
|
7acc66e37 gpio: pca953x: re... |
195 196 197 198 199 200 201 202 203 204 205 206 207 208 |
static int pca953x_write_regs_24(struct pca953x_chip *chip, int reg, u8 *val) { int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ); return i2c_smbus_write_i2c_block_data(chip->client, (reg << bank_shift) | REG_ADDR_AI, NBANK(chip), val); } static int pca953x_write_regs(struct pca953x_chip *chip, int reg, u8 *val) { int ret = 0; ret = chip->write_regs(chip, reg, val); |
f5e8ff483 gpio: handle pca9... |
209 210 211 |
if (ret < 0) { dev_err(&chip->client->dev, "failed writing register "); |
ab5dc3720 gpio: pca953x han... |
212 |
return ret; |
f5e8ff483 gpio: handle pca9... |
213 214 215 |
} return 0; |
9e60fdcf0 gpiolib: pca9539 ... |
216 |
} |
c6e3cf01d gpio: pca953x: re... |
217 |
static int pca953x_read_regs_8(struct pca953x_chip *chip, int reg, u8 *val) |
9e60fdcf0 gpiolib: pca9539 ... |
218 219 |
{ int ret; |
c6e3cf01d gpio: pca953x: re... |
220 221 |
ret = i2c_smbus_read_byte_data(chip->client, reg); *val = ret; |
f5f0b7aa8 gpio: pca953x: ma... |
222 |
|
c6e3cf01d gpio: pca953x: re... |
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 |
return ret; } static int pca953x_read_regs_16(struct pca953x_chip *chip, int reg, u8 *val) { int ret; ret = i2c_smbus_read_word_data(chip->client, reg << 1); val[0] = (u16)ret & 0xFF; val[1] = (u16)ret >> 8; return ret; } static int pca953x_read_regs_24(struct pca953x_chip *chip, int reg, u8 *val) { int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ); return i2c_smbus_read_i2c_block_data(chip->client, (reg << bank_shift) | REG_ADDR_AI, NBANK(chip), val); } static int pca953x_read_regs(struct pca953x_chip *chip, int reg, u8 *val) { int ret; ret = chip->read_regs(chip, reg, val); |
9e60fdcf0 gpiolib: pca9539 ... |
251 252 253 |
if (ret < 0) { dev_err(&chip->client->dev, "failed reading register "); |
ab5dc3720 gpio: pca953x han... |
254 |
return ret; |
9e60fdcf0 gpiolib: pca9539 ... |
255 |
} |
9e60fdcf0 gpiolib: pca9539 ... |
256 257 |
return 0; } |
f3dc3630f gpio: rename pca9... |
258 |
static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off) |
9e60fdcf0 gpiolib: pca9539 ... |
259 |
{ |
468e67f6e gpio: pca953x: us... |
260 |
struct pca953x_chip *chip = gpiochip_get_data(gc); |
f5f0b7aa8 gpio: pca953x: ma... |
261 |
u8 reg_val; |
53661f3bc gpio: pca953x: co... |
262 |
int ret; |
9e60fdcf0 gpiolib: pca9539 ... |
263 |
|
6e20fb180 drivers/gpio/pca9... |
264 |
mutex_lock(&chip->i2c_lock); |
f5f0b7aa8 gpio: pca953x: ma... |
265 |
reg_val = chip->reg_direction[off / BANK_SZ] | (1u << (off % BANK_SZ)); |
33226ffd0 gpio/pca953x: Add... |
266 |
|
53661f3bc gpio: pca953x: co... |
267 |
ret = pca953x_write_single(chip, chip->regs->direction, reg_val, off); |
9e60fdcf0 gpiolib: pca9539 ... |
268 |
if (ret) |
6e20fb180 drivers/gpio/pca9... |
269 |
goto exit; |
9e60fdcf0 gpiolib: pca9539 ... |
270 |
|
f5f0b7aa8 gpio: pca953x: ma... |
271 |
chip->reg_direction[off / BANK_SZ] = reg_val; |
6e20fb180 drivers/gpio/pca9... |
272 273 274 |
exit: mutex_unlock(&chip->i2c_lock); return ret; |
9e60fdcf0 gpiolib: pca9539 ... |
275 |
} |
f3dc3630f gpio: rename pca9... |
276 |
static int pca953x_gpio_direction_output(struct gpio_chip *gc, |
9e60fdcf0 gpiolib: pca9539 ... |
277 278 |
unsigned off, int val) { |
468e67f6e gpio: pca953x: us... |
279 |
struct pca953x_chip *chip = gpiochip_get_data(gc); |
f5f0b7aa8 gpio: pca953x: ma... |
280 |
u8 reg_val; |
53661f3bc gpio: pca953x: co... |
281 |
int ret; |
9e60fdcf0 gpiolib: pca9539 ... |
282 |
|
6e20fb180 drivers/gpio/pca9... |
283 |
mutex_lock(&chip->i2c_lock); |
9e60fdcf0 gpiolib: pca9539 ... |
284 285 |
/* set output level */ if (val) |
f5f0b7aa8 gpio: pca953x: ma... |
286 287 |
reg_val = chip->reg_output[off / BANK_SZ] | (1u << (off % BANK_SZ)); |
9e60fdcf0 gpiolib: pca9539 ... |
288 |
else |
f5f0b7aa8 gpio: pca953x: ma... |
289 290 |
reg_val = chip->reg_output[off / BANK_SZ] & ~(1u << (off % BANK_SZ)); |
9e60fdcf0 gpiolib: pca9539 ... |
291 |
|
53661f3bc gpio: pca953x: co... |
292 |
ret = pca953x_write_single(chip, chip->regs->output, reg_val, off); |
9e60fdcf0 gpiolib: pca9539 ... |
293 |
if (ret) |
6e20fb180 drivers/gpio/pca9... |
294 |
goto exit; |
9e60fdcf0 gpiolib: pca9539 ... |
295 |
|
f5f0b7aa8 gpio: pca953x: ma... |
296 |
chip->reg_output[off / BANK_SZ] = reg_val; |
9e60fdcf0 gpiolib: pca9539 ... |
297 298 |
/* then direction */ |
f5f0b7aa8 gpio: pca953x: ma... |
299 |
reg_val = chip->reg_direction[off / BANK_SZ] & ~(1u << (off % BANK_SZ)); |
53661f3bc gpio: pca953x: co... |
300 |
ret = pca953x_write_single(chip, chip->regs->direction, reg_val, off); |
9e60fdcf0 gpiolib: pca9539 ... |
301 |
if (ret) |
6e20fb180 drivers/gpio/pca9... |
302 |
goto exit; |
9e60fdcf0 gpiolib: pca9539 ... |
303 |
|
f5f0b7aa8 gpio: pca953x: ma... |
304 |
chip->reg_direction[off / BANK_SZ] = reg_val; |
6e20fb180 drivers/gpio/pca9... |
305 306 307 |
exit: mutex_unlock(&chip->i2c_lock); return ret; |
9e60fdcf0 gpiolib: pca9539 ... |
308 |
} |
f3dc3630f gpio: rename pca9... |
309 |
static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off) |
9e60fdcf0 gpiolib: pca9539 ... |
310 |
{ |
468e67f6e gpio: pca953x: us... |
311 |
struct pca953x_chip *chip = gpiochip_get_data(gc); |
ae79c1904 Add support for T... |
312 |
u32 reg_val; |
53661f3bc gpio: pca953x: co... |
313 |
int ret; |
9e60fdcf0 gpiolib: pca9539 ... |
314 |
|
6e20fb180 drivers/gpio/pca9... |
315 |
mutex_lock(&chip->i2c_lock); |
53661f3bc gpio: pca953x: co... |
316 |
ret = pca953x_read_single(chip, chip->regs->input, ®_val, off); |
6e20fb180 drivers/gpio/pca9... |
317 |
mutex_unlock(&chip->i2c_lock); |
9e60fdcf0 gpiolib: pca9539 ... |
318 319 320 321 322 323 324 |
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; } |
40a625daa gpio: pca953x: fi... |
325 |
return (reg_val & (1u << (off % BANK_SZ))) ? 1 : 0; |
9e60fdcf0 gpiolib: pca9539 ... |
326 |
} |
f3dc3630f gpio: rename pca9... |
327 |
static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val) |
9e60fdcf0 gpiolib: pca9539 ... |
328 |
{ |
468e67f6e gpio: pca953x: us... |
329 |
struct pca953x_chip *chip = gpiochip_get_data(gc); |
f5f0b7aa8 gpio: pca953x: ma... |
330 |
u8 reg_val; |
53661f3bc gpio: pca953x: co... |
331 |
int ret; |
9e60fdcf0 gpiolib: pca9539 ... |
332 |
|
6e20fb180 drivers/gpio/pca9... |
333 |
mutex_lock(&chip->i2c_lock); |
9e60fdcf0 gpiolib: pca9539 ... |
334 |
if (val) |
f5f0b7aa8 gpio: pca953x: ma... |
335 336 |
reg_val = chip->reg_output[off / BANK_SZ] | (1u << (off % BANK_SZ)); |
9e60fdcf0 gpiolib: pca9539 ... |
337 |
else |
f5f0b7aa8 gpio: pca953x: ma... |
338 339 |
reg_val = chip->reg_output[off / BANK_SZ] & ~(1u << (off % BANK_SZ)); |
9e60fdcf0 gpiolib: pca9539 ... |
340 |
|
53661f3bc gpio: pca953x: co... |
341 |
ret = pca953x_write_single(chip, chip->regs->output, reg_val, off); |
9e60fdcf0 gpiolib: pca9539 ... |
342 |
if (ret) |
6e20fb180 drivers/gpio/pca9... |
343 |
goto exit; |
9e60fdcf0 gpiolib: pca9539 ... |
344 |
|
f5f0b7aa8 gpio: pca953x: ma... |
345 |
chip->reg_output[off / BANK_SZ] = reg_val; |
6e20fb180 drivers/gpio/pca9... |
346 347 |
exit: mutex_unlock(&chip->i2c_lock); |
9e60fdcf0 gpiolib: pca9539 ... |
348 |
} |
b4818afea gpio: pca953x: Ad... |
349 |
static void pca953x_gpio_set_multiple(struct gpio_chip *gc, |
ea3d579d8 gpio: pca953x: co... |
350 |
unsigned long *mask, unsigned long *bits) |
b4818afea gpio: pca953x: Ad... |
351 |
{ |
468e67f6e gpio: pca953x: us... |
352 |
struct pca953x_chip *chip = gpiochip_get_data(gc); |
ea3d579d8 gpio: pca953x: co... |
353 354 |
unsigned int bank_mask, bank_val; int bank_shift, bank; |
b4818afea gpio: pca953x: Ad... |
355 |
u8 reg_val[MAX_BANK]; |
53661f3bc gpio: pca953x: co... |
356 |
int ret; |
ea3d579d8 gpio: pca953x: co... |
357 358 |
bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ); |
b4818afea gpio: pca953x: Ad... |
359 |
|
b4818afea gpio: pca953x: Ad... |
360 |
mutex_lock(&chip->i2c_lock); |
386377b54 gpio: pca953x: Mo... |
361 |
memcpy(reg_val, chip->reg_output, NBANK(chip)); |
ea3d579d8 gpio: pca953x: co... |
362 363 364 365 366 367 |
for (bank = 0; bank < NBANK(chip); bank++) { bank_mask = mask[bank / sizeof(*mask)] >> ((bank % sizeof(*mask)) * 8); if (bank_mask) { bank_val = bits[bank / sizeof(*bits)] >> ((bank % sizeof(*bits)) * 8); |
53f8d3222 gpio: pca953x: Fi... |
368 |
bank_val &= bank_mask; |
ea3d579d8 gpio: pca953x: co... |
369 |
reg_val[bank] = (reg_val[bank] & ~bank_mask) | bank_val; |
b4818afea gpio: pca953x: Ad... |
370 371 |
} } |
ea3d579d8 gpio: pca953x: co... |
372 |
|
53661f3bc gpio: pca953x: co... |
373 374 375 |
ret = i2c_smbus_write_i2c_block_data(chip->client, chip->regs->output << bank_shift, NBANK(chip), reg_val); |
b4818afea gpio: pca953x: Ad... |
376 377 378 379 380 381 382 |
if (ret) goto exit; memcpy(chip->reg_output, reg_val, NBANK(chip)); exit: mutex_unlock(&chip->i2c_lock); } |
f5e8ff483 gpio: handle pca9... |
383 |
static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios) |
9e60fdcf0 gpiolib: pca9539 ... |
384 385 386 387 |
{ struct gpio_chip *gc; gc = &chip->gpio_chip; |
f3dc3630f gpio: rename pca9... |
388 389 390 391 |
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; |
b4818afea gpio: pca953x: Ad... |
392 |
gc->set_multiple = pca953x_gpio_set_multiple; |
9fb1f39eb gpio/pinctrl: mak... |
393 |
gc->can_sleep = true; |
9e60fdcf0 gpiolib: pca9539 ... |
394 395 |
gc->base = chip->gpio_start; |
f5e8ff483 gpio: handle pca9... |
396 397 |
gc->ngpio = gpios; gc->label = chip->client->name; |
58383c784 gpio: change memb... |
398 |
gc->parent = &chip->client->dev; |
d72cbed0c gpiolib: i2c/spi ... |
399 |
gc->owner = THIS_MODULE; |
77906a546 pca953x: support ... |
400 |
gc->names = chip->names; |
9e60fdcf0 gpiolib: pca9539 ... |
401 |
} |
89ea8bbe9 gpio: pca953x.c: ... |
402 |
#ifdef CONFIG_GPIO_PCA953X_IRQ |
6f5cfc0e2 gpio: pca953x: ir... |
403 |
static void pca953x_irq_mask(struct irq_data *d) |
89ea8bbe9 gpio: pca953x.c: ... |
404 |
{ |
7bcbce55f gpio: pca953x: us... |
405 |
struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
468e67f6e gpio: pca953x: us... |
406 |
struct pca953x_chip *chip = gpiochip_get_data(gc); |
89ea8bbe9 gpio: pca953x.c: ... |
407 |
|
f5f0b7aa8 gpio: pca953x: ma... |
408 |
chip->irq_mask[d->hwirq / BANK_SZ] &= ~(1 << (d->hwirq % BANK_SZ)); |
89ea8bbe9 gpio: pca953x.c: ... |
409 |
} |
6f5cfc0e2 gpio: pca953x: ir... |
410 |
static void pca953x_irq_unmask(struct irq_data *d) |
89ea8bbe9 gpio: pca953x.c: ... |
411 |
{ |
7bcbce55f gpio: pca953x: us... |
412 |
struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
468e67f6e gpio: pca953x: us... |
413 |
struct pca953x_chip *chip = gpiochip_get_data(gc); |
89ea8bbe9 gpio: pca953x.c: ... |
414 |
|
f5f0b7aa8 gpio: pca953x: ma... |
415 |
chip->irq_mask[d->hwirq / BANK_SZ] |= 1 << (d->hwirq % BANK_SZ); |
89ea8bbe9 gpio: pca953x.c: ... |
416 |
} |
6f5cfc0e2 gpio: pca953x: ir... |
417 |
static void pca953x_irq_bus_lock(struct irq_data *d) |
89ea8bbe9 gpio: pca953x.c: ... |
418 |
{ |
7bcbce55f gpio: pca953x: us... |
419 |
struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
468e67f6e gpio: pca953x: us... |
420 |
struct pca953x_chip *chip = gpiochip_get_data(gc); |
89ea8bbe9 gpio: pca953x.c: ... |
421 422 423 |
mutex_lock(&chip->irq_lock); } |
6f5cfc0e2 gpio: pca953x: ir... |
424 |
static void pca953x_irq_bus_sync_unlock(struct irq_data *d) |
89ea8bbe9 gpio: pca953x.c: ... |
425 |
{ |
7bcbce55f gpio: pca953x: us... |
426 |
struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
468e67f6e gpio: pca953x: us... |
427 |
struct pca953x_chip *chip = gpiochip_get_data(gc); |
f5f0b7aa8 gpio: pca953x: ma... |
428 429 |
u8 new_irqs; int level, i; |
44896beae gpio: pca953x: ad... |
430 431 432 433 434 435 436 437 438 439 440 441 |
u8 invert_irq_mask[MAX_BANK]; if (chip->driver_data & PCA_PCAL) { /* Enable latch on interrupt-enabled inputs */ pca953x_write_regs(chip, PCAL953X_IN_LATCH, chip->irq_mask); for (i = 0; i < NBANK(chip); i++) invert_irq_mask[i] = ~chip->irq_mask[i]; /* Unmask enabled interrupts */ pca953x_write_regs(chip, PCAL953X_INT_MASK, invert_irq_mask); } |
a2cb9aeb3 gpio: fix pca953x... |
442 443 |
/* Look for any newly setup interrupt */ |
f5f0b7aa8 gpio: pca953x: ma... |
444 445 446 447 448 449 450 451 452 453 |
for (i = 0; i < NBANK(chip); i++) { new_irqs = chip->irq_trig_fall[i] | chip->irq_trig_raise[i]; new_irqs &= ~chip->reg_direction[i]; while (new_irqs) { level = __ffs(new_irqs); pca953x_gpio_direction_input(&chip->gpio_chip, level + (BANK_SZ * i)); new_irqs &= ~(1 << level); } |
a2cb9aeb3 gpio: fix pca953x... |
454 |
} |
89ea8bbe9 gpio: pca953x.c: ... |
455 456 457 |
mutex_unlock(&chip->irq_lock); } |
6f5cfc0e2 gpio: pca953x: ir... |
458 |
static int pca953x_irq_set_type(struct irq_data *d, unsigned int type) |
89ea8bbe9 gpio: pca953x.c: ... |
459 |
{ |
7bcbce55f gpio: pca953x: us... |
460 |
struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
468e67f6e gpio: pca953x: us... |
461 |
struct pca953x_chip *chip = gpiochip_get_data(gc); |
f5f0b7aa8 gpio: pca953x: ma... |
462 463 |
int bank_nb = d->hwirq / BANK_SZ; u8 mask = 1 << (d->hwirq % BANK_SZ); |
89ea8bbe9 gpio: pca953x.c: ... |
464 465 466 467 |
if (!(type & IRQ_TYPE_EDGE_BOTH)) { dev_err(&chip->client->dev, "irq %d: unsupported type %d ", |
6f5cfc0e2 gpio: pca953x: ir... |
468 |
d->irq, type); |
89ea8bbe9 gpio: pca953x.c: ... |
469 470 471 472 |
return -EINVAL; } if (type & IRQ_TYPE_EDGE_FALLING) |
f5f0b7aa8 gpio: pca953x: ma... |
473 |
chip->irq_trig_fall[bank_nb] |= mask; |
89ea8bbe9 gpio: pca953x.c: ... |
474 |
else |
f5f0b7aa8 gpio: pca953x: ma... |
475 |
chip->irq_trig_fall[bank_nb] &= ~mask; |
89ea8bbe9 gpio: pca953x.c: ... |
476 477 |
if (type & IRQ_TYPE_EDGE_RISING) |
f5f0b7aa8 gpio: pca953x: ma... |
478 |
chip->irq_trig_raise[bank_nb] |= mask; |
89ea8bbe9 gpio: pca953x.c: ... |
479 |
else |
f5f0b7aa8 gpio: pca953x: ma... |
480 |
chip->irq_trig_raise[bank_nb] &= ~mask; |
89ea8bbe9 gpio: pca953x.c: ... |
481 |
|
a2cb9aeb3 gpio: fix pca953x... |
482 |
return 0; |
89ea8bbe9 gpio: pca953x.c: ... |
483 484 485 486 |
} static struct irq_chip pca953x_irq_chip = { .name = "pca953x", |
6f5cfc0e2 gpio: pca953x: ir... |
487 488 489 490 491 |
.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: ... |
492 |
}; |
b6ac1280b gpio: Prevent an ... |
493 |
static bool pca953x_irq_pending(struct pca953x_chip *chip, u8 *pending) |
89ea8bbe9 gpio: pca953x.c: ... |
494 |
{ |
f5f0b7aa8 gpio: pca953x: ma... |
495 496 |
u8 cur_stat[MAX_BANK]; u8 old_stat[MAX_BANK]; |
b6ac1280b gpio: Prevent an ... |
497 498 499 |
bool pending_seen = false; bool trigger_seen = false; u8 trigger[MAX_BANK]; |
53661f3bc gpio: pca953x: co... |
500 |
int ret, i; |
33226ffd0 gpio/pca953x: Add... |
501 |
|
44896beae gpio: pca953x: ad... |
502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 |
if (chip->driver_data & PCA_PCAL) { /* Read the current interrupt status from the device */ ret = pca953x_read_regs(chip, PCAL953X_INT_STAT, trigger); if (ret) return false; /* Check latched inputs and clear interrupt status */ ret = pca953x_read_regs(chip, PCA953X_INPUT, cur_stat); if (ret) return false; for (i = 0; i < NBANK(chip); i++) { /* Apply filter for rising/falling edge selection */ pending[i] = (~cur_stat[i] & chip->irq_trig_fall[i]) | (cur_stat[i] & chip->irq_trig_raise[i]); pending[i] &= trigger[i]; if (pending[i]) pending_seen = true; } return pending_seen; } |
53661f3bc gpio: pca953x: co... |
524 |
ret = pca953x_read_regs(chip, chip->regs->input, cur_stat); |
89ea8bbe9 gpio: pca953x.c: ... |
525 |
if (ret) |
b6ac1280b gpio: Prevent an ... |
526 |
return false; |
89ea8bbe9 gpio: pca953x.c: ... |
527 528 |
/* Remove output pins from the equation */ |
f5f0b7aa8 gpio: pca953x: ma... |
529 530 |
for (i = 0; i < NBANK(chip); i++) cur_stat[i] &= chip->reg_direction[i]; |
89ea8bbe9 gpio: pca953x.c: ... |
531 |
|
f5f0b7aa8 gpio: pca953x: ma... |
532 |
memcpy(old_stat, chip->irq_stat, NBANK(chip)); |
89ea8bbe9 gpio: pca953x.c: ... |
533 |
|
f5f0b7aa8 gpio: pca953x: ma... |
534 535 |
for (i = 0; i < NBANK(chip); i++) { trigger[i] = (cur_stat[i] ^ old_stat[i]) & chip->irq_mask[i]; |
b6ac1280b gpio: Prevent an ... |
536 537 |
if (trigger[i]) trigger_seen = true; |
f5f0b7aa8 gpio: pca953x: ma... |
538 |
} |
b6ac1280b gpio: Prevent an ... |
539 540 |
if (!trigger_seen) return false; |
89ea8bbe9 gpio: pca953x.c: ... |
541 |
|
f5f0b7aa8 gpio: pca953x: ma... |
542 |
memcpy(chip->irq_stat, cur_stat, NBANK(chip)); |
89ea8bbe9 gpio: pca953x.c: ... |
543 |
|
f5f0b7aa8 gpio: pca953x: ma... |
544 545 546 547 |
for (i = 0; i < NBANK(chip); i++) { pending[i] = (old_stat[i] & chip->irq_trig_fall[i]) | (cur_stat[i] & chip->irq_trig_raise[i]); pending[i] &= trigger[i]; |
b6ac1280b gpio: Prevent an ... |
548 549 |
if (pending[i]) pending_seen = true; |
f5f0b7aa8 gpio: pca953x: ma... |
550 |
} |
89ea8bbe9 gpio: pca953x.c: ... |
551 |
|
b6ac1280b gpio: Prevent an ... |
552 |
return pending_seen; |
89ea8bbe9 gpio: pca953x.c: ... |
553 554 555 556 557 |
} static irqreturn_t pca953x_irq_handler(int irq, void *devid) { struct pca953x_chip *chip = devid; |
f5f0b7aa8 gpio: pca953x: ma... |
558 559 |
u8 pending[MAX_BANK]; u8 level; |
3275d0723 gpio: pca953x: re... |
560 |
unsigned nhandled = 0; |
f5f0b7aa8 gpio: pca953x: ma... |
561 |
int i; |
89ea8bbe9 gpio: pca953x.c: ... |
562 |
|
f5f0b7aa8 gpio: pca953x: ma... |
563 |
if (!pca953x_irq_pending(chip, pending)) |
3275d0723 gpio: pca953x: re... |
564 |
return IRQ_NONE; |
89ea8bbe9 gpio: pca953x.c: ... |
565 |
|
f5f0b7aa8 gpio: pca953x: ma... |
566 567 568 |
for (i = 0; i < NBANK(chip); i++) { while (pending[i]) { level = __ffs(pending[i]); |
7bcbce55f gpio: pca953x: us... |
569 |
handle_nested_irq(irq_find_mapping(chip->gpio_chip.irqdomain, |
f5f0b7aa8 gpio: pca953x: ma... |
570 571 |
level + (BANK_SZ * i))); pending[i] &= ~(1 << level); |
3275d0723 gpio: pca953x: re... |
572 |
nhandled++; |
f5f0b7aa8 gpio: pca953x: ma... |
573 574 |
} } |
89ea8bbe9 gpio: pca953x.c: ... |
575 |
|
3275d0723 gpio: pca953x: re... |
576 |
return (nhandled > 0) ? IRQ_HANDLED : IRQ_NONE; |
89ea8bbe9 gpio: pca953x.c: ... |
577 578 579 |
} static int pca953x_irq_setup(struct pca953x_chip *chip, |
c6dcf5924 gpio/pca953x: Rem... |
580 |
int irq_base) |
89ea8bbe9 gpio: pca953x.c: ... |
581 582 |
{ struct i2c_client *client = chip->client; |
53661f3bc gpio: pca953x: co... |
583 |
int ret, i; |
89ea8bbe9 gpio: pca953x.c: ... |
584 |
|
4bb93349d gpio: pca953x: Dr... |
585 |
if (client->irq && irq_base != -1 |
c6664149a gpio: pca953x: st... |
586 |
&& (chip->driver_data & PCA_INT)) { |
53661f3bc gpio: pca953x: co... |
587 588 |
ret = pca953x_read_regs(chip, chip->regs->input, chip->irq_stat); |
89ea8bbe9 gpio: pca953x.c: ... |
589 |
if (ret) |
b42748c97 gpio: pca953x: us... |
590 |
return ret; |
89ea8bbe9 gpio: pca953x.c: ... |
591 592 593 594 595 596 |
/* * There is no way to know which GPIO line generated the * interrupt. We have to rely on the previous read for * this purpose. */ |
f5f0b7aa8 gpio: pca953x: ma... |
597 598 |
for (i = 0; i < NBANK(chip); i++) chip->irq_stat[i] &= chip->reg_direction[i]; |
89ea8bbe9 gpio: pca953x.c: ... |
599 |
mutex_init(&chip->irq_lock); |
b42748c97 gpio: pca953x: us... |
600 601 |
ret = devm_request_threaded_irq(&client->dev, client->irq, |
89ea8bbe9 gpio: pca953x.c: ... |
602 603 |
NULL, pca953x_irq_handler, |
91329132c gpio: pca953x: re... |
604 605 |
IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED, |
89ea8bbe9 gpio: pca953x.c: ... |
606 607 608 609 610 |
dev_name(&client->dev), chip); if (ret) { dev_err(&client->dev, "failed to request irq %d ", client->irq); |
0e8f2fdac gpio: pca953x: us... |
611 |
return ret; |
89ea8bbe9 gpio: pca953x.c: ... |
612 |
} |
7bcbce55f gpio: pca953x: us... |
613 614 615 616 617 618 619 620 621 622 623 |
ret = gpiochip_irqchip_add(&chip->gpio_chip, &pca953x_irq_chip, irq_base, handle_simple_irq, IRQ_TYPE_NONE); if (ret) { dev_err(&client->dev, "could not connect irqchip to gpiochip "); return ret; } |
fdd50409c gpio: pca953x: fi... |
624 625 626 627 |
gpiochip_set_chained_irqchip(&chip->gpio_chip, &pca953x_irq_chip, client->irq, NULL); |
89ea8bbe9 gpio: pca953x.c: ... |
628 629 630 |
} return 0; |
89ea8bbe9 gpio: pca953x.c: ... |
631 |
} |
89ea8bbe9 gpio: pca953x.c: ... |
632 633 |
#else /* CONFIG_GPIO_PCA953X_IRQ */ static int pca953x_irq_setup(struct pca953x_chip *chip, |
c6dcf5924 gpio/pca953x: Rem... |
634 |
int irq_base) |
89ea8bbe9 gpio: pca953x.c: ... |
635 636 |
{ struct i2c_client *client = chip->client; |
89ea8bbe9 gpio: pca953x.c: ... |
637 |
|
c6664149a gpio: pca953x: st... |
638 |
if (irq_base != -1 && (chip->driver_data & PCA_INT)) |
89ea8bbe9 gpio: pca953x.c: ... |
639 640 641 642 643 |
dev_warn(&client->dev, "interrupt support not compiled in "); return 0; } |
89ea8bbe9 gpio: pca953x.c: ... |
644 |
#endif |
3836309d9 gpio: remove use ... |
645 |
static int device_pca953x_init(struct pca953x_chip *chip, u32 invert) |
33226ffd0 gpio/pca953x: Add... |
646 647 |
{ int ret; |
f5f0b7aa8 gpio: pca953x: ma... |
648 |
u8 val[MAX_BANK]; |
33226ffd0 gpio/pca953x: Add... |
649 |
|
53661f3bc gpio: pca953x: co... |
650 651 652 |
chip->regs = &pca953x_regs; ret = pca953x_read_regs(chip, chip->regs->output, chip->reg_output); |
33226ffd0 gpio/pca953x: Add... |
653 654 |
if (ret) goto out; |
53661f3bc gpio: pca953x: co... |
655 656 |
ret = pca953x_read_regs(chip, chip->regs->direction, chip->reg_direction); |
33226ffd0 gpio/pca953x: Add... |
657 658 659 660 |
if (ret) goto out; /* set platform specific polarity inversion */ |
f5f0b7aa8 gpio: pca953x: ma... |
661 662 663 664 665 666 |
if (invert) memset(val, 0xFF, NBANK(chip)); else memset(val, 0, NBANK(chip)); ret = pca953x_write_regs(chip, PCA953X_INVERT, val); |
33226ffd0 gpio/pca953x: Add... |
667 668 669 |
out: return ret; } |
3836309d9 gpio: remove use ... |
670 |
static int device_pca957x_init(struct pca953x_chip *chip, u32 invert) |
33226ffd0 gpio/pca953x: Add... |
671 672 |
{ int ret; |
f5f0b7aa8 gpio: pca953x: ma... |
673 |
u8 val[MAX_BANK]; |
33226ffd0 gpio/pca953x: Add... |
674 |
|
53661f3bc gpio: pca953x: co... |
675 676 677 |
chip->regs = &pca957x_regs; ret = pca953x_read_regs(chip, chip->regs->output, chip->reg_output); |
33226ffd0 gpio/pca953x: Add... |
678 679 |
if (ret) goto out; |
53661f3bc gpio: pca953x: co... |
680 681 |
ret = pca953x_read_regs(chip, chip->regs->direction, chip->reg_direction); |
33226ffd0 gpio/pca953x: Add... |
682 683 684 685 |
if (ret) goto out; /* set platform specific polarity inversion */ |
f5f0b7aa8 gpio: pca953x: ma... |
686 687 688 689 |
if (invert) memset(val, 0xFF, NBANK(chip)); else memset(val, 0, NBANK(chip)); |
c75a37720 gpio: Fix error c... |
690 691 692 |
ret = pca953x_write_regs(chip, PCA957X_INVRT, val); if (ret) goto out; |
33226ffd0 gpio/pca953x: Add... |
693 |
|
20a8a9687 Drivers: gpio: Fi... |
694 |
/* To enable register 6, 7 to control pull up and pull down */ |
f5f0b7aa8 gpio: pca953x: ma... |
695 |
memset(val, 0x02, NBANK(chip)); |
c75a37720 gpio: Fix error c... |
696 697 698 |
ret = pca953x_write_regs(chip, PCA957X_BKEN, val); if (ret) goto out; |
33226ffd0 gpio/pca953x: Add... |
699 700 701 702 703 |
return 0; out: return ret; } |
6f29c9afb gpio: pca935x: fi... |
704 |
static const struct of_device_id pca953x_dt_ids[]; |
3836309d9 gpio: remove use ... |
705 |
static int pca953x_probe(struct i2c_client *client, |
6212e1d6e gpio: pca953x: va... |
706 |
const struct i2c_device_id *i2c_id) |
9e60fdcf0 gpiolib: pca9539 ... |
707 |
{ |
f3dc3630f gpio: rename pca9... |
708 709 |
struct pca953x_platform_data *pdata; struct pca953x_chip *chip; |
6a7b36aa4 GPIO: PCA953X: In... |
710 |
int irq_base = 0; |
7ea2aa204 gpio: pca953x: pr... |
711 |
int ret; |
6a7b36aa4 GPIO: PCA953X: In... |
712 |
u32 invert = 0; |
e23efa311 gpio: pca954x: Ad... |
713 |
struct regulator *reg; |
9e60fdcf0 gpiolib: pca9539 ... |
714 |
|
b42748c97 gpio: pca953x: us... |
715 716 |
chip = devm_kzalloc(&client->dev, sizeof(struct pca953x_chip), GFP_KERNEL); |
1965d3035 gpio: pca953x: Ge... |
717 718 |
if (chip == NULL) return -ENOMEM; |
e56aee189 gpio: use dev_get... |
719 |
pdata = dev_get_platdata(&client->dev); |
c6dcf5924 gpio/pca953x: Rem... |
720 721 722 723 724 725 |
if (pdata) { irq_base = pdata->irq_base; chip->gpio_start = pdata->gpio_base; invert = pdata->invert; chip->names = pdata->names; } else { |
4bb93349d gpio: pca953x: Dr... |
726 727 |
chip->gpio_start = -1; irq_base = 0; |
1965d3035 gpio: pca953x: Ge... |
728 |
} |
9e60fdcf0 gpiolib: pca9539 ... |
729 730 |
chip->client = client; |
e23efa311 gpio: pca954x: Ad... |
731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 |
reg = devm_regulator_get(&client->dev, "vcc"); if (IS_ERR(reg)) { ret = PTR_ERR(reg); if (ret != -EPROBE_DEFER) dev_err(&client->dev, "reg get err: %d ", ret); return ret; } ret = regulator_enable(reg); if (ret) { dev_err(&client->dev, "reg en err: %d ", ret); return ret; } chip->regulator = reg; |
6212e1d6e gpio: pca953x: va... |
746 747 |
if (i2c_id) { chip->driver_data = i2c_id->driver_data; |
f32517bf1 gpio: pca953x: su... |
748 |
} else { |
6212e1d6e gpio: pca953x: va... |
749 |
const struct acpi_device_id *acpi_id; |
6f29c9afb gpio: pca935x: fi... |
750 |
const struct of_device_id *match; |
f32517bf1 gpio: pca953x: su... |
751 |
|
6f29c9afb gpio: pca935x: fi... |
752 753 754 755 |
match = of_match_device(pca953x_dt_ids, &client->dev); if (match) { chip->driver_data = (int)(uintptr_t)match->data; } else { |
6212e1d6e gpio: pca953x: va... |
756 |
acpi_id = acpi_match_device(pca953x_acpi_ids, &client->dev); |
87840a2b7 Merge branch 'i2c... |
757 |
if (!acpi_id) { |
e23efa311 gpio: pca954x: Ad... |
758 759 760 |
ret = -ENODEV; goto err_exit; } |
f32517bf1 gpio: pca953x: su... |
761 |
|
6212e1d6e gpio: pca953x: va... |
762 |
chip->driver_data = acpi_id->driver_data; |
6f29c9afb gpio: pca935x: fi... |
763 |
} |
f32517bf1 gpio: pca953x: su... |
764 |
} |
6e20fb180 drivers/gpio/pca9... |
765 |
mutex_init(&chip->i2c_lock); |
74f47f07e gpio: pca953x: ad... |
766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 |
/* * In case we have an i2c-mux controlled by a GPIO provided by an * expander using the same driver higher on the device tree, read the * i2c adapter nesting depth and use the retrieved value as lockdep * subclass for chip->i2c_lock. * * REVISIT: This solution is not complete. It protects us from lockdep * false positives when the expander controlling the i2c-mux is on * a different level on the device tree, but not when it's on the same * level on a different branch (in which case the subclass number * would be the same). * * TODO: Once a correct solution is developed, a similar fix should be * applied to all other i2c-controlled GPIO expanders (and potentially * regmap-i2c). */ |
559b46990 gpio: pca953x: fi... |
782 783 |
lockdep_set_subclass(&chip->i2c_lock, i2c_adapter_depth(client->adapter)); |
6e20fb180 drivers/gpio/pca9... |
784 |
|
bab58491c MLK-11293: gpio: ... |
785 |
ret = device_reset(&client->dev); |
67d607f7f MLK-13773 gpio: p... |
786 |
if (ret == -EPROBE_DEFER) |
bab58491c MLK-11293: gpio: ... |
787 |
return -EPROBE_DEFER; |
9e60fdcf0 gpiolib: pca9539 ... |
788 789 790 |
/* initialize cached registers from their original values. * we can't share this chip with another i2c master. */ |
c6664149a gpio: pca953x: st... |
791 |
pca953x_setup_gpio(chip, chip->driver_data & PCA_GPIO_MASK); |
f5e8ff483 gpio: handle pca9... |
792 |
|
7acc66e37 gpio: pca953x: re... |
793 794 |
if (chip->gpio_chip.ngpio <= 8) { chip->write_regs = pca953x_write_regs_8; |
c6e3cf01d gpio: pca953x: re... |
795 |
chip->read_regs = pca953x_read_regs_8; |
7acc66e37 gpio: pca953x: re... |
796 797 |
} else if (chip->gpio_chip.ngpio >= 24) { chip->write_regs = pca953x_write_regs_24; |
c6e3cf01d gpio: pca953x: re... |
798 |
chip->read_regs = pca953x_read_regs_24; |
7acc66e37 gpio: pca953x: re... |
799 800 801 802 803 |
} else { if (PCA_CHIP_TYPE(chip->driver_data) == PCA953X_TYPE) chip->write_regs = pca953x_write_regs_16; else chip->write_regs = pca957x_write_regs_16; |
c6e3cf01d gpio: pca953x: re... |
804 |
chip->read_regs = pca953x_read_regs_16; |
7acc66e37 gpio: pca953x: re... |
805 |
} |
60f547be8 gpio: pca953x: re... |
806 |
if (PCA_CHIP_TYPE(chip->driver_data) == PCA953X_TYPE) |
7ea2aa204 gpio: pca953x: pr... |
807 |
ret = device_pca953x_init(chip, invert); |
33226ffd0 gpio/pca953x: Add... |
808 |
else |
7ea2aa204 gpio: pca953x: pr... |
809 810 |
ret = device_pca957x_init(chip, invert); if (ret) |
e23efa311 gpio: pca954x: Ad... |
811 |
goto err_exit; |
9e60fdcf0 gpiolib: pca9539 ... |
812 |
|
0ece84f54 gpio: pca953x: Us... |
813 |
ret = devm_gpiochip_add_data(&client->dev, &chip->gpio_chip, chip); |
89ea8bbe9 gpio: pca953x.c: ... |
814 |
if (ret) |
e23efa311 gpio: pca954x: Ad... |
815 |
goto err_exit; |
f5e8ff483 gpio: handle pca9... |
816 |
|
c6664149a gpio: pca953x: st... |
817 |
ret = pca953x_irq_setup(chip, irq_base); |
9e60fdcf0 gpiolib: pca9539 ... |
818 |
if (ret) |
e23efa311 gpio: pca954x: Ad... |
819 |
goto err_exit; |
9e60fdcf0 gpiolib: pca9539 ... |
820 |
|
c6dcf5924 gpio/pca953x: Rem... |
821 |
if (pdata && pdata->setup) { |
9e60fdcf0 gpiolib: pca9539 ... |
822 823 824 825 826 827 828 829 830 |
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; |
e23efa311 gpio: pca954x: Ad... |
831 832 833 834 |
err_exit: regulator_disable(chip->regulator); return ret; |
9e60fdcf0 gpiolib: pca9539 ... |
835 |
} |
f3dc3630f gpio: rename pca9... |
836 |
static int pca953x_remove(struct i2c_client *client) |
9e60fdcf0 gpiolib: pca9539 ... |
837 |
{ |
e56aee189 gpio: use dev_get... |
838 |
struct pca953x_platform_data *pdata = dev_get_platdata(&client->dev); |
f3dc3630f gpio: rename pca9... |
839 |
struct pca953x_chip *chip = i2c_get_clientdata(client); |
d147d5489 Revert "gpio: pca... |
840 |
int ret; |
9e60fdcf0 gpiolib: pca9539 ... |
841 |
|
c6dcf5924 gpio/pca953x: Rem... |
842 |
if (pdata && pdata->teardown) { |
9e60fdcf0 gpiolib: pca9539 ... |
843 844 |
ret = pdata->teardown(client, chip->gpio_chip.base, chip->gpio_chip.ngpio, pdata->context); |
e23efa311 gpio: pca954x: Ad... |
845 |
if (ret < 0) |
9e60fdcf0 gpiolib: pca9539 ... |
846 847 848 |
dev_err(&client->dev, "%s failed, %d ", "teardown", ret); |
bf62efeb1 gpio: pca954x: fi... |
849 850 |
} else { ret = 0; |
9e60fdcf0 gpiolib: pca9539 ... |
851 |
} |
e23efa311 gpio: pca954x: Ad... |
852 853 854 |
regulator_disable(chip->regulator); return ret; |
9e60fdcf0 gpiolib: pca9539 ... |
855 |
} |
6f29c9afb gpio: pca935x: fi... |
856 857 858 |
/* convenience to stop overlong match-table lines */ #define OF_953X(__nrgpio, __int) (void *)(__nrgpio | PCA953X_TYPE | __int) #define OF_957X(__nrgpio, __int) (void *)(__nrgpio | PCA957X_TYPE | __int) |
ed32620ea gpio: pca953x: Ad... |
859 |
static const struct of_device_id pca953x_dt_ids[] = { |
6f29c9afb gpio: pca935x: fi... |
860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 |
{ .compatible = "nxp,pca9505", .data = OF_953X(40, PCA_INT), }, { .compatible = "nxp,pca9534", .data = OF_953X( 8, PCA_INT), }, { .compatible = "nxp,pca9535", .data = OF_953X(16, PCA_INT), }, { .compatible = "nxp,pca9536", .data = OF_953X( 4, 0), }, { .compatible = "nxp,pca9537", .data = OF_953X( 4, PCA_INT), }, { .compatible = "nxp,pca9538", .data = OF_953X( 8, PCA_INT), }, { .compatible = "nxp,pca9539", .data = OF_953X(16, PCA_INT), }, { .compatible = "nxp,pca9554", .data = OF_953X( 8, PCA_INT), }, { .compatible = "nxp,pca9555", .data = OF_953X(16, PCA_INT), }, { .compatible = "nxp,pca9556", .data = OF_953X( 8, 0), }, { .compatible = "nxp,pca9557", .data = OF_953X( 8, 0), }, { .compatible = "nxp,pca9574", .data = OF_957X( 8, PCA_INT), }, { .compatible = "nxp,pca9575", .data = OF_957X(16, PCA_INT), }, { .compatible = "nxp,pca9698", .data = OF_953X(40, 0), }, { .compatible = "maxim,max7310", .data = OF_953X( 8, 0), }, { .compatible = "maxim,max7312", .data = OF_953X(16, PCA_INT), }, { .compatible = "maxim,max7313", .data = OF_953X(16, PCA_INT), }, { .compatible = "maxim,max7315", .data = OF_953X( 8, PCA_INT), }, { .compatible = "ti,pca6107", .data = OF_953X( 8, PCA_INT), }, |
353661dfe gpio: pca953x: Ad... |
881 |
{ .compatible = "ti,pca9536", .data = OF_953X( 4, 0), }, |
6f29c9afb gpio: pca935x: fi... |
882 883 884 885 886 887 888 |
{ .compatible = "ti,tca6408", .data = OF_953X( 8, PCA_INT), }, { .compatible = "ti,tca6416", .data = OF_953X(16, PCA_INT), }, { .compatible = "ti,tca6424", .data = OF_953X(24, PCA_INT), }, { .compatible = "onsemi,pca9654", .data = OF_953X( 8, PCA_INT), }, { .compatible = "exar,xra1202", .data = OF_953X( 8, 0), }, |
ed32620ea gpio: pca953x: Ad... |
889 890 891 892 |
{ } }; MODULE_DEVICE_TABLE(of, pca953x_dt_ids); |
f3dc3630f gpio: rename pca9... |
893 |
static struct i2c_driver pca953x_driver = { |
9e60fdcf0 gpiolib: pca9539 ... |
894 |
.driver = { |
f3dc3630f gpio: rename pca9... |
895 |
.name = "pca953x", |
ed32620ea gpio: pca953x: Ad... |
896 |
.of_match_table = pca953x_dt_ids, |
f32517bf1 gpio: pca953x: su... |
897 |
.acpi_match_table = ACPI_PTR(pca953x_acpi_ids), |
9e60fdcf0 gpiolib: pca9539 ... |
898 |
}, |
f3dc3630f gpio: rename pca9... |
899 900 |
.probe = pca953x_probe, .remove = pca953x_remove, |
3760f7367 i2c: Convert most... |
901 |
.id_table = pca953x_id, |
9e60fdcf0 gpiolib: pca9539 ... |
902 |
}; |
f3dc3630f gpio: rename pca9... |
903 |
static int __init pca953x_init(void) |
9e60fdcf0 gpiolib: pca9539 ... |
904 |
{ |
f3dc3630f gpio: rename pca9... |
905 |
return i2c_add_driver(&pca953x_driver); |
9e60fdcf0 gpiolib: pca9539 ... |
906 |
} |
2f8d11971 gpio: i2c expande... |
907 908 909 910 |
/* register after i2c postcore initcall and before * subsys initcalls that may rely on these GPIOs */ subsys_initcall(pca953x_init); |
9e60fdcf0 gpiolib: pca9539 ... |
911 |
|
f3dc3630f gpio: rename pca9... |
912 |
static void __exit pca953x_exit(void) |
9e60fdcf0 gpiolib: pca9539 ... |
913 |
{ |
f3dc3630f gpio: rename pca9... |
914 |
i2c_del_driver(&pca953x_driver); |
9e60fdcf0 gpiolib: pca9539 ... |
915 |
} |
f3dc3630f gpio: rename pca9... |
916 |
module_exit(pca953x_exit); |
9e60fdcf0 gpiolib: pca9539 ... |
917 918 |
MODULE_AUTHOR("eric miao <eric.miao@marvell.com>"); |
f3dc3630f gpio: rename pca9... |
919 |
MODULE_DESCRIPTION("GPIO expander driver for PCA953x"); |
9e60fdcf0 gpiolib: pca9539 ... |
920 |
MODULE_LICENSE("GPL"); |