Skip to content

Commit e35a6ae

Browse files
Lina IyerMarc Zyngier
authored andcommitted
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 <[email protected]> Signed-off-by: Lina Iyer <[email protected]> Signed-off-by: Marc Zyngier <[email protected]> Reviewed-by: Stephen Boyd <[email protected]> Link: https://lore.kernel.org/r/[email protected] ---- 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
1 parent e71374c commit e35a6ae

File tree

3 files changed

+137
-2
lines changed

3 files changed

+137
-2
lines changed

drivers/pinctrl/qcom/pinctrl-msm.c

Lines changed: 110 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
#include <linux/pm.h>
2424
#include <linux/log2.h>
2525

26+
#include <linux/soc/qcom/irq.h>
27+
2628
#include "../core.h"
2729
#include "../pinconf.h"
2830
#include "pinctrl-msm.h"
@@ -44,6 +46,7 @@
4446
* @enabled_irqs: Bitmap of currently enabled irqs.
4547
* @dual_edge_irqs: Bitmap of irqs that need sw emulated dual edge
4648
* detection.
49+
* @skip_wake_irqs: Skip IRQs that are handled by wakeup interrupt controller
4750
* @soc; Reference to soc_data of platform specific data.
4851
* @regs: Base addresses for the TLMM tiles.
4952
*/
@@ -61,6 +64,7 @@ struct msm_pinctrl {
6164

6265
DECLARE_BITMAP(dual_edge_irqs, MAX_NR_GPIO);
6366
DECLARE_BITMAP(enabled_irqs, MAX_NR_GPIO);
67+
DECLARE_BITMAP(skip_wake_irqs, MAX_NR_GPIO);
6468

6569
const struct msm_pinctrl_soc_data *soc;
6670
void __iomem *regs[MAX_NR_TILES];
@@ -707,6 +711,12 @@ static void msm_gpio_irq_mask(struct irq_data *d)
707711
unsigned long flags;
708712
u32 val;
709713

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+
710720
g = &pctrl->soc->groups[d->hwirq];
711721

712722
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)
751761
unsigned long flags;
752762
u32 val;
753763

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+
754770
g = &pctrl->soc->groups[d->hwirq];
755771

756772
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)
778794

779795
static void msm_gpio_irq_enable(struct irq_data *d)
780796
{
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+
}
781810

782811
msm_gpio_irq_clear_unmask(d, true);
783812
}
784813

814+
static 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+
785826
static void msm_gpio_irq_unmask(struct irq_data *d)
786827
{
787828
msm_gpio_irq_clear_unmask(d, false);
@@ -795,6 +836,9 @@ static void msm_gpio_irq_ack(struct irq_data *d)
795836
unsigned long flags;
796837
u32 val;
797838

839+
if (test_bit(d->hwirq, pctrl->skip_wake_irqs))
840+
return;
841+
798842
g = &pctrl->soc->groups[d->hwirq];
799843

800844
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)
820864
unsigned long flags;
821865
u32 val;
822866

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+
823873
g = &pctrl->soc->groups[d->hwirq];
824874

825875
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)
912962
struct msm_pinctrl *pctrl = gpiochip_get_data(gc);
913963
unsigned long flags;
914964

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+
915974
raw_spin_lock_irqsave(&pctrl->lock, flags);
916975

917976
irq_set_irq_wake(pctrl->irq, on);
@@ -990,6 +1049,30 @@ static void msm_gpio_irq_handler(struct irq_desc *desc)
9901049
chained_irq_exit(chip, desc);
9911050
}
9921051

1052+
static 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+
9931076
static bool msm_gpio_needs_valid_mask(struct msm_pinctrl *pctrl)
9941077
{
9951078
if (pctrl->soc->reserved_gpios)
@@ -1002,8 +1085,10 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl)
10021085
{
10031086
struct gpio_chip *chip;
10041087
struct gpio_irq_chip *girq;
1005-
int ret;
1006-
unsigned ngpio = pctrl->soc->ngpios;
1088+
int i, ret;
1089+
unsigned gpio, ngpio = pctrl->soc->ngpios;
1090+
struct device_node *np;
1091+
bool skip;
10071092

10081093
if (WARN_ON(ngpio > MAX_NR_GPIO))
10091094
return -EINVAL;
@@ -1020,17 +1105,40 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl)
10201105

10211106
pctrl->irq_chip.name = "msmgpio";
10221107
pctrl->irq_chip.irq_enable = msm_gpio_irq_enable;
1108+
pctrl->irq_chip.irq_disable = msm_gpio_irq_disable;
10231109
pctrl->irq_chip.irq_mask = msm_gpio_irq_mask;
10241110
pctrl->irq_chip.irq_unmask = msm_gpio_irq_unmask;
10251111
pctrl->irq_chip.irq_ack = msm_gpio_irq_ack;
1112+
pctrl->irq_chip.irq_eoi = irq_chip_eoi_parent;
10261113
pctrl->irq_chip.irq_set_type = msm_gpio_irq_set_type;
10271114
pctrl->irq_chip.irq_set_wake = msm_gpio_irq_set_wake;
10281115
pctrl->irq_chip.irq_request_resources = msm_gpio_irq_reqres;
10291116
pctrl->irq_chip.irq_release_resources = msm_gpio_irq_relres;
10301117

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+
10311138
girq = &chip->irq;
10321139
girq->chip = &pctrl->irq_chip;
10331140
girq->parent_handler = msm_gpio_irq_handler;
1141+
girq->fwnode = pctrl->dev->fwnode;
10341142
girq->num_parents = 1;
10351143
girq->parents = devm_kcalloc(pctrl->dev, 1, sizeof(*girq->parents),
10361144
GFP_KERNEL);

drivers/pinctrl/qcom/pinctrl-msm.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,16 @@ struct msm_pingroup {
9191
unsigned intr_detection_width:5;
9292
};
9393

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+
*/
99+
struct msm_gpio_wakeirq_map {
100+
unsigned int gpio;
101+
unsigned int wakeirq;
102+
};
103+
94104
/**
95105
* struct msm_pinctrl_soc_data - Qualcomm pin controller driver configuration
96106
* @pins: An array describing all pins the pin controller affects.
@@ -101,6 +111,8 @@ struct msm_pingroup {
101111
* @ngroups: The numbmer of entries in @groups.
102112
* @ngpio: The number of pingroups the driver should expose as GPIOs.
103113
* @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
104116
*/
105117
struct msm_pinctrl_soc_data {
106118
const struct pinctrl_pin_desc *pins;
@@ -114,6 +126,8 @@ struct msm_pinctrl_soc_data {
114126
const char *const *tiles;
115127
unsigned int ntiles;
116128
const int *reserved_gpios;
129+
const struct msm_gpio_wakeirq_map *wakeirq_map;
130+
unsigned int nwakeirq_map;
117131
};
118132

119133
extern const struct dev_pm_ops msm_pinctrl_dev_pm_ops;

include/linux/soc/qcom/irq.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,17 @@
1818
#define IRQ_DOMAIN_FLAG_QCOM_PDC_WAKEUP (IRQ_DOMAIN_FLAG_NONCORE << 0)
1919
#define IRQ_DOMAIN_FLAG_QCOM_MPM_WAKEUP (IRQ_DOMAIN_FLAG_NONCORE << 1)
2020

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+
*/
29+
static 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+
2134
#endif

0 commit comments

Comments
 (0)