Hi,
This is an attempt at a solution to enable wake up from suspend and deep idle
using GPIO as a wakeup source. The 845 uses a new interrupt controller (PDC)
that lies in the always-on domain and can sense interrupts that are routed to
it, when the GIC is powered off. It would then wakeup the GIC and replay the
interrupt which would then be relayed to the AP. The PDC interrupt controller
driver is merged upstream [1],[2]. The following set of patches extends the
wakeup capability to GPIOs using the PDC. The TLMM pinctrl driver for the SoC
available at [3].
The complexity with the solution stems from the fact that only a selected few
GPIO lines are routed to the PDC in addition the TLMMs. They are also from
different banks on the pinctrl and the TLMM summary line is not routed to the
PDC. Hence the PDC cannot be considered as parent of the TLMM irqchip (or can
we ?). This is what it looks like -
[ PIN ] -----[ TLMM ]---------------> [ GIC ] ---> [ CPU ]
| <summary IRQ> ^
| |
----------------------------------> [ PDC ]
<wakeup IRQs>
I had a brief discussion with Linus on this and the idea implemented is based
on his suggestion.
When an IRQ (let's call this latent IRQ) for a GPIO is requested, the
->irq_request_resources() is used by the TLMM driver to request a PDC pin. The
PDC pin associated with the GPIO is read from a static map available in the
pinctrl-sdm845.c. (I think there should be a better location than a static map,
more on that later). Knowing the PDC pin from the map, we could look up the DT
bindings and request the PDC interrupt with the same trigger mask as the
interrupt requested. The ->set_type and ->set_wake are also trapped to set the
PDC IRQ's polarity and enable it when the latent IRQ is requested. When the PDC
detects the interrupt at suspend, it wakes up the GIC and replays the wakeup
IRQ. The GPIO handler function for the latent IRQ is invoked in turn.
Please review these patches and your inputs would be greatly appreciated and
(kindly) let me know if I have committed any blunders with this approach. There
is definitely opportunity to improve the location of the static GPIO-PDC pin
map. We could possibly put it as an data argument in the interrupts definition
of the PDC or with interrupt names. Also, I am still sorting out some issues
with the IRQ handling part of these patches. And I am unsure of how to set the
polarity of the PDC pin without locking, since we are not in hierarchy with the
PDC interrupt controller. Again, your inputs on these would be greatly helpful.
Thanks,
Lina
[1]. drivers/irqchip/qcom-pdc.c
[2]. Documentation/devicetree/bindings/interrupt-controller/qcom,pdc.txt
[3]. drivers/pinctrl/qcom/pinctrl-msm.c
Lina Iyer (4):
drivers: pinctrl: qcom: add wakeup capability to GPIO
drivers: pinctrl: qcom: add wakeup gpio map for sdm845
arm64: dts: msm: add PDC device bindings for sdm845
arm64: dts: qcom: add wake up interrupts for GPIOs
arch/arm64/boot/dts/qcom/sdm845.dtsi | 78 ++++++++++++
drivers/pinctrl/qcom/pinctrl-msm.c | 163 ++++++++++++++++++++++++++
drivers/pinctrl/qcom/pinctrl-msm.h | 14 +++
drivers/pinctrl/qcom/pinctrl-sdm845.c | 76 ++++++++++++
4 files changed, 331 insertions(+)
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
GPIOs that are wakeup capable have interrupt lines that are routed to
the always-on interrupt controller (PDC) in parallel to the pinctrl. The
interrupts listed here are the wake up lines corresponding to GPIOs.
Signed-off-by: Lina Iyer <[email protected]>
---
arch/arm64/boot/dts/qcom/sdm845.dtsi | 69 ++++++++++++++++++++++++++++
1 file changed, 69 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index 8ccce42885c1..96ef18ced85b 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -720,6 +720,75 @@
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
+ interrupts-extended = <&pdc 30 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 31 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 32 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 33 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 34 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 35 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 36 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 37 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 38 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 39 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 41 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 42 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 43 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 44 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 45 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 46 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 47 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 49 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 50 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 51 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 52 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 54 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 55 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 56 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 57 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 58 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 59 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 60 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 61 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 62 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 63 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 64 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 65 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 66 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 67 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 68 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 69 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 70 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 71 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 72 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 73 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 74 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 75 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 76 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 77 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 79 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 80 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 81 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 82 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 83 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 84 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 85 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 86 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 90 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 91 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 92 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 95 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 96 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 97 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 98 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 99 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 100 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 102 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 103 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 104 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 105 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 106 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 107 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 108 IRQ_TYPE_LEVEL_HIGH>;
qup_i2c0_default: qup-i2c0-default {
pinmux {
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
Add PDC interrupt controller device bindings for SDM845.
Signed-off-by: Lina Iyer <[email protected]>
---
arch/arm64/boot/dts/qcom/sdm845.dtsi | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index 2acc17ce1a9c..8ccce42885c1 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -1213,6 +1213,15 @@
};
};
+ pdc: interrupt-controller@b220000 {
+ compatible = "qcom,sdm845-pdc";
+ reg = <0xb220000 0x30000>;
+ qcom,pdc-ranges = <0 512 94>, <94 641 15>, <115 662 7>;
+ #interrupt-cells = <2>;
+ interrupt-parent = <&intc>;
+ interrupt-controller;
+ };
+
timer@17c90000 {
#address-cells = <1>;
#size-cells = <1>;
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
QCOM SoC's that have Power Domain Controller (PDC) chip in the always-on
domain can wakeup the SoC, when interrupts and GPIOs are routed to the
its interrupt controller. Select GPIOs that are deemed wakeup capable are
routed to specific PDC pins. The PDC wakes up the GIC and replays the
interrupt at the GIC and the interrupt handler for the GPIO is invoked.
Setup the PDC IRQ when the GPIO's IRQ is requested and enable the PDC
IRQ when the GPIO's IRQ is enabled.
Signed-off-by: Lina Iyer <[email protected]>
---
drivers/pinctrl/qcom/pinctrl-msm.c | 163 +++++++++++++++++++++++++++++
drivers/pinctrl/qcom/pinctrl-msm.h | 14 +++
2 files changed, 177 insertions(+)
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c
index 0e22f52b2a19..39c3934712f7 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm.c
@@ -71,6 +71,13 @@ struct msm_pinctrl {
const struct msm_pinctrl_soc_data *soc;
void __iomem *regs;
+ struct list_head pdc_irqs;
+};
+
+struct wakeup_gpio_irq_map {
+ struct list_head list;
+ unsigned gpio;
+ unsigned pdc_irq;
};
static int msm_get_groups_count(struct pinctrl_dev *pctldev)
@@ -558,6 +565,39 @@ static void msm_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
#define msm_gpio_dbg_show NULL
#endif
+static int msm_gpio_get_pdc_pin(struct msm_pinctrl *pctrl, unsigned hwirq)
+{
+ struct msm_pinctrl_pdc_map *map = pctrl->soc->pdc_map;
+ int i;
+
+ for (i = 0; i < pctrl->soc->npdc_pins; i++) {
+ if (map[i].hwirq == hwirq)
+ return map[i].pdc_pin;
+ }
+
+ return -ENOTCONN;
+}
+
+static struct irq_data *msm_get_pdc_irq_data(struct irq_data *d)
+{
+ struct wakeup_gpio_irq_map *p;
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct msm_pinctrl *pctrl = gpiochip_get_data(gc);
+ struct irq_data *data = NULL;
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&pctrl->lock, flags);
+ list_for_each_entry(p, &pctrl->pdc_irqs, list) {
+ if (p->gpio == d->hwirq) {
+ data = irq_get_irq_data(p->pdc_irq);
+ break;
+ }
+ }
+ raw_spin_unlock_irqrestore(&pctrl->lock, flags);
+
+ return data;
+}
+
static const struct gpio_chip msm_gpio_template = {
.direction_input = msm_gpio_direction_input,
.direction_output = msm_gpio_direction_output,
@@ -687,6 +727,11 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type)
const struct msm_pingroup *g;
unsigned long flags;
u32 val;
+ struct irq_data *pdc_irqd = msm_get_pdc_irq_data(d);
+
+ // TODO: Lock PDC irq chip and set type?
+ if (pdc_irqd)
+ pdc_irqd->chip->irq_set_type(pdc_irqd, type);
g = &pctrl->soc->groups[d->hwirq];
@@ -779,9 +824,13 @@ static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct msm_pinctrl *pctrl = gpiochip_get_data(gc);
unsigned long flags;
+ struct irq_data *pdc_irqd = msm_get_pdc_irq_data(d);
raw_spin_lock_irqsave(&pctrl->lock, flags);
+ if (pdc_irqd)
+ irq_set_irq_wake(pdc_irqd->irq, on);
+
irq_set_irq_wake(pctrl->irq, on);
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
@@ -863,6 +912,117 @@ static bool msm_gpio_needs_valid_mask(struct msm_pinctrl *pctrl)
return device_property_read_u16_array(pctrl->dev, "gpios", NULL, 0) > 0;
}
+static irqreturn_t wake_irq_gpio_handler(int irq, void *data)
+{
+ struct irq_data *irqd = data;
+ struct irq_desc *desc = irq_data_to_desc(irqd);
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
+ int irq_pin = irq_find_mapping(gc->irq.domain, irqd->hwirq);
+
+ chained_irq_enter(chip, desc);
+ generic_handle_irq(irq_pin);
+ chained_irq_exit(chip, desc);
+
+ return IRQ_HANDLED;
+}
+
+static int msm_gpio_pdc_pin_request(struct irq_data *d)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct msm_pinctrl *pctrl = gpiochip_get_data(gc);
+ struct platform_device *pdev = to_platform_device(pctrl->dev);
+ unsigned pin, npins, irq;
+ struct wakeup_gpio_irq_map *p;
+ unsigned long flags, trigger;
+ const char *pin_name;
+ int i, ret;
+
+ pin = msm_gpio_get_pdc_pin(pctrl, d->hwirq);
+ if (pin < 0)
+ return 0;
+
+ npins = platform_irq_count(pdev);
+ if (npins <= 0)
+ return npins;
+
+ for (i = 0; i < npins; i++) {
+ irq = platform_get_irq(pdev, i);
+ if (irq >= 0 && pin == irq_get_irq_data(irq)->hwirq)
+ break;
+ }
+ if (i == npins)
+ return 0;
+
+ pin_name = kasprintf(GFP_KERNEL, "gpio-%lu", d->hwirq);
+ if (!pin_name)
+ return -ENOMEM;
+
+ trigger = irqd_get_trigger_type(d) | IRQF_ONESHOT | IRQF_NO_SUSPEND;
+ ret = request_irq(irq, wake_irq_gpio_handler, trigger, pin_name, d);
+ if (ret) {
+ pr_warn("GPIO-%lu could not be set up as wakeup", d->hwirq);
+ return ret;
+ }
+
+ p = kzalloc(sizeof(p), GFP_KERNEL);
+ if (!p)
+ return -ENOMEM;
+
+ p->pdc_irq = irq;
+ p->gpio = d->hwirq;
+ raw_spin_lock_irqsave(&pctrl->lock, flags);
+ list_add(&p->list, &pctrl->pdc_irqs);
+ raw_spin_unlock_irqrestore(&pctrl->lock, flags);
+
+ return 0;
+}
+
+static int msm_gpio_pdc_pin_release(struct irq_data *d)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct msm_pinctrl *pctrl = gpiochip_get_data(gc);
+ struct wakeup_gpio_irq_map *p, *n, *t = NULL;
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&pctrl->lock, flags);
+ list_for_each_entry_safe(p, n, &pctrl->pdc_irqs, list) {
+ if (p->gpio == d->hwirq) {
+ list_del(&p->list);
+ t = p;
+ break;
+ }
+ }
+ raw_spin_unlock_irqrestore(&pctrl->lock, flags);
+ if (t) {
+ free_irq(t->pdc_irq, NULL);
+ kfree(t);
+ }
+
+ return 0;
+}
+
+static int msm_gpio_irq_reqres(struct irq_data *d)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+
+ if (gpiochip_lock_as_irq(gc, irqd_to_hwirq(d))) {
+ dev_err(gc->parent,"unable to lock HW IRQ %lu for IRQ\n",
+ irqd_to_hwirq(d));
+ return -EINVAL;
+ }
+
+ return msm_gpio_pdc_pin_request(d);
+}
+
+static void msm_gpio_irq_relres(struct irq_data *d)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+
+ msm_gpio_pdc_pin_release(d);
+ gpiochip_unlock_as_irq(gc, irqd_to_hwirq(d));
+}
+
static int msm_gpio_init(struct msm_pinctrl *pctrl)
{
struct gpio_chip *chip;
@@ -887,6 +1047,9 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl)
pctrl->irq_chip.irq_ack = msm_gpio_irq_ack;
pctrl->irq_chip.irq_set_type = msm_gpio_irq_set_type;
pctrl->irq_chip.irq_set_wake = msm_gpio_irq_set_wake;
+ pctrl->irq_chip.irq_request_resources = msm_gpio_irq_reqres;
+ pctrl->irq_chip.irq_release_resources = msm_gpio_irq_relres;
+ INIT_LIST_HEAD(&pctrl->pdc_irqs);
ret = gpiochip_add_data(&pctrl->chip, pctrl);
if (ret) {
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.h b/drivers/pinctrl/qcom/pinctrl-msm.h
index 9b9feea540ff..5b7f3160affe 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.h
+++ b/drivers/pinctrl/qcom/pinctrl-msm.h
@@ -97,6 +97,16 @@ struct msm_pingroup {
unsigned intr_detection_width:5;
};
+/**
+ * struct msm_pinctrl_pdc_map - Map GPIOs to PDC pins on RPMH based SoCs
+ * @hwirq: The GPIO that is mapped.
+ * @pdc_pin: The PDC pin to with the GPIO IRQ line is routed.
+ */
+struct msm_pinctrl_pdc_map {
+ u32 hwirq;
+ u32 pdc_pin;
+};
+
/**
* struct msm_pinctrl_soc_data - Qualcomm pin controller driver configuration
* @pins: An array describing all pins the pin controller affects.
@@ -107,6 +117,8 @@ struct msm_pingroup {
* @ngroups: The numbmer of entries in @groups.
* @ngpio: The number of pingroups the driver should expose as GPIOs.
* @pull_no_keeper: The SoC does not support keeper bias.
+ * @pdc_map: The map of GPIOs to the always-on PDC interrupt lines.
+ * @npdc_pins: The number of GPIOs mapped to the PDC pins in @pdc_map.
*/
struct msm_pinctrl_soc_data {
const struct pinctrl_pin_desc *pins;
@@ -117,6 +129,8 @@ struct msm_pinctrl_soc_data {
unsigned ngroups;
unsigned ngpios;
bool pull_no_keeper;
+ struct msm_pinctrl_pdc_map *pdc_map;
+ unsigned npdc_pins;
};
int msm_pinctrl_probe(struct platform_device *pdev,
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
Add GPIO to PDC pin map for the SDM845 SoC.
Signed-off-by: Lina Iyer <[email protected]>
---
drivers/pinctrl/qcom/pinctrl-sdm845.c | 76 +++++++++++++++++++++++++++
1 file changed, 76 insertions(+)
diff --git a/drivers/pinctrl/qcom/pinctrl-sdm845.c b/drivers/pinctrl/qcom/pinctrl-sdm845.c
index 2ab7a8885757..e93660922dc2 100644
--- a/drivers/pinctrl/qcom/pinctrl-sdm845.c
+++ b/drivers/pinctrl/qcom/pinctrl-sdm845.c
@@ -1277,6 +1277,80 @@ static const struct msm_pingroup sdm845_groups[] = {
UFS_RESET(ufs_reset, 0x99f000),
};
+static struct msm_pinctrl_pdc_map sdm845_wakeup_gpios[] = {
+ {1, 30},
+ {3, 31},
+ {5, 32},
+ {10, 33},
+ {11, 34},
+ {20, 35},
+ {22, 36},
+ {24, 37},
+ {26, 38},
+ {30, 39},
+ {32, 41},
+ {34, 42},
+ {36, 43},
+ {37, 44},
+ {38, 45},
+ {39, 46},
+ {40, 47},
+ {43, 49},
+ {44, 50},
+ {46, 51},
+ {48, 52},
+ {52, 54},
+ {53, 55},
+ {54, 56},
+ {56, 57},
+ {57, 58},
+ {58, 59},
+ {59, 60},
+ {60, 61},
+ {61, 62},
+ {62, 63},
+ {63, 64},
+ {64, 65},
+ {66, 66},
+ {68, 67},
+ {71, 68},
+ {73, 69},
+ {77, 70},
+ {78, 71},
+ {79, 72},
+ {80, 73},
+ {84, 74},
+ {85, 75},
+ {86, 76},
+ {88, 77},
+ {91, 79},
+ {92, 80},
+ {95, 81},
+ {96, 82},
+ {97, 83},
+ {101, 84},
+ {103, 85},
+ {104, 86},
+ {115, 90},
+ {116, 91},
+ {117, 92},
+ {118, 93},
+ {119, 94},
+ {120, 95},
+ {121, 96},
+ {122, 97},
+ {123, 98},
+ {124, 99},
+ {125, 100},
+ {127, 102},
+ {128, 103},
+ {129, 104},
+ {130, 105},
+ {132, 106},
+ {133, 107},
+ {145, 108},
+};
+
static const struct msm_pinctrl_soc_data sdm845_pinctrl = {
.pins = sdm845_pins,
.npins = ARRAY_SIZE(sdm845_pins),
@@ -1285,6 +1359,8 @@ static const struct msm_pinctrl_soc_data sdm845_pinctrl = {
.groups = sdm845_groups,
.ngroups = ARRAY_SIZE(sdm845_groups),
.ngpios = 150,
+ .pdc_map = sdm845_wakeup_gpios,
+ .npdc_pins = ARRAY_SIZE(sdm845_wakeup_gpios),
};
static int sdm845_pinctrl_probe(struct platform_device *pdev)
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
On Tue, Jul 31, 2018 at 3:44 PM Lina Iyer <[email protected]> wrote:
>
> GPIOs that are wakeup capable have interrupt lines that are routed to
> the always-on interrupt controller (PDC) in parallel to the pinctrl. The
> interrupts listed here are the wake up lines corresponding to GPIOs.
>
> Signed-off-by: Lina Iyer <[email protected]>
> ---
> arch/arm64/boot/dts/qcom/sdm845.dtsi | 69 ++++++++++++++++++++++++++++
> 1 file changed, 69 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
> index 8ccce42885c1..96ef18ced85b 100644
> --- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
> +++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
> @@ -720,6 +720,75 @@
> #gpio-cells = <2>;
> interrupt-controller;
> #interrupt-cells = <2>;
> + interrupts-extended = <&pdc 30 IRQ_TYPE_LEVEL_HIGH>,
In order to get any GPIO interrupts on my board, I needed to add the
summary IRQ first in this list. My reading of platform_get_irq is that
"interrupts-extended" is queried before "interrupts", so we
accidentally wire the summary IRQ to PDC 30. Given this, you can
probably remove the regular "interrupts" property.
-Evan
> + <&pdc 31 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 32 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 33 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 34 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 35 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 36 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 37 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 38 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 39 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 41 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 42 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 43 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 44 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 45 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 46 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 47 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 49 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 50 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 51 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 52 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 54 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 55 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 56 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 57 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 58 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 59 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 60 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 61 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 62 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 63 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 64 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 65 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 66 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 67 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 68 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 69 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 70 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 71 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 72 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 73 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 74 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 75 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 76 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 77 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 79 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 80 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 81 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 82 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 83 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 84 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 85 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 86 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 90 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 91 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 92 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 95 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 96 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 97 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 98 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 99 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 100 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 102 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 103 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 104 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 105 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 106 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 107 IRQ_TYPE_LEVEL_HIGH>,
> + <&pdc 108 IRQ_TYPE_LEVEL_HIGH>;
>
> qup_i2c0_default: qup-i2c0-default {
> pinmux {
> --
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
> a Linux Foundation Collaborative Project
>
On Tue, Aug 07 2018 at 13:57 -0600, Evan Green wrote:
>On Tue, Jul 31, 2018 at 3:44 PM Lina Iyer <[email protected]> wrote:
>>
>> GPIOs that are wakeup capable have interrupt lines that are routed to
>> the always-on interrupt controller (PDC) in parallel to the pinctrl. The
>> interrupts listed here are the wake up lines corresponding to GPIOs.
>>
>> Signed-off-by: Lina Iyer <[email protected]>
>> ---
>> arch/arm64/boot/dts/qcom/sdm845.dtsi | 69 ++++++++++++++++++++++++++++
>> 1 file changed, 69 insertions(+)
>>
>> diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
>> index 8ccce42885c1..96ef18ced85b 100644
>> --- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
>> +++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
>> @@ -720,6 +720,75 @@
>> #gpio-cells = <2>;
>> interrupt-controller;
>> #interrupt-cells = <2>;
>> + interrupts-extended = <&pdc 30 IRQ_TYPE_LEVEL_HIGH>,
>
>In order to get any GPIO interrupts on my board, I needed to add the
>summary IRQ first in this list. My reading of platform_get_irq is that
>"interrupts-extended" is queried before "interrupts", so we
>accidentally wire the summary IRQ to PDC 30. Given this, you can
>probably remove the regular "interrupts" property.
>
Sure. Will fix that.
-- Lina
>> + <&pdc 31 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 32 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 33 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 34 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 35 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 36 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 37 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 38 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 39 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 41 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 42 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 43 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 44 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 45 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 46 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 47 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 49 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 50 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 51 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 52 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 54 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 55 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 56 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 57 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 58 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 59 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 60 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 61 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 62 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 63 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 64 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 65 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 66 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 67 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 68 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 69 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 70 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 71 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 72 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 73 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 74 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 75 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 76 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 77 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 79 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 80 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 81 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 82 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 83 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 84 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 85 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 86 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 90 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 91 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 92 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 95 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 96 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 97 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 98 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 99 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 100 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 102 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 103 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 104 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 105 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 106 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 107 IRQ_TYPE_LEVEL_HIGH>,
>> + <&pdc 108 IRQ_TYPE_LEVEL_HIGH>;
>>
>> qup_i2c0_default: qup-i2c0-default {
>> pinmux {
>> --
>> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
>> a Linux Foundation Collaborative Project
>>