diff options
author | Linus Walleij <linus.walleij@linaro.org> | 2014-04-29 14:00:40 -0400 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2014-05-22 18:40:04 -0400 |
commit | cdcb0ab63052b0b509013abfb9be1cc9175767f1 (patch) | |
tree | 07f96beb4430f406c9b65accb1cf42000b4ee2bf | |
parent | ba6764d57d9f0b7d0db6b8233f018d10244e36a8 (diff) |
pinctrl: msm: switch to using generic GPIO irqchip helpers
This switches the Qualcomm MSM pin control driver over to using
the generic GPIO irqchip helpers.
Cc: Stephen Boyd <sboyd@codeaurora.org>
Cc: Josh Cartwright <joshc@codeaurora.org>
Acked-by: Bjorn Andersson <bjorn.andersson@sonymobile.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r-- | drivers/pinctrl/Kconfig | 1 | ||||
-rw-r--r-- | drivers/pinctrl/pinctrl-msm.c | 99 |
2 files changed, 28 insertions, 72 deletions
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index f8475ede8632..29a0d8993456 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig | |||
@@ -224,6 +224,7 @@ config PINCTRL_MSM | |||
224 | select PINMUX | 224 | select PINMUX |
225 | select PINCONF | 225 | select PINCONF |
226 | select GENERIC_PINCONF | 226 | select GENERIC_PINCONF |
227 | select GPIOLIB_IRQCHIP | ||
227 | 228 | ||
228 | config PINCTRL_APQ8064 | 229 | config PINCTRL_APQ8064 |
229 | tristate "Qualcomm APQ8064 pin controller driver" | 230 | tristate "Qualcomm APQ8064 pin controller driver" |
diff --git a/drivers/pinctrl/pinctrl-msm.c b/drivers/pinctrl/pinctrl-msm.c index 5fa9341cc589..df6dda4ce803 100644 --- a/drivers/pinctrl/pinctrl-msm.c +++ b/drivers/pinctrl/pinctrl-msm.c | |||
@@ -13,7 +13,6 @@ | |||
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/err.h> | 15 | #include <linux/err.h> |
16 | #include <linux/irqdomain.h> | ||
17 | #include <linux/io.h> | 16 | #include <linux/io.h> |
18 | #include <linux/module.h> | 17 | #include <linux/module.h> |
19 | #include <linux/of.h> | 18 | #include <linux/of.h> |
@@ -26,8 +25,6 @@ | |||
26 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
27 | #include <linux/gpio.h> | 26 | #include <linux/gpio.h> |
28 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
29 | #include <linux/irq.h> | ||
30 | #include <linux/irqchip/chained_irq.h> | ||
31 | #include <linux/spinlock.h> | 28 | #include <linux/spinlock.h> |
32 | 29 | ||
33 | #include "core.h" | 30 | #include "core.h" |
@@ -41,7 +38,6 @@ | |||
41 | * struct msm_pinctrl - state for a pinctrl-msm device | 38 | * struct msm_pinctrl - state for a pinctrl-msm device |
42 | * @dev: device handle. | 39 | * @dev: device handle. |
43 | * @pctrl: pinctrl handle. | 40 | * @pctrl: pinctrl handle. |
44 | * @domain: irqdomain handle. | ||
45 | * @chip: gpiochip handle. | 41 | * @chip: gpiochip handle. |
46 | * @irq: parent irq for the TLMM irq_chip. | 42 | * @irq: parent irq for the TLMM irq_chip. |
47 | * @lock: Spinlock to protect register resources as well | 43 | * @lock: Spinlock to protect register resources as well |
@@ -55,7 +51,6 @@ | |||
55 | struct msm_pinctrl { | 51 | struct msm_pinctrl { |
56 | struct device *dev; | 52 | struct device *dev; |
57 | struct pinctrl_dev *pctrl; | 53 | struct pinctrl_dev *pctrl; |
58 | struct irq_domain *domain; | ||
59 | struct gpio_chip chip; | 54 | struct gpio_chip chip; |
60 | int irq; | 55 | int irq; |
61 | 56 | ||
@@ -68,6 +63,11 @@ struct msm_pinctrl { | |||
68 | void __iomem *regs; | 63 | void __iomem *regs; |
69 | }; | 64 | }; |
70 | 65 | ||
66 | static inline struct msm_pinctrl *to_msm_pinctrl(struct gpio_chip *gc) | ||
67 | { | ||
68 | return container_of(gc, struct msm_pinctrl, chip); | ||
69 | } | ||
70 | |||
71 | static int msm_get_groups_count(struct pinctrl_dev *pctldev) | 71 | static int msm_get_groups_count(struct pinctrl_dev *pctldev) |
72 | { | 72 | { |
73 | struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); | 73 | struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); |
@@ -480,13 +480,6 @@ static void msm_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | |||
480 | spin_unlock_irqrestore(&pctrl->lock, flags); | 480 | spin_unlock_irqrestore(&pctrl->lock, flags); |
481 | } | 481 | } |
482 | 482 | ||
483 | static int msm_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | ||
484 | { | ||
485 | struct msm_pinctrl *pctrl = container_of(chip, struct msm_pinctrl, chip); | ||
486 | |||
487 | return irq_find_mapping(pctrl->domain, offset); | ||
488 | } | ||
489 | |||
490 | static int msm_gpio_request(struct gpio_chip *chip, unsigned offset) | 483 | static int msm_gpio_request(struct gpio_chip *chip, unsigned offset) |
491 | { | 484 | { |
492 | int gpio = chip->base + offset; | 485 | int gpio = chip->base + offset; |
@@ -556,7 +549,6 @@ static struct gpio_chip msm_gpio_template = { | |||
556 | .direction_output = msm_gpio_direction_output, | 549 | .direction_output = msm_gpio_direction_output, |
557 | .get = msm_gpio_get, | 550 | .get = msm_gpio_get, |
558 | .set = msm_gpio_set, | 551 | .set = msm_gpio_set, |
559 | .to_irq = msm_gpio_to_irq, | ||
560 | .request = msm_gpio_request, | 552 | .request = msm_gpio_request, |
561 | .free = msm_gpio_free, | 553 | .free = msm_gpio_free, |
562 | .dbg_show = msm_gpio_dbg_show, | 554 | .dbg_show = msm_gpio_dbg_show, |
@@ -608,12 +600,12 @@ static void msm_gpio_update_dual_edge_pos(struct msm_pinctrl *pctrl, | |||
608 | 600 | ||
609 | static void msm_gpio_irq_mask(struct irq_data *d) | 601 | static void msm_gpio_irq_mask(struct irq_data *d) |
610 | { | 602 | { |
603 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); | ||
604 | struct msm_pinctrl *pctrl = to_msm_pinctrl(gc); | ||
611 | const struct msm_pingroup *g; | 605 | const struct msm_pingroup *g; |
612 | struct msm_pinctrl *pctrl; | ||
613 | unsigned long flags; | 606 | unsigned long flags; |
614 | u32 val; | 607 | u32 val; |
615 | 608 | ||
616 | pctrl = irq_data_get_irq_chip_data(d); | ||
617 | g = &pctrl->soc->groups[d->hwirq]; | 609 | g = &pctrl->soc->groups[d->hwirq]; |
618 | 610 | ||
619 | spin_lock_irqsave(&pctrl->lock, flags); | 611 | spin_lock_irqsave(&pctrl->lock, flags); |
@@ -629,12 +621,12 @@ static void msm_gpio_irq_mask(struct irq_data *d) | |||
629 | 621 | ||
630 | static void msm_gpio_irq_unmask(struct irq_data *d) | 622 | static void msm_gpio_irq_unmask(struct irq_data *d) |
631 | { | 623 | { |
624 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); | ||
625 | struct msm_pinctrl *pctrl = to_msm_pinctrl(gc); | ||
632 | const struct msm_pingroup *g; | 626 | const struct msm_pingroup *g; |
633 | struct msm_pinctrl *pctrl; | ||
634 | unsigned long flags; | 627 | unsigned long flags; |
635 | u32 val; | 628 | u32 val; |
636 | 629 | ||
637 | pctrl = irq_data_get_irq_chip_data(d); | ||
638 | g = &pctrl->soc->groups[d->hwirq]; | 630 | g = &pctrl->soc->groups[d->hwirq]; |
639 | 631 | ||
640 | spin_lock_irqsave(&pctrl->lock, flags); | 632 | spin_lock_irqsave(&pctrl->lock, flags); |
@@ -654,12 +646,12 @@ static void msm_gpio_irq_unmask(struct irq_data *d) | |||
654 | 646 | ||
655 | static void msm_gpio_irq_ack(struct irq_data *d) | 647 | static void msm_gpio_irq_ack(struct irq_data *d) |
656 | { | 648 | { |
649 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); | ||
650 | struct msm_pinctrl *pctrl = to_msm_pinctrl(gc); | ||
657 | const struct msm_pingroup *g; | 651 | const struct msm_pingroup *g; |
658 | struct msm_pinctrl *pctrl; | ||
659 | unsigned long flags; | 652 | unsigned long flags; |
660 | u32 val; | 653 | u32 val; |
661 | 654 | ||
662 | pctrl = irq_data_get_irq_chip_data(d); | ||
663 | g = &pctrl->soc->groups[d->hwirq]; | 655 | g = &pctrl->soc->groups[d->hwirq]; |
664 | 656 | ||
665 | spin_lock_irqsave(&pctrl->lock, flags); | 657 | spin_lock_irqsave(&pctrl->lock, flags); |
@@ -681,12 +673,12 @@ static void msm_gpio_irq_ack(struct irq_data *d) | |||
681 | 673 | ||
682 | static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type) | 674 | static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type) |
683 | { | 675 | { |
676 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); | ||
677 | struct msm_pinctrl *pctrl = to_msm_pinctrl(gc); | ||
684 | const struct msm_pingroup *g; | 678 | const struct msm_pingroup *g; |
685 | struct msm_pinctrl *pctrl; | ||
686 | unsigned long flags; | 679 | unsigned long flags; |
687 | u32 val; | 680 | u32 val; |
688 | 681 | ||
689 | pctrl = irq_data_get_irq_chip_data(d); | ||
690 | g = &pctrl->soc->groups[d->hwirq]; | 682 | g = &pctrl->soc->groups[d->hwirq]; |
691 | 683 | ||
692 | spin_lock_irqsave(&pctrl->lock, flags); | 684 | spin_lock_irqsave(&pctrl->lock, flags); |
@@ -775,11 +767,10 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type) | |||
775 | 767 | ||
776 | static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on) | 768 | static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on) |
777 | { | 769 | { |
778 | struct msm_pinctrl *pctrl; | 770 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
771 | struct msm_pinctrl *pctrl = to_msm_pinctrl(gc); | ||
779 | unsigned long flags; | 772 | unsigned long flags; |
780 | 773 | ||
781 | pctrl = irq_data_get_irq_chip_data(d); | ||
782 | |||
783 | spin_lock_irqsave(&pctrl->lock, flags); | 774 | spin_lock_irqsave(&pctrl->lock, flags); |
784 | 775 | ||
785 | irq_set_irq_wake(pctrl->irq, on); | 776 | irq_set_irq_wake(pctrl->irq, on); |
@@ -789,25 +780,6 @@ static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on) | |||
789 | return 0; | 780 | return 0; |
790 | } | 781 | } |
791 | 782 | ||
792 | static int msm_gpio_irq_reqres(struct irq_data *d) | ||
793 | { | ||
794 | struct msm_pinctrl *pctrl = irq_data_get_irq_chip_data(d); | ||
795 | |||
796 | if (gpio_lock_as_irq(&pctrl->chip, d->hwirq)) { | ||
797 | dev_err(pctrl->dev, "unable to lock HW IRQ %lu for IRQ\n", | ||
798 | d->hwirq); | ||
799 | return -EINVAL; | ||
800 | } | ||
801 | return 0; | ||
802 | } | ||
803 | |||
804 | static void msm_gpio_irq_relres(struct irq_data *d) | ||
805 | { | ||
806 | struct msm_pinctrl *pctrl = irq_data_get_irq_chip_data(d); | ||
807 | |||
808 | gpio_unlock_as_irq(&pctrl->chip, d->hwirq); | ||
809 | } | ||
810 | |||
811 | static struct irq_chip msm_gpio_irq_chip = { | 783 | static struct irq_chip msm_gpio_irq_chip = { |
812 | .name = "msmgpio", | 784 | .name = "msmgpio", |
813 | .irq_mask = msm_gpio_irq_mask, | 785 | .irq_mask = msm_gpio_irq_mask, |
@@ -815,14 +787,13 @@ static struct irq_chip msm_gpio_irq_chip = { | |||
815 | .irq_ack = msm_gpio_irq_ack, | 787 | .irq_ack = msm_gpio_irq_ack, |
816 | .irq_set_type = msm_gpio_irq_set_type, | 788 | .irq_set_type = msm_gpio_irq_set_type, |
817 | .irq_set_wake = msm_gpio_irq_set_wake, | 789 | .irq_set_wake = msm_gpio_irq_set_wake, |
818 | .irq_request_resources = msm_gpio_irq_reqres, | ||
819 | .irq_release_resources = msm_gpio_irq_relres, | ||
820 | }; | 790 | }; |
821 | 791 | ||
822 | static void msm_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) | 792 | static void msm_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) |
823 | { | 793 | { |
794 | struct gpio_chip *gc = irq_desc_get_handler_data(desc); | ||
824 | const struct msm_pingroup *g; | 795 | const struct msm_pingroup *g; |
825 | struct msm_pinctrl *pctrl = irq_desc_get_handler_data(desc); | 796 | struct msm_pinctrl *pctrl = to_msm_pinctrl(gc); |
826 | struct irq_chip *chip = irq_get_chip(irq); | 797 | struct irq_chip *chip = irq_get_chip(irq); |
827 | int irq_pin; | 798 | int irq_pin; |
828 | int handled = 0; | 799 | int handled = 0; |
@@ -839,7 +810,7 @@ static void msm_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) | |||
839 | g = &pctrl->soc->groups[i]; | 810 | g = &pctrl->soc->groups[i]; |
840 | val = readl(pctrl->regs + g->intr_status_reg); | 811 | val = readl(pctrl->regs + g->intr_status_reg); |
841 | if (val & BIT(g->intr_status_bit)) { | 812 | if (val & BIT(g->intr_status_bit)) { |
842 | irq_pin = irq_find_mapping(pctrl->domain, i); | 813 | irq_pin = irq_find_mapping(gc->irqdomain, i); |
843 | generic_handle_irq(irq_pin); | 814 | generic_handle_irq(irq_pin); |
844 | handled++; | 815 | handled++; |
845 | } | 816 | } |
@@ -852,19 +823,10 @@ static void msm_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) | |||
852 | chained_irq_exit(chip, desc); | 823 | chained_irq_exit(chip, desc); |
853 | } | 824 | } |
854 | 825 | ||
855 | /* | ||
856 | * This lock class tells lockdep that GPIO irqs are in a different | ||
857 | * category than their parents, so it won't report false recursion. | ||
858 | */ | ||
859 | static struct lock_class_key gpio_lock_class; | ||
860 | |||
861 | static int msm_gpio_init(struct msm_pinctrl *pctrl) | 826 | static int msm_gpio_init(struct msm_pinctrl *pctrl) |
862 | { | 827 | { |
863 | struct gpio_chip *chip; | 828 | struct gpio_chip *chip; |
864 | int irq; | ||
865 | int ret; | 829 | int ret; |
866 | int i; | ||
867 | int r; | ||
868 | unsigned ngpio = pctrl->soc->ngpios; | 830 | unsigned ngpio = pctrl->soc->ngpios; |
869 | 831 | ||
870 | if (WARN_ON(ngpio > MAX_NR_GPIO)) | 832 | if (WARN_ON(ngpio > MAX_NR_GPIO)) |
@@ -890,23 +852,18 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl) | |||
890 | return ret; | 852 | return ret; |
891 | } | 853 | } |
892 | 854 | ||
893 | pctrl->domain = irq_domain_add_linear(pctrl->dev->of_node, chip->ngpio, | 855 | ret = gpiochip_irqchip_add(chip, |
894 | &irq_domain_simple_ops, NULL); | 856 | &msm_gpio_irq_chip, |
895 | if (!pctrl->domain) { | 857 | 0, |
896 | dev_err(pctrl->dev, "Failed to register irq domain\n"); | 858 | handle_edge_irq, |
897 | r = gpiochip_remove(&pctrl->chip); | 859 | IRQ_TYPE_NONE); |
860 | if (ret) { | ||
861 | dev_err(pctrl->dev, "Failed to add irqchip to gpiochip\n"); | ||
898 | return -ENOSYS; | 862 | return -ENOSYS; |
899 | } | 863 | } |
900 | 864 | ||
901 | for (i = 0; i < chip->ngpio; i++) { | 865 | gpiochip_set_chained_irqchip(chip, &msm_gpio_irq_chip, pctrl->irq, |
902 | irq = irq_create_mapping(pctrl->domain, i); | 866 | msm_gpio_irq_handler); |
903 | irq_set_lockdep_class(irq, &gpio_lock_class); | ||
904 | irq_set_chip_and_handler(irq, &msm_gpio_irq_chip, handle_edge_irq); | ||
905 | irq_set_chip_data(irq, pctrl); | ||
906 | } | ||
907 | |||
908 | irq_set_handler_data(pctrl->irq, pctrl); | ||
909 | irq_set_chained_handler(pctrl->irq, msm_gpio_irq_handler); | ||
910 | 867 | ||
911 | return 0; | 868 | return 0; |
912 | } | 869 | } |
@@ -974,8 +931,6 @@ int msm_pinctrl_remove(struct platform_device *pdev) | |||
974 | return ret; | 931 | return ret; |
975 | } | 932 | } |
976 | 933 | ||
977 | irq_set_chained_handler(pctrl->irq, NULL); | ||
978 | irq_domain_remove(pctrl->domain); | ||
979 | pinctrl_unregister(pctrl->pctrl); | 934 | pinctrl_unregister(pctrl->pctrl); |
980 | 935 | ||
981 | return 0; | 936 | return 0; |