Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f01b1f90 authored by Benoit Cousson's avatar Benoit Cousson Committed by Samuel Ortiz
Browse files

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: default avatarFelipe Balbi <balbi@ti.com>
Signed-off-by: default avatarBenoit Cousson <b-cousson@ti.com>
Signed-off-by: default avatarSamuel Ortiz <sameo@linux.intel.com>
parent 78518ffa
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -404,7 +404,8 @@ static int __devinit gpio_twl4030_probe(struct platform_device *pdev)
				"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);
+6 −17
Original line number Diff line number Diff line
@@ -629,27 +629,20 @@ static irqreturn_t handle_twl4030_sih(int irq, void *data)
	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;
			break;
		}
@@ -661,8 +654,6 @@ int twl4030_sih_setup(int module)
	if (!agent)
		return -ENOMEM;

	status = 0;

	agent->irq_base = irq_base;
	agent->sih = sih;
	agent->imr = ~0;
@@ -678,8 +669,6 @@ int twl4030_sih_setup(int module)
		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 @@ int twl4030_sih_setup(int module)
				      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 @@ int twl4030_init_irq(struct device *dev, int irq_num)
		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;
+1 −1
Original line number Diff line number Diff line
@@ -751,7 +751,7 @@ struct twl4030_platform_data {

/*----------------------------------------------------------------------*/

int twl4030_sih_setup(int module);
int twl4030_sih_setup(struct device *dev, int module, int irq_base);

/* Offsets to Power Registers */
#define TWL4030_VDAC_DEV_GRP		0x3B