Blame view

drivers/gpio/gpio-pca953x.c 24.1 KB
9e60fdcf0   eric miao   gpiolib: pca9539 ...
1
  /*
1e1916950   Aaron Sierra   gpio: pca953x: Ad...
2
   *  PCA953x 4/8/16/24/40 bit I/O ports
9e60fdcf0   eric miao   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   H Hartley Sweeten   gpio: include <li...
16
  #include <linux/gpio.h>
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
17
  #include <linux/interrupt.h>
9e60fdcf0   eric miao   gpiolib: pca9539 ...
18
  #include <linux/i2c.h>
5877457a9   Vivien Didelot   gpio: (gpio-pca95...
19
  #include <linux/platform_data/pca953x.h>
bab58491c   Shawn Guo   MLK-11293: gpio: ...
20
  #include <linux/reset.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
21
  #include <linux/slab.h>
9b8e3ec34   Yong Li   gpio: pca953x: Us...
22
  #include <asm/unaligned.h>
1965d3035   Nate Case   gpio: pca953x: Ge...
23
  #include <linux/of_platform.h>
f32517bf1   Andy Shevchenko   gpio: pca953x: su...
24
  #include <linux/acpi.h>
e23efa311   Phil Reid   gpio: pca954x: Ad...
25
  #include <linux/regulator/consumer.h>
9e60fdcf0   eric miao   gpiolib: pca9539 ...
26

33226ffd0   Haojian Zhuang   gpio/pca953x: Add...
27
28
29
30
  #define PCA953X_INPUT		0
  #define PCA953X_OUTPUT		1
  #define PCA953X_INVERT		2
  #define PCA953X_DIRECTION	3
ae79c1904   Andreas Schallenberg   Add support for T...
31
  #define REG_ADDR_AI		0x80
33226ffd0   Haojian Zhuang   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   Yong Li   gpio: pca953x: ad...
40
41
42
  #define PCAL953X_IN_LATCH	34
  #define PCAL953X_INT_MASK	37
  #define PCAL953X_INT_STAT	38
33226ffd0   Haojian Zhuang   gpio/pca953x: Add...
43
44
  #define PCA_GPIO_MASK		0x00FF
  #define PCA_INT			0x0100
8c7a92dad   Andy Shevchenko   gpio: pca953x: re...
45
  #define PCA_PCAL		0x0200
33226ffd0   Haojian Zhuang   gpio/pca953x: Add...
46
47
  #define PCA953X_TYPE		0x1000
  #define PCA957X_TYPE		0x2000
c6664149a   Andy Shevchenko   gpio: pca953x: st...
48
49
50
  #define PCA_TYPE_MASK		0xF000
  
  #define PCA_CHIP_TYPE(x)	((x) & PCA_TYPE_MASK)
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
51

3760f7367   Jean Delvare   i2c: Convert most...
52
  static const struct i2c_device_id pca953x_id[] = {
89f5df01c   Gregory CLEMENT   gpio: pca953x: ad...
53
  	{ "pca9505", 40 | PCA953X_TYPE | PCA_INT, },
33226ffd0   Haojian Zhuang   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   Aaron Sierra   gpio: pca953x: Ad...
66
  	{ "pca9698", 40 | PCA953X_TYPE, },
33226ffd0   Haojian Zhuang   gpio/pca953x: Add...
67

747e42a1c   Andy Shevchenko   gpio: pca953x: en...
68
  	{ "pcal9555a", 16 | PCA953X_TYPE | PCA_INT | PCA_PCAL, },
33226ffd0   Haojian Zhuang   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   Andreas Schallenberg   Add support for T...
76
  	{ "tca6424", 24 | PCA953X_TYPE | PCA_INT, },
2db8aba86   Thierry Reding   gpio: pca953x: Ad...
77
  	{ "tca9539", 16 | PCA953X_TYPE | PCA_INT, },
e73760a60   Aaron Sierra   gpio: pca953x: Ad...
78
  	{ "xra1202", 8  | PCA953X_TYPE },
3760f7367   Jean Delvare   i2c: Convert most...
79
  	{ }
f5e8ff483   Guennadi Liakhovetski   gpio: handle pca9...
80
  };
3760f7367   Jean Delvare   i2c: Convert most...
81
  MODULE_DEVICE_TABLE(i2c, pca953x_id);
9e60fdcf0   eric miao   gpiolib: pca9539 ...
82

f32517bf1   Andy Shevchenko   gpio: pca953x: su...
83
  static const struct acpi_device_id pca953x_acpi_ids[] = {
44896beae   Yong Li   gpio: pca953x: ad...
84
  	{ "INT3491", 16 | PCA953X_TYPE | PCA_INT | PCA_PCAL, },
f32517bf1   Andy Shevchenko   gpio: pca953x: su...
85
86
87
  	{ }
  };
  MODULE_DEVICE_TABLE(acpi, pca953x_acpi_ids);
f5f0b7aa8   Gregory CLEMENT   gpio: pca953x: ma...
88
89
  #define MAX_BANK 5
  #define BANK_SZ 8
a246b8198   Vignesh R   gpio: pca953x: Fi...
90
  #define NBANK(chip) DIV_ROUND_UP(chip->gpio_chip.ngpio, BANK_SZ)
f5f0b7aa8   Gregory CLEMENT   gpio: pca953x: ma...
91

53661f3bc   Bartosz Golaszewski   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   Guennadi Liakhovetski   gpio: rename pca9...
109
  struct pca953x_chip {
9e60fdcf0   eric miao   gpiolib: pca9539 ...
110
  	unsigned gpio_start;
f5f0b7aa8   Gregory CLEMENT   gpio: pca953x: ma...
111
112
  	u8 reg_output[MAX_BANK];
  	u8 reg_direction[MAX_BANK];
6e20fb180   Roland Stigge   drivers/gpio/pca9...
113
  	struct mutex i2c_lock;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
114

89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
115
116
  #ifdef CONFIG_GPIO_PCA953X_IRQ
  	struct mutex irq_lock;
f5f0b7aa8   Gregory CLEMENT   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   Marc Zyngier   gpio: pca953x.c: ...
121
  #endif
9e60fdcf0   eric miao   gpiolib: pca9539 ...
122
123
  	struct i2c_client *client;
  	struct gpio_chip gpio_chip;
62154991a   Uwe Kleine-König   gpiolib: make nam...
124
  	const char *const *names;
c6664149a   Andy Shevchenko   gpio: pca953x: st...
125
  	unsigned long driver_data;
e23efa311   Phil Reid   gpio: pca954x: Ad...
126
  	struct regulator *regulator;
53661f3bc   Bartosz Golaszewski   gpio: pca953x: co...
127
128
  
  	const struct pca953x_reg_config *regs;
7acc66e37   Bartosz Golaszewski   gpio: pca953x: re...
129
130
  
  	int (*write_regs)(struct pca953x_chip *, int, u8 *);
c6e3cf01d   Bartosz Golaszewski   gpio: pca953x: re...
131
  	int (*read_regs)(struct pca953x_chip *, int, u8 *);
9e60fdcf0   eric miao   gpiolib: pca9539 ...
132
  };
f5f0b7aa8   Gregory CLEMENT   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   Andy Shevchenko   gpio: pca953x: re...
156
  	int ret;
f5f0b7aa8   Gregory CLEMENT   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   Bartosz Golaszewski   gpio: pca953x: re...
171
  static int pca953x_write_regs_8(struct pca953x_chip *chip, int reg, u8 *val)
9e60fdcf0   eric miao   gpiolib: pca9539 ...
172
  {
7acc66e37   Bartosz Golaszewski   gpio: pca953x: re...
173
174
  	return i2c_smbus_write_byte_data(chip->client, reg, *val);
  }
f5e8ff483   Guennadi Liakhovetski   gpio: handle pca9...
175

7acc66e37   Bartosz Golaszewski   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   Andy Shevchenko   gpio: pca953x: en...
179

7acc66e37   Bartosz Golaszewski   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   Guennadi Liakhovetski   gpio: handle pca9...
194

7acc66e37   Bartosz Golaszewski   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   Guennadi Liakhovetski   gpio: handle pca9...
209
210
211
  	if (ret < 0) {
  		dev_err(&chip->client->dev, "failed writing register
  ");
ab5dc3720   David Brownell   gpio: pca953x han...
212
  		return ret;
f5e8ff483   Guennadi Liakhovetski   gpio: handle pca9...
213
214
215
  	}
  
  	return 0;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
216
  }
c6e3cf01d   Bartosz Golaszewski   gpio: pca953x: re...
217
  static int pca953x_read_regs_8(struct pca953x_chip *chip, int reg, u8 *val)
9e60fdcf0   eric miao   gpiolib: pca9539 ...
218
219
  {
  	int ret;
c6e3cf01d   Bartosz Golaszewski   gpio: pca953x: re...
220
221
  	ret = i2c_smbus_read_byte_data(chip->client, reg);
  	*val = ret;
f5f0b7aa8   Gregory CLEMENT   gpio: pca953x: ma...
222

c6e3cf01d   Bartosz Golaszewski   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   eric miao   gpiolib: pca9539 ...
251
252
253
  	if (ret < 0) {
  		dev_err(&chip->client->dev, "failed reading register
  ");
ab5dc3720   David Brownell   gpio: pca953x han...
254
  		return ret;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
255
  	}
9e60fdcf0   eric miao   gpiolib: pca9539 ...
256
257
  	return 0;
  }
f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
258
  static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off)
9e60fdcf0   eric miao   gpiolib: pca9539 ...
259
  {
468e67f6e   Linus Walleij   gpio: pca953x: us...
260
  	struct pca953x_chip *chip = gpiochip_get_data(gc);
f5f0b7aa8   Gregory CLEMENT   gpio: pca953x: ma...
261
  	u8 reg_val;
53661f3bc   Bartosz Golaszewski   gpio: pca953x: co...
262
  	int ret;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
263

6e20fb180   Roland Stigge   drivers/gpio/pca9...
264
  	mutex_lock(&chip->i2c_lock);
f5f0b7aa8   Gregory CLEMENT   gpio: pca953x: ma...
265
  	reg_val = chip->reg_direction[off / BANK_SZ] | (1u << (off % BANK_SZ));
33226ffd0   Haojian Zhuang   gpio/pca953x: Add...
266

53661f3bc   Bartosz Golaszewski   gpio: pca953x: co...
267
  	ret = pca953x_write_single(chip, chip->regs->direction, reg_val, off);
9e60fdcf0   eric miao   gpiolib: pca9539 ...
268
  	if (ret)
6e20fb180   Roland Stigge   drivers/gpio/pca9...
269
  		goto exit;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
270

f5f0b7aa8   Gregory CLEMENT   gpio: pca953x: ma...
271
  	chip->reg_direction[off / BANK_SZ] = reg_val;
6e20fb180   Roland Stigge   drivers/gpio/pca9...
272
273
274
  exit:
  	mutex_unlock(&chip->i2c_lock);
  	return ret;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
275
  }
f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
276
  static int pca953x_gpio_direction_output(struct gpio_chip *gc,
9e60fdcf0   eric miao   gpiolib: pca9539 ...
277
278
  		unsigned off, int val)
  {
468e67f6e   Linus Walleij   gpio: pca953x: us...
279
  	struct pca953x_chip *chip = gpiochip_get_data(gc);
f5f0b7aa8   Gregory CLEMENT   gpio: pca953x: ma...
280
  	u8 reg_val;
53661f3bc   Bartosz Golaszewski   gpio: pca953x: co...
281
  	int ret;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
282

6e20fb180   Roland Stigge   drivers/gpio/pca9...
283
  	mutex_lock(&chip->i2c_lock);
9e60fdcf0   eric miao   gpiolib: pca9539 ...
284
285
  	/* set output level */
  	if (val)
f5f0b7aa8   Gregory CLEMENT   gpio: pca953x: ma...
286
287
  		reg_val = chip->reg_output[off / BANK_SZ]
  			| (1u << (off % BANK_SZ));
9e60fdcf0   eric miao   gpiolib: pca9539 ...
288
  	else
f5f0b7aa8   Gregory CLEMENT   gpio: pca953x: ma...
289
290
  		reg_val = chip->reg_output[off / BANK_SZ]
  			& ~(1u << (off % BANK_SZ));
9e60fdcf0   eric miao   gpiolib: pca9539 ...
291

53661f3bc   Bartosz Golaszewski   gpio: pca953x: co...
292
  	ret = pca953x_write_single(chip, chip->regs->output, reg_val, off);
9e60fdcf0   eric miao   gpiolib: pca9539 ...
293
  	if (ret)
6e20fb180   Roland Stigge   drivers/gpio/pca9...
294
  		goto exit;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
295

f5f0b7aa8   Gregory CLEMENT   gpio: pca953x: ma...
296
  	chip->reg_output[off / BANK_SZ] = reg_val;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
297
298
  
  	/* then direction */
f5f0b7aa8   Gregory CLEMENT   gpio: pca953x: ma...
299
  	reg_val = chip->reg_direction[off / BANK_SZ] & ~(1u << (off % BANK_SZ));
53661f3bc   Bartosz Golaszewski   gpio: pca953x: co...
300
  	ret = pca953x_write_single(chip, chip->regs->direction, reg_val, off);
9e60fdcf0   eric miao   gpiolib: pca9539 ...
301
  	if (ret)
6e20fb180   Roland Stigge   drivers/gpio/pca9...
302
  		goto exit;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
303

f5f0b7aa8   Gregory CLEMENT   gpio: pca953x: ma...
304
  	chip->reg_direction[off / BANK_SZ] = reg_val;
6e20fb180   Roland Stigge   drivers/gpio/pca9...
305
306
307
  exit:
  	mutex_unlock(&chip->i2c_lock);
  	return ret;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
308
  }
f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
309
  static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
9e60fdcf0   eric miao   gpiolib: pca9539 ...
310
  {
468e67f6e   Linus Walleij   gpio: pca953x: us...
311
  	struct pca953x_chip *chip = gpiochip_get_data(gc);
ae79c1904   Andreas Schallenberg   Add support for T...
312
  	u32 reg_val;
53661f3bc   Bartosz Golaszewski   gpio: pca953x: co...
313
  	int ret;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
314

6e20fb180   Roland Stigge   drivers/gpio/pca9...
315
  	mutex_lock(&chip->i2c_lock);
53661f3bc   Bartosz Golaszewski   gpio: pca953x: co...
316
  	ret = pca953x_read_single(chip, chip->regs->input, &reg_val, off);
6e20fb180   Roland Stigge   drivers/gpio/pca9...
317
  	mutex_unlock(&chip->i2c_lock);
9e60fdcf0   eric miao   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   Andrew Ruder   gpio: pca953x: fi...
325
  	return (reg_val & (1u << (off % BANK_SZ))) ? 1 : 0;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
326
  }
f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
327
  static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
9e60fdcf0   eric miao   gpiolib: pca9539 ...
328
  {
468e67f6e   Linus Walleij   gpio: pca953x: us...
329
  	struct pca953x_chip *chip = gpiochip_get_data(gc);
f5f0b7aa8   Gregory CLEMENT   gpio: pca953x: ma...
330
  	u8 reg_val;
53661f3bc   Bartosz Golaszewski   gpio: pca953x: co...
331
  	int ret;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
332

6e20fb180   Roland Stigge   drivers/gpio/pca9...
333
  	mutex_lock(&chip->i2c_lock);
9e60fdcf0   eric miao   gpiolib: pca9539 ...
334
  	if (val)
f5f0b7aa8   Gregory CLEMENT   gpio: pca953x: ma...
335
336
  		reg_val = chip->reg_output[off / BANK_SZ]
  			| (1u << (off % BANK_SZ));
9e60fdcf0   eric miao   gpiolib: pca9539 ...
337
  	else
f5f0b7aa8   Gregory CLEMENT   gpio: pca953x: ma...
338
339
  		reg_val = chip->reg_output[off / BANK_SZ]
  			& ~(1u << (off % BANK_SZ));
9e60fdcf0   eric miao   gpiolib: pca9539 ...
340

53661f3bc   Bartosz Golaszewski   gpio: pca953x: co...
341
  	ret = pca953x_write_single(chip, chip->regs->output, reg_val, off);
9e60fdcf0   eric miao   gpiolib: pca9539 ...
342
  	if (ret)
6e20fb180   Roland Stigge   drivers/gpio/pca9...
343
  		goto exit;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
344

f5f0b7aa8   Gregory CLEMENT   gpio: pca953x: ma...
345
  	chip->reg_output[off / BANK_SZ] = reg_val;
6e20fb180   Roland Stigge   drivers/gpio/pca9...
346
347
  exit:
  	mutex_unlock(&chip->i2c_lock);
9e60fdcf0   eric miao   gpiolib: pca9539 ...
348
  }
b4818afea   Phil Reid   gpio: pca953x: Ad...
349
  static void pca953x_gpio_set_multiple(struct gpio_chip *gc,
ea3d579d8   Bartosz Golaszewski   gpio: pca953x: co...
350
  				      unsigned long *mask, unsigned long *bits)
b4818afea   Phil Reid   gpio: pca953x: Ad...
351
  {
468e67f6e   Linus Walleij   gpio: pca953x: us...
352
  	struct pca953x_chip *chip = gpiochip_get_data(gc);
ea3d579d8   Bartosz Golaszewski   gpio: pca953x: co...
353
354
  	unsigned int bank_mask, bank_val;
  	int bank_shift, bank;
b4818afea   Phil Reid   gpio: pca953x: Ad...
355
  	u8 reg_val[MAX_BANK];
53661f3bc   Bartosz Golaszewski   gpio: pca953x: co...
356
  	int ret;
ea3d579d8   Bartosz Golaszewski   gpio: pca953x: co...
357
358
  
  	bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ);
b4818afea   Phil Reid   gpio: pca953x: Ad...
359

b4818afea   Phil Reid   gpio: pca953x: Ad...
360
  	mutex_lock(&chip->i2c_lock);
386377b54   Phil Reid   gpio: pca953x: Mo...
361
  	memcpy(reg_val, chip->reg_output, NBANK(chip));
ea3d579d8   Bartosz Golaszewski   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   Phil Reid   gpio: pca953x: Fi...
368
  			bank_val &= bank_mask;
ea3d579d8   Bartosz Golaszewski   gpio: pca953x: co...
369
  			reg_val[bank] = (reg_val[bank] & ~bank_mask) | bank_val;
b4818afea   Phil Reid   gpio: pca953x: Ad...
370
371
  		}
  	}
ea3d579d8   Bartosz Golaszewski   gpio: pca953x: co...
372

53661f3bc   Bartosz Golaszewski   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   Phil Reid   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   Guennadi Liakhovetski   gpio: handle pca9...
383
  static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
9e60fdcf0   eric miao   gpiolib: pca9539 ...
384
385
386
387
  {
  	struct gpio_chip *gc;
  
  	gc = &chip->gpio_chip;
f3dc3630f   Guennadi Liakhovetski   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   Phil Reid   gpio: pca953x: Ad...
392
  	gc->set_multiple = pca953x_gpio_set_multiple;
9fb1f39eb   Linus Walleij   gpio/pinctrl: mak...
393
  	gc->can_sleep = true;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
394
395
  
  	gc->base = chip->gpio_start;
f5e8ff483   Guennadi Liakhovetski   gpio: handle pca9...
396
397
  	gc->ngpio = gpios;
  	gc->label = chip->client->name;
58383c784   Linus Walleij   gpio: change memb...
398
  	gc->parent = &chip->client->dev;
d72cbed0c   Guennadi Liakhovetski   gpiolib: i2c/spi ...
399
  	gc->owner = THIS_MODULE;
77906a546   Daniel Silverstone   pca953x: support ...
400
  	gc->names = chip->names;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
401
  }
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
402
  #ifdef CONFIG_GPIO_PCA953X_IRQ
6f5cfc0e2   Lennert Buytenhek   gpio: pca953x: ir...
403
  static void pca953x_irq_mask(struct irq_data *d)
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
404
  {
7bcbce55f   Linus Walleij   gpio: pca953x: us...
405
  	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
468e67f6e   Linus Walleij   gpio: pca953x: us...
406
  	struct pca953x_chip *chip = gpiochip_get_data(gc);
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
407

f5f0b7aa8   Gregory CLEMENT   gpio: pca953x: ma...
408
  	chip->irq_mask[d->hwirq / BANK_SZ] &= ~(1 << (d->hwirq % BANK_SZ));
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
409
  }
6f5cfc0e2   Lennert Buytenhek   gpio: pca953x: ir...
410
  static void pca953x_irq_unmask(struct irq_data *d)
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
411
  {
7bcbce55f   Linus Walleij   gpio: pca953x: us...
412
  	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
468e67f6e   Linus Walleij   gpio: pca953x: us...
413
  	struct pca953x_chip *chip = gpiochip_get_data(gc);
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
414

f5f0b7aa8   Gregory CLEMENT   gpio: pca953x: ma...
415
  	chip->irq_mask[d->hwirq / BANK_SZ] |= 1 << (d->hwirq % BANK_SZ);
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
416
  }
6f5cfc0e2   Lennert Buytenhek   gpio: pca953x: ir...
417
  static void pca953x_irq_bus_lock(struct irq_data *d)
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
418
  {
7bcbce55f   Linus Walleij   gpio: pca953x: us...
419
  	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
468e67f6e   Linus Walleij   gpio: pca953x: us...
420
  	struct pca953x_chip *chip = gpiochip_get_data(gc);
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
421
422
423
  
  	mutex_lock(&chip->irq_lock);
  }
6f5cfc0e2   Lennert Buytenhek   gpio: pca953x: ir...
424
  static void pca953x_irq_bus_sync_unlock(struct irq_data *d)
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
425
  {
7bcbce55f   Linus Walleij   gpio: pca953x: us...
426
  	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
468e67f6e   Linus Walleij   gpio: pca953x: us...
427
  	struct pca953x_chip *chip = gpiochip_get_data(gc);
f5f0b7aa8   Gregory CLEMENT   gpio: pca953x: ma...
428
429
  	u8 new_irqs;
  	int level, i;
44896beae   Yong Li   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   Marc Zyngier   gpio: fix pca953x...
442
443
  
  	/* Look for any newly setup interrupt */
f5f0b7aa8   Gregory CLEMENT   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   Marc Zyngier   gpio: fix pca953x...
454
  	}
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
455
456
457
  
  	mutex_unlock(&chip->irq_lock);
  }
6f5cfc0e2   Lennert Buytenhek   gpio: pca953x: ir...
458
  static int pca953x_irq_set_type(struct irq_data *d, unsigned int type)
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
459
  {
7bcbce55f   Linus Walleij   gpio: pca953x: us...
460
  	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
468e67f6e   Linus Walleij   gpio: pca953x: us...
461
  	struct pca953x_chip *chip = gpiochip_get_data(gc);
f5f0b7aa8   Gregory CLEMENT   gpio: pca953x: ma...
462
463
  	int bank_nb = d->hwirq / BANK_SZ;
  	u8 mask = 1 << (d->hwirq % BANK_SZ);
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
464
465
466
467
  
  	if (!(type & IRQ_TYPE_EDGE_BOTH)) {
  		dev_err(&chip->client->dev, "irq %d: unsupported type %d
  ",
6f5cfc0e2   Lennert Buytenhek   gpio: pca953x: ir...
468
  			d->irq, type);
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
469
470
471
472
  		return -EINVAL;
  	}
  
  	if (type & IRQ_TYPE_EDGE_FALLING)
f5f0b7aa8   Gregory CLEMENT   gpio: pca953x: ma...
473
  		chip->irq_trig_fall[bank_nb] |= mask;
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
474
  	else
f5f0b7aa8   Gregory CLEMENT   gpio: pca953x: ma...
475
  		chip->irq_trig_fall[bank_nb] &= ~mask;
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
476
477
  
  	if (type & IRQ_TYPE_EDGE_RISING)
f5f0b7aa8   Gregory CLEMENT   gpio: pca953x: ma...
478
  		chip->irq_trig_raise[bank_nb] |= mask;
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
479
  	else
f5f0b7aa8   Gregory CLEMENT   gpio: pca953x: ma...
480
  		chip->irq_trig_raise[bank_nb] &= ~mask;
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
481

a2cb9aeb3   Marc Zyngier   gpio: fix pca953x...
482
  	return 0;
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
483
484
485
486
  }
  
  static struct irq_chip pca953x_irq_chip = {
  	.name			= "pca953x",
6f5cfc0e2   Lennert Buytenhek   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   Marc Zyngier   gpio: pca953x.c: ...
492
  };
b6ac1280b   Joshua Scott   gpio: Prevent an ...
493
  static bool pca953x_irq_pending(struct pca953x_chip *chip, u8 *pending)
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
494
  {
f5f0b7aa8   Gregory CLEMENT   gpio: pca953x: ma...
495
496
  	u8 cur_stat[MAX_BANK];
  	u8 old_stat[MAX_BANK];
b6ac1280b   Joshua Scott   gpio: Prevent an ...
497
498
499
  	bool pending_seen = false;
  	bool trigger_seen = false;
  	u8 trigger[MAX_BANK];
53661f3bc   Bartosz Golaszewski   gpio: pca953x: co...
500
  	int ret, i;
33226ffd0   Haojian Zhuang   gpio/pca953x: Add...
501

44896beae   Yong Li   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   Bartosz Golaszewski   gpio: pca953x: co...
524
  	ret = pca953x_read_regs(chip, chip->regs->input, cur_stat);
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
525
  	if (ret)
b6ac1280b   Joshua Scott   gpio: Prevent an ...
526
  		return false;
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
527
528
  
  	/* Remove output pins from the equation */
f5f0b7aa8   Gregory CLEMENT   gpio: pca953x: ma...
529
530
  	for (i = 0; i < NBANK(chip); i++)
  		cur_stat[i] &= chip->reg_direction[i];
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
531

f5f0b7aa8   Gregory CLEMENT   gpio: pca953x: ma...
532
  	memcpy(old_stat, chip->irq_stat, NBANK(chip));
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
533

f5f0b7aa8   Gregory CLEMENT   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   Joshua Scott   gpio: Prevent an ...
536
537
  		if (trigger[i])
  			trigger_seen = true;
f5f0b7aa8   Gregory CLEMENT   gpio: pca953x: ma...
538
  	}
b6ac1280b   Joshua Scott   gpio: Prevent an ...
539
540
  	if (!trigger_seen)
  		return false;
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
541

f5f0b7aa8   Gregory CLEMENT   gpio: pca953x: ma...
542
  	memcpy(chip->irq_stat, cur_stat, NBANK(chip));
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
543

f5f0b7aa8   Gregory CLEMENT   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   Joshua Scott   gpio: Prevent an ...
548
549
  		if (pending[i])
  			pending_seen = true;
f5f0b7aa8   Gregory CLEMENT   gpio: pca953x: ma...
550
  	}
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
551

b6ac1280b   Joshua Scott   gpio: Prevent an ...
552
  	return pending_seen;
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
553
554
555
556
557
  }
  
  static irqreturn_t pca953x_irq_handler(int irq, void *devid)
  {
  	struct pca953x_chip *chip = devid;
f5f0b7aa8   Gregory CLEMENT   gpio: pca953x: ma...
558
559
  	u8 pending[MAX_BANK];
  	u8 level;
3275d0723   Toby Smith   gpio: pca953x: re...
560
  	unsigned nhandled = 0;
f5f0b7aa8   Gregory CLEMENT   gpio: pca953x: ma...
561
  	int i;
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
562

f5f0b7aa8   Gregory CLEMENT   gpio: pca953x: ma...
563
  	if (!pca953x_irq_pending(chip, pending))
3275d0723   Toby Smith   gpio: pca953x: re...
564
  		return IRQ_NONE;
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
565

f5f0b7aa8   Gregory CLEMENT   gpio: pca953x: ma...
566
567
568
  	for (i = 0; i < NBANK(chip); i++) {
  		while (pending[i]) {
  			level = __ffs(pending[i]);
7bcbce55f   Linus Walleij   gpio: pca953x: us...
569
  			handle_nested_irq(irq_find_mapping(chip->gpio_chip.irqdomain,
f5f0b7aa8   Gregory CLEMENT   gpio: pca953x: ma...
570
571
  							level + (BANK_SZ * i)));
  			pending[i] &= ~(1 << level);
3275d0723   Toby Smith   gpio: pca953x: re...
572
  			nhandled++;
f5f0b7aa8   Gregory CLEMENT   gpio: pca953x: ma...
573
574
  		}
  	}
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
575

3275d0723   Toby Smith   gpio: pca953x: re...
576
  	return (nhandled > 0) ? IRQ_HANDLED : IRQ_NONE;
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
577
578
579
  }
  
  static int pca953x_irq_setup(struct pca953x_chip *chip,
c6dcf5924   David Jander   gpio/pca953x: Rem...
580
  			     int irq_base)
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
581
582
  {
  	struct i2c_client *client = chip->client;
53661f3bc   Bartosz Golaszewski   gpio: pca953x: co...
583
  	int ret, i;
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
584

4bb93349d   Markus Pargmann   gpio: pca953x: Dr...
585
  	if (client->irq && irq_base != -1
c6664149a   Andy Shevchenko   gpio: pca953x: st...
586
  			&& (chip->driver_data & PCA_INT)) {
53661f3bc   Bartosz Golaszewski   gpio: pca953x: co...
587
588
  		ret = pca953x_read_regs(chip,
  					chip->regs->input, chip->irq_stat);
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
589
  		if (ret)
b42748c97   Linus Walleij   gpio: pca953x: us...
590
  			return ret;
89ea8bbe9   Marc Zyngier   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   Gregory CLEMENT   gpio: pca953x: ma...
597
598
  		for (i = 0; i < NBANK(chip); i++)
  			chip->irq_stat[i] &= chip->reg_direction[i];
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
599
  		mutex_init(&chip->irq_lock);
b42748c97   Linus Walleij   gpio: pca953x: us...
600
601
  		ret = devm_request_threaded_irq(&client->dev,
  					client->irq,
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
602
603
  					   NULL,
  					   pca953x_irq_handler,
91329132c   Toby Smith   gpio: pca953x: re...
604
605
  					   IRQF_TRIGGER_LOW | IRQF_ONESHOT |
  						   IRQF_SHARED,
89ea8bbe9   Marc Zyngier   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   Gregory CLEMENT   gpio: pca953x: us...
611
  			return ret;
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
612
  		}
7bcbce55f   Linus Walleij   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   Grygorii Strashko   gpio: pca953x: fi...
624
625
626
627
  
  		gpiochip_set_chained_irqchip(&chip->gpio_chip,
  					     &pca953x_irq_chip,
  					     client->irq, NULL);
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
628
629
630
  	}
  
  	return 0;
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
631
  }
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
632
633
  #else /* CONFIG_GPIO_PCA953X_IRQ */
  static int pca953x_irq_setup(struct pca953x_chip *chip,
c6dcf5924   David Jander   gpio/pca953x: Rem...
634
  			     int irq_base)
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
635
636
  {
  	struct i2c_client *client = chip->client;
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
637

c6664149a   Andy Shevchenko   gpio: pca953x: st...
638
  	if (irq_base != -1 && (chip->driver_data & PCA_INT))
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
639
640
641
642
643
  		dev_warn(&client->dev, "interrupt support not compiled in
  ");
  
  	return 0;
  }
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
644
  #endif
3836309d9   Bill Pemberton   gpio: remove use ...
645
  static int device_pca953x_init(struct pca953x_chip *chip, u32 invert)
33226ffd0   Haojian Zhuang   gpio/pca953x: Add...
646
647
  {
  	int ret;
f5f0b7aa8   Gregory CLEMENT   gpio: pca953x: ma...
648
  	u8 val[MAX_BANK];
33226ffd0   Haojian Zhuang   gpio/pca953x: Add...
649

53661f3bc   Bartosz Golaszewski   gpio: pca953x: co...
650
651
652
  	chip->regs = &pca953x_regs;
  
  	ret = pca953x_read_regs(chip, chip->regs->output, chip->reg_output);
33226ffd0   Haojian Zhuang   gpio/pca953x: Add...
653
654
  	if (ret)
  		goto out;
53661f3bc   Bartosz Golaszewski   gpio: pca953x: co...
655
656
  	ret = pca953x_read_regs(chip, chip->regs->direction,
  				chip->reg_direction);
33226ffd0   Haojian Zhuang   gpio/pca953x: Add...
657
658
659
660
  	if (ret)
  		goto out;
  
  	/* set platform specific polarity inversion */
f5f0b7aa8   Gregory CLEMENT   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   Haojian Zhuang   gpio/pca953x: Add...
667
668
669
  out:
  	return ret;
  }
3836309d9   Bill Pemberton   gpio: remove use ...
670
  static int device_pca957x_init(struct pca953x_chip *chip, u32 invert)
33226ffd0   Haojian Zhuang   gpio/pca953x: Add...
671
672
  {
  	int ret;
f5f0b7aa8   Gregory CLEMENT   gpio: pca953x: ma...
673
  	u8 val[MAX_BANK];
33226ffd0   Haojian Zhuang   gpio/pca953x: Add...
674

53661f3bc   Bartosz Golaszewski   gpio: pca953x: co...
675
676
677
  	chip->regs = &pca957x_regs;
  
  	ret = pca953x_read_regs(chip, chip->regs->output, chip->reg_output);
33226ffd0   Haojian Zhuang   gpio/pca953x: Add...
678
679
  	if (ret)
  		goto out;
53661f3bc   Bartosz Golaszewski   gpio: pca953x: co...
680
681
  	ret = pca953x_read_regs(chip, chip->regs->direction,
  				chip->reg_direction);
33226ffd0   Haojian Zhuang   gpio/pca953x: Add...
682
683
684
685
  	if (ret)
  		goto out;
  
  	/* set platform specific polarity inversion */
f5f0b7aa8   Gregory CLEMENT   gpio: pca953x: ma...
686
687
688
689
  	if (invert)
  		memset(val, 0xFF, NBANK(chip));
  	else
  		memset(val, 0, NBANK(chip));
c75a37720   Nicholas Krause   gpio: Fix error c...
690
691
692
  	ret = pca953x_write_regs(chip, PCA957X_INVRT, val);
  	if (ret)
  		goto out;
33226ffd0   Haojian Zhuang   gpio/pca953x: Add...
693

20a8a9687   Colin Cronin   Drivers: gpio: Fi...
694
  	/* To enable register 6, 7 to control pull up and pull down */
f5f0b7aa8   Gregory CLEMENT   gpio: pca953x: ma...
695
  	memset(val, 0x02, NBANK(chip));
c75a37720   Nicholas Krause   gpio: Fix error c...
696
697
698
  	ret = pca953x_write_regs(chip, PCA957X_BKEN, val);
  	if (ret)
  		goto out;
33226ffd0   Haojian Zhuang   gpio/pca953x: Add...
699
700
701
702
703
  
  	return 0;
  out:
  	return ret;
  }
6f29c9afb   Ben Dooks   gpio: pca935x: fi...
704
  static const struct of_device_id pca953x_dt_ids[];
3836309d9   Bill Pemberton   gpio: remove use ...
705
  static int pca953x_probe(struct i2c_client *client,
6212e1d6e   Wolfram Sang   gpio: pca953x: va...
706
  				   const struct i2c_device_id *i2c_id)
9e60fdcf0   eric miao   gpiolib: pca9539 ...
707
  {
f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
708
709
  	struct pca953x_platform_data *pdata;
  	struct pca953x_chip *chip;
6a7b36aa4   Chandrabhanu Mahapatra   GPIO: PCA953X: In...
710
  	int irq_base = 0;
7ea2aa204   Wolfram Sang   gpio: pca953x: pr...
711
  	int ret;
6a7b36aa4   Chandrabhanu Mahapatra   GPIO: PCA953X: In...
712
  	u32 invert = 0;
e23efa311   Phil Reid   gpio: pca954x: Ad...
713
  	struct regulator *reg;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
714

b42748c97   Linus Walleij   gpio: pca953x: us...
715
716
  	chip = devm_kzalloc(&client->dev,
  			sizeof(struct pca953x_chip), GFP_KERNEL);
1965d3035   Nate Case   gpio: pca953x: Ge...
717
718
  	if (chip == NULL)
  		return -ENOMEM;
e56aee189   Jingoo Han   gpio: use dev_get...
719
  	pdata = dev_get_platdata(&client->dev);
c6dcf5924   David Jander   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   Markus Pargmann   gpio: pca953x: Dr...
726
727
  		chip->gpio_start = -1;
  		irq_base = 0;
1965d3035   Nate Case   gpio: pca953x: Ge...
728
  	}
9e60fdcf0   eric miao   gpiolib: pca9539 ...
729
730
  
  	chip->client = client;
e23efa311   Phil Reid   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   Wolfram Sang   gpio: pca953x: va...
746
747
  	if (i2c_id) {
  		chip->driver_data = i2c_id->driver_data;
f32517bf1   Andy Shevchenko   gpio: pca953x: su...
748
  	} else {
6212e1d6e   Wolfram Sang   gpio: pca953x: va...
749
  		const struct acpi_device_id *acpi_id;
6f29c9afb   Ben Dooks   gpio: pca935x: fi...
750
  		const struct of_device_id *match;
f32517bf1   Andy Shevchenko   gpio: pca953x: su...
751

6f29c9afb   Ben Dooks   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   Wolfram Sang   gpio: pca953x: va...
756
  			acpi_id = acpi_match_device(pca953x_acpi_ids, &client->dev);
87840a2b7   Linus Torvalds   Merge branch 'i2c...
757
  			if (!acpi_id) {
e23efa311   Phil Reid   gpio: pca954x: Ad...
758
759
760
  				ret = -ENODEV;
  				goto err_exit;
  			}
f32517bf1   Andy Shevchenko   gpio: pca953x: su...
761

6212e1d6e   Wolfram Sang   gpio: pca953x: va...
762
  			chip->driver_data = acpi_id->driver_data;
6f29c9afb   Ben Dooks   gpio: pca935x: fi...
763
  		}
f32517bf1   Andy Shevchenko   gpio: pca953x: su...
764
  	}
6e20fb180   Roland Stigge   drivers/gpio/pca9...
765
  	mutex_init(&chip->i2c_lock);
74f47f07e   Bartosz Golaszewski   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   Bartosz Golaszewski   gpio: pca953x: fi...
782
783
  	lockdep_set_subclass(&chip->i2c_lock,
  			     i2c_adapter_depth(client->adapter));
6e20fb180   Roland Stigge   drivers/gpio/pca9...
784

bab58491c   Shawn Guo   MLK-11293: gpio: ...
785
  	ret = device_reset(&client->dev);
67d607f7f   Andy Duan   MLK-13773 gpio: p...
786
  	if (ret == -EPROBE_DEFER)
bab58491c   Shawn Guo   MLK-11293: gpio: ...
787
  		return -EPROBE_DEFER;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
788
789
790
  	/* initialize cached registers from their original values.
  	 * we can't share this chip with another i2c master.
  	 */
c6664149a   Andy Shevchenko   gpio: pca953x: st...
791
  	pca953x_setup_gpio(chip, chip->driver_data & PCA_GPIO_MASK);
f5e8ff483   Guennadi Liakhovetski   gpio: handle pca9...
792

7acc66e37   Bartosz Golaszewski   gpio: pca953x: re...
793
794
  	if (chip->gpio_chip.ngpio <= 8) {
  		chip->write_regs = pca953x_write_regs_8;
c6e3cf01d   Bartosz Golaszewski   gpio: pca953x: re...
795
  		chip->read_regs = pca953x_read_regs_8;
7acc66e37   Bartosz Golaszewski   gpio: pca953x: re...
796
797
  	} else if (chip->gpio_chip.ngpio >= 24) {
  		chip->write_regs = pca953x_write_regs_24;
c6e3cf01d   Bartosz Golaszewski   gpio: pca953x: re...
798
  		chip->read_regs = pca953x_read_regs_24;
7acc66e37   Bartosz Golaszewski   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   Bartosz Golaszewski   gpio: pca953x: re...
804
  		chip->read_regs = pca953x_read_regs_16;
7acc66e37   Bartosz Golaszewski   gpio: pca953x: re...
805
  	}
60f547be8   Bartosz Golaszewski   gpio: pca953x: re...
806
  	if (PCA_CHIP_TYPE(chip->driver_data) == PCA953X_TYPE)
7ea2aa204   Wolfram Sang   gpio: pca953x: pr...
807
  		ret = device_pca953x_init(chip, invert);
33226ffd0   Haojian Zhuang   gpio/pca953x: Add...
808
  	else
7ea2aa204   Wolfram Sang   gpio: pca953x: pr...
809
810
  		ret = device_pca957x_init(chip, invert);
  	if (ret)
e23efa311   Phil Reid   gpio: pca954x: Ad...
811
  		goto err_exit;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
812

0ece84f54   Laxman Dewangan   gpio: pca953x: Us...
813
  	ret = devm_gpiochip_add_data(&client->dev, &chip->gpio_chip, chip);
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
814
  	if (ret)
e23efa311   Phil Reid   gpio: pca954x: Ad...
815
  		goto err_exit;
f5e8ff483   Guennadi Liakhovetski   gpio: handle pca9...
816

c6664149a   Andy Shevchenko   gpio: pca953x: st...
817
  	ret = pca953x_irq_setup(chip, irq_base);
9e60fdcf0   eric miao   gpiolib: pca9539 ...
818
  	if (ret)
e23efa311   Phil Reid   gpio: pca954x: Ad...
819
  		goto err_exit;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
820

c6dcf5924   David Jander   gpio/pca953x: Rem...
821
  	if (pdata && pdata->setup) {
9e60fdcf0   eric miao   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   Phil Reid   gpio: pca954x: Ad...
831
832
833
834
  
  err_exit:
  	regulator_disable(chip->regulator);
  	return ret;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
835
  }
f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
836
  static int pca953x_remove(struct i2c_client *client)
9e60fdcf0   eric miao   gpiolib: pca9539 ...
837
  {
e56aee189   Jingoo Han   gpio: use dev_get...
838
  	struct pca953x_platform_data *pdata = dev_get_platdata(&client->dev);
f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
839
  	struct pca953x_chip *chip = i2c_get_clientdata(client);
d147d5489   Linus Walleij   Revert "gpio: pca...
840
  	int ret;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
841

c6dcf5924   David Jander   gpio/pca953x: Rem...
842
  	if (pdata && pdata->teardown) {
9e60fdcf0   eric miao   gpiolib: pca9539 ...
843
844
  		ret = pdata->teardown(client, chip->gpio_chip.base,
  				chip->gpio_chip.ngpio, pdata->context);
e23efa311   Phil Reid   gpio: pca954x: Ad...
845
  		if (ret < 0)
9e60fdcf0   eric miao   gpiolib: pca9539 ...
846
847
848
  			dev_err(&client->dev, "%s failed, %d
  ",
  					"teardown", ret);
bf62efeb1   Arnd Bergmann   gpio: pca954x: fi...
849
850
  	} else {
  		ret = 0;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
851
  	}
e23efa311   Phil Reid   gpio: pca954x: Ad...
852
853
854
  	regulator_disable(chip->regulator);
  
  	return ret;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
855
  }
6f29c9afb   Ben Dooks   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   Maxime Ripard   gpio: pca953x: Ad...
859
  static const struct of_device_id pca953x_dt_ids[] = {
6f29c9afb   Ben Dooks   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   Vignesh R   gpio: pca953x: Ad...
881
  	{ .compatible = "ti,pca9536", .data = OF_953X( 4, 0), },
6f29c9afb   Ben Dooks   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   Maxime Ripard   gpio: pca953x: Ad...
889
890
891
892
  	{ }
  };
  
  MODULE_DEVICE_TABLE(of, pca953x_dt_ids);
f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
893
  static struct i2c_driver pca953x_driver = {
9e60fdcf0   eric miao   gpiolib: pca9539 ...
894
  	.driver = {
f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
895
  		.name	= "pca953x",
ed32620ea   Maxime Ripard   gpio: pca953x: Ad...
896
  		.of_match_table = pca953x_dt_ids,
f32517bf1   Andy Shevchenko   gpio: pca953x: su...
897
  		.acpi_match_table = ACPI_PTR(pca953x_acpi_ids),
9e60fdcf0   eric miao   gpiolib: pca9539 ...
898
  	},
f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
899
900
  	.probe		= pca953x_probe,
  	.remove		= pca953x_remove,
3760f7367   Jean Delvare   i2c: Convert most...
901
  	.id_table	= pca953x_id,
9e60fdcf0   eric miao   gpiolib: pca9539 ...
902
  };
f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
903
  static int __init pca953x_init(void)
9e60fdcf0   eric miao   gpiolib: pca9539 ...
904
  {
f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
905
  	return i2c_add_driver(&pca953x_driver);
9e60fdcf0   eric miao   gpiolib: pca9539 ...
906
  }
2f8d11971   David Brownell   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   eric miao   gpiolib: pca9539 ...
911

f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
912
  static void __exit pca953x_exit(void)
9e60fdcf0   eric miao   gpiolib: pca9539 ...
913
  {
f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
914
  	i2c_del_driver(&pca953x_driver);
9e60fdcf0   eric miao   gpiolib: pca9539 ...
915
  }
f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
916
  module_exit(pca953x_exit);
9e60fdcf0   eric miao   gpiolib: pca9539 ...
917
918
  
  MODULE_AUTHOR("eric miao <eric.miao@marvell.com>");
f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
919
  MODULE_DESCRIPTION("GPIO expander driver for PCA953x");
9e60fdcf0   eric miao   gpiolib: pca9539 ...
920
  MODULE_LICENSE("GPL");