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

Commit 76f93992 authored by Lee Jones's avatar Lee Jones Committed by Samuel Ortiz
Browse files

mfd: Provide the STMPE driver with its own IRQ domain



The STMPE driver is yet another IRQ controller which requires its
own IRQ domain. So, we provide it with one.

Acked-by: default avatarArnd Bergmann <arnd@arndb.de>
Acked-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Signed-off-by: default avatarLee Jones <lee.jones@linaro.org>
Signed-off-by: default avatarSamuel Ortiz <sameo@linux.intel.com>
parent 7da0cbfc
Loading
Loading
Loading
Loading
+50 −32
Original line number Original line Diff line number Diff line
@@ -12,6 +12,7 @@
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/pm.h>
#include <linux/pm.h>
#include <linux/slab.h>
#include <linux/slab.h>
#include <linux/mfd/core.h>
#include <linux/mfd/core.h>
@@ -757,7 +758,9 @@ static irqreturn_t stmpe_irq(int irq, void *data)
	int i;
	int i;


	if (variant->id_val == STMPE801_ID) {
	if (variant->id_val == STMPE801_ID) {
		handle_nested_irq(stmpe->irq_base);
		int base = irq_create_mapping(stmpe->domain, 0);

		handle_nested_irq(base);
		return IRQ_HANDLED;
		return IRQ_HANDLED;
	}
	}


@@ -778,8 +781,9 @@ static irqreturn_t stmpe_irq(int irq, void *data)
		while (status) {
		while (status) {
			int bit = __ffs(status);
			int bit = __ffs(status);
			int line = bank * 8 + bit;
			int line = bank * 8 + bit;
			int nestedirq = irq_create_mapping(stmpe->domain, line);


			handle_nested_irq(stmpe->irq_base + line);
			handle_nested_irq(nestedirq);
			status &= ~(1 << bit);
			status &= ~(1 << bit);
		}
		}


@@ -820,7 +824,7 @@ static void stmpe_irq_sync_unlock(struct irq_data *data)
static void stmpe_irq_mask(struct irq_data *data)
static void stmpe_irq_mask(struct irq_data *data)
{
{
	struct stmpe *stmpe = irq_data_get_irq_chip_data(data);
	struct stmpe *stmpe = irq_data_get_irq_chip_data(data);
	int offset = data->irq - stmpe->irq_base;
	int offset = data->hwirq;
	int regoffset = offset / 8;
	int regoffset = offset / 8;
	int mask = 1 << (offset % 8);
	int mask = 1 << (offset % 8);


@@ -830,7 +834,7 @@ static void stmpe_irq_mask(struct irq_data *data)
static void stmpe_irq_unmask(struct irq_data *data)
static void stmpe_irq_unmask(struct irq_data *data)
{
{
	struct stmpe *stmpe = irq_data_get_irq_chip_data(data);
	struct stmpe *stmpe = irq_data_get_irq_chip_data(data);
	int offset = data->irq - stmpe->irq_base;
	int offset = data->hwirq;
	int regoffset = offset / 8;
	int regoffset = offset / 8;
	int mask = 1 << (offset % 8);
	int mask = 1 << (offset % 8);


@@ -845,43 +849,62 @@ static struct irq_chip stmpe_irq_chip = {
	.irq_unmask		= stmpe_irq_unmask,
	.irq_unmask		= stmpe_irq_unmask,
};
};


static int __devinit stmpe_irq_init(struct stmpe *stmpe)
static int stmpe_irq_map(struct irq_domain *d, unsigned int virq,
                                irq_hw_number_t hwirq)
{
{
	struct stmpe *stmpe = d->host_data;
	struct irq_chip *chip = NULL;
	struct irq_chip *chip = NULL;
	int num_irqs = stmpe->variant->num_irqs;
	int base = stmpe->irq_base;
	int irq;


	if (stmpe->variant->id_val != STMPE801_ID)
	if (stmpe->variant->id_val != STMPE801_ID)
		chip = &stmpe_irq_chip;
		chip = &stmpe_irq_chip;


	for (irq = base; irq < base + num_irqs; irq++) {
	irq_set_chip_data(virq, stmpe);
		irq_set_chip_data(irq, stmpe);
	irq_set_chip_and_handler(virq, chip, handle_edge_irq);
		irq_set_chip_and_handler(irq, chip, handle_edge_irq);
	irq_set_nested_thread(virq, 1);
		irq_set_nested_thread(irq, 1);
#ifdef CONFIG_ARM
#ifdef CONFIG_ARM
		set_irq_flags(irq, IRQF_VALID);
	set_irq_flags(virq, IRQF_VALID);
#else
#else
		irq_set_noprobe(irq);
	irq_set_noprobe(virq);
#endif
#endif
	}


	return 0;
	return 0;
}
}


static void stmpe_irq_remove(struct stmpe *stmpe)
static void stmpe_irq_unmap(struct irq_domain *d, unsigned int virq)
{
{
	int num_irqs = stmpe->variant->num_irqs;
	int base = stmpe->irq_base;
	int irq;

	for (irq = base; irq < base + num_irqs; irq++) {
#ifdef CONFIG_ARM
#ifdef CONFIG_ARM
		set_irq_flags(irq, 0);
		set_irq_flags(virq, 0);
#endif
#endif
		irq_set_chip_and_handler(irq, NULL, NULL);
		irq_set_chip_and_handler(virq, NULL, NULL);
		irq_set_chip_data(irq, NULL);
		irq_set_chip_data(virq, NULL);
}

static struct irq_domain_ops stmpe_irq_ops = {
        .map    = stmpe_irq_map,
        .unmap  = stmpe_irq_unmap,
        .xlate  = irq_domain_xlate_twocell,
};

static int __devinit stmpe_irq_init(struct stmpe *stmpe)
{
	int base = stmpe->irq_base;
	int num_irqs = stmpe->variant->num_irqs;

	if (base) {
		stmpe->domain = irq_domain_add_legacy(
			NULL, num_irqs, base, 0, &stmpe_irq_ops, stmpe);
	}
	else {
		stmpe->domain = irq_domain_add_linear(
			NULL, num_irqs, &stmpe_irq_ops, stmpe);
	}

	if (!stmpe->domain) {
		dev_err(stmpe->dev, "Failed to create irqdomain\n");
		return -ENOSYS;
	}
	}

	return 0;
}
}


static int __devinit stmpe_chip_init(struct stmpe *stmpe)
static int __devinit stmpe_chip_init(struct stmpe *stmpe)
@@ -954,7 +977,7 @@ static int __devinit stmpe_add_device(struct stmpe *stmpe,
				      struct mfd_cell *cell)
				      struct mfd_cell *cell)
{
{
	return mfd_add_devices(stmpe->dev, stmpe->pdata->id, cell, 1,
	return mfd_add_devices(stmpe->dev, stmpe->pdata->id, cell, 1,
			       NULL, stmpe->irq_base, NULL);
			       NULL, stmpe->irq_base, stmpe->domain);
}
}


static int __devinit stmpe_devices_init(struct stmpe *stmpe)
static int __devinit stmpe_devices_init(struct stmpe *stmpe)
@@ -1067,7 +1090,7 @@ int __devinit stmpe_probe(struct stmpe_client_info *ci, int partnum)
		if (ret) {
		if (ret) {
			dev_err(stmpe->dev, "failed to request IRQ: %d\n",
			dev_err(stmpe->dev, "failed to request IRQ: %d\n",
					ret);
					ret);
			goto out_removeirq;
			goto free_gpio;
		}
		}
	}
	}


@@ -1083,9 +1106,6 @@ out_removedevs:
	mfd_remove_devices(stmpe->dev);
	mfd_remove_devices(stmpe->dev);
	if (stmpe->irq >= 0)
	if (stmpe->irq >= 0)
		free_irq(stmpe->irq, stmpe);
		free_irq(stmpe->irq, stmpe);
out_removeirq:
	if (stmpe->irq >= 0)
		stmpe_irq_remove(stmpe);
free_gpio:
free_gpio:
	if (pdata->irq_over_gpio)
	if (pdata->irq_over_gpio)
		gpio_free(pdata->irq_gpio);
		gpio_free(pdata->irq_gpio);
@@ -1098,10 +1118,8 @@ int stmpe_remove(struct stmpe *stmpe)
{
{
	mfd_remove_devices(stmpe->dev);
	mfd_remove_devices(stmpe->dev);


	if (stmpe->irq >= 0) {
	if (stmpe->irq >= 0)
		free_irq(stmpe->irq, stmpe);
		free_irq(stmpe->irq, stmpe);
		stmpe_irq_remove(stmpe);
	}


	if (stmpe->pdata->irq_over_gpio)
	if (stmpe->pdata->irq_over_gpio)
		gpio_free(stmpe->pdata->irq_gpio);
		gpio_free(stmpe->pdata->irq_gpio);
+2 −0
Original line number Original line Diff line number Diff line
@@ -62,6 +62,7 @@ struct stmpe_client_info;
 * @lock: lock protecting I/O operations
 * @lock: lock protecting I/O operations
 * @irq_lock: IRQ bus lock
 * @irq_lock: IRQ bus lock
 * @dev: device, mostly for dev_dbg()
 * @dev: device, mostly for dev_dbg()
 * @irq_domain: IRQ domain
 * @client: client - i2c or spi
 * @client: client - i2c or spi
 * @ci: client specific information
 * @ci: client specific information
 * @partnum: part number
 * @partnum: part number
@@ -79,6 +80,7 @@ struct stmpe {
	struct mutex lock;
	struct mutex lock;
	struct mutex irq_lock;
	struct mutex irq_lock;
	struct device *dev;
	struct device *dev;
	struct irq_domain *domain;
	void *client;
	void *client;
	struct stmpe_client_info *ci;
	struct stmpe_client_info *ci;
	enum stmpe_partnum partnum;
	enum stmpe_partnum partnum;