Blame view

drivers/gpio/gpio-pca953x.c 17 KB
9e60fdcf0   eric miao   gpiolib: pca9539 ...
1
  /*
c103de240   Grant Likely   gpio: reorganize ...
2
   *  PCA953x 4/8/16 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
18
  #include <linux/interrupt.h>
  #include <linux/irq.h>
9e60fdcf0   eric miao   gpiolib: pca9539 ...
19
  #include <linux/i2c.h>
d1c057e31   Guennadi Liakhovetski   gpio: rename pca9...
20
  #include <linux/i2c/pca953x.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
21
  #include <linux/slab.h>
1965d3035   Nate Case   gpio: pca953x: Ge...
22
23
  #ifdef CONFIG_OF_GPIO
  #include <linux/of_platform.h>
1965d3035   Nate Case   gpio: pca953x: Ge...
24
  #endif
9e60fdcf0   eric miao   gpiolib: pca9539 ...
25

33226ffd0   Haojian Zhuang   gpio/pca953x: Add...
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
  #define PCA953X_INPUT		0
  #define PCA953X_OUTPUT		1
  #define PCA953X_INVERT		2
  #define PCA953X_DIRECTION	3
  
  #define PCA957X_IN		0
  #define PCA957X_INVRT		1
  #define PCA957X_BKEN		2
  #define PCA957X_PUPD		3
  #define PCA957X_CFG		4
  #define PCA957X_OUT		5
  #define PCA957X_MSK		6
  #define PCA957X_INTS		7
  
  #define PCA_GPIO_MASK		0x00FF
  #define PCA_INT			0x0100
  #define PCA953X_TYPE		0x1000
  #define PCA957X_TYPE		0x2000
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
44

3760f7367   Jean Delvare   i2c: Convert most...
45
  static const struct i2c_device_id pca953x_id[] = {
33226ffd0   Haojian Zhuang   gpio/pca953x: Add...
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
  	{ "pca9534", 8  | PCA953X_TYPE | PCA_INT, },
  	{ "pca9535", 16 | PCA953X_TYPE | PCA_INT, },
  	{ "pca9536", 4  | PCA953X_TYPE, },
  	{ "pca9537", 4  | PCA953X_TYPE | PCA_INT, },
  	{ "pca9538", 8  | PCA953X_TYPE | PCA_INT, },
  	{ "pca9539", 16 | PCA953X_TYPE | PCA_INT, },
  	{ "pca9554", 8  | PCA953X_TYPE | PCA_INT, },
  	{ "pca9555", 16 | PCA953X_TYPE | PCA_INT, },
  	{ "pca9556", 8  | PCA953X_TYPE, },
  	{ "pca9557", 8  | PCA953X_TYPE, },
  	{ "pca9574", 8  | PCA957X_TYPE | PCA_INT, },
  	{ "pca9575", 16 | PCA957X_TYPE | PCA_INT, },
  
  	{ "max7310", 8  | PCA953X_TYPE, },
  	{ "max7312", 16 | PCA953X_TYPE | PCA_INT, },
  	{ "max7313", 16 | PCA953X_TYPE | PCA_INT, },
  	{ "max7315", 8  | PCA953X_TYPE | PCA_INT, },
  	{ "pca6107", 8  | PCA953X_TYPE | PCA_INT, },
  	{ "tca6408", 8  | PCA953X_TYPE | PCA_INT, },
  	{ "tca6416", 16 | PCA953X_TYPE | PCA_INT, },
ab5dc3720   David Brownell   gpio: pca953x han...
66
  	/* NYET:  { "tca6424", 24, }, */
3760f7367   Jean Delvare   i2c: Convert most...
67
  	{ }
f5e8ff483   Guennadi Liakhovetski   gpio: handle pca9...
68
  };
3760f7367   Jean Delvare   i2c: Convert most...
69
  MODULE_DEVICE_TABLE(i2c, pca953x_id);
9e60fdcf0   eric miao   gpiolib: pca9539 ...
70

f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
71
  struct pca953x_chip {
9e60fdcf0   eric miao   gpiolib: pca9539 ...
72
73
74
  	unsigned gpio_start;
  	uint16_t reg_output;
  	uint16_t reg_direction;
6e20fb180   Roland Stigge   drivers/gpio/pca9...
75
  	struct mutex i2c_lock;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
76

89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
77
78
79
80
81
82
83
84
  #ifdef CONFIG_GPIO_PCA953X_IRQ
  	struct mutex irq_lock;
  	uint16_t irq_mask;
  	uint16_t irq_stat;
  	uint16_t irq_trig_raise;
  	uint16_t irq_trig_fall;
  	int	 irq_base;
  #endif
9e60fdcf0   eric miao   gpiolib: pca9539 ...
85
86
  	struct i2c_client *client;
  	struct gpio_chip gpio_chip;
62154991a   Uwe Kleine-König   gpiolib: make nam...
87
  	const char *const *names;
33226ffd0   Haojian Zhuang   gpio/pca953x: Add...
88
  	int	chip_type;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
89
  };
f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
90
  static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val)
9e60fdcf0   eric miao   gpiolib: pca9539 ...
91
  {
33226ffd0   Haojian Zhuang   gpio/pca953x: Add...
92
  	int ret = 0;
f5e8ff483   Guennadi Liakhovetski   gpio: handle pca9...
93
94
95
  
  	if (chip->gpio_chip.ngpio <= 8)
  		ret = i2c_smbus_write_byte_data(chip->client, reg, val);
33226ffd0   Haojian Zhuang   gpio/pca953x: Add...
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
  	else {
  		switch (chip->chip_type) {
  		case PCA953X_TYPE:
  			ret = i2c_smbus_write_word_data(chip->client,
  							reg << 1, val);
  			break;
  		case PCA957X_TYPE:
  			ret = i2c_smbus_write_byte_data(chip->client, reg << 1,
  							val & 0xff);
  			if (ret < 0)
  				break;
  			ret = i2c_smbus_write_byte_data(chip->client,
  							(reg << 1) + 1,
  							(val & 0xff00) >> 8);
  			break;
  		}
  	}
f5e8ff483   Guennadi Liakhovetski   gpio: handle pca9...
113
114
115
116
  
  	if (ret < 0) {
  		dev_err(&chip->client->dev, "failed writing register
  ");
ab5dc3720   David Brownell   gpio: pca953x han...
117
  		return ret;
f5e8ff483   Guennadi Liakhovetski   gpio: handle pca9...
118
119
120
  	}
  
  	return 0;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
121
  }
f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
122
  static int pca953x_read_reg(struct pca953x_chip *chip, int reg, uint16_t *val)
9e60fdcf0   eric miao   gpiolib: pca9539 ...
123
124
  {
  	int ret;
f5e8ff483   Guennadi Liakhovetski   gpio: handle pca9...
125
126
127
128
  	if (chip->gpio_chip.ngpio <= 8)
  		ret = i2c_smbus_read_byte_data(chip->client, reg);
  	else
  		ret = i2c_smbus_read_word_data(chip->client, reg << 1);
9e60fdcf0   eric miao   gpiolib: pca9539 ...
129
130
131
  	if (ret < 0) {
  		dev_err(&chip->client->dev, "failed reading register
  ");
ab5dc3720   David Brownell   gpio: pca953x han...
132
  		return ret;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
133
134
135
136
137
  	}
  
  	*val = (uint16_t)ret;
  	return 0;
  }
f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
138
  static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off)
9e60fdcf0   eric miao   gpiolib: pca9539 ...
139
  {
f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
140
  	struct pca953x_chip *chip;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
141
  	uint16_t reg_val;
33226ffd0   Haojian Zhuang   gpio/pca953x: Add...
142
  	int ret, offset = 0;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
143

f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
144
  	chip = container_of(gc, struct pca953x_chip, gpio_chip);
9e60fdcf0   eric miao   gpiolib: pca9539 ...
145

6e20fb180   Roland Stigge   drivers/gpio/pca9...
146
  	mutex_lock(&chip->i2c_lock);
9e60fdcf0   eric miao   gpiolib: pca9539 ...
147
  	reg_val = chip->reg_direction | (1u << off);
33226ffd0   Haojian Zhuang   gpio/pca953x: Add...
148
149
150
151
152
153
154
155
156
157
  
  	switch (chip->chip_type) {
  	case PCA953X_TYPE:
  		offset = PCA953X_DIRECTION;
  		break;
  	case PCA957X_TYPE:
  		offset = PCA957X_CFG;
  		break;
  	}
  	ret = pca953x_write_reg(chip, offset, reg_val);
9e60fdcf0   eric miao   gpiolib: pca9539 ...
158
  	if (ret)
6e20fb180   Roland Stigge   drivers/gpio/pca9...
159
  		goto exit;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
160
161
  
  	chip->reg_direction = reg_val;
6e20fb180   Roland Stigge   drivers/gpio/pca9...
162
163
164
165
  	ret = 0;
  exit:
  	mutex_unlock(&chip->i2c_lock);
  	return ret;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
166
  }
f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
167
  static int pca953x_gpio_direction_output(struct gpio_chip *gc,
9e60fdcf0   eric miao   gpiolib: pca9539 ...
168
169
  		unsigned off, int val)
  {
f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
170
  	struct pca953x_chip *chip;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
171
  	uint16_t reg_val;
33226ffd0   Haojian Zhuang   gpio/pca953x: Add...
172
  	int ret, offset = 0;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
173

f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
174
  	chip = container_of(gc, struct pca953x_chip, gpio_chip);
9e60fdcf0   eric miao   gpiolib: pca9539 ...
175

6e20fb180   Roland Stigge   drivers/gpio/pca9...
176
  	mutex_lock(&chip->i2c_lock);
9e60fdcf0   eric miao   gpiolib: pca9539 ...
177
178
179
180
181
  	/* set output level */
  	if (val)
  		reg_val = chip->reg_output | (1u << off);
  	else
  		reg_val = chip->reg_output & ~(1u << off);
33226ffd0   Haojian Zhuang   gpio/pca953x: Add...
182
183
184
185
186
187
188
189
190
  	switch (chip->chip_type) {
  	case PCA953X_TYPE:
  		offset = PCA953X_OUTPUT;
  		break;
  	case PCA957X_TYPE:
  		offset = PCA957X_OUT;
  		break;
  	}
  	ret = pca953x_write_reg(chip, offset, reg_val);
9e60fdcf0   eric miao   gpiolib: pca9539 ...
191
  	if (ret)
6e20fb180   Roland Stigge   drivers/gpio/pca9...
192
  		goto exit;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
193
194
195
196
197
  
  	chip->reg_output = reg_val;
  
  	/* then direction */
  	reg_val = chip->reg_direction & ~(1u << off);
33226ffd0   Haojian Zhuang   gpio/pca953x: Add...
198
199
200
201
202
203
204
205
206
  	switch (chip->chip_type) {
  	case PCA953X_TYPE:
  		offset = PCA953X_DIRECTION;
  		break;
  	case PCA957X_TYPE:
  		offset = PCA957X_CFG;
  		break;
  	}
  	ret = pca953x_write_reg(chip, offset, reg_val);
9e60fdcf0   eric miao   gpiolib: pca9539 ...
207
  	if (ret)
6e20fb180   Roland Stigge   drivers/gpio/pca9...
208
  		goto exit;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
209
210
  
  	chip->reg_direction = reg_val;
6e20fb180   Roland Stigge   drivers/gpio/pca9...
211
212
213
214
  	ret = 0;
  exit:
  	mutex_unlock(&chip->i2c_lock);
  	return ret;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
215
  }
f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
216
  static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
9e60fdcf0   eric miao   gpiolib: pca9539 ...
217
  {
f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
218
  	struct pca953x_chip *chip;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
219
  	uint16_t reg_val;
33226ffd0   Haojian Zhuang   gpio/pca953x: Add...
220
  	int ret, offset = 0;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
221

f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
222
  	chip = container_of(gc, struct pca953x_chip, gpio_chip);
9e60fdcf0   eric miao   gpiolib: pca9539 ...
223

6e20fb180   Roland Stigge   drivers/gpio/pca9...
224
  	mutex_lock(&chip->i2c_lock);
33226ffd0   Haojian Zhuang   gpio/pca953x: Add...
225
226
227
228
229
230
231
232
233
  	switch (chip->chip_type) {
  	case PCA953X_TYPE:
  		offset = PCA953X_INPUT;
  		break;
  	case PCA957X_TYPE:
  		offset = PCA957X_IN;
  		break;
  	}
  	ret = pca953x_read_reg(chip, offset, &reg_val);
6e20fb180   Roland Stigge   drivers/gpio/pca9...
234
  	mutex_unlock(&chip->i2c_lock);
9e60fdcf0   eric miao   gpiolib: pca9539 ...
235
236
237
238
239
240
241
242
243
244
  	if (ret < 0) {
  		/* NOTE:  diagnostic already emitted; that's all we should
  		 * do unless gpio_*_value_cansleep() calls become different
  		 * from their nonsleeping siblings (and report faults).
  		 */
  		return 0;
  	}
  
  	return (reg_val & (1u << off)) ? 1 : 0;
  }
f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
245
  static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
9e60fdcf0   eric miao   gpiolib: pca9539 ...
246
  {
f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
247
  	struct pca953x_chip *chip;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
248
  	uint16_t reg_val;
33226ffd0   Haojian Zhuang   gpio/pca953x: Add...
249
  	int ret, offset = 0;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
250

f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
251
  	chip = container_of(gc, struct pca953x_chip, gpio_chip);
9e60fdcf0   eric miao   gpiolib: pca9539 ...
252

6e20fb180   Roland Stigge   drivers/gpio/pca9...
253
  	mutex_lock(&chip->i2c_lock);
9e60fdcf0   eric miao   gpiolib: pca9539 ...
254
255
256
257
  	if (val)
  		reg_val = chip->reg_output | (1u << off);
  	else
  		reg_val = chip->reg_output & ~(1u << off);
33226ffd0   Haojian Zhuang   gpio/pca953x: Add...
258
259
260
261
262
263
264
265
266
  	switch (chip->chip_type) {
  	case PCA953X_TYPE:
  		offset = PCA953X_OUTPUT;
  		break;
  	case PCA957X_TYPE:
  		offset = PCA957X_OUT;
  		break;
  	}
  	ret = pca953x_write_reg(chip, offset, reg_val);
9e60fdcf0   eric miao   gpiolib: pca9539 ...
267
  	if (ret)
6e20fb180   Roland Stigge   drivers/gpio/pca9...
268
  		goto exit;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
269
270
  
  	chip->reg_output = reg_val;
6e20fb180   Roland Stigge   drivers/gpio/pca9...
271
272
  exit:
  	mutex_unlock(&chip->i2c_lock);
9e60fdcf0   eric miao   gpiolib: pca9539 ...
273
  }
f5e8ff483   Guennadi Liakhovetski   gpio: handle pca9...
274
  static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
9e60fdcf0   eric miao   gpiolib: pca9539 ...
275
276
277
278
  {
  	struct gpio_chip *gc;
  
  	gc = &chip->gpio_chip;
f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
279
280
281
282
  	gc->direction_input  = pca953x_gpio_direction_input;
  	gc->direction_output = pca953x_gpio_direction_output;
  	gc->get = pca953x_gpio_get_value;
  	gc->set = pca953x_gpio_set_value;
842078054   Arnaud Patard   gpio/pca953x bugf...
283
  	gc->can_sleep = 1;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
284
285
  
  	gc->base = chip->gpio_start;
f5e8ff483   Guennadi Liakhovetski   gpio: handle pca9...
286
287
  	gc->ngpio = gpios;
  	gc->label = chip->client->name;
d8f388d8d   David Brownell   gpio: sysfs inter...
288
  	gc->dev = &chip->client->dev;
d72cbed0c   Guennadi Liakhovetski   gpiolib: i2c/spi ...
289
  	gc->owner = THIS_MODULE;
77906a546   Daniel Silverstone   pca953x: support ...
290
  	gc->names = chip->names;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
291
  }
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
292
293
294
295
296
297
298
299
  #ifdef CONFIG_GPIO_PCA953X_IRQ
  static int pca953x_gpio_to_irq(struct gpio_chip *gc, unsigned off)
  {
  	struct pca953x_chip *chip;
  
  	chip = container_of(gc, struct pca953x_chip, gpio_chip);
  	return chip->irq_base + off;
  }
6f5cfc0e2   Lennert Buytenhek   gpio: pca953x: ir...
300
  static void pca953x_irq_mask(struct irq_data *d)
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
301
  {
6f5cfc0e2   Lennert Buytenhek   gpio: pca953x: ir...
302
  	struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
303

6f5cfc0e2   Lennert Buytenhek   gpio: pca953x: ir...
304
  	chip->irq_mask &= ~(1 << (d->irq - chip->irq_base));
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
305
  }
6f5cfc0e2   Lennert Buytenhek   gpio: pca953x: ir...
306
  static void pca953x_irq_unmask(struct irq_data *d)
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
307
  {
6f5cfc0e2   Lennert Buytenhek   gpio: pca953x: ir...
308
  	struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
309

6f5cfc0e2   Lennert Buytenhek   gpio: pca953x: ir...
310
  	chip->irq_mask |= 1 << (d->irq - chip->irq_base);
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
311
  }
6f5cfc0e2   Lennert Buytenhek   gpio: pca953x: ir...
312
  static void pca953x_irq_bus_lock(struct irq_data *d)
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
313
  {
6f5cfc0e2   Lennert Buytenhek   gpio: pca953x: ir...
314
  	struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
315
316
317
  
  	mutex_lock(&chip->irq_lock);
  }
6f5cfc0e2   Lennert Buytenhek   gpio: pca953x: ir...
318
  static void pca953x_irq_bus_sync_unlock(struct irq_data *d)
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
319
  {
6f5cfc0e2   Lennert Buytenhek   gpio: pca953x: ir...
320
  	struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
a2cb9aeb3   Marc Zyngier   gpio: fix pca953x...
321
322
323
324
325
326
327
328
329
330
331
332
  	uint16_t new_irqs;
  	uint16_t level;
  
  	/* Look for any newly setup interrupt */
  	new_irqs = chip->irq_trig_fall | chip->irq_trig_raise;
  	new_irqs &= ~chip->reg_direction;
  
  	while (new_irqs) {
  		level = __ffs(new_irqs);
  		pca953x_gpio_direction_input(&chip->gpio_chip, level);
  		new_irqs &= ~(1 << level);
  	}
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
333
334
335
  
  	mutex_unlock(&chip->irq_lock);
  }
6f5cfc0e2   Lennert Buytenhek   gpio: pca953x: ir...
336
  static int pca953x_irq_set_type(struct irq_data *d, unsigned int type)
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
337
  {
6f5cfc0e2   Lennert Buytenhek   gpio: pca953x: ir...
338
339
  	struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
  	uint16_t level = d->irq - chip->irq_base;
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
340
341
342
343
344
  	uint16_t mask = 1 << level;
  
  	if (!(type & IRQ_TYPE_EDGE_BOTH)) {
  		dev_err(&chip->client->dev, "irq %d: unsupported type %d
  ",
6f5cfc0e2   Lennert Buytenhek   gpio: pca953x: ir...
345
  			d->irq, type);
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
346
347
348
349
350
351
352
353
354
355
356
357
  		return -EINVAL;
  	}
  
  	if (type & IRQ_TYPE_EDGE_FALLING)
  		chip->irq_trig_fall |= mask;
  	else
  		chip->irq_trig_fall &= ~mask;
  
  	if (type & IRQ_TYPE_EDGE_RISING)
  		chip->irq_trig_raise |= mask;
  	else
  		chip->irq_trig_raise &= ~mask;
a2cb9aeb3   Marc Zyngier   gpio: fix pca953x...
358
  	return 0;
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
359
360
361
362
  }
  
  static struct irq_chip pca953x_irq_chip = {
  	.name			= "pca953x",
6f5cfc0e2   Lennert Buytenhek   gpio: pca953x: ir...
363
364
365
366
367
  	.irq_mask		= pca953x_irq_mask,
  	.irq_unmask		= pca953x_irq_unmask,
  	.irq_bus_lock		= pca953x_irq_bus_lock,
  	.irq_bus_sync_unlock	= pca953x_irq_bus_sync_unlock,
  	.irq_set_type		= pca953x_irq_set_type,
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
368
369
370
371
372
373
374
375
  };
  
  static uint16_t pca953x_irq_pending(struct pca953x_chip *chip)
  {
  	uint16_t cur_stat;
  	uint16_t old_stat;
  	uint16_t pending;
  	uint16_t trigger;
33226ffd0   Haojian Zhuang   gpio/pca953x: Add...
376
377
378
379
380
381
382
383
384
385
386
  	int ret, offset = 0;
  
  	switch (chip->chip_type) {
  	case PCA953X_TYPE:
  		offset = PCA953X_INPUT;
  		break;
  	case PCA957X_TYPE:
  		offset = PCA957X_IN;
  		break;
  	}
  	ret = pca953x_read_reg(chip, offset, &cur_stat);
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
  	if (ret)
  		return 0;
  
  	/* Remove output pins from the equation */
  	cur_stat &= chip->reg_direction;
  
  	old_stat = chip->irq_stat;
  	trigger = (cur_stat ^ old_stat) & chip->irq_mask;
  
  	if (!trigger)
  		return 0;
  
  	chip->irq_stat = cur_stat;
  
  	pending = (old_stat & chip->irq_trig_fall) |
  		  (cur_stat & chip->irq_trig_raise);
  	pending &= trigger;
  
  	return pending;
  }
  
  static irqreturn_t pca953x_irq_handler(int irq, void *devid)
  {
  	struct pca953x_chip *chip = devid;
  	uint16_t pending;
  	uint16_t level;
  
  	pending = pca953x_irq_pending(chip);
  
  	if (!pending)
  		return IRQ_HANDLED;
  
  	do {
  		level = __ffs(pending);
6dd599f8a   David Jander   gpio/pca953x: Fix...
421
  		handle_nested_irq(level + chip->irq_base);
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
422
423
424
425
426
427
428
429
  
  		pending &= ~(1 << level);
  	} while (pending);
  
  	return IRQ_HANDLED;
  }
  
  static int pca953x_irq_setup(struct pca953x_chip *chip,
c6dcf5924   David Jander   gpio/pca953x: Rem...
430
431
  			     const struct i2c_device_id *id,
  			     int irq_base)
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
432
433
  {
  	struct i2c_client *client = chip->client;
33226ffd0   Haojian Zhuang   gpio/pca953x: Add...
434
  	int ret, offset = 0;
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
435

c6dcf5924   David Jander   gpio/pca953x: Rem...
436
  	if (irq_base != -1
33226ffd0   Haojian Zhuang   gpio/pca953x: Add...
437
  			&& (id->driver_data & PCA_INT)) {
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
438
  		int lvl;
33226ffd0   Haojian Zhuang   gpio/pca953x: Add...
439
440
441
442
443
444
445
446
447
  		switch (chip->chip_type) {
  		case PCA953X_TYPE:
  			offset = PCA953X_INPUT;
  			break;
  		case PCA957X_TYPE:
  			offset = PCA957X_IN;
  			break;
  		}
  		ret = pca953x_read_reg(chip, offset, &chip->irq_stat);
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
448
449
450
451
452
453
454
455
456
  		if (ret)
  			goto out_failed;
  
  		/*
  		 * There is no way to know which GPIO line generated the
  		 * interrupt.  We have to rely on the previous read for
  		 * this purpose.
  		 */
  		chip->irq_stat &= chip->reg_direction;
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
457
  		mutex_init(&chip->irq_lock);
c6dcf5924   David Jander   gpio/pca953x: Rem...
458
  		chip->irq_base = irq_alloc_descs(-1, irq_base, chip->gpio_chip.ngpio, -1);
910c8fb6b   David Jander   gpio/pca953x: Fix...
459
460
  		if (chip->irq_base < 0)
  			goto out_failed;
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
461
462
  		for (lvl = 0; lvl < chip->gpio_chip.ngpio; lvl++) {
  			int irq = lvl + chip->irq_base;
910c8fb6b   David Jander   gpio/pca953x: Fix...
463
  			irq_clear_status_flags(irq, IRQ_NOREQUEST);
b51804bcf   Thomas Gleixner   gpio: Cleanup gen...
464
  			irq_set_chip_data(irq, chip);
6dd599f8a   David Jander   gpio/pca953x: Fix...
465
466
  			irq_set_chip(irq, &pca953x_irq_chip);
  			irq_set_nested_thread(irq, true);
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
467
468
469
  #ifdef CONFIG_ARM
  			set_irq_flags(irq, IRQF_VALID);
  #else
b51804bcf   Thomas Gleixner   gpio: Cleanup gen...
470
  			irq_set_noprobe(irq);
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
471
472
473
474
475
476
  #endif
  		}
  
  		ret = request_threaded_irq(client->irq,
  					   NULL,
  					   pca953x_irq_handler,
17e8b42c1   David Jander   gpio/pca953x: Int...
477
  					   IRQF_TRIGGER_LOW | IRQF_ONESHOT,
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
478
479
480
481
482
483
484
485
486
487
488
489
490
491
  					   dev_name(&client->dev), chip);
  		if (ret) {
  			dev_err(&client->dev, "failed to request irq %d
  ",
  				client->irq);
  			goto out_failed;
  		}
  
  		chip->gpio_chip.to_irq = pca953x_gpio_to_irq;
  	}
  
  	return 0;
  
  out_failed:
8a233f01b   Alek Du   pca953x: pca953x ...
492
  	chip->irq_base = -1;
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
493
494
495
496
497
  	return ret;
  }
  
  static void pca953x_irq_teardown(struct pca953x_chip *chip)
  {
c609c05db   David Jander   gpio/pca953x: Fix...
498
499
  	if (chip->irq_base != -1) {
  		irq_free_descs(chip->irq_base, chip->gpio_chip.ngpio);
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
500
  		free_irq(chip->client->irq, chip);
c609c05db   David Jander   gpio/pca953x: Fix...
501
  	}
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
502
503
504
  }
  #else /* CONFIG_GPIO_PCA953X_IRQ */
  static int pca953x_irq_setup(struct pca953x_chip *chip,
c6dcf5924   David Jander   gpio/pca953x: Rem...
505
506
  			     const struct i2c_device_id *id,
  			     int irq_base)
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
507
508
  {
  	struct i2c_client *client = chip->client;
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
509

c6dcf5924   David Jander   gpio/pca953x: Rem...
510
  	if (irq_base != -1 && (id->driver_data & PCA_INT))
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
511
512
513
514
515
516
517
518
519
520
  		dev_warn(&client->dev, "interrupt support not compiled in
  ");
  
  	return 0;
  }
  
  static void pca953x_irq_teardown(struct pca953x_chip *chip)
  {
  }
  #endif
1965d3035   Nate Case   gpio: pca953x: Ge...
521
522
523
524
525
526
  /*
   * Handlers for alternative sources of platform_data
   */
  #ifdef CONFIG_OF_GPIO
  /*
   * Translate OpenFirmware node properties into platform_data
a57339b4b   David Jander   gpio/pca953x: Dep...
527
   * WARNING: This is DEPRECATED and will be removed eventually!
1965d3035   Nate Case   gpio: pca953x: Ge...
528
   */
404ba2b8f   Mark Brown   gpio: pca953x: St...
529
  static void
c6dcf5924   David Jander   gpio/pca953x: Rem...
530
  pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, int *invert)
1965d3035   Nate Case   gpio: pca953x: Ge...
531
  {
1965d3035   Nate Case   gpio: pca953x: Ge...
532
  	struct device_node *node;
1648237dc   Dirk Eibach   gpio/pca953x: Fix...
533
534
  	const __be32 *val;
  	int size;
1965d3035   Nate Case   gpio: pca953x: Ge...
535

61c7a080a   Grant Likely   of: Always use 's...
536
  	node = client->dev.of_node;
1965d3035   Nate Case   gpio: pca953x: Ge...
537
  	if (node == NULL)
c6dcf5924   David Jander   gpio/pca953x: Rem...
538
  		return;
1965d3035   Nate Case   gpio: pca953x: Ge...
539

c6dcf5924   David Jander   gpio/pca953x: Rem...
540
  	*gpio_base = -1;
1648237dc   Dirk Eibach   gpio/pca953x: Fix...
541
  	val = of_get_property(node, "linux,gpio-base", &size);
a57339b4b   David Jander   gpio/pca953x: Dep...
542
  	WARN(val, "%s: device-tree property 'linux,gpio-base' is deprecated!", __func__);
1965d3035   Nate Case   gpio: pca953x: Ge...
543
  	if (val) {
1648237dc   Dirk Eibach   gpio/pca953x: Fix...
544
545
546
547
  		if (size != sizeof(*val))
  			dev_warn(&client->dev, "%s: wrong linux,gpio-base
  ",
  				 node->full_name);
1965d3035   Nate Case   gpio: pca953x: Ge...
548
  		else
c6dcf5924   David Jander   gpio/pca953x: Rem...
549
  			*gpio_base = be32_to_cpup(val);
1965d3035   Nate Case   gpio: pca953x: Ge...
550
551
552
  	}
  
  	val = of_get_property(node, "polarity", NULL);
a57339b4b   David Jander   gpio/pca953x: Dep...
553
  	WARN(val, "%s: device-tree property 'polarity' is deprecated!", __func__);
1965d3035   Nate Case   gpio: pca953x: Ge...
554
  	if (val)
c6dcf5924   David Jander   gpio/pca953x: Rem...
555
  		*invert = *val;
1965d3035   Nate Case   gpio: pca953x: Ge...
556
557
  }
  #else
404ba2b8f   Mark Brown   gpio: pca953x: St...
558
  static void
c6dcf5924   David Jander   gpio/pca953x: Rem...
559
  pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, int *invert)
1965d3035   Nate Case   gpio: pca953x: Ge...
560
  {
25fcf2b7f   Hartmut Knaack   gpio-pca953x: fix...
561
  	*gpio_base = -1;
1965d3035   Nate Case   gpio: pca953x: Ge...
562
563
  }
  #endif
33226ffd0   Haojian Zhuang   gpio/pca953x: Add...
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
  static int __devinit device_pca953x_init(struct pca953x_chip *chip, int invert)
  {
  	int ret;
  
  	ret = pca953x_read_reg(chip, PCA953X_OUTPUT, &chip->reg_output);
  	if (ret)
  		goto out;
  
  	ret = pca953x_read_reg(chip, PCA953X_DIRECTION,
  			       &chip->reg_direction);
  	if (ret)
  		goto out;
  
  	/* set platform specific polarity inversion */
  	ret = pca953x_write_reg(chip, PCA953X_INVERT, invert);
33226ffd0   Haojian Zhuang   gpio/pca953x: Add...
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
  out:
  	return ret;
  }
  
  static int __devinit device_pca957x_init(struct pca953x_chip *chip, int invert)
  {
  	int ret;
  	uint16_t val = 0;
  
  	/* Let every port in proper state, that could save power */
  	pca953x_write_reg(chip, PCA957X_PUPD, 0x0);
  	pca953x_write_reg(chip, PCA957X_CFG, 0xffff);
  	pca953x_write_reg(chip, PCA957X_OUT, 0x0);
  
  	ret = pca953x_read_reg(chip, PCA957X_IN, &val);
  	if (ret)
  		goto out;
  	ret = pca953x_read_reg(chip, PCA957X_OUT, &chip->reg_output);
  	if (ret)
  		goto out;
  	ret = pca953x_read_reg(chip, PCA957X_CFG, &chip->reg_direction);
  	if (ret)
  		goto out;
  
  	/* set platform specific polarity inversion */
  	pca953x_write_reg(chip, PCA957X_INVRT, invert);
  
  	/* To enable register 6, 7 to controll pull up and pull down */
  	pca953x_write_reg(chip, PCA957X_BKEN, 0x202);
  
  	return 0;
  out:
  	return ret;
  }
d2653e927   Jean Delvare   i2c: Add support ...
613
  static int __devinit pca953x_probe(struct i2c_client *client,
3760f7367   Jean Delvare   i2c: Convert most...
614
  				   const struct i2c_device_id *id)
9e60fdcf0   eric miao   gpiolib: pca9539 ...
615
  {
f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
616
617
  	struct pca953x_platform_data *pdata;
  	struct pca953x_chip *chip;
a57339b4b   David Jander   gpio/pca953x: Dep...
618
  	int irq_base=0, invert=0;
7ea2aa204   Wolfram Sang   gpio: pca953x: pr...
619
  	int ret;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
620

1965d3035   Nate Case   gpio: pca953x: Ge...
621
622
623
  	chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL);
  	if (chip == NULL)
  		return -ENOMEM;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
624
  	pdata = client->dev.platform_data;
c6dcf5924   David Jander   gpio/pca953x: Rem...
625
626
627
628
629
630
631
  	if (pdata) {
  		irq_base = pdata->irq_base;
  		chip->gpio_start = pdata->gpio_base;
  		invert = pdata->invert;
  		chip->names = pdata->names;
  	} else {
  		pca953x_get_alt_pdata(client, &chip->gpio_start, &invert);
a57339b4b   David Jander   gpio/pca953x: Dep...
632
633
634
635
636
  #ifdef CONFIG_OF_GPIO
  		/* If I2C node has no interrupts property, disable GPIO interrupts */
  		if (of_find_property(client->dev.of_node, "interrupts", NULL) == NULL)
  			irq_base = -1;
  #endif
1965d3035   Nate Case   gpio: pca953x: Ge...
637
  	}
9e60fdcf0   eric miao   gpiolib: pca9539 ...
638
639
  
  	chip->client = client;
33226ffd0   Haojian Zhuang   gpio/pca953x: Add...
640
  	chip->chip_type = id->driver_data & (PCA953X_TYPE | PCA957X_TYPE);
77906a546   Daniel Silverstone   pca953x: support ...
641

6e20fb180   Roland Stigge   drivers/gpio/pca9...
642
  	mutex_init(&chip->i2c_lock);
9e60fdcf0   eric miao   gpiolib: pca9539 ...
643
644
645
  	/* initialize cached registers from their original values.
  	 * we can't share this chip with another i2c master.
  	 */
33226ffd0   Haojian Zhuang   gpio/pca953x: Add...
646
  	pca953x_setup_gpio(chip, id->driver_data & PCA_GPIO_MASK);
f5e8ff483   Guennadi Liakhovetski   gpio: handle pca9...
647

33226ffd0   Haojian Zhuang   gpio/pca953x: Add...
648
  	if (chip->chip_type == PCA953X_TYPE)
7ea2aa204   Wolfram Sang   gpio: pca953x: pr...
649
  		ret = device_pca953x_init(chip, invert);
33226ffd0   Haojian Zhuang   gpio/pca953x: Add...
650
  	else
7ea2aa204   Wolfram Sang   gpio: pca953x: pr...
651
652
  		ret = device_pca957x_init(chip, invert);
  	if (ret)
9e60fdcf0   eric miao   gpiolib: pca9539 ...
653
  		goto out_failed;
c6dcf5924   David Jander   gpio/pca953x: Rem...
654
  	ret = pca953x_irq_setup(chip, id, irq_base);
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
655
656
  	if (ret)
  		goto out_failed;
f5e8ff483   Guennadi Liakhovetski   gpio: handle pca9...
657
658
  
  	ret = gpiochip_add(&chip->gpio_chip);
9e60fdcf0   eric miao   gpiolib: pca9539 ...
659
  	if (ret)
272df502b   Ben Dooks   gpio/pca953x: fix...
660
  		goto out_failed_irq;
9e60fdcf0   eric miao   gpiolib: pca9539 ...
661

c6dcf5924   David Jander   gpio/pca953x: Rem...
662
  	if (pdata && pdata->setup) {
9e60fdcf0   eric miao   gpiolib: pca9539 ...
663
664
665
666
667
668
669
670
671
  		ret = pdata->setup(client, chip->gpio_chip.base,
  				chip->gpio_chip.ngpio, pdata->context);
  		if (ret < 0)
  			dev_warn(&client->dev, "setup failed, %d
  ", ret);
  	}
  
  	i2c_set_clientdata(client, chip);
  	return 0;
272df502b   Ben Dooks   gpio/pca953x: fix...
672
  out_failed_irq:
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
673
  	pca953x_irq_teardown(chip);
272df502b   Ben Dooks   gpio/pca953x: fix...
674
  out_failed:
9e60fdcf0   eric miao   gpiolib: pca9539 ...
675
676
677
  	kfree(chip);
  	return ret;
  }
f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
678
  static int pca953x_remove(struct i2c_client *client)
9e60fdcf0   eric miao   gpiolib: pca9539 ...
679
  {
f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
680
681
  	struct pca953x_platform_data *pdata = client->dev.platform_data;
  	struct pca953x_chip *chip = i2c_get_clientdata(client);
9e60fdcf0   eric miao   gpiolib: pca9539 ...
682
  	int ret = 0;
c6dcf5924   David Jander   gpio/pca953x: Rem...
683
  	if (pdata && pdata->teardown) {
9e60fdcf0   eric miao   gpiolib: pca9539 ...
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
  		ret = pdata->teardown(client, chip->gpio_chip.base,
  				chip->gpio_chip.ngpio, pdata->context);
  		if (ret < 0) {
  			dev_err(&client->dev, "%s failed, %d
  ",
  					"teardown", ret);
  			return ret;
  		}
  	}
  
  	ret = gpiochip_remove(&chip->gpio_chip);
  	if (ret) {
  		dev_err(&client->dev, "%s failed, %d
  ",
  				"gpiochip_remove()", ret);
  		return ret;
  	}
89ea8bbe9   Marc Zyngier   gpio: pca953x.c: ...
701
  	pca953x_irq_teardown(chip);
9e60fdcf0   eric miao   gpiolib: pca9539 ...
702
703
704
  	kfree(chip);
  	return 0;
  }
f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
705
  static struct i2c_driver pca953x_driver = {
9e60fdcf0   eric miao   gpiolib: pca9539 ...
706
  	.driver = {
f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
707
  		.name	= "pca953x",
9e60fdcf0   eric miao   gpiolib: pca9539 ...
708
  	},
f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
709
710
  	.probe		= pca953x_probe,
  	.remove		= pca953x_remove,
3760f7367   Jean Delvare   i2c: Convert most...
711
  	.id_table	= pca953x_id,
9e60fdcf0   eric miao   gpiolib: pca9539 ...
712
  };
f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
713
  static int __init pca953x_init(void)
9e60fdcf0   eric miao   gpiolib: pca9539 ...
714
  {
f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
715
  	return i2c_add_driver(&pca953x_driver);
9e60fdcf0   eric miao   gpiolib: pca9539 ...
716
  }
2f8d11971   David Brownell   gpio: i2c expande...
717
718
719
720
  /* register after i2c postcore initcall and before
   * subsys initcalls that may rely on these GPIOs
   */
  subsys_initcall(pca953x_init);
9e60fdcf0   eric miao   gpiolib: pca9539 ...
721

f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
722
  static void __exit pca953x_exit(void)
9e60fdcf0   eric miao   gpiolib: pca9539 ...
723
  {
f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
724
  	i2c_del_driver(&pca953x_driver);
9e60fdcf0   eric miao   gpiolib: pca9539 ...
725
  }
f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
726
  module_exit(pca953x_exit);
9e60fdcf0   eric miao   gpiolib: pca9539 ...
727
728
  
  MODULE_AUTHOR("eric miao <eric.miao@marvell.com>");
f3dc3630f   Guennadi Liakhovetski   gpio: rename pca9...
729
  MODULE_DESCRIPTION("GPIO expander driver for PCA953x");
9e60fdcf0   eric miao   gpiolib: pca9539 ...
730
  MODULE_LICENSE("GPL");