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

Commit 21f7541d authored by Rhyland Klein's avatar Rhyland Klein Committed by Samuel Ortiz
Browse files

mfd: Add tps65910-irq devicetree init and irqdomain support



This change changes the tps65910-irq code to use irqdomain, and support
initialization from devicetree. This assumes that the irq_base in the
platform data is -1 if devicetree is used.

Signed-off-by: default avatarRhyland Klein <rklein@nvidia.com>
Signed-off-by: default avatarSamuel Ortiz <sameo@linux.intel.com>
parent b09530ef
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -190,6 +190,7 @@ config MFD_TPS65910
	depends on I2C=y && GPIOLIB
	depends on I2C=y && GPIOLIB
	select MFD_CORE
	select MFD_CORE
	select REGMAP_I2C
	select REGMAP_I2C
	select IRQ_DOMAIN
	help
	help
	  if you say yes here you get support for the TPS65910 series of
	  if you say yes here you get support for the TPS65910 series of
	  Power Management chips.
	  Power Management chips.
+62 −34
Original line number Original line Diff line number Diff line
@@ -20,15 +20,10 @@
#include <linux/device.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/gpio.h>
#include <linux/gpio.h>
#include <linux/mfd/tps65910.h>
#include <linux/mfd/tps65910.h>


static inline int irq_to_tps65910_irq(struct tps65910 *tps65910,
							int irq)
{
	return (irq - tps65910->irq_base);
}

/*
/*
 * This is a threaded IRQ handler so can access I2C/SPI.  Since all
 * This is a threaded IRQ handler so can access I2C/SPI.  Since all
 * interrupts are clear on read the IRQ line will be reasserted and
 * interrupts are clear on read the IRQ line will be reasserted and
@@ -76,7 +71,7 @@ static irqreturn_t tps65910_irq(int irq, void *irq_data)
		if (!(irq_sts & (1 << i)))
		if (!(irq_sts & (1 << i)))
			continue;
			continue;


		handle_nested_irq(tps65910->irq_base + i);
		handle_nested_irq(irq_find_mapping(tps65910->domain, i));
	}
	}


	/* Write the STS register back to clear IRQs we handled */
	/* Write the STS register back to clear IRQs we handled */
@@ -135,14 +130,14 @@ static void tps65910_irq_enable(struct irq_data *data)
{
{
	struct tps65910 *tps65910 = irq_data_get_irq_chip_data(data);
	struct tps65910 *tps65910 = irq_data_get_irq_chip_data(data);


	tps65910->irq_mask &= ~( 1 << irq_to_tps65910_irq(tps65910, data->irq));
	tps65910->irq_mask &= ~(1 << data->hwirq);
}
}


static void tps65910_irq_disable(struct irq_data *data)
static void tps65910_irq_disable(struct irq_data *data)
{
{
	struct tps65910 *tps65910 = irq_data_get_irq_chip_data(data);
	struct tps65910 *tps65910 = irq_data_get_irq_chip_data(data);


	tps65910->irq_mask |= ( 1 << irq_to_tps65910_irq(tps65910, data->irq));
	tps65910->irq_mask |= (1 << data->hwirq);
}
}


#ifdef CONFIG_PM_SLEEP
#ifdef CONFIG_PM_SLEEP
@@ -164,10 +159,35 @@ static struct irq_chip tps65910_irq_chip = {
	.irq_set_wake = tps65910_irq_set_wake,
	.irq_set_wake = tps65910_irq_set_wake,
};
};


static int tps65910_irq_map(struct irq_domain *h, unsigned int virq,
				irq_hw_number_t hw)
{
	struct tps65910 *tps65910 = h->host_data;

	irq_set_chip_data(virq, tps65910);
	irq_set_chip_and_handler(virq, &tps65910_irq_chip, handle_edge_irq);
	irq_set_nested_thread(virq, 1);

	/* ARM needs us to explicitly flag the IRQ as valid
	 * and will set them noprobe when we do so. */
#ifdef CONFIG_ARM
	set_irq_flags(virq, IRQF_VALID);
#else
	irq_set_noprobe(virq);
#endif

	return 0;
}

static struct irq_domain_ops tps65910_domain_ops = {
	.map	= tps65910_irq_map,
	.xlate	= irq_domain_xlate_twocell,
};

int tps65910_irq_init(struct tps65910 *tps65910, int irq,
int tps65910_irq_init(struct tps65910 *tps65910, int irq,
		    struct tps65910_platform_data *pdata)
		    struct tps65910_platform_data *pdata)
{
{
	int ret, cur_irq;
	int ret;
	int flags = IRQF_ONESHOT;
	int flags = IRQF_ONESHOT;


	if (!irq) {
	if (!irq) {
@@ -175,17 +195,11 @@ int tps65910_irq_init(struct tps65910 *tps65910, int irq,
		return -EINVAL;
		return -EINVAL;
	}
	}


	if (!pdata || !pdata->irq_base) {
	if (!pdata) {
		dev_warn(tps65910->dev, "No interrupt support, no IRQ base\n");
		dev_warn(tps65910->dev, "No interrupt support, no pdata\n");
		return -EINVAL;
		return -EINVAL;
	}
	}


	tps65910->irq_mask = 0xFFFFFF;

	mutex_init(&tps65910->irq_lock);
	tps65910->chip_irq = irq;
	tps65910->irq_base = pdata->irq_base;

	switch (tps65910_chip_id(tps65910)) {
	switch (tps65910_chip_id(tps65910)) {
	case TPS65910:
	case TPS65910:
		tps65910->irq_num = TPS65910_NUM_IRQ;
		tps65910->irq_num = TPS65910_NUM_IRQ;
@@ -195,22 +209,36 @@ int tps65910_irq_init(struct tps65910 *tps65910, int irq,
		break;
		break;
	}
	}


	/* Register with genirq */
	if (pdata->irq_base > 0) {
	for (cur_irq = tps65910->irq_base;
		pdata->irq_base = irq_alloc_descs(pdata->irq_base, 0,
	     cur_irq < tps65910->irq_num + tps65910->irq_base;
					tps65910->irq_num, -1);
	     cur_irq++) {
		if (pdata->irq_base < 0) {
		irq_set_chip_data(cur_irq, tps65910);
			dev_warn(tps65910->dev, "Failed to alloc IRQs: %d\n",
		irq_set_chip_and_handler(cur_irq, &tps65910_irq_chip,
					pdata->irq_base);
					 handle_edge_irq);
			return pdata->irq_base;
		irq_set_nested_thread(cur_irq, 1);
		}
	}


		/* ARM needs us to explicitly flag the IRQ as valid
	tps65910->irq_mask = 0xFFFFFF;
		 * and will set them noprobe when we do so. */

#ifdef CONFIG_ARM
	mutex_init(&tps65910->irq_lock);
		set_irq_flags(cur_irq, IRQF_VALID);
	tps65910->chip_irq = irq;
#else
	tps65910->irq_base = pdata->irq_base;
		irq_set_noprobe(cur_irq);

#endif
	if (pdata->irq_base > 0)
		tps65910->domain = irq_domain_add_legacy(tps65910->dev->of_node,
					tps65910->irq_num,
					pdata->irq_base,
					0,
					&tps65910_domain_ops, tps65910);
	else
		tps65910->domain = irq_domain_add_linear(tps65910->dev->of_node,
					tps65910->irq_num,
					&tps65910_domain_ops, tps65910);

	if (!tps65910->domain) {
		dev_err(tps65910->dev, "Failed to create IRQ domain\n");
		return -ENOMEM;
	}
	}


	ret = request_threaded_irq(irq, NULL, tps65910_irq, flags,
	ret = request_threaded_irq(irq, NULL, tps65910_irq, flags,
+1 −0
Original line number Original line Diff line number Diff line
@@ -836,6 +836,7 @@ struct tps65910 {
	int irq_base;
	int irq_base;
	int irq_num;
	int irq_num;
	u32 irq_mask;
	u32 irq_mask;
	struct irq_domain *domain;
};
};


struct tps65910_platform_data {
struct tps65910_platform_data {