mirror of https://gitee.com/openkylin/linux.git
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:
parent
ad5d25fef8
commit
8daeffb058
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue