Blame view

drivers/gpio/gpio-adp5588.c 11.2 KB
80884094e   Michael Hennerich   gpio: adp5588-gpi...
1
2
  /*
   * GPIO Chip driver for Analog Devices
459773ae8   Michael Hennerich   gpio: adp5588-gpi...
3
   * ADP5588/ADP5587 I/O Expander and QWERTY Keypad Controller
80884094e   Michael Hennerich   gpio: adp5588-gpi...
4
   *
459773ae8   Michael Hennerich   gpio: adp5588-gpi...
5
   * Copyright 2009-2010 Analog Devices Inc.
80884094e   Michael Hennerich   gpio: adp5588-gpi...
6
7
8
9
10
11
   *
   * Licensed under the GPL-2 or later.
   */
  
  #include <linux/module.h>
  #include <linux/kernel.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
12
  #include <linux/slab.h>
80884094e   Michael Hennerich   gpio: adp5588-gpi...
13
14
15
  #include <linux/init.h>
  #include <linux/i2c.h>
  #include <linux/gpio.h>
459773ae8   Michael Hennerich   gpio: adp5588-gpi...
16
17
  #include <linux/interrupt.h>
  #include <linux/irq.h>
80884094e   Michael Hennerich   gpio: adp5588-gpi...
18
19
  
  #include <linux/i2c/adp5588.h>
459773ae8   Michael Hennerich   gpio: adp5588-gpi...
20
21
22
23
24
25
26
27
  #define DRV_NAME	"adp5588-gpio"
  
  /*
   * Early pre 4.0 Silicon required to delay readout by at least 25ms,
   * since the Event Counter Register updated 25ms after the interrupt
   * asserted.
   */
  #define WA_DELAYED_READOUT_REVID(rev)	((rev) < 4)
80884094e   Michael Hennerich   gpio: adp5588-gpi...
28
29
30
31
32
  
  struct adp5588_gpio {
  	struct i2c_client *client;
  	struct gpio_chip gpio_chip;
  	struct mutex lock;	/* protect cached dir, dat_out */
459773ae8   Michael Hennerich   gpio: adp5588-gpi...
33
34
  	/* protect serialized access to the interrupt controller bus */
  	struct mutex irq_lock;
80884094e   Michael Hennerich   gpio: adp5588-gpi...
35
  	unsigned gpio_start;
459773ae8   Michael Hennerich   gpio: adp5588-gpi...
36
  	unsigned irq_base;
80884094e   Michael Hennerich   gpio: adp5588-gpi...
37
38
  	uint8_t dat_out[3];
  	uint8_t dir[3];
459773ae8   Michael Hennerich   gpio: adp5588-gpi...
39
40
41
42
  	uint8_t int_lvl[3];
  	uint8_t int_en[3];
  	uint8_t irq_mask[3];
  	uint8_t irq_stat[3];
80884094e   Michael Hennerich   gpio: adp5588-gpi...
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
  };
  
  static int adp5588_gpio_read(struct i2c_client *client, u8 reg)
  {
  	int ret = i2c_smbus_read_byte_data(client, reg);
  
  	if (ret < 0)
  		dev_err(&client->dev, "Read Error
  ");
  
  	return ret;
  }
  
  static int adp5588_gpio_write(struct i2c_client *client, u8 reg, u8 val)
  {
  	int ret = i2c_smbus_write_byte_data(client, reg, val);
  
  	if (ret < 0)
  		dev_err(&client->dev, "Write Error
  ");
  
  	return ret;
  }
  
  static int adp5588_gpio_get_value(struct gpio_chip *chip, unsigned off)
  {
f69255ce6   Linus Walleij   gpio: adp5588: us...
69
  	struct adp5588_gpio *dev = gpiochip_get_data(chip);
992196f28   Jean-Francois Dagenais   gpio: adp5588: ge...
70
71
72
  	unsigned bank = ADP5588_BANK(off);
  	unsigned bit = ADP5588_BIT(off);
  	int val;
80884094e   Michael Hennerich   gpio: adp5588-gpi...
73

992196f28   Jean-Francois Dagenais   gpio: adp5588: ge...
74
75
76
77
78
79
80
81
82
83
  	mutex_lock(&dev->lock);
  
  	if (dev->dir[bank] & bit)
  		val = dev->dat_out[bank];
  	else
  		val = adp5588_gpio_read(dev->client, GPIO_DAT_STAT1 + bank);
  
  	mutex_unlock(&dev->lock);
  
  	return !!(val & bit);
80884094e   Michael Hennerich   gpio: adp5588-gpi...
84
85
86
87
88
89
  }
  
  static void adp5588_gpio_set_value(struct gpio_chip *chip,
  				   unsigned off, int val)
  {
  	unsigned bank, bit;
f69255ce6   Linus Walleij   gpio: adp5588: us...
90
  	struct adp5588_gpio *dev = gpiochip_get_data(chip);
80884094e   Michael Hennerich   gpio: adp5588-gpi...
91

459773ae8   Michael Hennerich   gpio: adp5588-gpi...
92
93
  	bank = ADP5588_BANK(off);
  	bit = ADP5588_BIT(off);
80884094e   Michael Hennerich   gpio: adp5588-gpi...
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
  
  	mutex_lock(&dev->lock);
  	if (val)
  		dev->dat_out[bank] |= bit;
  	else
  		dev->dat_out[bank] &= ~bit;
  
  	adp5588_gpio_write(dev->client, GPIO_DAT_OUT1 + bank,
  			   dev->dat_out[bank]);
  	mutex_unlock(&dev->lock);
  }
  
  static int adp5588_gpio_direction_input(struct gpio_chip *chip, unsigned off)
  {
  	int ret;
  	unsigned bank;
f69255ce6   Linus Walleij   gpio: adp5588: us...
110
  	struct adp5588_gpio *dev = gpiochip_get_data(chip);
80884094e   Michael Hennerich   gpio: adp5588-gpi...
111

459773ae8   Michael Hennerich   gpio: adp5588-gpi...
112
  	bank = ADP5588_BANK(off);
80884094e   Michael Hennerich   gpio: adp5588-gpi...
113
114
  
  	mutex_lock(&dev->lock);
459773ae8   Michael Hennerich   gpio: adp5588-gpi...
115
  	dev->dir[bank] &= ~ADP5588_BIT(off);
80884094e   Michael Hennerich   gpio: adp5588-gpi...
116
117
118
119
120
121
122
123
124
125
126
  	ret = adp5588_gpio_write(dev->client, GPIO_DIR1 + bank, dev->dir[bank]);
  	mutex_unlock(&dev->lock);
  
  	return ret;
  }
  
  static int adp5588_gpio_direction_output(struct gpio_chip *chip,
  					 unsigned off, int val)
  {
  	int ret;
  	unsigned bank, bit;
f69255ce6   Linus Walleij   gpio: adp5588: us...
127
  	struct adp5588_gpio *dev = gpiochip_get_data(chip);
80884094e   Michael Hennerich   gpio: adp5588-gpi...
128

459773ae8   Michael Hennerich   gpio: adp5588-gpi...
129
130
  	bank = ADP5588_BANK(off);
  	bit = ADP5588_BIT(off);
80884094e   Michael Hennerich   gpio: adp5588-gpi...
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
  
  	mutex_lock(&dev->lock);
  	dev->dir[bank] |= bit;
  
  	if (val)
  		dev->dat_out[bank] |= bit;
  	else
  		dev->dat_out[bank] &= ~bit;
  
  	ret = adp5588_gpio_write(dev->client, GPIO_DAT_OUT1 + bank,
  				 dev->dat_out[bank]);
  	ret |= adp5588_gpio_write(dev->client, GPIO_DIR1 + bank,
  				 dev->dir[bank]);
  	mutex_unlock(&dev->lock);
  
  	return ret;
  }
459773ae8   Michael Hennerich   gpio: adp5588-gpi...
148
149
150
  #ifdef CONFIG_GPIO_ADP5588_IRQ
  static int adp5588_gpio_to_irq(struct gpio_chip *chip, unsigned off)
  {
f69255ce6   Linus Walleij   gpio: adp5588: us...
151
  	struct adp5588_gpio *dev = gpiochip_get_data(chip);
459773ae8   Michael Hennerich   gpio: adp5588-gpi...
152
153
  	return dev->irq_base + off;
  }
12401eedd   Lennert Buytenhek   gpio: adp5588-gpi...
154
  static void adp5588_irq_bus_lock(struct irq_data *d)
459773ae8   Michael Hennerich   gpio: adp5588-gpi...
155
  {
12401eedd   Lennert Buytenhek   gpio: adp5588-gpi...
156
  	struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d);
459773ae8   Michael Hennerich   gpio: adp5588-gpi...
157
158
159
160
161
162
163
164
165
166
  	mutex_lock(&dev->irq_lock);
  }
  
   /*
    * genirq core code can issue chip->mask/unmask from atomic context.
    * This doesn't work for slow busses where an access needs to sleep.
    * bus_sync_unlock() is therefore called outside the atomic context,
    * syncs the current irq mask state with the slow external controller
    * and unlocks the bus.
    */
12401eedd   Lennert Buytenhek   gpio: adp5588-gpi...
167
  static void adp5588_irq_bus_sync_unlock(struct irq_data *d)
459773ae8   Michael Hennerich   gpio: adp5588-gpi...
168
  {
12401eedd   Lennert Buytenhek   gpio: adp5588-gpi...
169
  	struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d);
459773ae8   Michael Hennerich   gpio: adp5588-gpi...
170
171
172
173
174
175
176
177
178
179
180
  	int i;
  
  	for (i = 0; i <= ADP5588_BANK(ADP5588_MAXGPIO); i++)
  		if (dev->int_en[i] ^ dev->irq_mask[i]) {
  			dev->int_en[i] = dev->irq_mask[i];
  			adp5588_gpio_write(dev->client, GPIO_INT_EN1 + i,
  					   dev->int_en[i]);
  		}
  
  	mutex_unlock(&dev->irq_lock);
  }
12401eedd   Lennert Buytenhek   gpio: adp5588-gpi...
181
  static void adp5588_irq_mask(struct irq_data *d)
459773ae8   Michael Hennerich   gpio: adp5588-gpi...
182
  {
12401eedd   Lennert Buytenhek   gpio: adp5588-gpi...
183
184
  	struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d);
  	unsigned gpio = d->irq - dev->irq_base;
459773ae8   Michael Hennerich   gpio: adp5588-gpi...
185
186
187
  
  	dev->irq_mask[ADP5588_BANK(gpio)] &= ~ADP5588_BIT(gpio);
  }
12401eedd   Lennert Buytenhek   gpio: adp5588-gpi...
188
  static void adp5588_irq_unmask(struct irq_data *d)
459773ae8   Michael Hennerich   gpio: adp5588-gpi...
189
  {
12401eedd   Lennert Buytenhek   gpio: adp5588-gpi...
190
191
  	struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d);
  	unsigned gpio = d->irq - dev->irq_base;
459773ae8   Michael Hennerich   gpio: adp5588-gpi...
192
193
194
  
  	dev->irq_mask[ADP5588_BANK(gpio)] |= ADP5588_BIT(gpio);
  }
12401eedd   Lennert Buytenhek   gpio: adp5588-gpi...
195
  static int adp5588_irq_set_type(struct irq_data *d, unsigned int type)
459773ae8   Michael Hennerich   gpio: adp5588-gpi...
196
  {
12401eedd   Lennert Buytenhek   gpio: adp5588-gpi...
197
198
  	struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d);
  	uint16_t gpio = d->irq - dev->irq_base;
459773ae8   Michael Hennerich   gpio: adp5588-gpi...
199
200
201
202
203
  	unsigned bank, bit;
  
  	if ((type & IRQ_TYPE_EDGE_BOTH)) {
  		dev_err(&dev->client->dev, "irq %d: unsupported type %d
  ",
12401eedd   Lennert Buytenhek   gpio: adp5588-gpi...
204
  			d->irq, type);
459773ae8   Michael Hennerich   gpio: adp5588-gpi...
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
  		return -EINVAL;
  	}
  
  	bank = ADP5588_BANK(gpio);
  	bit = ADP5588_BIT(gpio);
  
  	if (type & IRQ_TYPE_LEVEL_HIGH)
  		dev->int_lvl[bank] |= bit;
  	else if (type & IRQ_TYPE_LEVEL_LOW)
  		dev->int_lvl[bank] &= ~bit;
  	else
  		return -EINVAL;
  
  	adp5588_gpio_direction_input(&dev->gpio_chip, gpio);
  	adp5588_gpio_write(dev->client, GPIO_INT_LVL1 + bank,
  			   dev->int_lvl[bank]);
  
  	return 0;
  }
  
  static struct irq_chip adp5588_irq_chip = {
  	.name			= "adp5588",
12401eedd   Lennert Buytenhek   gpio: adp5588-gpi...
227
228
229
230
231
  	.irq_mask		= adp5588_irq_mask,
  	.irq_unmask		= adp5588_irq_unmask,
  	.irq_bus_lock		= adp5588_irq_bus_lock,
  	.irq_bus_sync_unlock	= adp5588_irq_bus_sync_unlock,
  	.irq_set_type		= adp5588_irq_set_type,
459773ae8   Michael Hennerich   gpio: adp5588-gpi...
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
  };
  
  static int adp5588_gpio_read_intstat(struct i2c_client *client, u8 *buf)
  {
  	int ret = i2c_smbus_read_i2c_block_data(client, GPIO_INT_STAT1, 3, buf);
  
  	if (ret < 0)
  		dev_err(&client->dev, "Read INT_STAT Error
  ");
  
  	return ret;
  }
  
  static irqreturn_t adp5588_irq_handler(int irq, void *devid)
  {
  	struct adp5588_gpio *dev = devid;
  	unsigned status, bank, bit, pending;
  	int ret;
  	status = adp5588_gpio_read(dev->client, INT_STAT);
  
  	if (status & ADP5588_GPI_INT) {
  		ret = adp5588_gpio_read_intstat(dev->client, dev->irq_stat);
  		if (ret < 0)
  			memset(dev->irq_stat, 0, ARRAY_SIZE(dev->irq_stat));
078dc65e6   Axel Lin   gpio: Fix uniniti...
256
  		for (bank = 0, bit = 0; bank <= ADP5588_BANK(ADP5588_MAXGPIO);
459773ae8   Michael Hennerich   gpio: adp5588-gpi...
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
  			bank++, bit = 0) {
  			pending = dev->irq_stat[bank] & dev->irq_mask[bank];
  
  			while (pending) {
  				if (pending & (1 << bit)) {
  					handle_nested_irq(dev->irq_base +
  							  (bank << 3) + bit);
  					pending &= ~(1 << bit);
  
  				}
  				bit++;
  			}
  		}
  	}
  
  	adp5588_gpio_write(dev->client, INT_STAT, status); /* Status is W1C */
  
  	return IRQ_HANDLED;
  }
  
  static int adp5588_irq_setup(struct adp5588_gpio *dev)
  {
  	struct i2c_client *client = dev->client;
e56aee189   Jingoo Han   gpio: use dev_get...
280
281
  	struct adp5588_gpio_platform_data *pdata =
  			dev_get_platdata(&client->dev);
459773ae8   Michael Hennerich   gpio: adp5588-gpi...
282
283
284
285
286
287
288
289
290
291
292
293
  	unsigned gpio;
  	int ret;
  
  	adp5588_gpio_write(client, CFG, ADP5588_AUTO_INC);
  	adp5588_gpio_write(client, INT_STAT, -1); /* status is W1C */
  	adp5588_gpio_read_intstat(client, dev->irq_stat); /* read to clear */
  
  	dev->irq_base = pdata->irq_base;
  	mutex_init(&dev->irq_lock);
  
  	for (gpio = 0; gpio < dev->gpio_chip.ngpio; gpio++) {
  		int irq = gpio + dev->irq_base;
b51804bcf   Thomas Gleixner   gpio: Cleanup gen...
294
295
  		irq_set_chip_data(irq, dev);
  		irq_set_chip_and_handler(irq, &adp5588_irq_chip,
459773ae8   Michael Hennerich   gpio: adp5588-gpi...
296
  					 handle_level_irq);
b51804bcf   Thomas Gleixner   gpio: Cleanup gen...
297
  		irq_set_nested_thread(irq, 1);
23393d49f   Rob Herring   gpio: kill off se...
298
  		irq_modify_status(irq, IRQ_NOREQUEST, IRQ_NOPROBE);
459773ae8   Michael Hennerich   gpio: adp5588-gpi...
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
  	}
  
  	ret = request_threaded_irq(client->irq,
  				   NULL,
  				   adp5588_irq_handler,
  				   IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
  				   dev_name(&client->dev), dev);
  	if (ret) {
  		dev_err(&client->dev, "failed to request irq %d
  ",
  			client->irq);
  		goto out;
  	}
  
  	dev->gpio_chip.to_irq = adp5588_gpio_to_irq;
  	adp5588_gpio_write(client, CFG,
  		ADP5588_AUTO_INC | ADP5588_INT_CFG | ADP5588_GPI_INT);
  
  	return 0;
  
  out:
  	dev->irq_base = 0;
  	return ret;
  }
  
  static void adp5588_irq_teardown(struct adp5588_gpio *dev)
  {
  	if (dev->irq_base)
  		free_irq(dev->client->irq, dev);
  }
  
  #else
  static int adp5588_irq_setup(struct adp5588_gpio *dev)
  {
  	struct i2c_client *client = dev->client;
  	dev_warn(&client->dev, "interrupt support not compiled in
  ");
  
  	return 0;
  }
  
  static void adp5588_irq_teardown(struct adp5588_gpio *dev)
  {
  }
  #endif /* CONFIG_GPIO_ADP5588_IRQ */
3836309d9   Bill Pemberton   gpio: remove use ...
344
  static int adp5588_gpio_probe(struct i2c_client *client,
80884094e   Michael Hennerich   gpio: adp5588-gpi...
345
346
  					const struct i2c_device_id *id)
  {
e56aee189   Jingoo Han   gpio: use dev_get...
347
348
  	struct adp5588_gpio_platform_data *pdata =
  			dev_get_platdata(&client->dev);
80884094e   Michael Hennerich   gpio: adp5588-gpi...
349
350
351
  	struct adp5588_gpio *dev;
  	struct gpio_chip *gc;
  	int ret, i, revid;
afeb7b45e   Varka Bhadram   gpio: use (!foo) ...
352
  	if (!pdata) {
80884094e   Michael Hennerich   gpio: adp5588-gpi...
353
354
355
356
357
358
359
360
361
362
363
  		dev_err(&client->dev, "missing platform data
  ");
  		return -ENODEV;
  	}
  
  	if (!i2c_check_functionality(client->adapter,
  					I2C_FUNC_SMBUS_BYTE_DATA)) {
  		dev_err(&client->dev, "SMBUS Byte Data not Supported
  ");
  		return -EIO;
  	}
7898b31eb   Varka Bhadram   gpio: use devm_kz...
364
  	dev = devm_kzalloc(&client->dev, sizeof(*dev), GFP_KERNEL);
afeb7b45e   Varka Bhadram   gpio: use (!foo) ...
365
  	if (!dev)
80884094e   Michael Hennerich   gpio: adp5588-gpi...
366
  		return -ENOMEM;
80884094e   Michael Hennerich   gpio: adp5588-gpi...
367
368
369
370
371
372
373
374
  
  	dev->client = client;
  
  	gc = &dev->gpio_chip;
  	gc->direction_input = adp5588_gpio_direction_input;
  	gc->direction_output = adp5588_gpio_direction_output;
  	gc->get = adp5588_gpio_get_value;
  	gc->set = adp5588_gpio_set_value;
9fb1f39eb   Linus Walleij   gpio/pinctrl: mak...
375
  	gc->can_sleep = true;
80884094e   Michael Hennerich   gpio: adp5588-gpi...
376
377
  
  	gc->base = pdata->gpio_start;
459773ae8   Michael Hennerich   gpio: adp5588-gpi...
378
  	gc->ngpio = ADP5588_MAXGPIO;
80884094e   Michael Hennerich   gpio: adp5588-gpi...
379
380
  	gc->label = client->name;
  	gc->owner = THIS_MODULE;
1163316e5   Jean-Francois Dagenais   gpio: adp5588 - a...
381
  	gc->names = pdata->names;
80884094e   Michael Hennerich   gpio: adp5588-gpi...
382
383
  
  	mutex_init(&dev->lock);
80884094e   Michael Hennerich   gpio: adp5588-gpi...
384
385
386
387
388
  	ret = adp5588_gpio_read(dev->client, DEV_ID);
  	if (ret < 0)
  		goto err;
  
  	revid = ret & ADP5588_DEVICE_ID_MASK;
459773ae8   Michael Hennerich   gpio: adp5588-gpi...
389
  	for (i = 0, ret = 0; i <= ADP5588_BANK(ADP5588_MAXGPIO); i++) {
80884094e   Michael Hennerich   gpio: adp5588-gpi...
390
391
392
393
394
  		dev->dat_out[i] = adp5588_gpio_read(client, GPIO_DAT_OUT1 + i);
  		dev->dir[i] = adp5588_gpio_read(client, GPIO_DIR1 + i);
  		ret |= adp5588_gpio_write(client, KP_GPIO1 + i, 0);
  		ret |= adp5588_gpio_write(client, GPIO_PULL1 + i,
  				(pdata->pullup_dis_mask >> (8 * i)) & 0xFF);
459773ae8   Michael Hennerich   gpio: adp5588-gpi...
395
  		ret |= adp5588_gpio_write(client, GPIO_INT_EN1 + i, 0);
80884094e   Michael Hennerich   gpio: adp5588-gpi...
396
397
398
  		if (ret)
  			goto err;
  	}
459773ae8   Michael Hennerich   gpio: adp5588-gpi...
399
400
401
402
403
404
405
406
407
408
  	if (pdata->irq_base) {
  		if (WA_DELAYED_READOUT_REVID(revid)) {
  			dev_warn(&client->dev, "GPIO int not supported
  ");
  		} else {
  			ret = adp5588_irq_setup(dev);
  			if (ret)
  				goto err;
  		}
  	}
7c263fe02   Laxman Dewangan   gpio: adp5588: Us...
409
  	ret = devm_gpiochip_add_data(&client->dev, &dev->gpio_chip, dev);
80884094e   Michael Hennerich   gpio: adp5588-gpi...
410
  	if (ret)
459773ae8   Michael Hennerich   gpio: adp5588-gpi...
411
  		goto err_irq;
80884094e   Michael Hennerich   gpio: adp5588-gpi...
412

64842aad5   Grant Likely   gpiolib: output b...
413
414
415
  	dev_info(&client->dev, "IRQ Base: %d Rev.: %d
  ",
  			pdata->irq_base, revid);
80884094e   Michael Hennerich   gpio: adp5588-gpi...
416
417
418
419
420
421
422
423
424
  
  	if (pdata->setup) {
  		ret = pdata->setup(client, gc->base, gc->ngpio, pdata->context);
  		if (ret < 0)
  			dev_warn(&client->dev, "setup failed, %d
  ", ret);
  	}
  
  	i2c_set_clientdata(client, dev);
459773ae8   Michael Hennerich   gpio: adp5588-gpi...
425

80884094e   Michael Hennerich   gpio: adp5588-gpi...
426
  	return 0;
459773ae8   Michael Hennerich   gpio: adp5588-gpi...
427
428
  err_irq:
  	adp5588_irq_teardown(dev);
80884094e   Michael Hennerich   gpio: adp5588-gpi...
429
  err:
80884094e   Michael Hennerich   gpio: adp5588-gpi...
430
431
  	return ret;
  }
206210ce6   Bill Pemberton   gpio: remove use ...
432
  static int adp5588_gpio_remove(struct i2c_client *client)
80884094e   Michael Hennerich   gpio: adp5588-gpi...
433
  {
e56aee189   Jingoo Han   gpio: use dev_get...
434
435
  	struct adp5588_gpio_platform_data *pdata =
  			dev_get_platdata(&client->dev);
80884094e   Michael Hennerich   gpio: adp5588-gpi...
436
437
438
439
440
441
442
443
444
445
446
447
448
  	struct adp5588_gpio *dev = i2c_get_clientdata(client);
  	int ret;
  
  	if (pdata->teardown) {
  		ret = pdata->teardown(client,
  				      dev->gpio_chip.base, dev->gpio_chip.ngpio,
  				      pdata->context);
  		if (ret < 0) {
  			dev_err(&client->dev, "teardown failed %d
  ", ret);
  			return ret;
  		}
  	}
459773ae8   Michael Hennerich   gpio: adp5588-gpi...
449
450
  	if (dev->irq_base)
  		free_irq(dev->client->irq, dev);
80884094e   Michael Hennerich   gpio: adp5588-gpi...
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
  	return 0;
  }
  
  static const struct i2c_device_id adp5588_gpio_id[] = {
  	{DRV_NAME, 0},
  	{}
  };
  
  MODULE_DEVICE_TABLE(i2c, adp5588_gpio_id);
  
  static struct i2c_driver adp5588_gpio_driver = {
  	.driver = {
  		   .name = DRV_NAME,
  		   },
  	.probe = adp5588_gpio_probe,
8283c4ff5   Bill Pemberton   gpio: remove use ...
466
  	.remove = adp5588_gpio_remove,
80884094e   Michael Hennerich   gpio: adp5588-gpi...
467
468
  	.id_table = adp5588_gpio_id,
  };
c8554d324   Axel Lin   gpio: adp5588: Us...
469
  module_i2c_driver(adp5588_gpio_driver);
80884094e   Michael Hennerich   gpio: adp5588-gpi...
470
471
472
473
  
  MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
  MODULE_DESCRIPTION("GPIO ADP5588 Driver");
  MODULE_LICENSE("GPL");