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>
diff --git a/drivers/gpio/gpio-twl4030.c b/drivers/gpio/gpio-twl4030.c
index b8b4f22..697396c 100644
--- a/drivers/gpio/gpio-twl4030.c
+++ b/drivers/gpio/gpio-twl4030.c
@@ -404,7 +404,8 @@
 				"can't dispatch IRQs from modules\n");
 			goto no_irqs;
 		}
-		ret = twl4030_sih_setup(TWL4030_MODULE_GPIO);
+		ret = twl4030_sih_setup(&pdev->dev, TWL4030_MODULE_GPIO,
+					pdata->irq_base);
 		if (ret < 0)
 			return ret;
 		WARN_ON(ret != pdata->irq_base);
diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c
index a3dc1d9..d6f3a5e 100644
--- a/drivers/mfd/twl4030-irq.c
+++ b/drivers/mfd/twl4030-irq.c
@@ -629,28 +629,21 @@
 	return IRQ_HANDLED;
 }
 
-static unsigned twl4030_irq_next;
-
 /* returns the first IRQ used by this SIH bank, or negative errno */
-int twl4030_sih_setup(int module)
+int twl4030_sih_setup(struct device *dev, int module, int irq_base)
 {
 	int			sih_mod;
 	const struct sih	*sih = NULL;
 	struct sih_agent	*agent;
 	int			i, irq;
 	int			status = -EINVAL;
-	unsigned		irq_base = twl4030_irq_next;
 
 	/* only support modules with standard clear-on-read for now */
 	for (sih_mod = 0, sih = sih_modules;
 			sih_mod < nr_sih_modules;
 			sih_mod++, sih++) {
 		if (sih->module == module && sih->set_cor) {
-			if (!WARN((irq_base + sih->bits) > NR_IRQS,
-					"irq %d for %s too big\n",
-					irq_base + sih->bits,
-					sih->name))
-				status = 0;
+			status = 0;
 			break;
 		}
 	}
@@ -661,8 +654,6 @@
 	if (!agent)
 		return -ENOMEM;
 
-	status = 0;
-
 	agent->irq_base = irq_base;
 	agent->sih = sih;
 	agent->imr = ~0;
@@ -678,8 +669,6 @@
 		activate_irq(irq);
 	}
 
-	twl4030_irq_next += i;
-
 	/* replace generic PIH handler (handle_simple_irq) */
 	irq = sih_mod + twl4030_irq_base;
 	irq_set_handler_data(irq, agent);
@@ -688,7 +677,7 @@
 				      agent->irq_name ?: sih->name, NULL);
 
 	pr_info("twl4030: %s (irq %d) chaining IRQs %d..%d\n", sih->name,
-			irq, irq_base, twl4030_irq_next - 1);
+			irq, irq_base, irq_base + i - 1);
 
 	return status < 0 ? status : irq_base;
 }
@@ -752,12 +741,12 @@
 		irq_set_nested_thread(i, 1);
 		activate_irq(i);
 	}
-	twl4030_irq_next = i;
+
 	pr_info("twl4030: %s (irq %d) chaining IRQs %d..%d\n", "PIH",
-			irq_num, irq_base, twl4030_irq_next - 1);
+			irq_num, irq_base, irq_end);
 
 	/* ... and the PWR_INT module ... */
-	status = twl4030_sih_setup(TWL4030_MODULE_INT);
+	status = twl4030_sih_setup(dev, TWL4030_MODULE_INT, irq_end);
 	if (status < 0) {
 		pr_err("twl4030: sih_setup PWR INT --> %d\n", status);
 		goto fail;