pinctrl: sirf: use only one irq_domain for the whole device node

in sirfsoc gpio probe(), we create 5 irq_domains for 5 gpio banks. but
in irq_create_of_mapping() of irqchip core level, irq_find_host() can
only return the 1st irq_domain attached the pinctrl dt device node as
we can see from the codes:

unsigned int irq_create_of_mapping(struct device_node *controller,
				   const u32 *intspec, unsigned int intsize)
{
	struct irq_domain *domain;
	...
	domain = controller ? irq_find_host(controller) : irq_default_domain;
}

struct irq_domain *irq_find_host(struct device_node *node)
{
	struct irq_domain *h, *found = NULL;
	int rc;

	/* We might want to match the legacy controller last since
	 * it might potentially be set to match all interrupts in
	 * the absence of a device node. This isn't a problem so far
	 * yet though...
	 */
	mutex_lock(&irq_domain_mutex);
	list_for_each_entry(h, &irq_domain_list, link) {
		if (h->ops->match)
			rc = h->ops->match(h, node);
		else
			rc = (h->of_node != NULL) && (h->of_node == node);

		if (rc) {
			found = h;
			break;
		}
	}
	mutex_unlock(&irq_domain_mutex);
	return found;
}

for sirfsoc, the 1st irq_domain attached to the device_node(controller) only
can do linear for the 1st 32 gpios. so for devices who use gpio hwirq above
32 and put the information in dt like:
                                tangoc-ts@5c{
                                        compatible = "pixcir,tangoc-ts";
+                                       interrupt-parent = <&gpio>;
+                                       interrupts = <34 0>;
                                };

we will fail to get the virq for these devices as hwirq will be bigger than
domain->revmap_data.linear.size in:
unsigned int irq_linear_revmap(struct irq_domain *domain,
			       irq_hw_number_t hwirq)
{

	/* Check revmap bounds; complain if exceeded */
	if (WARN_ON(hwirq >= domain->revmap_data.linear.size))
		return 0;

	return domain->revmap_data.linear.revmap[hwirq];
}

this patch drops redundant irq_domain and keep only one to fix the problem.

Signed-off-by: Barry Song <Baohua.Song@csr.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
Barry Song 2014-01-11 16:48:42 +08:00 committed by Linus Walleij
parent ad5d25fef8
commit 8daeffb058
1 changed files with 15 additions and 11 deletions

View File

@ -468,7 +468,8 @@ static inline int sirfsoc_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
struct sirfsoc_gpio_bank *bank = container_of(to_of_mm_gpio_chip(chip), struct sirfsoc_gpio_bank *bank = container_of(to_of_mm_gpio_chip(chip),
struct sirfsoc_gpio_bank, chip); struct sirfsoc_gpio_bank, chip);
return irq_create_mapping(bank->domain, offset); return irq_create_mapping(bank->domain, offset + bank->id *
SIRFSOC_GPIO_BANK_SIZE);
} }
static inline int sirfsoc_gpio_to_offset(unsigned int gpio) static inline int sirfsoc_gpio_to_offset(unsigned int gpio)
@ -629,7 +630,8 @@ static void sirfsoc_gpio_handle_irq(unsigned int irq, struct irq_desc *desc)
if ((status & 0x1) && (ctrl & SIRFSOC_GPIO_CTL_INTR_EN_MASK)) { if ((status & 0x1) && (ctrl & SIRFSOC_GPIO_CTL_INTR_EN_MASK)) {
pr_debug("%s: gpio id %d idx %d happens\n", pr_debug("%s: gpio id %d idx %d happens\n",
__func__, bank->id, idx); __func__, bank->id, idx);
generic_handle_irq(irq_find_mapping(bank->domain, idx)); generic_handle_irq(irq_find_mapping(bank->domain, idx +
bank->id * SIRFSOC_GPIO_BANK_SIZE));
} }
idx++; idx++;
@ -786,7 +788,7 @@ static int sirfsoc_gpio_irq_map(struct irq_domain *d, unsigned int irq,
irq_set_chip(irq, &sirfsoc_irq_chip); irq_set_chip(irq, &sirfsoc_irq_chip);
irq_set_handler(irq, handle_level_irq); irq_set_handler(irq, handle_level_irq);
irq_set_chip_data(irq, bank); irq_set_chip_data(irq, bank + hwirq / SIRFSOC_GPIO_BANK_SIZE);
set_irq_flags(irq, IRQF_VALID); set_irq_flags(irq, IRQF_VALID);
return 0; return 0;
@ -835,6 +837,7 @@ static int sirfsoc_gpio_probe(struct device_node *np)
struct sirfsoc_gpio_bank *bank; struct sirfsoc_gpio_bank *bank;
void __iomem *regs; void __iomem *regs;
struct platform_device *pdev; struct platform_device *pdev;
struct irq_domain *domain;
bool is_marco = false; bool is_marco = false;
u32 pullups[SIRFSOC_GPIO_NO_OF_BANKS], pulldowns[SIRFSOC_GPIO_NO_OF_BANKS]; u32 pullups[SIRFSOC_GPIO_NO_OF_BANKS], pulldowns[SIRFSOC_GPIO_NO_OF_BANKS];
@ -850,6 +853,14 @@ static int sirfsoc_gpio_probe(struct device_node *np)
if (of_device_is_compatible(np, "sirf,marco-pinctrl")) if (of_device_is_compatible(np, "sirf,marco-pinctrl"))
is_marco = 1; is_marco = 1;
domain = irq_domain_add_linear(np, SIRFSOC_GPIO_BANK_SIZE * SIRFSOC_GPIO_NO_OF_BANKS,
&sirfsoc_gpio_irq_simple_ops, sgpio_bank);
if (!domain) {
pr_err("%s: Failed to create irqdomain\n", np->full_name);
err = -ENOSYS;
goto out;
}
for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) { for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
bank = &sgpio_bank[i]; bank = &sgpio_bank[i];
spin_lock_init(&bank->lock); spin_lock_init(&bank->lock);
@ -882,14 +893,7 @@ static int sirfsoc_gpio_probe(struct device_node *np)
goto out; goto out;
} }
bank->domain = irq_domain_add_linear(np, SIRFSOC_GPIO_BANK_SIZE, bank->domain = domain;
&sirfsoc_gpio_irq_simple_ops, bank);
if (!bank->domain) {
pr_err("%s: Failed to create irqdomain\n", np->full_name);
err = -ENOSYS;
goto out;
}
irq_set_chained_handler(bank->parent_irq, sirfsoc_gpio_handle_irq); irq_set_chained_handler(bank->parent_irq, sirfsoc_gpio_handle_irq);
irq_set_handler_data(bank->parent_irq, bank); irq_set_handler_data(bank->parent_irq, bank);