aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl
diff options
context:
space:
mode:
authorBarry Song <Baohua.Song@csr.com>2014-01-11 03:48:42 -0500
committerLinus Walleij <linus.walleij@linaro.org>2014-01-15 03:07:56 -0500
commit8daeffb058f78deb0b0ef2cb67ef741c38788bf9 (patch)
treed7725a9eb7d4d6127beccd1ff85e92614a74ec64 /drivers/pinctrl
parentad5d25fef8f9459a9f67ec5fbae94287fdea3247 (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.c26
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
474static inline int sirfsoc_gpio_to_offset(unsigned int gpio) 475static 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);