aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2014-06-02 09:17:54 -0400
committerLinus Walleij <linus.walleij@linaro.org>2014-09-02 04:44:01 -0400
commit0752e169ba523e35f70d2fee4d06680b33e0e202 (patch)
tree1a97f9d7e271ef38934eab8fc3750858dda46e7d
parentabdc08a3a263a20e49534a36291d657bf53dda5b (diff)
gpio: adnp: switch to use irqchip helpers
This switches the ADNP GPIO driver to use the gpiolib irqchip helpers. Also do some random refactoring to make it look like most other GPIO drivers. Cc: Roland Stigge <stigge@antcom.de> Cc: Lars Poeschel <poeschel@lemonage.de> Cc: Thierry Reding <thierry.reding@gmail.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r--drivers/gpio/Kconfig1
-rw-r--r--drivers/gpio/gpio-adnp.c155
2 files changed, 48 insertions, 108 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 1fe93eb61927..ec27ec0be8c2 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -690,6 +690,7 @@ config GPIO_ADP5588_IRQ
690config GPIO_ADNP 690config GPIO_ADNP
691 tristate "Avionic Design N-bit GPIO expander" 691 tristate "Avionic Design N-bit GPIO expander"
692 depends on I2C && OF_GPIO 692 depends on I2C && OF_GPIO
693 select GPIOLIB_IRQCHIP
693 help 694 help
694 This option enables support for N GPIOs found on Avionic Design 695 This option enables support for N GPIOs found on Avionic Design
695 I2C GPIO expanders. The register space will be extended by powers 696 I2C GPIO expanders. The register space will be extended by powers
diff --git a/drivers/gpio/gpio-adnp.c b/drivers/gpio/gpio-adnp.c
index 416b2200d4f1..d3d0a90fe542 100644
--- a/drivers/gpio/gpio-adnp.c
+++ b/drivers/gpio/gpio-adnp.c
@@ -6,10 +6,9 @@
6 * published by the Free Software Foundation. 6 * published by the Free Software Foundation.
7 */ 7 */
8 8
9#include <linux/gpio.h> 9#include <linux/gpio/driver.h>
10#include <linux/i2c.h> 10#include <linux/i2c.h>
11#include <linux/interrupt.h> 11#include <linux/interrupt.h>
12#include <linux/irqdomain.h>
13#include <linux/module.h> 12#include <linux/module.h>
14#include <linux/of_irq.h> 13#include <linux/of_irq.h>
15#include <linux/seq_file.h> 14#include <linux/seq_file.h>
@@ -27,8 +26,6 @@ struct adnp {
27 unsigned int reg_shift; 26 unsigned int reg_shift;
28 27
29 struct mutex i2c_lock; 28 struct mutex i2c_lock;
30
31 struct irq_domain *domain;
32 struct mutex irq_lock; 29 struct mutex irq_lock;
33 30
34 u8 *irq_enable; 31 u8 *irq_enable;
@@ -253,6 +250,7 @@ static void adnp_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
253static int adnp_gpio_setup(struct adnp *adnp, unsigned int num_gpios) 250static int adnp_gpio_setup(struct adnp *adnp, unsigned int num_gpios)
254{ 251{
255 struct gpio_chip *chip = &adnp->gpio; 252 struct gpio_chip *chip = &adnp->gpio;
253 int err;
256 254
257 adnp->reg_shift = get_count_order(num_gpios) - 3; 255 adnp->reg_shift = get_count_order(num_gpios) - 3;
258 256
@@ -272,6 +270,10 @@ static int adnp_gpio_setup(struct adnp *adnp, unsigned int num_gpios)
272 chip->of_node = chip->dev->of_node; 270 chip->of_node = chip->dev->of_node;
273 chip->owner = THIS_MODULE; 271 chip->owner = THIS_MODULE;
274 272
273 err = gpiochip_add(chip);
274 if (err)
275 return err;
276
275 return 0; 277 return 0;
276} 278}
277 279
@@ -326,7 +328,8 @@ static irqreturn_t adnp_irq(int irq, void *data)
326 328
327 for_each_set_bit(bit, &pending, 8) { 329 for_each_set_bit(bit, &pending, 8) {
328 unsigned int child_irq; 330 unsigned int child_irq;
329 child_irq = irq_find_mapping(adnp->domain, base + bit); 331 child_irq = irq_find_mapping(adnp->gpio.irqdomain,
332 base + bit);
330 handle_nested_irq(child_irq); 333 handle_nested_irq(child_irq);
331 } 334 }
332 } 335 }
@@ -334,35 +337,32 @@ static irqreturn_t adnp_irq(int irq, void *data)
334 return IRQ_HANDLED; 337 return IRQ_HANDLED;
335} 338}
336 339
337static int adnp_gpio_to_irq(struct gpio_chip *chip, unsigned offset) 340static void adnp_irq_mask(struct irq_data *d)
338{
339 struct adnp *adnp = to_adnp(chip);
340 return irq_create_mapping(adnp->domain, offset);
341}
342
343static void adnp_irq_mask(struct irq_data *data)
344{ 341{
345 struct adnp *adnp = irq_data_get_irq_chip_data(data); 342 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
346 unsigned int reg = data->hwirq >> adnp->reg_shift; 343 struct adnp *adnp = to_adnp(gc);
347 unsigned int pos = data->hwirq & 7; 344 unsigned int reg = d->hwirq >> adnp->reg_shift;
345 unsigned int pos = d->hwirq & 7;
348 346
349 adnp->irq_enable[reg] &= ~BIT(pos); 347 adnp->irq_enable[reg] &= ~BIT(pos);
350} 348}
351 349
352static void adnp_irq_unmask(struct irq_data *data) 350static void adnp_irq_unmask(struct irq_data *d)
353{ 351{
354 struct adnp *adnp = irq_data_get_irq_chip_data(data); 352 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
355 unsigned int reg = data->hwirq >> adnp->reg_shift; 353 struct adnp *adnp = to_adnp(gc);
356 unsigned int pos = data->hwirq & 7; 354 unsigned int reg = d->hwirq >> adnp->reg_shift;
355 unsigned int pos = d->hwirq & 7;
357 356
358 adnp->irq_enable[reg] |= BIT(pos); 357 adnp->irq_enable[reg] |= BIT(pos);
359} 358}
360 359
361static int adnp_irq_set_type(struct irq_data *data, unsigned int type) 360static int adnp_irq_set_type(struct irq_data *d, unsigned int type)
362{ 361{
363 struct adnp *adnp = irq_data_get_irq_chip_data(data); 362 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
364 unsigned int reg = data->hwirq >> adnp->reg_shift; 363 struct adnp *adnp = to_adnp(gc);
365 unsigned int pos = data->hwirq & 7; 364 unsigned int reg = d->hwirq >> adnp->reg_shift;
365 unsigned int pos = d->hwirq & 7;
366 366
367 if (type & IRQ_TYPE_EDGE_RISING) 367 if (type & IRQ_TYPE_EDGE_RISING)
368 adnp->irq_rise[reg] |= BIT(pos); 368 adnp->irq_rise[reg] |= BIT(pos);
@@ -387,16 +387,18 @@ static int adnp_irq_set_type(struct irq_data *data, unsigned int type)
387 return 0; 387 return 0;
388} 388}
389 389
390static void adnp_irq_bus_lock(struct irq_data *data) 390static void adnp_irq_bus_lock(struct irq_data *d)
391{ 391{
392 struct adnp *adnp = irq_data_get_irq_chip_data(data); 392 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
393 struct adnp *adnp = to_adnp(gc);
393 394
394 mutex_lock(&adnp->irq_lock); 395 mutex_lock(&adnp->irq_lock);
395} 396}
396 397
397static void adnp_irq_bus_unlock(struct irq_data *data) 398static void adnp_irq_bus_unlock(struct irq_data *d)
398{ 399{
399 struct adnp *adnp = irq_data_get_irq_chip_data(data); 400 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
401 struct adnp *adnp = to_adnp(gc);
400 unsigned int num_regs = 1 << adnp->reg_shift, i; 402 unsigned int num_regs = 1 << adnp->reg_shift, i;
401 403
402 mutex_lock(&adnp->i2c_lock); 404 mutex_lock(&adnp->i2c_lock);
@@ -408,26 +410,6 @@ static void adnp_irq_bus_unlock(struct irq_data *data)
408 mutex_unlock(&adnp->irq_lock); 410 mutex_unlock(&adnp->irq_lock);
409} 411}
410 412
411static int adnp_irq_reqres(struct irq_data *data)
412{
413 struct adnp *adnp = irq_data_get_irq_chip_data(data);
414
415 if (gpio_lock_as_irq(&adnp->gpio, data->hwirq)) {
416 dev_err(adnp->gpio.dev,
417 "unable to lock HW IRQ %lu for IRQ\n",
418 data->hwirq);
419 return -EINVAL;
420 }
421 return 0;
422}
423
424static void adnp_irq_relres(struct irq_data *data)
425{
426 struct adnp *adnp = irq_data_get_irq_chip_data(data);
427
428 gpio_unlock_as_irq(&adnp->gpio, data->hwirq);
429}
430
431static struct irq_chip adnp_irq_chip = { 413static struct irq_chip adnp_irq_chip = {
432 .name = "gpio-adnp", 414 .name = "gpio-adnp",
433 .irq_mask = adnp_irq_mask, 415 .irq_mask = adnp_irq_mask,
@@ -435,29 +417,6 @@ static struct irq_chip adnp_irq_chip = {
435 .irq_set_type = adnp_irq_set_type, 417 .irq_set_type = adnp_irq_set_type,
436 .irq_bus_lock = adnp_irq_bus_lock, 418 .irq_bus_lock = adnp_irq_bus_lock,
437 .irq_bus_sync_unlock = adnp_irq_bus_unlock, 419 .irq_bus_sync_unlock = adnp_irq_bus_unlock,
438 .irq_request_resources = adnp_irq_reqres,
439 .irq_release_resources = adnp_irq_relres,
440};
441
442static 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
458static const struct irq_domain_ops adnp_irq_domain_ops = {
459 .map = adnp_irq_map,
460 .xlate = irq_domain_xlate_twocell,
461}; 420};
462 421
463static int adnp_irq_setup(struct adnp *adnp) 422static int adnp_irq_setup(struct adnp *adnp)
@@ -503,35 +462,28 @@ static int adnp_irq_setup(struct adnp *adnp)
503 adnp->irq_enable[i] = 0x00; 462 adnp->irq_enable[i] = 0x00;
504 } 463 }
505 464
506 adnp->domain = irq_domain_add_linear(chip->of_node, chip->ngpio, 465 err = devm_request_threaded_irq(chip->dev, adnp->client->irq,
507 &adnp_irq_domain_ops, adnp); 466 NULL, adnp_irq,
508 467 IRQF_TRIGGER_RISING | IRQF_ONESHOT,
509 err = request_threaded_irq(adnp->client->irq, NULL, adnp_irq, 468 dev_name(chip->dev), adnp);
510 IRQF_TRIGGER_RISING | IRQF_ONESHOT,
511 dev_name(chip->dev), adnp);
512 if (err != 0) { 469 if (err != 0) {
513 dev_err(chip->dev, "can't request IRQ#%d: %d\n", 470 dev_err(chip->dev, "can't request IRQ#%d: %d\n",
514 adnp->client->irq, err); 471 adnp->client->irq, err);
515 return err; 472 return err;
516 } 473 }
517 474
518 chip->to_irq = adnp_gpio_to_irq; 475 err = gpiochip_irqchip_add(chip,
519 return 0; 476 &adnp_irq_chip,
520} 477 0,
521 478 handle_simple_irq,
522static void adnp_irq_teardown(struct adnp *adnp) 479 IRQ_TYPE_NONE);
523{ 480 if (err) {
524 unsigned int irq, i; 481 dev_err(chip->dev,
525 482 "could not connect irqchip to gpiochip\n");
526 free_irq(adnp->client->irq, adnp); 483 return err;
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 } 484 }
533 485
534 irq_domain_remove(adnp->domain); 486 return 0;
535} 487}
536 488
537static int adnp_i2c_probe(struct i2c_client *client, 489static int adnp_i2c_probe(struct i2c_client *client,
@@ -558,38 +510,25 @@ static int adnp_i2c_probe(struct i2c_client *client,
558 adnp->client = client; 510 adnp->client = client;
559 511
560 err = adnp_gpio_setup(adnp, num_gpios); 512 err = adnp_gpio_setup(adnp, num_gpios);
561 if (err < 0) 513 if (err)
562 return err; 514 return err;
563 515
564 if (of_find_property(np, "interrupt-controller", NULL)) { 516 if (of_find_property(np, "interrupt-controller", NULL)) {
565 err = adnp_irq_setup(adnp); 517 err = adnp_irq_setup(adnp);
566 if (err < 0) 518 if (err)
567 goto teardown; 519 return err;
568 } 520 }
569 521
570 err = gpiochip_add(&adnp->gpio);
571 if (err < 0)
572 goto teardown;
573
574 i2c_set_clientdata(client, adnp); 522 i2c_set_clientdata(client, adnp);
575 return 0;
576 523
577teardown: 524 return 0;
578 if (of_find_property(np, "interrupt-controller", NULL))
579 adnp_irq_teardown(adnp);
580
581 return err;
582} 525}
583 526
584static int adnp_i2c_remove(struct i2c_client *client) 527static int adnp_i2c_remove(struct i2c_client *client)
585{ 528{
586 struct adnp *adnp = i2c_get_clientdata(client); 529 struct adnp *adnp = i2c_get_clientdata(client);
587 struct device_node *np = client->dev.of_node;
588 530
589 gpiochip_remove(&adnp->gpio); 531 gpiochip_remove(&adnp->gpio);
590 if (of_find_property(np, "interrupt-controller", NULL))
591 adnp_irq_teardown(adnp);
592
593 return 0; 532 return 0;
594} 533}
595 534