aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenoit Cousson <b-cousson@ti.com>2012-02-29 16:38:06 -0500
committerSamuel Ortiz <sameo@linux.intel.com>2012-03-22 08:04:54 -0400
commitf01b1f90bf46ddaf2a68215a9489364c974e5689 (patch)
tree3beb31a6777b16926d81eb10d1ec0c901a175503
parent78518ffa08fceee42d61359303c58bdd0a82033f (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.c3
-rw-r--r--drivers/mfd/twl4030-irq.c23
-rw-r--r--include/linux/i2c/twl.h2
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
632static 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 */
635int twl4030_sih_setup(int module) 633int 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
754int twl4030_sih_setup(int module); 754int 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