diff options
author | Barry Song <Baohua.Song@csr.com> | 2014-01-11 03:48:42 -0500 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2014-01-15 03:07:56 -0500 |
commit | 8daeffb058f78deb0b0ef2cb67ef741c38788bf9 (patch) | |
tree | d7725a9eb7d4d6127beccd1ff85e92614a74ec64 /drivers/pinctrl | |
parent | ad5d25fef8f9459a9f67ec5fbae94287fdea3247 (diff) |
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>
Diffstat (limited to 'drivers/pinctrl')
-rw-r--r-- | drivers/pinctrl/sirf/pinctrl-sirf.c | 26 |
1 files changed, 15 insertions, 11 deletions
diff --git a/drivers/pinctrl/sirf/pinctrl-sirf.c b/drivers/pinctrl/sirf/pinctrl-sirf.c index b81e388c50de..53a3bc5ac2dd 100644 --- a/drivers/pinctrl/sirf/pinctrl-sirf.c +++ b/drivers/pinctrl/sirf/pinctrl-sirf.c | |||
@@ -468,7 +468,8 @@ static inline int sirfsoc_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | |||
468 | struct sirfsoc_gpio_bank *bank = container_of(to_of_mm_gpio_chip(chip), | 468 | struct sirfsoc_gpio_bank *bank = container_of(to_of_mm_gpio_chip(chip), |
469 | struct sirfsoc_gpio_bank, chip); | 469 | struct sirfsoc_gpio_bank, chip); |
470 | 470 | ||
471 | return irq_create_mapping(bank->domain, offset); | 471 | return irq_create_mapping(bank->domain, offset + bank->id * |
472 | SIRFSOC_GPIO_BANK_SIZE); | ||
472 | } | 473 | } |
473 | 474 | ||
474 | static inline int sirfsoc_gpio_to_offset(unsigned int gpio) | 475 | 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) | |||
629 | if ((status & 0x1) && (ctrl & SIRFSOC_GPIO_CTL_INTR_EN_MASK)) { | 630 | if ((status & 0x1) && (ctrl & SIRFSOC_GPIO_CTL_INTR_EN_MASK)) { |
630 | pr_debug("%s: gpio id %d idx %d happens\n", | 631 | pr_debug("%s: gpio id %d idx %d happens\n", |
631 | __func__, bank->id, idx); | 632 | __func__, bank->id, idx); |
632 | generic_handle_irq(irq_find_mapping(bank->domain, idx)); | 633 | generic_handle_irq(irq_find_mapping(bank->domain, idx + |
634 | bank->id * SIRFSOC_GPIO_BANK_SIZE)); | ||
633 | } | 635 | } |
634 | 636 | ||
635 | idx++; | 637 | idx++; |
@@ -786,7 +788,7 @@ static int sirfsoc_gpio_irq_map(struct irq_domain *d, unsigned int irq, | |||
786 | 788 | ||
787 | irq_set_chip(irq, &sirfsoc_irq_chip); | 789 | irq_set_chip(irq, &sirfsoc_irq_chip); |
788 | irq_set_handler(irq, handle_level_irq); | 790 | irq_set_handler(irq, handle_level_irq); |
789 | irq_set_chip_data(irq, bank); | 791 | irq_set_chip_data(irq, bank + hwirq / SIRFSOC_GPIO_BANK_SIZE); |
790 | set_irq_flags(irq, IRQF_VALID); | 792 | set_irq_flags(irq, IRQF_VALID); |
791 | 793 | ||
792 | return 0; | 794 | return 0; |
@@ -835,6 +837,7 @@ static int sirfsoc_gpio_probe(struct device_node *np) | |||
835 | struct sirfsoc_gpio_bank *bank; | 837 | struct sirfsoc_gpio_bank *bank; |
836 | void __iomem *regs; | 838 | void __iomem *regs; |
837 | struct platform_device *pdev; | 839 | struct platform_device *pdev; |
840 | struct irq_domain *domain; | ||
838 | bool is_marco = false; | 841 | bool is_marco = false; |
839 | 842 | ||
840 | u32 pullups[SIRFSOC_GPIO_NO_OF_BANKS], pulldowns[SIRFSOC_GPIO_NO_OF_BANKS]; | 843 | 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) | |||
850 | if (of_device_is_compatible(np, "sirf,marco-pinctrl")) | 853 | if (of_device_is_compatible(np, "sirf,marco-pinctrl")) |
851 | is_marco = 1; | 854 | is_marco = 1; |
852 | 855 | ||
856 | domain = irq_domain_add_linear(np, SIRFSOC_GPIO_BANK_SIZE * SIRFSOC_GPIO_NO_OF_BANKS, | ||
857 | &sirfsoc_gpio_irq_simple_ops, sgpio_bank); | ||
858 | if (!domain) { | ||
859 | pr_err("%s: Failed to create irqdomain\n", np->full_name); | ||
860 | err = -ENOSYS; | ||
861 | goto out; | ||
862 | } | ||
863 | |||
853 | for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) { | 864 | for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) { |
854 | bank = &sgpio_bank[i]; | 865 | bank = &sgpio_bank[i]; |
855 | spin_lock_init(&bank->lock); | 866 | spin_lock_init(&bank->lock); |
@@ -882,14 +893,7 @@ static int sirfsoc_gpio_probe(struct device_node *np) | |||
882 | goto out; | 893 | goto out; |
883 | } | 894 | } |
884 | 895 | ||
885 | bank->domain = irq_domain_add_linear(np, SIRFSOC_GPIO_BANK_SIZE, | 896 | bank->domain = domain; |
886 | &sirfsoc_gpio_irq_simple_ops, bank); | ||
887 | |||
888 | if (!bank->domain) { | ||
889 | pr_err("%s: Failed to create irqdomain\n", np->full_name); | ||
890 | err = -ENOSYS; | ||
891 | goto out; | ||
892 | } | ||
893 | 897 | ||
894 | irq_set_chained_handler(bank->parent_irq, sirfsoc_gpio_handle_irq); | 898 | irq_set_chained_handler(bank->parent_irq, sirfsoc_gpio_handle_irq); |
895 | irq_set_handler_data(bank->parent_irq, bank); | 899 | irq_set_handler_data(bank->parent_irq, bank); |