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