diff options
author | Benoit Cousson <b-cousson@ti.com> | 2012-02-29 16:38:06 -0500 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2012-03-22 08:04:54 -0400 |
commit | f01b1f90bf46ddaf2a68215a9489364c974e5689 (patch) | |
tree | 3beb31a6777b16926d81eb10d1ec0c901a175503 | |
parent | 78518ffa08fceee42d61359303c58bdd0a82033f (diff) |
mfd: Make twl4030 SIH SPARSE_IRQ capable
twl4030 is using a two level irq controllers infrastruture.
So far, only the first level was using dynamic irq_desc allocation
to be able to have irq_domain support for device tree.
There is a need to allocate separate irq_descs for the SIH too to
avoid hacking the first level with interrupts from the second level.
Add an irq_base parameter to allow the caller to provide the base from
pdata or from dynamic allocation.
Affect TWL4030_NR_IRQS to the twl-core IRQs only.
Moreover that will allow the extraction of the of_node pointer for further
Device Tree conversion.
Signed-off-by: Felipe Balbi <balbi@ti.com>
Signed-off-by: Benoit Cousson <b-cousson@ti.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
-rw-r--r-- | drivers/gpio/gpio-twl4030.c | 3 | ||||
-rw-r--r-- | drivers/mfd/twl4030-irq.c | 23 | ||||
-rw-r--r-- | include/linux/i2c/twl.h | 2 |
3 files changed, 9 insertions, 19 deletions
diff --git a/drivers/gpio/gpio-twl4030.c b/drivers/gpio/gpio-twl4030.c index b8b4f228757c..697396c74627 100644 --- a/drivers/gpio/gpio-twl4030.c +++ b/drivers/gpio/gpio-twl4030.c | |||
@@ -404,7 +404,8 @@ static int __devinit gpio_twl4030_probe(struct platform_device *pdev) | |||
404 | "can't dispatch IRQs from modules\n"); | 404 | "can't dispatch IRQs from modules\n"); |
405 | goto no_irqs; | 405 | goto no_irqs; |
406 | } | 406 | } |
407 | ret = twl4030_sih_setup(TWL4030_MODULE_GPIO); | 407 | ret = twl4030_sih_setup(&pdev->dev, TWL4030_MODULE_GPIO, |
408 | pdata->irq_base); | ||
408 | if (ret < 0) | 409 | if (ret < 0) |
409 | return ret; | 410 | return ret; |
410 | WARN_ON(ret != pdata->irq_base); | 411 | WARN_ON(ret != pdata->irq_base); |
diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c index a3dc1d929070..d6f3a5e9f7bd 100644 --- a/drivers/mfd/twl4030-irq.c +++ b/drivers/mfd/twl4030-irq.c | |||
@@ -629,28 +629,21 @@ static irqreturn_t handle_twl4030_sih(int irq, void *data) | |||
629 | return IRQ_HANDLED; | 629 | return IRQ_HANDLED; |
630 | } | 630 | } |
631 | 631 | ||
632 | static unsigned twl4030_irq_next; | ||
633 | |||
634 | /* returns the first IRQ used by this SIH bank, or negative errno */ | 632 | /* returns the first IRQ used by this SIH bank, or negative errno */ |
635 | int twl4030_sih_setup(int module) | 633 | int twl4030_sih_setup(struct device *dev, int module, int irq_base) |
636 | { | 634 | { |
637 | int sih_mod; | 635 | int sih_mod; |
638 | const struct sih *sih = NULL; | 636 | const struct sih *sih = NULL; |
639 | struct sih_agent *agent; | 637 | struct sih_agent *agent; |
640 | int i, irq; | 638 | int i, irq; |
641 | int status = -EINVAL; | 639 | int status = -EINVAL; |
642 | unsigned irq_base = twl4030_irq_next; | ||
643 | 640 | ||
644 | /* only support modules with standard clear-on-read for now */ | 641 | /* only support modules with standard clear-on-read for now */ |
645 | for (sih_mod = 0, sih = sih_modules; | 642 | for (sih_mod = 0, sih = sih_modules; |
646 | sih_mod < nr_sih_modules; | 643 | sih_mod < nr_sih_modules; |
647 | sih_mod++, sih++) { | 644 | sih_mod++, sih++) { |
648 | if (sih->module == module && sih->set_cor) { | 645 | if (sih->module == module && sih->set_cor) { |
649 | if (!WARN((irq_base + sih->bits) > NR_IRQS, | 646 | status = 0; |
650 | "irq %d for %s too big\n", | ||
651 | irq_base + sih->bits, | ||
652 | sih->name)) | ||
653 | status = 0; | ||
654 | break; | 647 | break; |
655 | } | 648 | } |
656 | } | 649 | } |
@@ -661,8 +654,6 @@ int twl4030_sih_setup(int module) | |||
661 | if (!agent) | 654 | if (!agent) |
662 | return -ENOMEM; | 655 | return -ENOMEM; |
663 | 656 | ||
664 | status = 0; | ||
665 | |||
666 | agent->irq_base = irq_base; | 657 | agent->irq_base = irq_base; |
667 | agent->sih = sih; | 658 | agent->sih = sih; |
668 | agent->imr = ~0; | 659 | agent->imr = ~0; |
@@ -678,8 +669,6 @@ int twl4030_sih_setup(int module) | |||
678 | activate_irq(irq); | 669 | activate_irq(irq); |
679 | } | 670 | } |
680 | 671 | ||
681 | twl4030_irq_next += i; | ||
682 | |||
683 | /* replace generic PIH handler (handle_simple_irq) */ | 672 | /* replace generic PIH handler (handle_simple_irq) */ |
684 | irq = sih_mod + twl4030_irq_base; | 673 | irq = sih_mod + twl4030_irq_base; |
685 | irq_set_handler_data(irq, agent); | 674 | irq_set_handler_data(irq, agent); |
@@ -688,7 +677,7 @@ int twl4030_sih_setup(int module) | |||
688 | agent->irq_name ?: sih->name, NULL); | 677 | agent->irq_name ?: sih->name, NULL); |
689 | 678 | ||
690 | pr_info("twl4030: %s (irq %d) chaining IRQs %d..%d\n", sih->name, | 679 | pr_info("twl4030: %s (irq %d) chaining IRQs %d..%d\n", sih->name, |
691 | irq, irq_base, twl4030_irq_next - 1); | 680 | irq, irq_base, irq_base + i - 1); |
692 | 681 | ||
693 | return status < 0 ? status : irq_base; | 682 | return status < 0 ? status : irq_base; |
694 | } | 683 | } |
@@ -752,12 +741,12 @@ int twl4030_init_irq(struct device *dev, int irq_num) | |||
752 | irq_set_nested_thread(i, 1); | 741 | irq_set_nested_thread(i, 1); |
753 | activate_irq(i); | 742 | activate_irq(i); |
754 | } | 743 | } |
755 | twl4030_irq_next = i; | 744 | |
756 | pr_info("twl4030: %s (irq %d) chaining IRQs %d..%d\n", "PIH", | 745 | pr_info("twl4030: %s (irq %d) chaining IRQs %d..%d\n", "PIH", |
757 | irq_num, irq_base, twl4030_irq_next - 1); | 746 | irq_num, irq_base, irq_end); |
758 | 747 | ||
759 | /* ... and the PWR_INT module ... */ | 748 | /* ... and the PWR_INT module ... */ |
760 | status = twl4030_sih_setup(TWL4030_MODULE_INT); | 749 | status = twl4030_sih_setup(dev, TWL4030_MODULE_INT, irq_end); |
761 | if (status < 0) { | 750 | if (status < 0) { |
762 | pr_err("twl4030: sih_setup PWR INT --> %d\n", status); | 751 | pr_err("twl4030: sih_setup PWR INT --> %d\n", status); |
763 | goto fail; | 752 | goto fail; |
diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h index 78d3465251d6..8b9904abd9ca 100644 --- a/include/linux/i2c/twl.h +++ b/include/linux/i2c/twl.h | |||
@@ -751,7 +751,7 @@ struct twl4030_platform_data { | |||
751 | 751 | ||
752 | /*----------------------------------------------------------------------*/ | 752 | /*----------------------------------------------------------------------*/ |
753 | 753 | ||
754 | int twl4030_sih_setup(int module); | 754 | int twl4030_sih_setup(struct device *dev, int module, int irq_base); |
755 | 755 | ||
756 | /* Offsets to Power Registers */ | 756 | /* Offsets to Power Registers */ |
757 | #define TWL4030_VDAC_DEV_GRP 0x3B | 757 | #define TWL4030_VDAC_DEV_GRP 0x3B |