]>
Commit | Line | Data |
---|---|---|
5e969a40 TR |
1 | /* |
2 | * Copyright (C) 2011-2012 Avionic Design GmbH | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License version 2 as | |
6 | * published by the Free Software Foundation. | |
7 | */ | |
8 | ||
9 | #include <linux/gpio.h> | |
10 | #include <linux/i2c.h> | |
11 | #include <linux/interrupt.h> | |
12 | #include <linux/irqdomain.h> | |
13 | #include <linux/module.h> | |
14 | #include <linux/of_irq.h> | |
15 | #include <linux/seq_file.h> | |
16 | #include <linux/slab.h> | |
17 | ||
18 | #define GPIO_DDR(gpio) (0x00 << (gpio)->reg_shift) | |
19 | #define GPIO_PLR(gpio) (0x01 << (gpio)->reg_shift) | |
20 | #define GPIO_IER(gpio) (0x02 << (gpio)->reg_shift) | |
21 | #define GPIO_ISR(gpio) (0x03 << (gpio)->reg_shift) | |
22 | #define GPIO_PTR(gpio) (0x04 << (gpio)->reg_shift) | |
23 | ||
24 | struct adnp { | |
25 | struct i2c_client *client; | |
26 | struct gpio_chip gpio; | |
27 | unsigned int reg_shift; | |
28 | ||
29 | struct mutex i2c_lock; | |
30 | ||
31 | struct irq_domain *domain; | |
32 | struct mutex irq_lock; | |
33 | ||
34 | u8 *irq_enable; | |
35 | u8 *irq_level; | |
36 | u8 *irq_rise; | |
37 | u8 *irq_fall; | |
38 | u8 *irq_high; | |
39 | u8 *irq_low; | |
40 | }; | |
41 | ||
42 | static inline struct adnp *to_adnp(struct gpio_chip *chip) | |
43 | { | |
44 | return container_of(chip, struct adnp, gpio); | |
45 | } | |
46 | ||
47 | static int adnp_read(struct adnp *adnp, unsigned offset, uint8_t *value) | |
48 | { | |
49 | int err; | |
50 | ||
51 | err = i2c_smbus_read_byte_data(adnp->client, offset); | |
52 | if (err < 0) { | |
53 | dev_err(adnp->gpio.dev, "%s failed: %d\n", | |
54 | "i2c_smbus_read_byte_data()", err); | |
55 | return err; | |
56 | } | |
57 | ||
58 | *value = err; | |
59 | return 0; | |
60 | } | |
61 | ||
62 | static int adnp_write(struct adnp *adnp, unsigned offset, uint8_t value) | |
63 | { | |
64 | int err; | |
65 | ||
66 | err = i2c_smbus_write_byte_data(adnp->client, offset, value); | |
67 | if (err < 0) { | |
68 | dev_err(adnp->gpio.dev, "%s failed: %d\n", | |
69 | "i2c_smbus_write_byte_data()", err); | |
70 | return err; | |
71 | } | |
72 | ||
73 | return 0; | |
74 | } | |
75 | ||
76 | static int adnp_gpio_get(struct gpio_chip *chip, unsigned offset) | |
77 | { | |
78 | struct adnp *adnp = to_adnp(chip); | |
79 | unsigned int reg = offset >> adnp->reg_shift; | |
80 | unsigned int pos = offset & 7; | |
81 | u8 value; | |
82 | int err; | |
83 | ||
84 | err = adnp_read(adnp, GPIO_PLR(adnp) + reg, &value); | |
85 | if (err < 0) | |
86 | return err; | |
87 | ||
88 | return (value & BIT(pos)) ? 1 : 0; | |
89 | } | |
90 | ||
91 | static void __adnp_gpio_set(struct adnp *adnp, unsigned offset, int value) | |
92 | { | |
93 | unsigned int reg = offset >> adnp->reg_shift; | |
94 | unsigned int pos = offset & 7; | |
95 | int err; | |
96 | u8 val; | |
97 | ||
98 | err = adnp_read(adnp, GPIO_PLR(adnp) + reg, &val); | |
99 | if (err < 0) | |
100 | return; | |
101 | ||
102 | if (value) | |
103 | val |= BIT(pos); | |
104 | else | |
105 | val &= ~BIT(pos); | |
106 | ||
107 | adnp_write(adnp, GPIO_PLR(adnp) + reg, val); | |
108 | } | |
109 | ||
110 | static void adnp_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | |
111 | { | |
112 | struct adnp *adnp = to_adnp(chip); | |
113 | ||
114 | mutex_lock(&adnp->i2c_lock); | |
115 | __adnp_gpio_set(adnp, offset, value); | |
116 | mutex_unlock(&adnp->i2c_lock); | |
117 | } | |
118 | ||
119 | static int adnp_gpio_direction_input(struct gpio_chip *chip, unsigned offset) | |
120 | { | |
121 | struct adnp *adnp = to_adnp(chip); | |
122 | unsigned int reg = offset >> adnp->reg_shift; | |
123 | unsigned int pos = offset & 7; | |
124 | u8 value; | |
125 | int err; | |
126 | ||
127 | mutex_lock(&adnp->i2c_lock); | |
128 | ||
129 | err = adnp_read(adnp, GPIO_DDR(adnp) + reg, &value); | |
130 | if (err < 0) | |
131 | goto out; | |
132 | ||
133 | value &= ~BIT(pos); | |
134 | ||
135 | err = adnp_write(adnp, GPIO_DDR(adnp) + reg, value); | |
136 | if (err < 0) | |
137 | goto out; | |
138 | ||
139 | err = adnp_read(adnp, GPIO_DDR(adnp) + reg, &value); | |
140 | if (err < 0) | |
141 | goto out; | |
142 | ||
143 | if (err & BIT(pos)) | |
144 | err = -EACCES; | |
145 | ||
146 | err = 0; | |
147 | ||
148 | out: | |
149 | mutex_unlock(&adnp->i2c_lock); | |
150 | return err; | |
151 | } | |
152 | ||
153 | static int adnp_gpio_direction_output(struct gpio_chip *chip, unsigned offset, | |
154 | int value) | |
155 | { | |
156 | struct adnp *adnp = to_adnp(chip); | |
157 | unsigned int reg = offset >> adnp->reg_shift; | |
158 | unsigned int pos = offset & 7; | |
159 | int err; | |
160 | u8 val; | |
161 | ||
162 | mutex_lock(&adnp->i2c_lock); | |
163 | ||
164 | err = adnp_read(adnp, GPIO_DDR(adnp) + reg, &val); | |
165 | if (err < 0) | |
166 | goto out; | |
167 | ||
168 | val |= BIT(pos); | |
169 | ||
170 | err = adnp_write(adnp, GPIO_DDR(adnp) + reg, val); | |
171 | if (err < 0) | |
172 | goto out; | |
173 | ||
174 | err = adnp_read(adnp, GPIO_DDR(adnp) + reg, &val); | |
175 | if (err < 0) | |
176 | goto out; | |
177 | ||
178 | if (!(val & BIT(pos))) { | |
179 | err = -EPERM; | |
180 | goto out; | |
181 | } | |
182 | ||
183 | __adnp_gpio_set(adnp, offset, value); | |
184 | err = 0; | |
185 | ||
186 | out: | |
187 | mutex_unlock(&adnp->i2c_lock); | |
188 | return err; | |
189 | } | |
190 | ||
191 | static void adnp_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) | |
192 | { | |
193 | struct adnp *adnp = to_adnp(chip); | |
194 | unsigned int num_regs = 1 << adnp->reg_shift, i, j; | |
195 | int err; | |
196 | ||
197 | for (i = 0; i < num_regs; i++) { | |
198 | u8 ddr, plr, ier, isr; | |
199 | ||
200 | mutex_lock(&adnp->i2c_lock); | |
201 | ||
202 | err = adnp_read(adnp, GPIO_DDR(adnp) + i, &ddr); | |
203 | if (err < 0) { | |
204 | mutex_unlock(&adnp->i2c_lock); | |
205 | return; | |
206 | } | |
207 | ||
208 | err = adnp_read(adnp, GPIO_PLR(adnp) + i, &plr); | |
209 | if (err < 0) { | |
210 | mutex_unlock(&adnp->i2c_lock); | |
211 | return; | |
212 | } | |
213 | ||
214 | err = adnp_read(adnp, GPIO_IER(adnp) + i, &ier); | |
215 | if (err < 0) { | |
216 | mutex_unlock(&adnp->i2c_lock); | |
217 | return; | |
218 | } | |
219 | ||
220 | err = adnp_read(adnp, GPIO_ISR(adnp) + i, &isr); | |
221 | if (err < 0) { | |
222 | mutex_unlock(&adnp->i2c_lock); | |
223 | return; | |
224 | } | |
225 | ||
226 | mutex_unlock(&adnp->i2c_lock); | |
227 | ||
228 | for (j = 0; j < 8; j++) { | |
229 | unsigned int bit = (i << adnp->reg_shift) + j; | |
230 | const char *direction = "input "; | |
231 | const char *level = "low "; | |
232 | const char *interrupt = "disabled"; | |
233 | const char *pending = ""; | |
234 | ||
235 | if (ddr & BIT(j)) | |
236 | direction = "output"; | |
237 | ||
238 | if (plr & BIT(j)) | |
239 | level = "high"; | |
240 | ||
241 | if (ier & BIT(j)) | |
242 | interrupt = "enabled "; | |
243 | ||
244 | if (isr & BIT(j)) | |
245 | pending = "pending"; | |
246 | ||
247 | seq_printf(s, "%2u: %s %s IRQ %s %s\n", bit, | |
248 | direction, level, interrupt, pending); | |
249 | } | |
250 | } | |
251 | } | |
252 | ||
253 | static int adnp_gpio_setup(struct adnp *adnp, unsigned int num_gpios) | |
254 | { | |
255 | struct gpio_chip *chip = &adnp->gpio; | |
256 | ||
257 | adnp->reg_shift = get_count_order(num_gpios) - 3; | |
258 | ||
259 | chip->direction_input = adnp_gpio_direction_input; | |
260 | chip->direction_output = adnp_gpio_direction_output; | |
261 | chip->get = adnp_gpio_get; | |
262 | chip->set = adnp_gpio_set; | |
9fb1f39e | 263 | chip->can_sleep = true; |
5e969a40 TR |
264 | |
265 | if (IS_ENABLED(CONFIG_DEBUG_FS)) | |
266 | chip->dbg_show = adnp_gpio_dbg_show; | |
267 | ||
268 | chip->base = -1; | |
269 | chip->ngpio = num_gpios; | |
270 | chip->label = adnp->client->name; | |
271 | chip->dev = &adnp->client->dev; | |
272 | chip->of_node = chip->dev->of_node; | |
273 | chip->owner = THIS_MODULE; | |
274 | ||
275 | return 0; | |
276 | } | |
277 | ||
278 | static irqreturn_t adnp_irq(int irq, void *data) | |
279 | { | |
280 | struct adnp *adnp = data; | |
281 | unsigned int num_regs, i; | |
282 | ||
283 | num_regs = 1 << adnp->reg_shift; | |
284 | ||
285 | for (i = 0; i < num_regs; i++) { | |
286 | unsigned int base = i << adnp->reg_shift, bit; | |
287 | u8 changed, level, isr, ier; | |
288 | unsigned long pending; | |
289 | int err; | |
290 | ||
291 | mutex_lock(&adnp->i2c_lock); | |
292 | ||
293 | err = adnp_read(adnp, GPIO_PLR(adnp) + i, &level); | |
294 | if (err < 0) { | |
295 | mutex_unlock(&adnp->i2c_lock); | |
296 | continue; | |
297 | } | |
298 | ||
299 | err = adnp_read(adnp, GPIO_ISR(adnp) + i, &isr); | |
300 | if (err < 0) { | |
301 | mutex_unlock(&adnp->i2c_lock); | |
302 | continue; | |
303 | } | |
304 | ||
305 | err = adnp_read(adnp, GPIO_IER(adnp) + i, &ier); | |
306 | if (err < 0) { | |
307 | mutex_unlock(&adnp->i2c_lock); | |
308 | continue; | |
309 | } | |
310 | ||
311 | mutex_unlock(&adnp->i2c_lock); | |
312 | ||
313 | /* determine pins that changed levels */ | |
314 | changed = level ^ adnp->irq_level[i]; | |
315 | ||
316 | /* compute edge-triggered interrupts */ | |
317 | pending = changed & ((adnp->irq_fall[i] & ~level) | | |
318 | (adnp->irq_rise[i] & level)); | |
319 | ||
320 | /* add in level-triggered interrupts */ | |
321 | pending |= (adnp->irq_high[i] & level) | | |
322 | (adnp->irq_low[i] & ~level); | |
323 | ||
324 | /* mask out non-pending and disabled interrupts */ | |
325 | pending &= isr & ier; | |
326 | ||
327 | for_each_set_bit(bit, &pending, 8) { | |
472f95b9 LW |
328 | unsigned int child_irq; |
329 | child_irq = irq_find_mapping(adnp->domain, base + bit); | |
330 | handle_nested_irq(child_irq); | |
5e969a40 TR |
331 | } |
332 | } | |
333 | ||
334 | return IRQ_HANDLED; | |
335 | } | |
336 | ||
337 | static int adnp_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | |
338 | { | |
339 | struct adnp *adnp = to_adnp(chip); | |
340 | return irq_create_mapping(adnp->domain, offset); | |
341 | } | |
342 | ||
343 | static void adnp_irq_mask(struct irq_data *data) | |
344 | { | |
345 | struct adnp *adnp = irq_data_get_irq_chip_data(data); | |
346 | unsigned int reg = data->hwirq >> adnp->reg_shift; | |
347 | unsigned int pos = data->hwirq & 7; | |
348 | ||
349 | adnp->irq_enable[reg] &= ~BIT(pos); | |
350 | } | |
351 | ||
352 | static void adnp_irq_unmask(struct irq_data *data) | |
353 | { | |
354 | struct adnp *adnp = irq_data_get_irq_chip_data(data); | |
355 | unsigned int reg = data->hwirq >> adnp->reg_shift; | |
356 | unsigned int pos = data->hwirq & 7; | |
357 | ||
358 | adnp->irq_enable[reg] |= BIT(pos); | |
359 | } | |
360 | ||
361 | static int adnp_irq_set_type(struct irq_data *data, unsigned int type) | |
362 | { | |
363 | struct adnp *adnp = irq_data_get_irq_chip_data(data); | |
364 | unsigned int reg = data->hwirq >> adnp->reg_shift; | |
365 | unsigned int pos = data->hwirq & 7; | |
366 | ||
367 | if (type & IRQ_TYPE_EDGE_RISING) | |
368 | adnp->irq_rise[reg] |= BIT(pos); | |
369 | else | |
370 | adnp->irq_rise[reg] &= ~BIT(pos); | |
371 | ||
372 | if (type & IRQ_TYPE_EDGE_FALLING) | |
373 | adnp->irq_fall[reg] |= BIT(pos); | |
374 | else | |
375 | adnp->irq_fall[reg] &= ~BIT(pos); | |
376 | ||
377 | if (type & IRQ_TYPE_LEVEL_HIGH) | |
378 | adnp->irq_high[reg] |= BIT(pos); | |
379 | else | |
380 | adnp->irq_high[reg] &= ~BIT(pos); | |
381 | ||
382 | if (type & IRQ_TYPE_LEVEL_LOW) | |
383 | adnp->irq_low[reg] |= BIT(pos); | |
384 | else | |
385 | adnp->irq_low[reg] &= ~BIT(pos); | |
386 | ||
387 | return 0; | |
388 | } | |
389 | ||
390 | static void adnp_irq_bus_lock(struct irq_data *data) | |
391 | { | |
392 | struct adnp *adnp = irq_data_get_irq_chip_data(data); | |
393 | ||
394 | mutex_lock(&adnp->irq_lock); | |
395 | } | |
396 | ||
397 | static void adnp_irq_bus_unlock(struct irq_data *data) | |
398 | { | |
399 | struct adnp *adnp = irq_data_get_irq_chip_data(data); | |
400 | unsigned int num_regs = 1 << adnp->reg_shift, i; | |
401 | ||
402 | mutex_lock(&adnp->i2c_lock); | |
403 | ||
404 | for (i = 0; i < num_regs; i++) | |
405 | adnp_write(adnp, GPIO_IER(adnp) + i, adnp->irq_enable[i]); | |
406 | ||
407 | mutex_unlock(&adnp->i2c_lock); | |
408 | mutex_unlock(&adnp->irq_lock); | |
409 | } | |
410 | ||
57ef0428 | 411 | static int adnp_irq_reqres(struct irq_data *data) |
f41cd3c2 LW |
412 | { |
413 | struct adnp *adnp = irq_data_get_irq_chip_data(data); | |
414 | ||
57ef0428 | 415 | if (gpio_lock_as_irq(&adnp->gpio, data->hwirq)) { |
f41cd3c2 LW |
416 | dev_err(adnp->gpio.dev, |
417 | "unable to lock HW IRQ %lu for IRQ\n", | |
418 | data->hwirq); | |
57ef0428 LW |
419 | return -EINVAL; |
420 | } | |
f41cd3c2 LW |
421 | return 0; |
422 | } | |
423 | ||
57ef0428 | 424 | static void adnp_irq_relres(struct irq_data *data) |
f41cd3c2 LW |
425 | { |
426 | struct adnp *adnp = irq_data_get_irq_chip_data(data); | |
427 | ||
f41cd3c2 LW |
428 | gpio_unlock_as_irq(&adnp->gpio, data->hwirq); |
429 | } | |
430 | ||
5e969a40 TR |
431 | static struct irq_chip adnp_irq_chip = { |
432 | .name = "gpio-adnp", | |
433 | .irq_mask = adnp_irq_mask, | |
434 | .irq_unmask = adnp_irq_unmask, | |
435 | .irq_set_type = adnp_irq_set_type, | |
436 | .irq_bus_lock = adnp_irq_bus_lock, | |
437 | .irq_bus_sync_unlock = adnp_irq_bus_unlock, | |
57ef0428 LW |
438 | .irq_request_resources = adnp_irq_reqres, |
439 | .irq_release_resources = adnp_irq_relres, | |
5e969a40 TR |
440 | }; |
441 | ||
442 | static int adnp_irq_map(struct irq_domain *domain, unsigned int irq, | |
443 | irq_hw_number_t hwirq) | |
444 | { | |
445 | irq_set_chip_data(irq, domain->host_data); | |
446 | irq_set_chip(irq, &adnp_irq_chip); | |
447 | irq_set_nested_thread(irq, true); | |
448 | ||
449 | #ifdef CONFIG_ARM | |
450 | set_irq_flags(irq, IRQF_VALID); | |
451 | #else | |
452 | irq_set_noprobe(irq); | |
453 | #endif | |
454 | ||
455 | return 0; | |
456 | } | |
457 | ||
458 | static const struct irq_domain_ops adnp_irq_domain_ops = { | |
459 | .map = adnp_irq_map, | |
460 | .xlate = irq_domain_xlate_twocell, | |
461 | }; | |
462 | ||
463 | static int adnp_irq_setup(struct adnp *adnp) | |
464 | { | |
465 | unsigned int num_regs = 1 << adnp->reg_shift, i; | |
466 | struct gpio_chip *chip = &adnp->gpio; | |
467 | int err; | |
468 | ||
469 | mutex_init(&adnp->irq_lock); | |
470 | ||
471 | /* | |
472 | * Allocate memory to keep track of the current level and trigger | |
473 | * modes of the interrupts. To avoid multiple allocations, a single | |
474 | * large buffer is allocated and pointers are setup to point at the | |
475 | * corresponding offsets. For consistency, the layout of the buffer | |
476 | * is chosen to match the register layout of the hardware in that | |
477 | * each segment contains the corresponding bits for all interrupts. | |
478 | */ | |
479 | adnp->irq_enable = devm_kzalloc(chip->dev, num_regs * 6, GFP_KERNEL); | |
480 | if (!adnp->irq_enable) | |
481 | return -ENOMEM; | |
482 | ||
483 | adnp->irq_level = adnp->irq_enable + (num_regs * 1); | |
484 | adnp->irq_rise = adnp->irq_enable + (num_regs * 2); | |
485 | adnp->irq_fall = adnp->irq_enable + (num_regs * 3); | |
486 | adnp->irq_high = adnp->irq_enable + (num_regs * 4); | |
487 | adnp->irq_low = adnp->irq_enable + (num_regs * 5); | |
488 | ||
489 | for (i = 0; i < num_regs; i++) { | |
490 | /* | |
491 | * Read the initial level of all pins to allow the emulation | |
492 | * of edge triggered interrupts. | |
493 | */ | |
494 | err = adnp_read(adnp, GPIO_PLR(adnp) + i, &adnp->irq_level[i]); | |
495 | if (err < 0) | |
496 | return err; | |
497 | ||
498 | /* disable all interrupts */ | |
499 | err = adnp_write(adnp, GPIO_IER(adnp) + i, 0); | |
500 | if (err < 0) | |
501 | return err; | |
502 | ||
503 | adnp->irq_enable[i] = 0x00; | |
504 | } | |
505 | ||
506 | adnp->domain = irq_domain_add_linear(chip->of_node, chip->ngpio, | |
507 | &adnp_irq_domain_ops, adnp); | |
508 | ||
509 | err = request_threaded_irq(adnp->client->irq, NULL, adnp_irq, | |
510 | IRQF_TRIGGER_RISING | IRQF_ONESHOT, | |
511 | dev_name(chip->dev), adnp); | |
512 | if (err != 0) { | |
513 | dev_err(chip->dev, "can't request IRQ#%d: %d\n", | |
514 | adnp->client->irq, err); | |
5b21533b | 515 | return err; |
5e969a40 TR |
516 | } |
517 | ||
518 | chip->to_irq = adnp_gpio_to_irq; | |
519 | return 0; | |
5e969a40 TR |
520 | } |
521 | ||
522 | static void adnp_irq_teardown(struct adnp *adnp) | |
523 | { | |
524 | unsigned int irq, i; | |
525 | ||
526 | free_irq(adnp->client->irq, adnp); | |
527 | ||
528 | for (i = 0; i < adnp->gpio.ngpio; i++) { | |
529 | irq = irq_find_mapping(adnp->domain, i); | |
530 | if (irq > 0) | |
531 | irq_dispose_mapping(irq); | |
532 | } | |
533 | ||
534 | irq_domain_remove(adnp->domain); | |
535 | } | |
536 | ||
3836309d | 537 | static int adnp_i2c_probe(struct i2c_client *client, |
5e969a40 TR |
538 | const struct i2c_device_id *id) |
539 | { | |
540 | struct device_node *np = client->dev.of_node; | |
541 | struct adnp *adnp; | |
542 | u32 num_gpios; | |
543 | int err; | |
544 | ||
545 | err = of_property_read_u32(np, "nr-gpios", &num_gpios); | |
546 | if (err < 0) | |
547 | return err; | |
548 | ||
549 | client->irq = irq_of_parse_and_map(np, 0); | |
550 | if (!client->irq) | |
551 | return -EPROBE_DEFER; | |
552 | ||
553 | adnp = devm_kzalloc(&client->dev, sizeof(*adnp), GFP_KERNEL); | |
554 | if (!adnp) | |
555 | return -ENOMEM; | |
556 | ||
557 | mutex_init(&adnp->i2c_lock); | |
558 | adnp->client = client; | |
559 | ||
560 | err = adnp_gpio_setup(adnp, num_gpios); | |
561 | if (err < 0) | |
562 | return err; | |
563 | ||
564 | if (of_find_property(np, "interrupt-controller", NULL)) { | |
565 | err = adnp_irq_setup(adnp); | |
566 | if (err < 0) | |
567 | goto teardown; | |
568 | } | |
569 | ||
570 | err = gpiochip_add(&adnp->gpio); | |
571 | if (err < 0) | |
572 | goto teardown; | |
573 | ||
574 | i2c_set_clientdata(client, adnp); | |
575 | return 0; | |
576 | ||
577 | teardown: | |
578 | if (of_find_property(np, "interrupt-controller", NULL)) | |
579 | adnp_irq_teardown(adnp); | |
580 | ||
581 | return err; | |
582 | } | |
583 | ||
206210ce | 584 | static int adnp_i2c_remove(struct i2c_client *client) |
5e969a40 TR |
585 | { |
586 | struct adnp *adnp = i2c_get_clientdata(client); | |
587 | struct device_node *np = client->dev.of_node; | |
588 | int err; | |
589 | ||
590 | err = gpiochip_remove(&adnp->gpio); | |
591 | if (err < 0) { | |
592 | dev_err(&client->dev, "%s failed: %d\n", "gpiochip_remove()", | |
593 | err); | |
594 | return err; | |
595 | } | |
596 | ||
597 | if (of_find_property(np, "interrupt-controller", NULL)) | |
598 | adnp_irq_teardown(adnp); | |
599 | ||
600 | return 0; | |
601 | } | |
602 | ||
b5ba78de | 603 | static const struct i2c_device_id adnp_i2c_id[] = { |
5e969a40 TR |
604 | { "gpio-adnp" }, |
605 | { }, | |
606 | }; | |
607 | MODULE_DEVICE_TABLE(i2c, adnp_i2c_id); | |
608 | ||
b5ba78de | 609 | static const struct of_device_id adnp_of_match[] = { |
5e969a40 TR |
610 | { .compatible = "ad,gpio-adnp", }, |
611 | { }, | |
612 | }; | |
613 | MODULE_DEVICE_TABLE(of, adnp_of_match); | |
614 | ||
615 | static struct i2c_driver adnp_i2c_driver = { | |
616 | .driver = { | |
617 | .name = "gpio-adnp", | |
618 | .owner = THIS_MODULE, | |
83924fb3 | 619 | .of_match_table = adnp_of_match, |
5e969a40 TR |
620 | }, |
621 | .probe = adnp_i2c_probe, | |
8283c4ff | 622 | .remove = adnp_i2c_remove, |
5e969a40 TR |
623 | .id_table = adnp_i2c_id, |
624 | }; | |
625 | module_i2c_driver(adnp_i2c_driver); | |
626 | ||
627 | MODULE_DESCRIPTION("Avionic Design N-bit GPIO expander"); | |
628 | MODULE_AUTHOR("Thierry Reding <[email protected]>"); | |
629 | MODULE_LICENSE("GPL"); |