diff options
author | Linus Walleij <linus.walleij@linaro.org> | 2015-01-30 05:32:01 -0500 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2015-03-02 09:44:08 -0500 |
commit | 984f66432e357701194abc7f753dcad89a1f9de3 (patch) | |
tree | 42fee9c8f535c86a1efe679b2844e94402c34935 | |
parent | fd9c963c5661af3403e77e312c0d9941773b6c1b (diff) |
gpio: max732x: convert to GPIOLIB_IRQCHIP
Take a sweep to bring the irq support for the MAX732x expanders
into the gpiolib core to cut down on duplicated code.
Only compile tested! I need some feedback from people using this
expander with interrupts to tell me if things go right or
wrong when I do this.
Cc: Semen Protsenko <semen.protsenko@globallogic.com>
Cc: Mans Rullgard <mans@mansr.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r-- | drivers/gpio/Kconfig | 2 | ||||
-rw-r--r-- | drivers/gpio/gpio-max732x.c | 134 |
2 files changed, 43 insertions, 93 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index c1e2ca3d9a51..09bc70b3875b 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
@@ -543,7 +543,6 @@ config GPIO_MAX7300 | |||
543 | config GPIO_MAX732X | 543 | config GPIO_MAX732X |
544 | tristate "MAX7319, MAX7320-7327 I2C Port Expanders" | 544 | tristate "MAX7319, MAX7320-7327 I2C Port Expanders" |
545 | depends on I2C | 545 | depends on I2C |
546 | select IRQ_DOMAIN | ||
547 | help | 546 | help |
548 | Say yes here to support the MAX7319, MAX7320-7327 series of I2C | 547 | Say yes here to support the MAX7319, MAX7320-7327 series of I2C |
549 | Port Expanders. Each IO port on these chips has a fixed role of | 548 | Port Expanders. Each IO port on these chips has a fixed role of |
@@ -563,6 +562,7 @@ config GPIO_MAX732X | |||
563 | config GPIO_MAX732X_IRQ | 562 | config GPIO_MAX732X_IRQ |
564 | bool "Interrupt controller support for MAX732x" | 563 | bool "Interrupt controller support for MAX732x" |
565 | depends on GPIO_MAX732X=y | 564 | depends on GPIO_MAX732X=y |
565 | select GPIOLIB_IRQCHIP | ||
566 | help | 566 | help |
567 | Say yes here to enable the max732x to be used as an interrupt | 567 | Say yes here to enable the max732x to be used as an interrupt |
568 | controller. It requires the driver to be built in the kernel. | 568 | controller. It requires the driver to be built in the kernel. |
diff --git a/drivers/gpio/gpio-max732x.c b/drivers/gpio/gpio-max732x.c index a095b2393fe9..0fa4543c5e02 100644 --- a/drivers/gpio/gpio-max732x.c +++ b/drivers/gpio/gpio-max732x.c | |||
@@ -4,6 +4,7 @@ | |||
4 | * Copyright (C) 2007 Marvell International Ltd. | 4 | * Copyright (C) 2007 Marvell International Ltd. |
5 | * Copyright (C) 2008 Jack Ren <jack.ren@marvell.com> | 5 | * Copyright (C) 2008 Jack Ren <jack.ren@marvell.com> |
6 | * Copyright (C) 2008 Eric Miao <eric.miao@marvell.com> | 6 | * Copyright (C) 2008 Eric Miao <eric.miao@marvell.com> |
7 | * Copyright (C) 2015 Linus Walleij <linus.walleij@linaro.org> | ||
7 | * | 8 | * |
8 | * Derived from drivers/gpio/pca953x.c | 9 | * Derived from drivers/gpio/pca953x.c |
9 | * | 10 | * |
@@ -16,10 +17,8 @@ | |||
16 | #include <linux/init.h> | 17 | #include <linux/init.h> |
17 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
18 | #include <linux/string.h> | 19 | #include <linux/string.h> |
19 | #include <linux/gpio.h> | 20 | #include <linux/gpio/driver.h> |
20 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
21 | #include <linux/irq.h> | ||
22 | #include <linux/irqdomain.h> | ||
23 | #include <linux/i2c.h> | 22 | #include <linux/i2c.h> |
24 | #include <linux/i2c/max732x.h> | 23 | #include <linux/i2c/max732x.h> |
25 | #include <linux/of.h> | 24 | #include <linux/of.h> |
@@ -150,9 +149,7 @@ struct max732x_chip { | |||
150 | uint8_t reg_out[2]; | 149 | uint8_t reg_out[2]; |
151 | 150 | ||
152 | #ifdef CONFIG_GPIO_MAX732X_IRQ | 151 | #ifdef CONFIG_GPIO_MAX732X_IRQ |
153 | struct irq_domain *irq_domain; | ||
154 | struct mutex irq_lock; | 152 | struct mutex irq_lock; |
155 | int irq_base; | ||
156 | uint8_t irq_mask; | 153 | uint8_t irq_mask; |
157 | uint8_t irq_mask_cur; | 154 | uint8_t irq_mask_cur; |
158 | uint8_t irq_trig_raise; | 155 | uint8_t irq_trig_raise; |
@@ -356,35 +353,26 @@ static void max732x_irq_update_mask(struct max732x_chip *chip) | |||
356 | mutex_unlock(&chip->lock); | 353 | mutex_unlock(&chip->lock); |
357 | } | 354 | } |
358 | 355 | ||
359 | static int max732x_gpio_to_irq(struct gpio_chip *gc, unsigned off) | ||
360 | { | ||
361 | struct max732x_chip *chip = to_max732x(gc); | ||
362 | |||
363 | if (chip->irq_domain) { | ||
364 | return irq_create_mapping(chip->irq_domain, | ||
365 | chip->irq_base + off); | ||
366 | } else { | ||
367 | return -ENXIO; | ||
368 | } | ||
369 | } | ||
370 | |||
371 | static void max732x_irq_mask(struct irq_data *d) | 356 | static void max732x_irq_mask(struct irq_data *d) |
372 | { | 357 | { |
373 | struct max732x_chip *chip = irq_data_get_irq_chip_data(d); | 358 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
359 | struct max732x_chip *chip = to_max732x(gc); | ||
374 | 360 | ||
375 | chip->irq_mask_cur &= ~(1 << d->hwirq); | 361 | chip->irq_mask_cur &= ~(1 << d->hwirq); |
376 | } | 362 | } |
377 | 363 | ||
378 | static void max732x_irq_unmask(struct irq_data *d) | 364 | static void max732x_irq_unmask(struct irq_data *d) |
379 | { | 365 | { |
380 | struct max732x_chip *chip = irq_data_get_irq_chip_data(d); | 366 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
367 | struct max732x_chip *chip = to_max732x(gc); | ||
381 | 368 | ||
382 | chip->irq_mask_cur |= 1 << d->hwirq; | 369 | chip->irq_mask_cur |= 1 << d->hwirq; |
383 | } | 370 | } |
384 | 371 | ||
385 | static void max732x_irq_bus_lock(struct irq_data *d) | 372 | static void max732x_irq_bus_lock(struct irq_data *d) |
386 | { | 373 | { |
387 | struct max732x_chip *chip = irq_data_get_irq_chip_data(d); | 374 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
375 | struct max732x_chip *chip = to_max732x(gc); | ||
388 | 376 | ||
389 | mutex_lock(&chip->irq_lock); | 377 | mutex_lock(&chip->irq_lock); |
390 | chip->irq_mask_cur = chip->irq_mask; | 378 | chip->irq_mask_cur = chip->irq_mask; |
@@ -392,7 +380,8 @@ static void max732x_irq_bus_lock(struct irq_data *d) | |||
392 | 380 | ||
393 | static void max732x_irq_bus_sync_unlock(struct irq_data *d) | 381 | static void max732x_irq_bus_sync_unlock(struct irq_data *d) |
394 | { | 382 | { |
395 | struct max732x_chip *chip = irq_data_get_irq_chip_data(d); | 383 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
384 | struct max732x_chip *chip = to_max732x(gc); | ||
396 | uint16_t new_irqs; | 385 | uint16_t new_irqs; |
397 | uint16_t level; | 386 | uint16_t level; |
398 | 387 | ||
@@ -410,7 +399,8 @@ static void max732x_irq_bus_sync_unlock(struct irq_data *d) | |||
410 | 399 | ||
411 | static int max732x_irq_set_type(struct irq_data *d, unsigned int type) | 400 | static int max732x_irq_set_type(struct irq_data *d, unsigned int type) |
412 | { | 401 | { |
413 | struct max732x_chip *chip = irq_data_get_irq_chip_data(d); | 402 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
403 | struct max732x_chip *chip = to_max732x(gc); | ||
414 | uint16_t off = d->hwirq; | 404 | uint16_t off = d->hwirq; |
415 | uint16_t mask = 1 << off; | 405 | uint16_t mask = 1 << off; |
416 | 406 | ||
@@ -492,7 +482,8 @@ static irqreturn_t max732x_irq_handler(int irq, void *devid) | |||
492 | 482 | ||
493 | do { | 483 | do { |
494 | level = __ffs(pending); | 484 | level = __ffs(pending); |
495 | handle_nested_irq(irq_find_mapping(chip->irq_domain, level)); | 485 | handle_nested_irq(irq_find_mapping(chip->gpio_chip.irqdomain, |
486 | level)); | ||
496 | 487 | ||
497 | pending &= ~(1 << level); | 488 | pending &= ~(1 << level); |
498 | } while (pending); | 489 | } while (pending); |
@@ -500,86 +491,50 @@ static irqreturn_t max732x_irq_handler(int irq, void *devid) | |||
500 | return IRQ_HANDLED; | 491 | return IRQ_HANDLED; |
501 | } | 492 | } |
502 | 493 | ||
503 | static int max732x_irq_map(struct irq_domain *h, unsigned int virq, | ||
504 | irq_hw_number_t hw) | ||
505 | { | ||
506 | struct max732x_chip *chip = h->host_data; | ||
507 | |||
508 | if (!(chip->dir_input & (1 << hw))) { | ||
509 | dev_err(&chip->client->dev, | ||
510 | "Attempt to map output line as IRQ line: %lu\n", | ||
511 | hw); | ||
512 | return -EPERM; | ||
513 | } | ||
514 | |||
515 | irq_set_chip_data(virq, chip); | ||
516 | irq_set_chip_and_handler(virq, &max732x_irq_chip, | ||
517 | handle_edge_irq); | ||
518 | irq_set_nested_thread(virq, 1); | ||
519 | #ifdef CONFIG_ARM | ||
520 | /* ARM needs us to explicitly flag the IRQ as valid | ||
521 | * and will set them noprobe when we do so. */ | ||
522 | set_irq_flags(virq, IRQF_VALID); | ||
523 | #else | ||
524 | irq_set_noprobe(virq); | ||
525 | #endif | ||
526 | |||
527 | return 0; | ||
528 | } | ||
529 | |||
530 | static struct irq_domain_ops max732x_irq_domain_ops = { | ||
531 | .map = max732x_irq_map, | ||
532 | .xlate = irq_domain_xlate_twocell, | ||
533 | }; | ||
534 | |||
535 | static void max732x_irq_teardown(struct max732x_chip *chip) | ||
536 | { | ||
537 | if (chip->client->irq && chip->irq_domain) | ||
538 | irq_domain_remove(chip->irq_domain); | ||
539 | } | ||
540 | |||
541 | static int max732x_irq_setup(struct max732x_chip *chip, | 494 | static int max732x_irq_setup(struct max732x_chip *chip, |
542 | const struct i2c_device_id *id) | 495 | const struct i2c_device_id *id) |
543 | { | 496 | { |
544 | struct i2c_client *client = chip->client; | 497 | struct i2c_client *client = chip->client; |
545 | struct max732x_platform_data *pdata = dev_get_platdata(&client->dev); | 498 | struct max732x_platform_data *pdata = dev_get_platdata(&client->dev); |
546 | int has_irq = max732x_features[id->driver_data] >> 32; | 499 | int has_irq = max732x_features[id->driver_data] >> 32; |
500 | int irq_base = 0; | ||
547 | int ret; | 501 | int ret; |
548 | 502 | ||
549 | if (((pdata && pdata->irq_base) || client->irq) | 503 | if (((pdata && pdata->irq_base) || client->irq) |
550 | && has_irq != INT_NONE) { | 504 | && has_irq != INT_NONE) { |
551 | if (pdata) | 505 | if (pdata) |
552 | chip->irq_base = pdata->irq_base; | 506 | irq_base = pdata->irq_base; |
553 | chip->irq_features = has_irq; | 507 | chip->irq_features = has_irq; |
554 | mutex_init(&chip->irq_lock); | 508 | mutex_init(&chip->irq_lock); |
555 | 509 | ||
556 | chip->irq_domain = irq_domain_add_simple(client->dev.of_node, | 510 | ret = devm_request_threaded_irq(&client->dev, |
557 | chip->gpio_chip.ngpio, chip->irq_base, | 511 | client->irq, |
558 | &max732x_irq_domain_ops, chip); | 512 | NULL, |
559 | if (!chip->irq_domain) { | 513 | max732x_irq_handler, |
560 | dev_err(&client->dev, "Failed to create IRQ domain\n"); | 514 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, |
561 | return -ENOMEM; | 515 | dev_name(&client->dev), chip); |
562 | } | ||
563 | |||
564 | ret = request_threaded_irq(client->irq, | ||
565 | NULL, | ||
566 | max732x_irq_handler, | ||
567 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | ||
568 | dev_name(&client->dev), chip); | ||
569 | if (ret) { | 516 | if (ret) { |
570 | dev_err(&client->dev, "failed to request irq %d\n", | 517 | dev_err(&client->dev, "failed to request irq %d\n", |
571 | client->irq); | 518 | client->irq); |
572 | goto out_failed; | 519 | return ret; |
573 | } | 520 | } |
574 | 521 | ret = gpiochip_irqchip_add(&chip->gpio_chip, | |
575 | chip->gpio_chip.to_irq = max732x_gpio_to_irq; | 522 | &max732x_irq_chip, |
523 | irq_base, | ||
524 | handle_edge_irq, | ||
525 | IRQ_TYPE_NONE); | ||
526 | if (ret) { | ||
527 | dev_err(&client->dev, | ||
528 | "could not connect irqchip to gpiochip\n"); | ||
529 | return ret; | ||
530 | } | ||
531 | gpiochip_set_chained_irqchip(&chip->gpio_chip, | ||
532 | &max732x_irq_chip, | ||
533 | client->irq, | ||
534 | NULL); | ||
576 | } | 535 | } |
577 | 536 | ||
578 | return 0; | 537 | return 0; |
579 | |||
580 | out_failed: | ||
581 | max732x_irq_teardown(chip); | ||
582 | return ret; | ||
583 | } | 538 | } |
584 | 539 | ||
585 | #else /* CONFIG_GPIO_MAX732X_IRQ */ | 540 | #else /* CONFIG_GPIO_MAX732X_IRQ */ |
@@ -595,10 +550,6 @@ static int max732x_irq_setup(struct max732x_chip *chip, | |||
595 | 550 | ||
596 | return 0; | 551 | return 0; |
597 | } | 552 | } |
598 | |||
599 | static void max732x_irq_teardown(struct max732x_chip *chip) | ||
600 | { | ||
601 | } | ||
602 | #endif | 553 | #endif |
603 | 554 | ||
604 | static int max732x_setup_gpio(struct max732x_chip *chip, | 555 | static int max732x_setup_gpio(struct max732x_chip *chip, |
@@ -730,13 +681,15 @@ static int max732x_probe(struct i2c_client *client, | |||
730 | if (nr_port > 8) | 681 | if (nr_port > 8) |
731 | max732x_readb(chip, is_group_a(chip, 8), &chip->reg_out[1]); | 682 | max732x_readb(chip, is_group_a(chip, 8), &chip->reg_out[1]); |
732 | 683 | ||
733 | ret = max732x_irq_setup(chip, id); | 684 | ret = gpiochip_add(&chip->gpio_chip); |
734 | if (ret) | 685 | if (ret) |
735 | goto out_failed; | 686 | goto out_failed; |
736 | 687 | ||
737 | ret = gpiochip_add(&chip->gpio_chip); | 688 | ret = max732x_irq_setup(chip, id); |
738 | if (ret) | 689 | if (ret) { |
690 | gpiochip_remove(&chip->gpio_chip); | ||
739 | goto out_failed; | 691 | goto out_failed; |
692 | } | ||
740 | 693 | ||
741 | if (pdata && pdata->setup) { | 694 | if (pdata && pdata->setup) { |
742 | ret = pdata->setup(client, chip->gpio_chip.base, | 695 | ret = pdata->setup(client, chip->gpio_chip.base, |
@@ -751,7 +704,6 @@ static int max732x_probe(struct i2c_client *client, | |||
751 | out_failed: | 704 | out_failed: |
752 | if (chip->client_dummy) | 705 | if (chip->client_dummy) |
753 | i2c_unregister_device(chip->client_dummy); | 706 | i2c_unregister_device(chip->client_dummy); |
754 | max732x_irq_teardown(chip); | ||
755 | return ret; | 707 | return ret; |
756 | } | 708 | } |
757 | 709 | ||
@@ -774,8 +726,6 @@ static int max732x_remove(struct i2c_client *client) | |||
774 | 726 | ||
775 | gpiochip_remove(&chip->gpio_chip); | 727 | gpiochip_remove(&chip->gpio_chip); |
776 | 728 | ||
777 | max732x_irq_teardown(chip); | ||
778 | |||
779 | /* unregister any dummy i2c_client */ | 729 | /* unregister any dummy i2c_client */ |
780 | if (chip->client_dummy) | 730 | if (chip->client_dummy) |
781 | i2c_unregister_device(chip->client_dummy); | 731 | i2c_unregister_device(chip->client_dummy); |