History

pinctrl/msm: Setup GPIO chip in hierarchy

Some GPIOs are marked as wakeup capable and are routed to another interrupt controller that is an always-domain and can detect interrupts even when most of the SoC is powered off. The wakeup interrupt controller wakes up the GIC and replays the interrupt at the GIC. Setup the TLMM irqchip in hierarchy with the wakeup interrupt controller and ensure the wakeup GPIOs are handled correctly. Co-developed-by: Maulik Shah <mkshah@codeaurora.org> Signed-off-by: Lina Iyer <ilina@codeaurora.org> Signed-off-by: Marc Zyngier <maz@kernel.org> Reviewed-by: Stephen Boyd <swboyd@chromium.org> Link: https://lore.kernel.org/r/1573855915-9841-9-git-send-email-ilina@codeaurora.org ---- Changes in v2: - Address review comments - Fix Co-developed-by tag Changes in v1: - Address minor review comments - Remove redundant call to set irq handler - Move irq_domain_qcom_handle_wakeup() to this patch Changes in RFC v2: - Rebase on top of GPIO hierarchy support in linux-next - Set the chained irq handler for summary line

Lina Iyer committed 7 years ago

Commit e35a6ae1 parent e71374c3 files · +137 −2Browse files

Unified · Split

3 files
  1. drivers/pinctrl/qcom/pinctrl-msm.c +110 −2
  2. drivers/pinctrl/qcom/pinctrl-msm.h +14 −0
  3. include/linux/soc/qcom/irq.h +13 −0
drivers/pinctrl/qcom/pinctrl-msm.c+110−2
@@ -23,6 +23,8 @@ · 22 unmodified lines
23#include <linux/pm.h>23#include <linux/pm.h>
24#include <linux/log2.h>24#include <linux/log2.h>
25 25
26#include <linux/soc/qcom/irq.h>
27
26#include "../core.h"28#include "../core.h"
27#include "../pinconf.h"29#include "../pinconf.h"
28#include "pinctrl-msm.h"30#include "pinctrl-msm.h"
@@ -44,6 +46,7 @@ · 15 unmodified lines
44 * @enabled_irqs: Bitmap of currently enabled irqs.46 * @enabled_irqs: Bitmap of currently enabled irqs.
45 * @dual_edge_irqs: Bitmap of irqs that need sw emulated dual edge47 * @dual_edge_irqs: Bitmap of irqs that need sw emulated dual edge
46 * detection.48 * detection.
49 * @skip_wake_irqs: Skip IRQs that are handled by wakeup interrupt controller
47 * @soc; Reference to soc_data of platform specific data.50 * @soc; Reference to soc_data of platform specific data.
48 * @regs: Base addresses for the TLMM tiles.51 * @regs: Base addresses for the TLMM tiles.
49 */52 */
@@ -61,6 +64,7 @@ struct msm_pinctrl { · 11 unmodified lines
61 64
62 DECLARE_BITMAP(dual_edge_irqs, MAX_NR_GPIO);65 DECLARE_BITMAP(dual_edge_irqs, MAX_NR_GPIO);
63 DECLARE_BITMAP(enabled_irqs, MAX_NR_GPIO);66 DECLARE_BITMAP(enabled_irqs, MAX_NR_GPIO);
67 DECLARE_BITMAP(skip_wake_irqs, MAX_NR_GPIO);
64 68
65 const struct msm_pinctrl_soc_data *soc;69 const struct msm_pinctrl_soc_data *soc;
66 void __iomem *regs[MAX_NR_TILES];70 void __iomem *regs[MAX_NR_TILES];
@@ -707,6 +711,12 @@ static void msm_gpio_irq_mask(struct irq_data *d) · 640 unmodified lines
707 unsigned long flags;711 unsigned long flags;
708 u32 val;712 u32 val;
709 713
714 if (d->parent_data)
715 irq_chip_mask_parent(d);
716
717 if (test_bit(d->hwirq, pctrl->skip_wake_irqs))
718 return;
719
710 g = &pctrl->soc->groups[d->hwirq];720 g = &pctrl->soc->groups[d->hwirq];
711 721
712 raw_spin_lock_irqsave(&pctrl->lock, flags);722 raw_spin_lock_irqsave(&pctrl->lock, flags);
@@ -751,6 +761,12 @@ static void msm_gpio_irq_clear_unmask(struct irq_data *d, bool status_clear) · 38 unmodified lines
751 unsigned long flags;761 unsigned long flags;
752 u32 val;762 u32 val;
753 763
764 if (d->parent_data)
765 irq_chip_unmask_parent(d);
766
767 if (test_bit(d->hwirq, pctrl->skip_wake_irqs))
768 return;
769
754 g = &pctrl->soc->groups[d->hwirq];770 g = &pctrl->soc->groups[d->hwirq];
755 771
756 raw_spin_lock_irqsave(&pctrl->lock, flags);772 raw_spin_lock_irqsave(&pctrl->lock, flags);
@@ -778,10 +794,35 @@ static void msm_gpio_irq_clear_unmask(struct irq_data *d, bool status_clear) · 21 unmodified lines
778 794
779static void msm_gpio_irq_enable(struct irq_data *d)795static void msm_gpio_irq_enable(struct irq_data *d)
780{796{
797 /*
798 * Clear the interrupt that may be pending before we enable
799 * the line.
800 * This is especially a problem with the GPIOs routed to the
801 * PDC. These GPIOs are direct-connect interrupts to the GIC.
802 * Disabling the interrupt line at the PDC does not prevent
803 * the interrupt from being latched at the GIC. The state at
804 * GIC needs to be cleared before enabling.
805 */
806 if (d->parent_data) {
807 irq_chip_set_parent_state(d, IRQCHIP_STATE_PENDING, 0);
808 irq_chip_enable_parent(d);
809 }
781 810
782 msm_gpio_irq_clear_unmask(d, true);811 msm_gpio_irq_clear_unmask(d, true);
783}812}
784 813
814static void msm_gpio_irq_disable(struct irq_data *d)
815{
816 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
817 struct msm_pinctrl *pctrl = gpiochip_get_data(gc);
818
819 if (d->parent_data)
820 irq_chip_disable_parent(d);
821
822 if (!test_bit(d->hwirq, pctrl->skip_wake_irqs))
823 msm_gpio_irq_mask(d);
824}
825
785static void msm_gpio_irq_unmask(struct irq_data *d)826static void msm_gpio_irq_unmask(struct irq_data *d)
786{827{
787 msm_gpio_irq_clear_unmask(d, false);828 msm_gpio_irq_clear_unmask(d, false);
@@ -795,6 +836,9 @@ static void msm_gpio_irq_ack(struct irq_data *d) · 7 unmodified lines
795 unsigned long flags;836 unsigned long flags;
796 u32 val;837 u32 val;
797 838
839 if (test_bit(d->hwirq, pctrl->skip_wake_irqs))
840 return;
841
798 g = &pctrl->soc->groups[d->hwirq];842 g = &pctrl->soc->groups[d->hwirq];
799 843
800 raw_spin_lock_irqsave(&pctrl->lock, flags);844 raw_spin_lock_irqsave(&pctrl->lock, flags);
@@ -820,6 +864,12 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type) · 19 unmodified lines
820 unsigned long flags;864 unsigned long flags;
821 u32 val;865 u32 val;
822 866
867 if (d->parent_data)
868 irq_chip_set_type_parent(d, type);
869
870 if (test_bit(d->hwirq, pctrl->skip_wake_irqs))
871 return 0;
872
823 g = &pctrl->soc->groups[d->hwirq];873 g = &pctrl->soc->groups[d->hwirq];
824 874
825 raw_spin_lock_irqsave(&pctrl->lock, flags);875 raw_spin_lock_irqsave(&pctrl->lock, flags);
@@ -912,6 +962,15 @@ static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on) · 86 unmodified lines
912 struct msm_pinctrl *pctrl = gpiochip_get_data(gc);962 struct msm_pinctrl *pctrl = gpiochip_get_data(gc);
913 unsigned long flags;963 unsigned long flags;
914 964
965 /*
966 * While they may not wake up when the TLMM is powered off,
967 * some GPIOs would like to wakeup the system from suspend
968 * when TLMM is powered on. To allow that, enable the GPIO
969 * summary line to be wakeup capable at GIC.
970 */
971 if (d->parent_data)
972 irq_chip_set_wake_parent(d, on);
973
915 raw_spin_lock_irqsave(&pctrl->lock, flags);974 raw_spin_lock_irqsave(&pctrl->lock, flags);
916 975
917 irq_set_irq_wake(pctrl->irq, on);976 irq_set_irq_wake(pctrl->irq, on);
@@ -990,6 +1049,30 @@ static void msm_gpio_irq_handler(struct irq_desc *desc) · 72 unmodified lines
990 chained_irq_exit(chip, desc);1049 chained_irq_exit(chip, desc);
991}1050}
992 1051
1052static int msm_gpio_wakeirq(struct gpio_chip *gc,
1053 unsigned int child,
1054 unsigned int child_type,
1055 unsigned int *parent,
1056 unsigned int *parent_type)
1057{
1058 struct msm_pinctrl *pctrl = gpiochip_get_data(gc);
1059 const struct msm_gpio_wakeirq_map *map;
1060 int i;
1061
1062 *parent = GPIO_NO_WAKE_IRQ;
1063 *parent_type = IRQ_TYPE_EDGE_RISING;
1064
1065 for (i = 0; i < pctrl->soc->nwakeirq_map; i++) {
1066 map = &pctrl->soc->wakeirq_map[i];
1067 if (map->gpio == child) {
1068 *parent = map->wakeirq;
1069 break;
1070 }
1071 }
1072
1073 return 0;
1074}
1075
993static bool msm_gpio_needs_valid_mask(struct msm_pinctrl *pctrl)1076static bool msm_gpio_needs_valid_mask(struct msm_pinctrl *pctrl)
994{1077{
995 if (pctrl->soc->reserved_gpios)1078 if (pctrl->soc->reserved_gpios)
@@ -1002,8 +1085,10 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl) · 6 unmodified lines
1002{1085{
1003 struct gpio_chip *chip;1086 struct gpio_chip *chip;
1004 struct gpio_irq_chip *girq;1087 struct gpio_irq_chip *girq;
1005 int ret;1088 int i, ret;
1006 unsigned ngpio = pctrl->soc->ngpios;1089 unsigned gpio, ngpio = pctrl->soc->ngpios;
1090 struct device_node *np;
1091 bool skip;
1007 1092
1008 if (WARN_ON(ngpio > MAX_NR_GPIO))1093 if (WARN_ON(ngpio > MAX_NR_GPIO))
1009 return -EINVAL;1094 return -EINVAL;
@@ -1020,17 +1105,40 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl) · 10 unmodified lines
1020 1105
1021 pctrl->irq_chip.name = "msmgpio";1106 pctrl->irq_chip.name = "msmgpio";
1022 pctrl->irq_chip.irq_enable = msm_gpio_irq_enable;1107 pctrl->irq_chip.irq_enable = msm_gpio_irq_enable;
1108 pctrl->irq_chip.irq_disable = msm_gpio_irq_disable;
1023 pctrl->irq_chip.irq_mask = msm_gpio_irq_mask;1109 pctrl->irq_chip.irq_mask = msm_gpio_irq_mask;
1024 pctrl->irq_chip.irq_unmask = msm_gpio_irq_unmask;1110 pctrl->irq_chip.irq_unmask = msm_gpio_irq_unmask;
1025 pctrl->irq_chip.irq_ack = msm_gpio_irq_ack;1111 pctrl->irq_chip.irq_ack = msm_gpio_irq_ack;
1112 pctrl->irq_chip.irq_eoi = irq_chip_eoi_parent;
1026 pctrl->irq_chip.irq_set_type = msm_gpio_irq_set_type;1113 pctrl->irq_chip.irq_set_type = msm_gpio_irq_set_type;
1027 pctrl->irq_chip.irq_set_wake = msm_gpio_irq_set_wake;1114 pctrl->irq_chip.irq_set_wake = msm_gpio_irq_set_wake;
1028 pctrl->irq_chip.irq_request_resources = msm_gpio_irq_reqres;1115 pctrl->irq_chip.irq_request_resources = msm_gpio_irq_reqres;
1029 pctrl->irq_chip.irq_release_resources = msm_gpio_irq_relres;1116 pctrl->irq_chip.irq_release_resources = msm_gpio_irq_relres;
1030 1117
1118 np = of_parse_phandle(pctrl->dev->of_node, "wakeup-parent", 0);
1119 if (np) {
1120 chip->irq.parent_domain = irq_find_matching_host(np,
1121 DOMAIN_BUS_WAKEUP);
1122 of_node_put(np);
1123 if (!chip->irq.parent_domain)
1124 return -EPROBE_DEFER;
1125 chip->irq.child_to_parent_hwirq = msm_gpio_wakeirq;
1126
1127 /*
1128 * Let's skip handling the GPIOs, if the parent irqchip
1129 * is handling the direct connect IRQ of the GPIO.
1130 */
1131 skip = irq_domain_qcom_handle_wakeup(chip->irq.parent_domain);
1132 for (i = 0; skip && i < pctrl->soc->nwakeirq_map; i++) {
1133 gpio = pctrl->soc->wakeirq_map[i].gpio;
1134 set_bit(gpio, pctrl->skip_wake_irqs);
1135 }
1136 }
1137
1031 girq = &chip->irq;1138 girq = &chip->irq;
1032 girq->chip = &pctrl->irq_chip;1139 girq->chip = &pctrl->irq_chip;
1033 girq->parent_handler = msm_gpio_irq_handler;1140 girq->parent_handler = msm_gpio_irq_handler;
1141 girq->fwnode = pctrl->dev->fwnode;
1034 girq->num_parents = 1;1142 girq->num_parents = 1;
1035 girq->parents = devm_kcalloc(pctrl->dev, 1, sizeof(*girq->parents),1143 girq->parents = devm_kcalloc(pctrl->dev, 1, sizeof(*girq->parents),
1036 GFP_KERNEL);1144 GFP_KERNEL);
drivers/pinctrl/qcom/pinctrl-msm.h+14−0
@@ -91,6 +91,16 @@ struct msm_pingroup { · 90 unmodified lines
91 unsigned intr_detection_width:5;91 unsigned intr_detection_width:5;
92};92};
93 93
94/**
95 * struct msm_gpio_wakeirq_map - Map of GPIOs and their wakeup pins
96 * @gpio: The GPIOs that are wakeup capable
97 * @wakeirq: The interrupt at the always-on interrupt controller
98 */
99struct msm_gpio_wakeirq_map {
100 unsigned int gpio;
101 unsigned int wakeirq;
102};
103
94/**104/**
95 * struct msm_pinctrl_soc_data - Qualcomm pin controller driver configuration105 * struct msm_pinctrl_soc_data - Qualcomm pin controller driver configuration
96 * @pins: An array describing all pins the pin controller affects.106 * @pins: An array describing all pins the pin controller affects.
@@ -101,6 +111,8 @@ struct msm_pingroup { · 4 unmodified lines
101 * @ngroups: The numbmer of entries in @groups.111 * @ngroups: The numbmer of entries in @groups.
102 * @ngpio: The number of pingroups the driver should expose as GPIOs.112 * @ngpio: The number of pingroups the driver should expose as GPIOs.
103 * @pull_no_keeper: The SoC does not support keeper bias.113 * @pull_no_keeper: The SoC does not support keeper bias.
114 * @wakeirq_map: The map of wakeup capable GPIOs and the pin at PDC/MPM
115 * @nwakeirq_map: The number of entries in @wakeirq_map
104 */116 */
105struct msm_pinctrl_soc_data {117struct msm_pinctrl_soc_data {
106 const struct pinctrl_pin_desc *pins;118 const struct pinctrl_pin_desc *pins;
@@ -114,6 +126,8 @@ struct msm_pinctrl_soc_data { · 7 unmodified lines
114 const char *const *tiles;126 const char *const *tiles;
115 unsigned int ntiles;127 unsigned int ntiles;
116 const int *reserved_gpios;128 const int *reserved_gpios;
129 const struct msm_gpio_wakeirq_map *wakeirq_map;
130 unsigned int nwakeirq_map;
117};131};
118 132
119extern const struct dev_pm_ops msm_pinctrl_dev_pm_ops;133extern const struct dev_pm_ops msm_pinctrl_dev_pm_ops;
include/linux/soc/qcom/irq.h+13−0
@@ -18,4 +18,17 @@ · 17 unmodified lines
18#define IRQ_DOMAIN_FLAG_QCOM_PDC_WAKEUP (IRQ_DOMAIN_FLAG_NONCORE << 0)18#define IRQ_DOMAIN_FLAG_QCOM_PDC_WAKEUP (IRQ_DOMAIN_FLAG_NONCORE << 0)
19#define IRQ_DOMAIN_FLAG_QCOM_MPM_WAKEUP (IRQ_DOMAIN_FLAG_NONCORE << 1)19#define IRQ_DOMAIN_FLAG_QCOM_MPM_WAKEUP (IRQ_DOMAIN_FLAG_NONCORE << 1)
20 20
21/**
22 * irq_domain_qcom_handle_wakeup: Return if the domain handles interrupt
23 * configuration
24 * @d: irq domain
25 *
26 * This QCOM specific irq domain call returns if the interrupt controller
27 * requires the interrupt be masked at the child interrupt controller.
28 */
29static inline bool irq_domain_qcom_handle_wakeup(const struct irq_domain *d)
30{
31 return (d->flags & IRQ_DOMAIN_FLAG_QCOM_PDC_WAKEUP);
32}
33
21#endif34#endif

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t