* [PATCH v3 0/8] x1e80100: Enable PDC wake GPIOs and deepest idle state
@ 2026-06-16 9:25 Maulik Shah
2026-06-16 9:25 ` [PATCH v3 1/8] irqchip/qcom-pdc: restructure version support Maulik Shah
` (9 more replies)
0 siblings, 10 replies; 32+ messages in thread
From: Maulik Shah @ 2026-06-16 9:25 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Thomas Gleixner, Linus Walleij
Cc: linux-arm-msm, linux-kernel, devicetree, linux-gpio, Sneh Mankad,
Maulik Shah, Stephan Gerhold
There are two modes PDC irqchip can work in
- pass through mode
- secondary controller mode
Secondary mode is supported depending on SoC using PDC HW Version v3.0
or higher.
+------------------------------------------------------------------------+
| SoC | SM8350, SM8450 | SM8550, Hamoa | SM8650, SM8750 |
|----------------------------------------------------------- ------------|
| Version | v2.7 | v3.0 | v3.2 |
|------------------------------------------------------------------------|
| Pass through | Yes | Yes | Yes |
|------------------------------------------------------------------------|
| Secondary | No | Yes | Yes |
+------------------------------------------------------------------------+
All PDC irqchip supports pass through mode in which both Direct SPIs and
GPIO IRQs (as SPIs) are sent to GIC without latching at PDC, PDC only does
inversion when needed for falling edge to rising edge or level low to level
high, as the GIC do not support falling edge/level low interrupts.
Newer PDCs (v3.0 onwards) also support additional secondary controller mode
where PDC latches GPIO IRQs and sends to GIC as level type IRQ. Direct SPIs
still works same as pass through mode without latching at PDC even in
secondary controller mode.
All the SoCs defaulted to pass through mode with the exception of some x1e.
x1e PDC may be set to secondary controller mode for builds on CRD boards
whereas it may be set to pass through mode for IoT-EVK boards. The mode
configuration is done in firmware and initially shipped windows firmware
did not have SCM interface to read or modify the PDC configuration.
Later only write access is opened up for non secure world.
Using the write access available add changes to modify the PDC mode to
pass through mode via SCM write. When the write fails (on older firmware)
assume to work in secondary mode.
As the deepest idle state as the PDC can now wake up SoC from GPIOs and
revert commit 602cb14e310a ("pinctrl: qcom: x1e80100: Bypass PDC wakeup
parent for now").
The series has been tested on x1e80100 CRD with both old and new firmware
and also on kaanapali. Test conducted with tlmm-test module after
applying [3] as test module needed to be fixed first.
All 17/17 passes in pass through mode and 16/17 passes in secondary mode.
Failing test tlmm_test_rising_while_disabled seems to be because when in
irq disabled state PDC is not latching the edge interrupt.
Test #1: Pass through mode on x1e80100 CRD (New firmware)
root@qcom-armv8a:~# insmod tlmm-test.ko gpio=91
KTAP version 1
1..1
KTAP version 1
# Subtest: tlmm-test
# module: tlmm_test
1..17
ok 1 tlmm_test_silent_rising
ok 2 tlmm_test_silent_falling
ok 3 tlmm_test_silent_low
ok 4 tlmm_test_silent_high
ok 5 tlmm_test_rising
ok 6 tlmm_test_falling
ok 7 tlmm_test_high
ok 8 tlmm_test_low
ok 9 tlmm_test_rising_in_handler
ok 10 tlmm_test_falling_in_handler
ok 11 tlmm_test_thread_rising
ok 12 tlmm_test_thread_falling
ok 13 tlmm_test_thread_high
ok 14 tlmm_test_thread_low
ok 15 tlmm_test_thread_rising_in_handler
ok 16 tlmm_test_thread_falling_in_handler
ok 17 tlmm_test_rising_while_disabled
ok 1 tlmm-test
Test #2: Secondary mode on x1e80100 CRD (Old firmware)
root@qcom-armv8a:~# insmod tlmm-test.ko gpio=91
KTAP version 1
1..1
KTAP version 1
# Subtest: tlmm-test
# module: tlmm_test
1..17
ok 1 tlmm_test_silent_rising
ok 2 tlmm_test_silent_falling
ok 3 tlmm_test_silent_low
ok 4 tlmm_test_silent_high
ok 5 tlmm_test_rising
ok 6 tlmm_test_falling
ok 7 tlmm_test_high
ok 8 tlmm_test_low
ok 9 tlmm_test_rising_in_handler
ok 10 tlmm_test_falling_in_handler
ok 11 tlmm_test_thread_rising
ok 12 tlmm_test_thread_falling
ok 13 tlmm_test_thread_high
ok 14 tlmm_test_thread_low
ok 15 tlmm_test_thread_rising_in_handler
ok 16 tlmm_test_thread_falling_in_handler
# tlmm_test_rising_while_disabled: ASSERTION FAILED at drivers/pinctrl/qcom/tlmm-test.c:545
Expected atomic_read(&priv->intr_count) == 1, but
atomic_read(&priv->intr_count) == 0 (0x0)
not ok 17 tlmm_test_rising_while_disabled
not ok 1 tlmm-test
root@qcom-armv8a:~#
v2 series is dependent on [1] as mostly all changes are already reviewed.
v3 series is dependent on [2] which is already merged in linux-next
[1] https://lore.kernel.org/linux-arm-msm/20260410184124.1068210-1-mukesh.ojha@oss.qualcomm.com/
[2] https://lore.kernel.org/linux-arm-msm/20260527095426.2324504-1-mukesh.ojha@oss.qualcomm.com/
[3] https://lore.kernel.org/linux-arm-msm/20260529-tlmm_test_changes-v1-0-88bfdccb4369@oss.qualcomm.com/
---
Changes in v3:
- Add test results in cover letter with tlmm-test module
- Fix coding style and struct defination
- Convert raw_spin_lock to guard(raw_spin_lock) and remove _irqsave
- Use bit number instead of GENMASK() for single bit fields
- Use __assign_bit() and __clear_bit() APIs for single bit modifications
- Use devm_ioremap() instead of ioremap()
- Use devm_kcalloc() instead of kzalloc_objs()
- Add separate irq chips for pass through and secondary mode IRQs
- Add IRQCHIP_EOI_THREADED flag for threaded IRQ on pinctrl irqchip
- Link to v2: https://patch.msgid.link/20260526-hamoa_pdc-v2-0-f6857af1ce91@oss.qualcomm.com
Changes in v2:
- Update to mention SoC names along with PDC versions in cover letter
- Drop devicetree change to remove scm interconnects
- Use qcom_scm_is_available() to wait for dependency on SCM
- Drop binding change mentioning qcom,qmp and PDC config reg
- Restructure version support and move all statics to struct pdc_desc
- Remove pdc_enable_intr() wrapper
- Differentiate direct SPI and GPIOs as SPI using PDC IRQ PARAM reg
- Add changes to make PDC work in secondary controller mode
- Rework and include Stephan's change to invoke irq_ack() for edge interrupt
- Mention dependency via b4 prerequisites and cover letter
- Link to v1: https://lore.kernel.org/r/20260312-hamoa_pdc-v1-0-760c8593ce50@oss.qualcomm.com
---
To: Bjorn Andersson <andersson@kernel.org>
To: Konrad Dybcio <konradybcio@kernel.org>
To: Rob Herring <robh@kernel.org>
To: Krzysztof Kozlowski <krzk+dt@kernel.org>
To: Conor Dooley <conor+dt@kernel.org>
To: Thomas Gleixner <tglx@kernel.org>
To: Linus Walleij <linusw@kernel.org>
Cc: linux-arm-msm@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: devicetree@vger.kernel.org
Cc: linux-gpio@vger.kernel.org
Cc: Sneh Mankad <sneh.mankad@oss.qualcomm.com>
Signed-off-by: Maulik Shah <maulik.shah@oss.qualcomm.com>
---
Maulik Shah (7):
irqchip/qcom-pdc: restructure version support
irqchip/qcom-pdc: Move all statics to struct pdc_desc
irqchip/qcom-pdc: Remove pdc_enable_intr() wrapper
irqchip/qcom-pdc: Differentiate between direct SPI and GPIO as SPI
irqchip/qcom-pdc: Configure PDC to pass through mode
Revert "pinctrl: qcom: x1e80100: Bypass PDC wakeup parent for now"
arm64: dts: qcom: x1e80100: Add deepest idle state
Stephan Gerhold (1):
pinctrl: qcom: Acknowledge IRQs for PDC interrupt controller
arch/arm64/boot/dts/qcom/hamoa.dtsi | 10 +-
drivers/irqchip/qcom-pdc.c | 506 +++++++++++++++++++++++++-------
drivers/pinctrl/qcom/pinctrl-msm.c | 16 +-
drivers/pinctrl/qcom/pinctrl-x1e80100.c | 4 +-
4 files changed, 430 insertions(+), 106 deletions(-)
---
base-commit: 8d6dbbbe3ba62de0a63e962ee004afb848c8e3ac
change-id: 20260605-hamoa_pdc_v3-6dabc845021c
Best regards,
--
Maulik Shah <maulik.shah@oss.qualcomm.com>
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH v3 1/8] irqchip/qcom-pdc: restructure version support
2026-06-16 9:25 [PATCH v3 0/8] x1e80100: Enable PDC wake GPIOs and deepest idle state Maulik Shah
@ 2026-06-16 9:25 ` Maulik Shah
2026-06-17 13:12 ` Konrad Dybcio
2026-06-30 14:38 ` Thomas Gleixner
2026-06-16 9:25 ` [PATCH v3 2/8] irqchip/qcom-pdc: Move all statics to struct pdc_desc Maulik Shah
` (8 subsequent siblings)
9 siblings, 2 replies; 32+ messages in thread
From: Maulik Shah @ 2026-06-16 9:25 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Thomas Gleixner, Linus Walleij
Cc: linux-arm-msm, linux-kernel, devicetree, linux-gpio, Sneh Mankad,
Maulik Shah
PDC irqchip updates IRQ_ENABLE and IRQ_CFG and for three different
versions v2.7, v3.0 and v3.2. These registers are organized in H/W
as below on various SoCs.
+---------------------------------------------------------------+
| SM8350, SM8450 | SM8550, Hamoa | SM8650, SM8750 |
|---------------------------------------------------------------|
| v2.7 | v3.0 | v3.2 |
|---------------------------------------------------------------|
| IRQ_ENABLE_BANK | IRQ_ENABLE_BANK | NA |
|---------------------------------------------------------------|
| IRQ_CFG | IRQ_CFG | IRQ_CFG |
| | | |
| | | [31:6] Unused |
| | [31:5] Unused | [5] GPIO_STATUS |
| | [4] GPIO_STATUS| [4] GPIO_MASK |
| [31:3] Unused | [3] GPIO_MASK | [3] IRQ_ENABLE |
| [0:2] Type | [0:2] Type | [0:2] Type |
+---------------------------------------------------------------|
All SoCs PDC irqchip supports "pass through mode" in which all interrupts
are forwarded to the GIC without any latching at PDC H/W.
So far irqchip did not utilize GPIO_STATUS and GPIO_MASK from IRQ_CFG
register for v3.0 and v3.2 since they are only needed to be configured
when PDC runs in specific mode named "second level interrupt controller"
where it can latch the GPIO interrupts in GPIO_STATUS and forward GPIO
interrupts to GIC as LEVEL_HIGH type SPI interrupt.
All the SoCs defaulted to pass through mode with the exception of some
x1e. x1e PDC may be set to secondary controller mode for builds on CRD
boards whereas it may be set to pass through mode for IoT-EVK boards.
Restructure in preparation to add the second level interrupt controller
mode utilizing GPIO_STATUS and GPIO_MASK bits which changed the bit
positions between v3.0 and v3.2.
No functional impact with the change.
Signed-off-by: Maulik Shah <maulik.shah@oss.qualcomm.com>
---
drivers/irqchip/qcom-pdc.c | 207 ++++++++++++++++++++++++++++++++-------------
1 file changed, 149 insertions(+), 58 deletions(-)
diff --git a/drivers/irqchip/qcom-pdc.c b/drivers/irqchip/qcom-pdc.c
index 2014dbb0bc43..23276325211d 100644
--- a/drivers/irqchip/qcom-pdc.c
+++ b/drivers/irqchip/qcom-pdc.c
@@ -21,21 +21,12 @@
#include <linux/slab.h>
#include <linux/types.h>
-#define PDC_MAX_GPIO_IRQS 256
-#define PDC_DRV_SIZE 0x10000
-
-/* Valid only on HW version < 3.2 */
-#define IRQ_ENABLE_BANK 0x10
-#define IRQ_ENABLE_BANK_MAX (IRQ_ENABLE_BANK + BITS_TO_BYTES(PDC_MAX_GPIO_IRQS))
+#define PDC_MAX_IRQS 256
+#define IRQ_ENABLE_BANK_MAX BITS_TO_BYTES(PDC_MAX_IRQS)
#define IRQ_ENABLE_BANK_INDEX_MASK GENMASK(31, 5)
#define IRQ_ENABLE_BANK_BIT_MASK GENMASK(4, 0)
-#define IRQ_i_CFG 0x110
-
-/* Valid only on HW version >= 3.2 */
-#define IRQ_i_CFG_IRQ_ENABLE 3
-
-#define IRQ_i_CFG_TYPE_MASK GENMASK(2, 0)
+#define PDC_DRV_SIZE 0x10000
#define PDC_VERSION_REG 0x1000
#define PDC_VERSION_MAJOR GENMASK(23, 16)
#define PDC_VERSION_MINOR GENMASK(15, 8)
@@ -46,6 +37,98 @@
/* Notable PDC versions */
#define PDC_VERSION_3_2 PDC_VERSION(3, 2, 0)
+#define PDC_VERSION_3_0 PDC_VERSION(3, 0, 0)
+#define PDC_VERSION_2_7 PDC_VERSION(2, 7, 0)
+
+/*
+ * PDC H/W registers layout per version:
+ *
+ * IRQ_ENABLE_BANK[b], b = 0....BITS_TO_BYTES(PDC_MAX_IRQS)
+ * IRQ_CFG[n], n = 0....PDC_MAX_IRQS
+ *
+ * +---------------------------------------------------------------+
+ * | v2.7 | v3.0 | v3.2 |
+ * |---------------------------------------------------------------|
+ * | BASE | BASE | BASE |
+ * |---------------------------------------------------------------|
+ * | |
+ * | IRQ_ENABLE_BANK | IRQ_ENABLE_BANK | NA |
+ * |---------------------------------------------------------------|
+ * | IRQ_CFG | IRQ_CFG | IRQ_CFG |
+ * | | | |
+ * | | | [31:6] Unused |
+ * | | [31:5] Unused | [5] GPIO_STATUS |
+ * | | [4] GPIO_STATUS| [4] GPIO_MASK |
+ * | [31:3] Unused | [3] GPIO_MASK | [3] IRQ_ENABLE |
+ * | [0:2] Type | [0:2] Type | [0:2] Type |
+ * +---------------------------------------------------------------+
+ */
+
+/**
+ * struct pdc_regs: PDC registers location
+ *
+ * @irq_en_reg: IRQ_ENABLE_BANK register location
+ * @irq_cfg_reg: IRQ_CFG register location
+ */
+struct pdc_regs {
+ u32 irq_en_reg;
+ u32 irq_cfg_reg;
+};
+
+/**
+ * struct pdc_irq_cfg: bit fields for PDC IRQ_CFG register
+ *
+ * @irq_enable: bit number for IRQ_ENABLE field
+ * @irq_type: GENMASK for IRQ_TYPE field
+ */
+struct pdc_irq_cfg {
+ u32 irq_enable;
+ u32 irq_type;
+};
+
+/**
+ * struct pdc_desc: PDC driver state
+ *
+ * @base: PDC base register for DRV2 / HLOS
+ * @prev_base: PDC DRV1 base, applicable only for x1e RTL bug.
+ * @version: PDC version
+ * @regs: PDC regs (IRQ_ENABLE_BANK and IRQ_CFG)
+ * @cfg_fields: Fields of IRQ_CFG reg
+ */
+struct pdc_desc {
+ void __iomem *base;
+ void __iomem *prev_base;
+ u32 version;
+ const struct pdc_regs *regs;
+ const struct pdc_irq_cfg *cfg_fields;
+};
+
+static const struct pdc_regs pdc_v3_2 = {
+ .irq_cfg_reg = 0x110,
+};
+
+static const struct pdc_irq_cfg pdc_cfg_v3_2 = {
+ .irq_enable = 3,
+ .irq_type = GENMASK(2, 0),
+};
+
+static const struct pdc_regs pdc_v3_0 = {
+ .irq_en_reg = 0x10,
+ .irq_cfg_reg = 0x110,
+};
+
+static const struct pdc_irq_cfg pdc_cfg_v3_0 = {
+ .irq_type = GENMASK(2, 0),
+};
+
+static const struct pdc_regs pdc_v2_7 = {
+ .irq_en_reg = 0x10,
+ .irq_cfg_reg = 0x110,
+};
+
+static const struct pdc_irq_cfg pdc_cfg_v2_7 = {
+ .irq_type = GENMASK(2, 0),
+};
struct pdc_pin_region {
u32 pin_base;
@@ -56,12 +139,11 @@ struct pdc_pin_region {
#define pin_to_hwirq(r, p) ((r)->parent_base + (p) - (r)->pin_base)
static DEFINE_RAW_SPINLOCK(pdc_lock);
-static void __iomem *pdc_base;
-static void __iomem *pdc_prev_base;
static struct pdc_pin_region *pdc_region;
static int pdc_region_cnt;
static unsigned int pdc_version;
static bool pdc_x1e_quirk;
+static struct pdc_desc *pdc;
static void pdc_base_reg_write(void __iomem *base, int reg, u32 i, u32 val)
{
@@ -70,12 +152,12 @@ static void pdc_base_reg_write(void __iomem *base, int reg, u32 i, u32 val)
static void pdc_reg_write(int reg, u32 i, u32 val)
{
- pdc_base_reg_write(pdc_base, reg, i, val);
+ pdc_base_reg_write(pdc->base, reg, i, val);
}
static u32 pdc_reg_read(int reg, u32 i)
{
- return readl_relaxed(pdc_base + reg + i * sizeof(u32));
+ return readl_relaxed(pdc->base + reg + i * sizeof(u32));
}
static void pdc_x1e_irq_enable_write(u32 bank, u32 enable)
@@ -86,24 +168,24 @@ static void pdc_x1e_irq_enable_write(u32 bank, u32 enable)
switch (bank) {
case 0 ... 1:
/* Use previous DRV (client) region and shift to bank 3-4 */
- base = pdc_prev_base;
+ base = pdc->prev_base;
bank += 3;
break;
case 2 ... 4:
/* Use our own region and shift to bank 0-2 */
- base = pdc_base;
+ base = pdc->base;
bank -= 2;
break;
case 5:
/* No fixup required for bank 5 */
- base = pdc_base;
+ base = pdc->base;
break;
default:
WARN_ON(1);
return;
}
- pdc_base_reg_write(base, IRQ_ENABLE_BANK, bank, enable);
+ pdc_base_reg_write(base, pdc->regs->irq_en_reg, bank, enable);
}
static void pdc_enable_intr_bank(int pin_out, bool on)
@@ -114,21 +196,21 @@ static void pdc_enable_intr_bank(int pin_out, bool on)
index = FIELD_GET(IRQ_ENABLE_BANK_INDEX_MASK, pin_out);
mask = FIELD_GET(IRQ_ENABLE_BANK_BIT_MASK, pin_out);
- enable = pdc_reg_read(IRQ_ENABLE_BANK, index);
+ enable = pdc_reg_read(pdc->regs->irq_en_reg, index);
__assign_bit(mask, &enable, on);
if (pdc_x1e_quirk)
pdc_x1e_irq_enable_write(index, enable);
else
- pdc_reg_write(IRQ_ENABLE_BANK, index, enable);
+ pdc_reg_write(pdc->regs->irq_en_reg, index, enable);
}
static void pdc_enable_intr_cfg(int pin_out, bool on)
{
- unsigned long enable = pdc_reg_read(IRQ_i_CFG, pin_out);
+ unsigned long enable = pdc_reg_read(pdc->regs->irq_cfg_reg, pin_out);
- __assign_bit(IRQ_i_CFG_IRQ_ENABLE, &enable, on);
- pdc_reg_write(IRQ_i_CFG, pin_out, enable);
+ __assign_bit(pdc->cfg_fields->irq_enable, &enable, on);
+ pdc_reg_write(pdc->regs->irq_cfg_reg, pin_out, enable);
}
static void __pdc_enable_intr(int pin_out, bool on)
@@ -224,9 +306,9 @@ static int qcom_pdc_gic_set_type(struct irq_data *d, unsigned int type)
return -EINVAL;
}
- old_pdc_type = pdc_reg_read(IRQ_i_CFG, d->hwirq);
- pdc_type |= (old_pdc_type & ~IRQ_i_CFG_TYPE_MASK);
- pdc_reg_write(IRQ_i_CFG, d->hwirq, pdc_type);
+ old_pdc_type = pdc_reg_read(pdc->regs->irq_cfg_reg, d->hwirq);
+ pdc_type |= (old_pdc_type & ~pdc->cfg_fields->irq_type);
+ pdc_reg_write(pdc->regs->irq_cfg_reg, d->hwirq, pdc_type);
ret = irq_chip_set_type_parent(d, type);
if (ret)
@@ -327,7 +409,7 @@ static const struct irq_domain_ops qcom_pdc_ops = {
.free = irq_domain_free_irqs_common,
};
-static int pdc_setup_pin_mapping(struct device_node *np)
+static int pdc_setup_pin_mapping(struct device *dev, struct device_node *np)
{
int ret, n, i;
@@ -336,7 +418,8 @@ static int pdc_setup_pin_mapping(struct device_node *np)
return -EINVAL;
pdc_region_cnt = n / 3;
- pdc_region = kzalloc_objs(*pdc_region, pdc_region_cnt);
+ pdc_region = devm_kcalloc(dev, pdc_region_cnt, sizeof(*pdc_region),
+ GFP_KERNEL);
if (!pdc_region) {
pdc_region_cnt = 0;
return -ENOMEM;
@@ -366,11 +449,11 @@ static int pdc_setup_pin_mapping(struct device_node *np)
return 0;
}
-
static int qcom_pdc_probe(struct platform_device *pdev, struct device_node *parent)
{
struct irq_domain *parent_domain, *pdc_domain;
struct device_node *node = pdev->dev.of_node;
+ struct device *dev = &pdev->dev;
resource_size_t res_size;
struct resource res;
int ret;
@@ -383,6 +466,30 @@ static int qcom_pdc_probe(struct platform_device *pdev, struct device_node *pare
if (res_size > resource_size(&res))
pr_warn("%pOF: invalid reg size, please fix DT\n", node);
+ pdc = devm_kzalloc(dev, sizeof(*pdc), GFP_KERNEL);
+ if (!pdc)
+ return -ENOMEM;
+
+ pdc->base = devm_ioremap(dev, res.start, res_size);
+ if (!pdc->base) {
+ pr_err("%pOF: unable to map PDC registers\n", node);
+ return -ENXIO;
+ }
+
+ pdc->version = pdc_reg_read(PDC_VERSION_REG, 0);
+
+ if (pdc->version >= PDC_VERSION_3_2) {
+ pdc->cfg_fields = &pdc_cfg_v3_2;
+ pdc->regs = &pdc_v3_2;
+ } else if (pdc->version < PDC_VERSION_3_2 &&
+ pdc->version >= PDC_VERSION_3_0) {
+ pdc->cfg_fields = &pdc_cfg_v3_0;
+ pdc->regs = &pdc_v3_0;
+ } else {
+ pdc->cfg_fields = &pdc_cfg_v2_7;
+ pdc->regs = &pdc_v2_7;
+ }
+
/*
* PDC has multiple DRV regions, each one provides the same set of
* registers for a particular client in the system. Due to a hardware
@@ -392,8 +499,9 @@ static int qcom_pdc_probe(struct platform_device *pdev, struct device_node *pare
* region with the expected offset to preserve support for old DTs.
*/
if (of_device_is_compatible(node, "qcom,x1e80100-pdc")) {
- pdc_prev_base = ioremap(res.start - PDC_DRV_SIZE, IRQ_ENABLE_BANK_MAX);
- if (!pdc_prev_base) {
+ pdc->prev_base = devm_ioremap(dev, res.start - PDC_DRV_SIZE,
+ pdc->regs->irq_en_reg + IRQ_ENABLE_BANK_MAX);
+ if (!pdc->prev_base) {
pr_err("%pOF: unable to map previous PDC DRV region\n", node);
return -ENXIO;
}
@@ -401,48 +509,31 @@ static int qcom_pdc_probe(struct platform_device *pdev, struct device_node *pare
pdc_x1e_quirk = true;
}
- pdc_base = ioremap(res.start, res_size);
- if (!pdc_base) {
- pr_err("%pOF: unable to map PDC registers\n", node);
- ret = -ENXIO;
- goto fail;
- }
-
- pdc_version = pdc_reg_read(PDC_VERSION_REG, 0);
-
parent_domain = irq_find_host(parent);
if (!parent_domain) {
pr_err("%pOF: unable to find PDC's parent domain\n", node);
- ret = -ENXIO;
- goto fail;
+ return -ENXIO;
}
- ret = pdc_setup_pin_mapping(node);
+ ret = pdc_setup_pin_mapping(dev, node);
if (ret) {
pr_err("%pOF: failed to init PDC pin-hwirq mapping\n", node);
- goto fail;
+ return ret;
}
pdc_domain = irq_domain_create_hierarchy(parent_domain,
- IRQ_DOMAIN_FLAG_QCOM_PDC_WAKEUP,
- PDC_MAX_GPIO_IRQS,
- of_fwnode_handle(node),
- &qcom_pdc_ops, NULL);
+ IRQ_DOMAIN_FLAG_QCOM_PDC_WAKEUP,
+ PDC_MAX_IRQS,
+ of_fwnode_handle(node),
+ &qcom_pdc_ops, NULL);
if (!pdc_domain) {
pr_err("%pOF: PDC domain add failed\n", node);
- ret = -ENOMEM;
- goto fail;
+ return -ENOMEM;
}
irq_domain_update_bus_token(pdc_domain, DOMAIN_BUS_WAKEUP);
return 0;
-
-fail:
- kfree(pdc_region);
- iounmap(pdc_base);
- iounmap(pdc_prev_base);
- return ret;
}
IRQCHIP_PLATFORM_DRIVER_BEGIN(qcom_pdc)
--
2.43.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v3 2/8] irqchip/qcom-pdc: Move all statics to struct pdc_desc
2026-06-16 9:25 [PATCH v3 0/8] x1e80100: Enable PDC wake GPIOs and deepest idle state Maulik Shah
2026-06-16 9:25 ` [PATCH v3 1/8] irqchip/qcom-pdc: restructure version support Maulik Shah
@ 2026-06-16 9:25 ` Maulik Shah
2026-06-17 13:26 ` Konrad Dybcio
2026-06-30 14:46 ` Thomas Gleixner
2026-06-16 9:25 ` [PATCH v3 3/8] irqchip/qcom-pdc: Remove pdc_enable_intr() wrapper Maulik Shah
` (7 subsequent siblings)
9 siblings, 2 replies; 32+ messages in thread
From: Maulik Shah @ 2026-06-16 9:25 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Thomas Gleixner, Linus Walleij
Cc: linux-arm-msm, linux-kernel, devicetree, linux-gpio, Sneh Mankad,
Maulik Shah
There are multiple statics used. Move all to struct pdc_desc to better
align with versioning support. Document them.
No functional impact.
Signed-off-by: Maulik Shah <maulik.shah@oss.qualcomm.com>
---
drivers/irqchip/qcom-pdc.c | 77 ++++++++++++++++++++++++----------------------
1 file changed, 40 insertions(+), 37 deletions(-)
diff --git a/drivers/irqchip/qcom-pdc.c b/drivers/irqchip/qcom-pdc.c
index 23276325211d..b9acb0f25c9c 100644
--- a/drivers/irqchip/qcom-pdc.c
+++ b/drivers/irqchip/qcom-pdc.c
@@ -92,15 +92,30 @@ struct pdc_irq_cfg {
* @base: PDC base register for DRV2 / HLOS
* @prev_base: PDC DRV1 base, applicable only for x1e RTL bug.
* @version: PDC version
+ * @region: PDC interrupt continuous range
+ * @region_cnt: Total PDC ranges
+ * @x1e_quirk: x1e H/W Bug handling
+ * @lock: lock for IRQ_ENABLE_BANK protection
* @regs: PDC regs (IRQ_ENABLE_BANK and IRQ_CFG)
* @cfg_fields: Fields of IRQ_CFG reg
+ * @enable_intr: pointer to enable function based on PDC version
*/
struct pdc_desc {
void __iomem *base;
void __iomem *prev_base;
u32 version;
+
+ struct pdc_pin_region *region;
+ int region_cnt;
+
+ bool x1e_quirk;
+
+ raw_spinlock_t lock;
+
const struct pdc_regs *regs;
const struct pdc_irq_cfg *cfg_fields;
+
+ void (*enable_intr)(int pin_out, bool on);
};
static const struct pdc_regs pdc_v3_2 = {
@@ -138,11 +153,6 @@ struct pdc_pin_region {
#define pin_to_hwirq(r, p) ((r)->parent_base + (p) - (r)->pin_base)
-static DEFINE_RAW_SPINLOCK(pdc_lock);
-static struct pdc_pin_region *pdc_region;
-static int pdc_region_cnt;
-static unsigned int pdc_version;
-static bool pdc_x1e_quirk;
static struct pdc_desc *pdc;
static void pdc_base_reg_write(void __iomem *base, int reg, u32 i, u32 val)
@@ -199,7 +209,7 @@ static void pdc_enable_intr_bank(int pin_out, bool on)
enable = pdc_reg_read(pdc->regs->irq_en_reg, index);
__assign_bit(mask, &enable, on);
- if (pdc_x1e_quirk)
+ if (pdc->x1e_quirk)
pdc_x1e_irq_enable_write(index, enable);
else
pdc_reg_write(pdc->regs->irq_en_reg, index, enable);
@@ -213,21 +223,11 @@ static void pdc_enable_intr_cfg(int pin_out, bool on)
pdc_reg_write(pdc->regs->irq_cfg_reg, pin_out, enable);
}
-static void __pdc_enable_intr(int pin_out, bool on)
-{
- if (pdc_version < PDC_VERSION_3_2)
- pdc_enable_intr_bank(pin_out, on);
- else
- pdc_enable_intr_cfg(pin_out, on);
-}
-
static void pdc_enable_intr(struct irq_data *d, bool on)
{
- unsigned long flags;
+ guard(raw_spinlock)(&pdc->lock);
- raw_spin_lock_irqsave(&pdc_lock, flags);
- __pdc_enable_intr(d->hwirq, on);
- raw_spin_unlock_irqrestore(&pdc_lock, flags);
+ pdc->enable_intr(d->hwirq, on);
}
static void qcom_pdc_gic_disable(struct irq_data *d)
@@ -350,12 +350,10 @@ static struct irq_chip qcom_pdc_gic_chip = {
static struct pdc_pin_region *get_pin_region(int pin)
{
- int i;
-
- for (i = 0; i < pdc_region_cnt; i++) {
- if (pin >= pdc_region[i].pin_base &&
- pin < pdc_region[i].pin_base + pdc_region[i].cnt)
- return &pdc_region[i];
+ for (int i = 0; i < pdc->region_cnt; i++) {
+ if (pin >= pdc->region[i].pin_base &&
+ pin < pdc->region[i].pin_base + pdc->region[i].cnt)
+ return &pdc->region[i];
}
return NULL;
@@ -411,39 +409,39 @@ static const struct irq_domain_ops qcom_pdc_ops = {
static int pdc_setup_pin_mapping(struct device *dev, struct device_node *np)
{
- int ret, n, i;
+ int ret, n;
n = of_property_count_elems_of_size(np, "qcom,pdc-ranges", sizeof(u32));
if (n <= 0 || n % 3)
return -EINVAL;
- pdc_region_cnt = n / 3;
- pdc_region = devm_kcalloc(dev, pdc_region_cnt, sizeof(*pdc_region),
- GFP_KERNEL);
- if (!pdc_region) {
- pdc_region_cnt = 0;
+ pdc->region_cnt = n / 3;
+ pdc->region = devm_kcalloc(dev, pdc->region_cnt, sizeof(*pdc->region),
+ GFP_KERNEL);
+ if (!pdc->region) {
+ pdc->region_cnt = 0;
return -ENOMEM;
}
- for (n = 0; n < pdc_region_cnt; n++) {
+ for (n = 0; n < pdc->region_cnt; n++) {
ret = of_property_read_u32_index(np, "qcom,pdc-ranges",
n * 3 + 0,
- &pdc_region[n].pin_base);
+ &pdc->region[n].pin_base);
if (ret)
return ret;
ret = of_property_read_u32_index(np, "qcom,pdc-ranges",
n * 3 + 1,
- &pdc_region[n].parent_base);
+ &pdc->region[n].parent_base);
if (ret)
return ret;
ret = of_property_read_u32_index(np, "qcom,pdc-ranges",
n * 3 + 2,
- &pdc_region[n].cnt);
+ &pdc->region[n].cnt);
if (ret)
return ret;
- for (i = 0; i < pdc_region[n].cnt; i++)
- __pdc_enable_intr(i + pdc_region[n].pin_base, 0);
+ for (int i = 0; i < pdc->region[n].cnt; i++)
+ pdc->enable_intr(i + pdc->region[n].pin_base, 0);
}
return 0;
@@ -481,13 +479,16 @@ static int qcom_pdc_probe(struct platform_device *pdev, struct device_node *pare
if (pdc->version >= PDC_VERSION_3_2) {
pdc->cfg_fields = &pdc_cfg_v3_2;
pdc->regs = &pdc_v3_2;
+ pdc->enable_intr = pdc_enable_intr_cfg;
} else if (pdc->version < PDC_VERSION_3_2 &&
pdc->version >= PDC_VERSION_3_0) {
pdc->cfg_fields = &pdc_cfg_v3_0;
pdc->regs = &pdc_v3_0;
+ pdc->enable_intr = pdc_enable_intr_bank;
} else {
pdc->cfg_fields = &pdc_cfg_v2_7;
pdc->regs = &pdc_v2_7;
+ pdc->enable_intr = pdc_enable_intr_bank;
}
/*
@@ -506,7 +507,7 @@ static int qcom_pdc_probe(struct platform_device *pdev, struct device_node *pare
return -ENXIO;
}
- pdc_x1e_quirk = true;
+ pdc->x1e_quirk = true;
}
parent_domain = irq_find_host(parent);
@@ -521,6 +522,8 @@ static int qcom_pdc_probe(struct platform_device *pdev, struct device_node *pare
return ret;
}
+ raw_spin_lock_init(&pdc->lock);
+
pdc_domain = irq_domain_create_hierarchy(parent_domain,
IRQ_DOMAIN_FLAG_QCOM_PDC_WAKEUP,
PDC_MAX_IRQS,
--
2.43.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v3 3/8] irqchip/qcom-pdc: Remove pdc_enable_intr() wrapper
2026-06-16 9:25 [PATCH v3 0/8] x1e80100: Enable PDC wake GPIOs and deepest idle state Maulik Shah
2026-06-16 9:25 ` [PATCH v3 1/8] irqchip/qcom-pdc: restructure version support Maulik Shah
2026-06-16 9:25 ` [PATCH v3 2/8] irqchip/qcom-pdc: Move all statics to struct pdc_desc Maulik Shah
@ 2026-06-16 9:25 ` Maulik Shah
2026-06-28 17:54 ` Val Packett
2026-06-16 9:25 ` [PATCH v3 4/8] irqchip/qcom-pdc: Differentiate between direct SPI and GPIO as SPI Maulik Shah
` (6 subsequent siblings)
9 siblings, 1 reply; 32+ messages in thread
From: Maulik Shah @ 2026-06-16 9:25 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Thomas Gleixner, Linus Walleij
Cc: linux-arm-msm, linux-kernel, devicetree, linux-gpio, Sneh Mankad,
Maulik Shah
pdc->enable_intr() function already points to respective version
specific enable function. pdc_enable_intr() now only kept as wrapper.
Remove the wrapper and invoke pdc->enable_intr() from caller.
Locking in pdc_enable_intr() applies lock to all pdc->enable_intr()
however its only required for pdc_enable_intr_bank() which uses
a shared bank across all interrupts. pdc_enable_intr_cfg() do not
required locking as IRQ_CFG registers are one per interrupt. Move
locking accordingly.
Signed-off-by: Maulik Shah <maulik.shah@oss.qualcomm.com>
---
drivers/irqchip/qcom-pdc.c | 13 ++++---------
1 file changed, 4 insertions(+), 9 deletions(-)
diff --git a/drivers/irqchip/qcom-pdc.c b/drivers/irqchip/qcom-pdc.c
index b9acb0f25c9c..6c556464d37c 100644
--- a/drivers/irqchip/qcom-pdc.c
+++ b/drivers/irqchip/qcom-pdc.c
@@ -206,6 +206,8 @@ static void pdc_enable_intr_bank(int pin_out, bool on)
index = FIELD_GET(IRQ_ENABLE_BANK_INDEX_MASK, pin_out);
mask = FIELD_GET(IRQ_ENABLE_BANK_BIT_MASK, pin_out);
+ guard(raw_spinlock)(&pdc->lock);
+
enable = pdc_reg_read(pdc->regs->irq_en_reg, index);
__assign_bit(mask, &enable, on);
@@ -223,22 +225,15 @@ static void pdc_enable_intr_cfg(int pin_out, bool on)
pdc_reg_write(pdc->regs->irq_cfg_reg, pin_out, enable);
}
-static void pdc_enable_intr(struct irq_data *d, bool on)
-{
- guard(raw_spinlock)(&pdc->lock);
-
- pdc->enable_intr(d->hwirq, on);
-}
-
static void qcom_pdc_gic_disable(struct irq_data *d)
{
- pdc_enable_intr(d, false);
+ pdc->enable_intr(d->hwirq, false);
irq_chip_disable_parent(d);
}
static void qcom_pdc_gic_enable(struct irq_data *d)
{
- pdc_enable_intr(d, true);
+ pdc->enable_intr(d->hwirq, true);
irq_chip_enable_parent(d);
}
--
2.43.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v3 4/8] irqchip/qcom-pdc: Differentiate between direct SPI and GPIO as SPI
2026-06-16 9:25 [PATCH v3 0/8] x1e80100: Enable PDC wake GPIOs and deepest idle state Maulik Shah
` (2 preceding siblings ...)
2026-06-16 9:25 ` [PATCH v3 3/8] irqchip/qcom-pdc: Remove pdc_enable_intr() wrapper Maulik Shah
@ 2026-06-16 9:25 ` Maulik Shah
2026-06-18 8:02 ` Konrad Dybcio
2026-06-30 14:57 ` Thomas Gleixner
2026-06-16 9:25 ` [PATCH v3 5/8] irqchip/qcom-pdc: Configure PDC to pass through mode Maulik Shah
` (5 subsequent siblings)
9 siblings, 2 replies; 32+ messages in thread
From: Maulik Shah @ 2026-06-16 9:25 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Thomas Gleixner, Linus Walleij
Cc: linux-arm-msm, linux-kernel, devicetree, linux-gpio, Sneh Mankad,
Maulik Shah
Before commit 4dc70713dc24 ("irqchip/qcom-pdc: Kill non-wakeup irqdomain")
there are separate domains for direct SPIs and GPIO used as SPIs. Separate
domains can be useful in case irqchip want to differentiate both of them.
Since commit unified both the domains there is no way to differentiate.
In preparation to add the second level interrupt controller support where
GPIO interrupts get latched at PDC (but not direct SPIs) there is a need to
differentiate between SPIs and GPIOs as SPIs. Reverting above commit do not
seem a good option either which leads to waste of resources.
PDC HW have the IRQ_PARAM register telling number of direct SPIs and number
of GPIOs as SPIs. Further PDC allocates direct SPIs at the beginning and
all GPIOs as SPIs are allocated at the end. This information can be used in
driver to differentiate them.
Add the support to read this register and keep this information in
struct pdc_desc. Later change utilizes same.
Signed-off-by: Maulik Shah <maulik.shah@oss.qualcomm.com>
---
drivers/irqchip/qcom-pdc.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/drivers/irqchip/qcom-pdc.c b/drivers/irqchip/qcom-pdc.c
index 6c556464d37c..1aa6be42307c 100644
--- a/drivers/irqchip/qcom-pdc.c
+++ b/drivers/irqchip/qcom-pdc.c
@@ -61,6 +61,11 @@
* | | [4] GPIO_STATUS| [4] GPIO_MASK |
* | [31:3] Unused | [3] GPIO_MASK | [3] IRQ_ENABLE |
* | [0:2] Type | [0:2] Type | [0:2] Type |
+ * |---------------------------------------------------------------|
+ * | IRQ_PARAM | IRQ_PARAM | IRQ_PARAM |
+ * | | |
+ * | [15:8] NUM_GPIO | [15:8] NUM_GPIO | [15:8] NUM_GPIO |
+ * | [7:0] NUM_SPI | [7:0] NUM_SPI | [7:0] NUM_SPI |
* +---------------------------------------------------------------+
*/
@@ -69,10 +74,12 @@
*
* @irq_en_reg: IRQ_ENABLE_BANK register location
* @irq_cfg_reg: IRQ_CFG register location
+ * @irq_param_reg: IRQ_PARAM register location
*/
struct pdc_regs {
u32 irq_en_reg;
u32 irq_cfg_reg;
+ u32 irq_param_reg;
};
/**
@@ -92,6 +99,8 @@ struct pdc_irq_cfg {
* @base: PDC base register for DRV2 / HLOS
* @prev_base: PDC DRV1 base, applicable only for x1e RTL bug.
* @version: PDC version
+ * @num_spis: Total number of direct SPI interrupts
+ * @num_gpios: Total number of GPIOs forwarded as SPI interrupts
* @region: PDC interrupt continuous range
* @region_cnt: Total PDC ranges
* @x1e_quirk: x1e H/W Bug handling
@@ -104,6 +113,8 @@ struct pdc_desc {
void __iomem *base;
void __iomem *prev_base;
u32 version;
+ u32 num_spis;
+ u32 num_gpios;
struct pdc_pin_region *region;
int region_cnt;
@@ -120,6 +131,7 @@ struct pdc_desc {
static const struct pdc_regs pdc_v3_2 = {
.irq_cfg_reg = 0x110,
+ .irq_param_reg = 0x100c,
};
static const struct pdc_irq_cfg pdc_cfg_v3_2 = {
@@ -130,6 +142,7 @@ static const struct pdc_irq_cfg pdc_cfg_v3_2 = {
static const struct pdc_regs pdc_v3_0 = {
.irq_en_reg = 0x10,
.irq_cfg_reg = 0x110,
+ .irq_param_reg = 0x100c,
};
static const struct pdc_irq_cfg pdc_cfg_v3_0 = {
@@ -139,6 +152,7 @@ static const struct pdc_irq_cfg pdc_cfg_v3_0 = {
static const struct pdc_regs pdc_v2_7 = {
.irq_en_reg = 0x10,
.irq_cfg_reg = 0x110,
+ .irq_param_reg = 0x100c,
};
static const struct pdc_irq_cfg pdc_cfg_v2_7 = {
@@ -449,6 +463,7 @@ static int qcom_pdc_probe(struct platform_device *pdev, struct device_node *pare
struct device *dev = &pdev->dev;
resource_size_t res_size;
struct resource res;
+ u32 irq_param;
int ret;
/* compat with old sm8150 DT which had very small region for PDC */
@@ -505,6 +520,10 @@ static int qcom_pdc_probe(struct platform_device *pdev, struct device_node *pare
pdc->x1e_quirk = true;
}
+ irq_param = pdc_reg_read(pdc->regs->irq_param_reg, 0);
+ pdc->num_spis = FIELD_GET(GENMASK(7, 0), irq_param);
+ pdc->num_gpios = FIELD_GET(GENMASK(15, 8), irq_param);
+
parent_domain = irq_find_host(parent);
if (!parent_domain) {
pr_err("%pOF: unable to find PDC's parent domain\n", node);
--
2.43.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v3 5/8] irqchip/qcom-pdc: Configure PDC to pass through mode
2026-06-16 9:25 [PATCH v3 0/8] x1e80100: Enable PDC wake GPIOs and deepest idle state Maulik Shah
` (3 preceding siblings ...)
2026-06-16 9:25 ` [PATCH v3 4/8] irqchip/qcom-pdc: Differentiate between direct SPI and GPIO as SPI Maulik Shah
@ 2026-06-16 9:25 ` Maulik Shah
2026-06-18 8:18 ` Konrad Dybcio
` (2 more replies)
2026-06-16 9:25 ` [PATCH v3 6/8] pinctrl: qcom: Acknowledge IRQs for PDC interrupt controller Maulik Shah
` (4 subsequent siblings)
9 siblings, 3 replies; 32+ messages in thread
From: Maulik Shah @ 2026-06-16 9:25 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Thomas Gleixner, Linus Walleij
Cc: linux-arm-msm, linux-kernel, devicetree, linux-gpio, Sneh Mankad,
Maulik Shah
All PDC irqchip supports pass through mode in which both Direct SPIs and
GPIO IRQs (as SPIs) are sent to GIC without latching at PDC.
Newer PDCs (v3.0 onwards) also support additional secondary controller mode
where PDC latches GPIO IRQs and sends to GIC as level type IRQ. Direct SPIs
still works same as pass through mode without latching at PDC even in
secondary controller mode.
All the SoCs so far default uses pass through mode with the exception of
x1e. x1e PDC may be set to secondary controller mode for builds on CRD
boards whereas it may be set to pass through mode for IoT-EVK boards.
The mode configuration is done in firmware and initially shipped windows
firmware did not have SCM interface to read or modify the PDC mode.
Later only write access is opened up for non secure world.
Using the write access available add changes to modify the PDC mode to
pass through mode via SCM write. When the write fails (on older firmware)
assume to work in secondary mode.
In secondary mode set the separate irqchip for the GPIOs to perform
additional operations only for the GPIO irqs.
Co-developed-by: Sneh Mankad <sneh.mankad@oss.qualcomm.com>
Signed-off-by: Sneh Mankad <sneh.mankad@oss.qualcomm.com>
Signed-off-by: Maulik Shah <maulik.shah@oss.qualcomm.com>
---
drivers/irqchip/qcom-pdc.c | 220 ++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 208 insertions(+), 12 deletions(-)
diff --git a/drivers/irqchip/qcom-pdc.c b/drivers/irqchip/qcom-pdc.c
index 1aa6be42307c..c6f2935ff788 100644
--- a/drivers/irqchip/qcom-pdc.c
+++ b/drivers/irqchip/qcom-pdc.c
@@ -20,12 +20,18 @@
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/types.h>
+#include <linux/firmware/qcom/qcom_scm.h>
#define PDC_MAX_IRQS 256
#define IRQ_ENABLE_BANK_MAX BITS_TO_BYTES(PDC_MAX_IRQS)
#define IRQ_ENABLE_BANK_INDEX_MASK GENMASK(31, 5)
#define IRQ_ENABLE_BANK_BIT_MASK GENMASK(4, 0)
+/* Secure DRV register to configure the PDC mode via qcom_scm_io_writel() */
+#define PDC_GPIO_INT_CTL_ENABLE 0xb2045e8
+#define PDC_PASS_THROUGH_MODE 0x0
+#define PDC_SECONDARY_MODE 0x1
+
#define PDC_DRV_SIZE 0x10000
#define PDC_VERSION_REG 0x1000
#define PDC_VERSION_MAJOR GENMASK(23, 16)
@@ -85,10 +91,14 @@ struct pdc_regs {
/**
* struct pdc_irq_cfg: bit fields for PDC IRQ_CFG register
*
+ * @gpio_irq_sts: bit number for GPIO_STATUS field
+ * @gpio_irq_mask: bit number for GPIO_MASK field
* @irq_enable: bit number for IRQ_ENABLE field
* @irq_type: GENMASK for IRQ_TYPE field
*/
struct pdc_irq_cfg {
+ u32 gpio_irq_sts;
+ u32 gpio_irq_mask;
u32 irq_enable;
u32 irq_type;
};
@@ -103,11 +113,14 @@ struct pdc_irq_cfg {
* @num_gpios: Total number of GPIOs forwarded as SPI interrupts
* @region: PDC interrupt continuous range
* @region_cnt: Total PDC ranges
+ * @mode: PDC_PASS_THROUGH_MODE or PDC_SECONDARY_MODE
* @x1e_quirk: x1e H/W Bug handling
* @lock: lock for IRQ_ENABLE_BANK protection
* @regs: PDC regs (IRQ_ENABLE_BANK and IRQ_CFG)
* @cfg_fields: Fields of IRQ_CFG reg
* @enable_intr: pointer to enable function based on PDC version
+ * @unmask_gpio: pointer to GPIO irq unmask function
+ * @clear_gpio: pointer to GPIO irq clear function
*/
struct pdc_desc {
void __iomem *base;
@@ -119,6 +132,7 @@ struct pdc_desc {
struct pdc_pin_region *region;
int region_cnt;
+ u8 mode;
bool x1e_quirk;
raw_spinlock_t lock;
@@ -127,6 +141,8 @@ struct pdc_desc {
const struct pdc_irq_cfg *cfg_fields;
void (*enable_intr)(int pin_out, bool on);
+ void (*unmask_gpio)(int pin_out, bool on);
+ void (*clear_gpio)(int pin_out);
};
static const struct pdc_regs pdc_v3_2 = {
@@ -135,6 +151,8 @@ static const struct pdc_regs pdc_v3_2 = {
};
static const struct pdc_irq_cfg pdc_cfg_v3_2 = {
+ .gpio_irq_sts = 5,
+ .gpio_irq_mask = 4,
.irq_enable = 3,
.irq_type = GENMASK(2, 0),
};
@@ -146,6 +164,8 @@ static const struct pdc_regs pdc_v3_0 = {
};
static const struct pdc_irq_cfg pdc_cfg_v3_0 = {
+ .gpio_irq_sts = 4,
+ .gpio_irq_mask = 3,
.irq_type = GENMASK(2, 0),
};
@@ -184,6 +204,15 @@ static u32 pdc_reg_read(int reg, u32 i)
return readl_relaxed(pdc->base + reg + i * sizeof(u32));
}
+static inline bool pdc_pin_is_gpio(int pin_out)
+{
+ /*
+ * PDC allocates direct SPIs at the beginning and
+ * all GPIOs as SPIs are allocated after direct SPIs.
+ */
+ return pin_out >= pdc->num_spis;
+}
+
static void pdc_x1e_irq_enable_write(u32 bank, u32 enable)
{
void __iomem *base;
@@ -231,6 +260,30 @@ static void pdc_enable_intr_bank(int pin_out, bool on)
pdc_reg_write(pdc->regs->irq_en_reg, index, enable);
}
+static void pdc_clear_gpio_cfg(int pin_out)
+{
+ unsigned long gpio_sts;
+
+ if (pdc->version < PDC_VERSION_3_0)
+ return;
+
+ gpio_sts = pdc_reg_read(pdc->regs->irq_cfg_reg, pin_out);
+ __clear_bit(pdc->cfg_fields->gpio_irq_sts, &gpio_sts);
+ pdc_reg_write(pdc->regs->irq_cfg_reg, pin_out, gpio_sts);
+}
+
+static void pdc_unmask_gpio_cfg(int pin_out, bool unmask)
+{
+ unsigned long gpio_mask;
+
+ if (pdc->version < PDC_VERSION_3_0)
+ return;
+
+ gpio_mask = pdc_reg_read(pdc->regs->irq_cfg_reg, pin_out);
+ __assign_bit(pdc->cfg_fields->gpio_irq_mask, &gpio_mask, !unmask);
+ pdc_reg_write(pdc->regs->irq_cfg_reg, pin_out, gpio_mask);
+}
+
static void pdc_enable_intr_cfg(int pin_out, bool on)
{
unsigned long enable = pdc_reg_read(pdc->regs->irq_cfg_reg, pin_out);
@@ -245,12 +298,40 @@ static void qcom_pdc_gic_disable(struct irq_data *d)
irq_chip_disable_parent(d);
}
+static void qcom_pdc_gic_secondary_disable(struct irq_data *d)
+{
+ pdc->enable_intr(d->hwirq, false);
+ pdc->unmask_gpio(d->hwirq, false);
+ irq_chip_disable_parent(d);
+}
+
static void qcom_pdc_gic_enable(struct irq_data *d)
{
pdc->enable_intr(d->hwirq, true);
irq_chip_enable_parent(d);
}
+static void qcom_pdc_gic_secondary_enable(struct irq_data *d)
+{
+ pdc->enable_intr(d->hwirq, true);
+ pdc->unmask_gpio(d->hwirq, true);
+ irq_chip_enable_parent(d);
+}
+
+static void qcom_pdc_secondary_ack(struct irq_data *d)
+{
+ if (!irqd_is_level_type(d))
+ pdc->clear_gpio(d->hwirq);
+}
+
+static void qcom_pdc_gic_secondary_eoi(struct irq_data *d)
+{
+ if (irqd_is_level_type(d))
+ pdc->clear_gpio(d->hwirq);
+
+ irq_chip_eoi_parent(d);
+}
+
/*
* GIC does not handle falling edge or active low. To allow falling edge and
* active low interrupts to be handled at GIC, PDC has an inverter that inverts
@@ -338,6 +419,67 @@ static int qcom_pdc_gic_set_type(struct irq_data *d, unsigned int type)
return 0;
}
+/**
+ * qcom_pdc_gic_set_type: Configure PDC for the interrupt
+ *
+ * @d: the interrupt data
+ * @type: the interrupt type
+ *
+ * All @type are forwarded as Level type to parent GIC
+ */
+static int qcom_pdc_gic_secondary_set_type(struct irq_data *d, unsigned int type)
+{
+ enum pdc_irq_config_bits pdc_type;
+ enum pdc_irq_config_bits old_pdc_type;
+ int ret;
+
+ switch (type) {
+ case IRQ_TYPE_EDGE_RISING:
+ pdc_type = PDC_EDGE_RISING;
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ pdc_type = PDC_EDGE_FALLING;
+ break;
+ case IRQ_TYPE_EDGE_BOTH:
+ pdc_type = PDC_EDGE_DUAL;
+ break;
+ case IRQ_TYPE_LEVEL_HIGH:
+ pdc_type = PDC_LEVEL_HIGH;
+ break;
+ case IRQ_TYPE_LEVEL_LOW:
+ pdc_type = PDC_LEVEL_LOW;
+ break;
+ default:
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ old_pdc_type = pdc_reg_read(pdc->regs->irq_cfg_reg, d->hwirq);
+ pdc_type |= (old_pdc_type & ~pdc->cfg_fields->irq_type);
+ pdc_reg_write(pdc->regs->irq_cfg_reg, d->hwirq, pdc_type);
+
+ type = IRQ_TYPE_LEVEL_HIGH;
+ pdc->clear_gpio(d->hwirq);
+
+ ret = irq_chip_set_type_parent(d, type);
+ if (ret)
+ return ret;
+
+ /*
+ * When we change types the PDC can give a phantom interrupt.
+ * Clear it. Specifically the phantom shows up when reconfiguring
+ * polarity of interrupt without changing the state of the signal
+ * but let's be consistent and clear it always.
+ *
+ * Doing this works because we have IRQCHIP_SET_TYPE_MASKED so the
+ * interrupt will be cleared before the rest of the system sees it.
+ */
+ if (old_pdc_type != pdc_type)
+ irq_chip_set_parent_state(d, IRQCHIP_STATE_PENDING, false);
+
+ return 0;
+}
+
static struct irq_chip qcom_pdc_gic_chip = {
.name = "PDC",
.irq_eoi = irq_chip_eoi_parent,
@@ -357,6 +499,26 @@ static struct irq_chip qcom_pdc_gic_chip = {
.irq_set_affinity = irq_chip_set_affinity_parent,
};
+static struct irq_chip qcom_pdc_gic_secondary_chip = {
+ .name = "PDC",
+ .irq_ack = qcom_pdc_secondary_ack,
+ .irq_eoi = qcom_pdc_gic_secondary_eoi,
+ .irq_mask = irq_chip_mask_parent,
+ .irq_unmask = irq_chip_unmask_parent,
+ .irq_disable = qcom_pdc_gic_secondary_disable,
+ .irq_enable = qcom_pdc_gic_secondary_enable,
+ .irq_get_irqchip_state = irq_chip_get_parent_state,
+ .irq_set_irqchip_state = irq_chip_set_parent_state,
+ .irq_retrigger = irq_chip_retrigger_hierarchy,
+ .irq_set_type = qcom_pdc_gic_secondary_set_type,
+ .flags = IRQCHIP_MASK_ON_SUSPEND |
+ IRQCHIP_SET_TYPE_MASKED |
+ IRQCHIP_SKIP_SET_WAKE |
+ IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND,
+ .irq_set_vcpu_affinity = irq_chip_set_vcpu_affinity_parent,
+ .irq_set_affinity = irq_chip_set_affinity_parent,
+};
+
static struct pdc_pin_region *get_pin_region(int pin)
{
for (int i = 0; i < pdc->region_cnt; i++) {
@@ -385,20 +547,37 @@ static int qcom_pdc_alloc(struct irq_domain *domain, unsigned int virq,
if (hwirq == GPIO_NO_WAKE_IRQ)
return irq_domain_disconnect_hierarchy(domain, virq);
- ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq,
- &qcom_pdc_gic_chip, NULL);
- if (ret)
- return ret;
+ /*
+ * PDC secondary chip is only set for the GPIO interrupts as SPIs.
+ * Direct SPI interrupts are still in pass through mode (no latching
+ * at PDC).
+ */
+ if (pdc->mode == PDC_PASS_THROUGH_MODE || !pdc_pin_is_gpio(hwirq)) {
+ ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq,
+ &qcom_pdc_gic_chip,
+ NULL);
+ if (ret)
+ return ret;
- region = get_pin_region(hwirq);
- if (!region)
- return irq_domain_disconnect_hierarchy(domain->parent, virq);
+ if (type & IRQ_TYPE_EDGE_BOTH)
+ type = IRQ_TYPE_EDGE_RISING;
- if (type & IRQ_TYPE_EDGE_BOTH)
- type = IRQ_TYPE_EDGE_RISING;
+ if (type & IRQ_TYPE_LEVEL_MASK)
+ type = IRQ_TYPE_LEVEL_HIGH;
+ } else {
+ ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq,
+ &qcom_pdc_gic_secondary_chip,
+ NULL);
+ if (ret)
+ return ret;
- if (type & IRQ_TYPE_LEVEL_MASK)
+ /* Secondary mode converts all interrupts to LEVEL HIGH type */
type = IRQ_TYPE_LEVEL_HIGH;
+ }
+
+ region = get_pin_region(hwirq);
+ if (!region)
+ return irq_domain_disconnect_hierarchy(domain->parent, virq);
parent_fwspec.fwnode = domain->parent->fwnode;
parent_fwspec.param_count = 3;
@@ -449,8 +628,13 @@ static int pdc_setup_pin_mapping(struct device *dev, struct device_node *np)
if (ret)
return ret;
- for (int i = 0; i < pdc->region[n].cnt; i++)
- pdc->enable_intr(i + pdc->region[n].pin_base, 0);
+ for (int i = 0; i < pdc->region[n].cnt; i++) {
+ if (pdc_pin_is_gpio(i + pdc->region[n].pin_base) &&
+ pdc->mode == PDC_SECONDARY_MODE)
+ pdc->clear_gpio(i + pdc->region[n].pin_base);
+
+ pdc->enable_intr(i + pdc->region[n].pin_base, false);
+ }
}
return 0;
@@ -501,6 +685,8 @@ static int qcom_pdc_probe(struct platform_device *pdev, struct device_node *pare
pdc->enable_intr = pdc_enable_intr_bank;
}
+ pdc->mode = PDC_PASS_THROUGH_MODE;
+
/*
* PDC has multiple DRV regions, each one provides the same set of
* registers for a particular client in the system. Due to a hardware
@@ -518,6 +704,16 @@ static int qcom_pdc_probe(struct platform_device *pdev, struct device_node *pare
}
pdc->x1e_quirk = true;
+
+ if (!qcom_scm_is_available())
+ return -EPROBE_DEFER;
+
+ ret = qcom_scm_io_writel(PDC_GPIO_INT_CTL_ENABLE, PDC_PASS_THROUGH_MODE);
+ if (ret) {
+ pdc->mode = PDC_SECONDARY_MODE;
+ pdc->unmask_gpio = pdc_unmask_gpio_cfg;
+ pdc->clear_gpio = pdc_clear_gpio_cfg;
+ }
}
irq_param = pdc_reg_read(pdc->regs->irq_param_reg, 0);
--
2.43.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v3 6/8] pinctrl: qcom: Acknowledge IRQs for PDC interrupt controller
2026-06-16 9:25 [PATCH v3 0/8] x1e80100: Enable PDC wake GPIOs and deepest idle state Maulik Shah
` (4 preceding siblings ...)
2026-06-16 9:25 ` [PATCH v3 5/8] irqchip/qcom-pdc: Configure PDC to pass through mode Maulik Shah
@ 2026-06-16 9:25 ` Maulik Shah
2026-06-16 9:25 ` [PATCH v3 7/8] Revert "pinctrl: qcom: x1e80100: Bypass PDC wakeup parent for now" Maulik Shah
` (3 subsequent siblings)
9 siblings, 0 replies; 32+ messages in thread
From: Maulik Shah @ 2026-06-16 9:25 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Thomas Gleixner, Linus Walleij
Cc: linux-arm-msm, linux-kernel, devicetree, linux-gpio, Sneh Mankad,
Maulik Shah, Stephan Gerhold
From: Stephan Gerhold <stephan.gerhold@linaro.org>
PDC needs to acknowledge incoming GPIO interrupts to clear the latched
interrupt status in secondary mode of PDC. For level-triggered IRQs this
happens automatically in irq_eoi() but for edge-triggered IRQs this needs
to happen as early as possible in the IRQ handler.
Implement this by using handle_fasteoi_ack_irq() as IRQ handler in this
situation and forward the irq_ack() callback to the parent IRQ chip.
Signed-off-by: Stephan Gerhold <stephan.gerhold@linaro.org>
Signed-off-by: Maulik Shah <maulik.shah@oss.qualcomm.com>
---
drivers/pinctrl/qcom/pinctrl-msm.c | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c
index 11db6564c44d..17665e1a9dbc 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm.c
@@ -995,6 +995,16 @@ static void msm_gpio_irq_ack(struct irq_data *d)
if (test_bit(d->hwirq, pctrl->skip_wake_irqs)) {
if (test_bit(d->hwirq, pctrl->dual_edge_irqs))
msm_gpio_update_dual_edge_parent(d);
+
+ /*
+ * During early initialization of the IRQ hierarchy,
+ * irq_ack() is called by __irq_set_handler() before
+ * the parent IRQ chip has been set up. This is why
+ * we additionally need to check for d->parent_data->chip.
+ */
+
+ if (d->parent_data->chip && d->parent_data->chip->irq_ack)
+ irq_chip_ack_parent(d);
return;
}
@@ -1067,7 +1077,10 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type)
if (test_bit(d->hwirq, pctrl->skip_wake_irqs)) {
clear_bit(d->hwirq, pctrl->dual_edge_irqs);
- irq_set_handler_locked(d, handle_fasteoi_irq);
+ if (type & IRQ_TYPE_LEVEL_MASK)
+ irq_set_handler_locked(d, handle_fasteoi_irq);
+ else
+ irq_set_handler_locked(d, handle_fasteoi_ack_irq);
return 0;
}
@@ -1395,6 +1408,7 @@ static const struct irq_chip msm_gpio_irq_chip = {
.flags = (IRQCHIP_MASK_ON_SUSPEND |
IRQCHIP_SET_TYPE_MASKED |
IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND |
+ IRQCHIP_EOI_THREADED |
IRQCHIP_IMMUTABLE),
};
--
2.43.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v3 7/8] Revert "pinctrl: qcom: x1e80100: Bypass PDC wakeup parent for now"
2026-06-16 9:25 [PATCH v3 0/8] x1e80100: Enable PDC wake GPIOs and deepest idle state Maulik Shah
` (5 preceding siblings ...)
2026-06-16 9:25 ` [PATCH v3 6/8] pinctrl: qcom: Acknowledge IRQs for PDC interrupt controller Maulik Shah
@ 2026-06-16 9:25 ` Maulik Shah
2026-06-16 9:25 ` [PATCH v3 8/8] arm64: dts: qcom: x1e80100: Add deepest idle state Maulik Shah
` (2 subsequent siblings)
9 siblings, 0 replies; 32+ messages in thread
From: Maulik Shah @ 2026-06-16 9:25 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Thomas Gleixner, Linus Walleij
Cc: linux-arm-msm, linux-kernel, devicetree, linux-gpio, Sneh Mankad,
Maulik Shah
This reverts commit 602cb14e310a ("pinctrl: qcom: x1e80100: Bypass PDC
wakeup parent for now").
PDC interrupts no more break GPIOs PDC irqchip is updated to work for
pass through or secondary mode. Update nwakeirq_map to reflect the GPIO
to PDC irq map size.
Signed-off-by: Maulik Shah <maulik.shah@oss.qualcomm.com>
---
drivers/pinctrl/qcom/pinctrl-x1e80100.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/pinctrl/qcom/pinctrl-x1e80100.c b/drivers/pinctrl/qcom/pinctrl-x1e80100.c
index 8d2b8246170b..e4c0abcd95b9 100644
--- a/drivers/pinctrl/qcom/pinctrl-x1e80100.c
+++ b/drivers/pinctrl/qcom/pinctrl-x1e80100.c
@@ -1836,9 +1836,7 @@ static const struct msm_pinctrl_soc_data x1e80100_pinctrl = {
.ngroups = ARRAY_SIZE(x1e80100_groups),
.ngpios = 239,
.wakeirq_map = x1e80100_pdc_map,
- /* TODO: Enabling PDC currently breaks GPIO interrupts */
- .nwakeirq_map = 0,
- /* .nwakeirq_map = ARRAY_SIZE(x1e80100_pdc_map), */
+ .nwakeirq_map = ARRAY_SIZE(x1e80100_pdc_map),
.egpio_func = 9,
};
--
2.43.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v3 8/8] arm64: dts: qcom: x1e80100: Add deepest idle state
2026-06-16 9:25 [PATCH v3 0/8] x1e80100: Enable PDC wake GPIOs and deepest idle state Maulik Shah
` (6 preceding siblings ...)
2026-06-16 9:25 ` [PATCH v3 7/8] Revert "pinctrl: qcom: x1e80100: Bypass PDC wakeup parent for now" Maulik Shah
@ 2026-06-16 9:25 ` Maulik Shah
2026-06-18 8:25 ` Konrad Dybcio
2026-06-28 18:39 ` [PATCH v3 0/8] x1e80100: Enable PDC wake GPIOs and " Val Packett
2026-06-30 11:42 ` Linus Walleij
9 siblings, 1 reply; 32+ messages in thread
From: Maulik Shah @ 2026-06-16 9:25 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Thomas Gleixner, Linus Walleij
Cc: linux-arm-msm, linux-kernel, devicetree, linux-gpio, Sneh Mankad,
Maulik Shah
Add deepest idle state as GPIO IRQs can work as wakeup capable interrupts
in deepest idle state.
Signed-off-by: Maulik Shah <maulik.shah@oss.qualcomm.com>
---
arch/arm64/boot/dts/qcom/hamoa.dtsi | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/qcom/hamoa.dtsi b/arch/arm64/boot/dts/qcom/hamoa.dtsi
index 4ba751a65142..47e425003028 100644
--- a/arch/arm64/boot/dts/qcom/hamoa.dtsi
+++ b/arch/arm64/boot/dts/qcom/hamoa.dtsi
@@ -302,6 +302,14 @@ cluster_cl5: cluster-sleep-1 {
exit-latency-us = <4000>;
min-residency-us = <7000>;
};
+
+ domain_ss3: domain-sleep-0 {
+ compatible = "domain-idle-state";
+ arm,psci-suspend-param = <0x0200c354>;
+ entry-latency-us = <2800>;
+ exit-latency-us = <4400>;
+ min-residency-us = <9000>;
+ };
};
};
@@ -460,7 +468,7 @@ cluster_pd2: power-domain-cpu-cluster2 {
system_pd: power-domain-system {
#power-domain-cells = <0>;
- /* TODO: system-wide idle states */
+ domain-idle-states = <&domain_ss3>;
};
};
--
2.43.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* Re: [PATCH v3 1/8] irqchip/qcom-pdc: restructure version support
2026-06-16 9:25 ` [PATCH v3 1/8] irqchip/qcom-pdc: restructure version support Maulik Shah
@ 2026-06-17 13:12 ` Konrad Dybcio
2026-06-25 9:19 ` Maulik Shah (mkshah)
2026-06-30 14:38 ` Thomas Gleixner
1 sibling, 1 reply; 32+ messages in thread
From: Konrad Dybcio @ 2026-06-17 13:12 UTC (permalink / raw)
To: Maulik Shah, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Thomas Gleixner, Linus Walleij
Cc: linux-arm-msm, linux-kernel, devicetree, linux-gpio, Sneh Mankad
On 6/16/26 11:25 AM, Maulik Shah wrote:
> PDC irqchip updates IRQ_ENABLE and IRQ_CFG and for three different
> versions v2.7, v3.0 and v3.2. These registers are organized in H/W
> as below on various SoCs.
[...]
> - ret = pdc_setup_pin_mapping(node);
> + ret = pdc_setup_pin_mapping(dev, node);
dev is enough, we can get the np in that function from dev->of_node
otherwise:
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Konrad
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v3 2/8] irqchip/qcom-pdc: Move all statics to struct pdc_desc
2026-06-16 9:25 ` [PATCH v3 2/8] irqchip/qcom-pdc: Move all statics to struct pdc_desc Maulik Shah
@ 2026-06-17 13:26 ` Konrad Dybcio
2026-06-25 9:19 ` Maulik Shah (mkshah)
2026-06-30 14:46 ` Thomas Gleixner
1 sibling, 1 reply; 32+ messages in thread
From: Konrad Dybcio @ 2026-06-17 13:26 UTC (permalink / raw)
To: Maulik Shah, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Thomas Gleixner, Linus Walleij
Cc: linux-arm-msm, linux-kernel, devicetree, linux-gpio, Sneh Mankad
On 6/16/26 11:25 AM, Maulik Shah wrote:
> There are multiple statics used. Move all to struct pdc_desc to better
> align with versioning support. Document them.
>
> No functional impact.
>
> Signed-off-by: Maulik Shah <maulik.shah@oss.qualcomm.com>
> ---
[...]
> static void pdc_enable_intr(struct irq_data *d, bool on)
> {
> - unsigned long flags;
> + guard(raw_spinlock)(&pdc->lock);
tglx suggested to use guard(irq) around "the other callsite"..
which I'm not sure where it'd be - maybe around __pdc_enable_intr()
in pdc_setup_pin_mapping()?
Otherwise this patch looks good to me
Konrad
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v3 4/8] irqchip/qcom-pdc: Differentiate between direct SPI and GPIO as SPI
2026-06-16 9:25 ` [PATCH v3 4/8] irqchip/qcom-pdc: Differentiate between direct SPI and GPIO as SPI Maulik Shah
@ 2026-06-18 8:02 ` Konrad Dybcio
2026-06-25 9:20 ` Maulik Shah (mkshah)
2026-06-30 14:57 ` Thomas Gleixner
1 sibling, 1 reply; 32+ messages in thread
From: Konrad Dybcio @ 2026-06-18 8:02 UTC (permalink / raw)
To: Maulik Shah, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Thomas Gleixner, Linus Walleij
Cc: linux-arm-msm, linux-kernel, devicetree, linux-gpio, Sneh Mankad
On 6/16/26 11:25 AM, Maulik Shah wrote:
> Before commit 4dc70713dc24 ("irqchip/qcom-pdc: Kill non-wakeup irqdomain")
> there are separate domains for direct SPIs and GPIO used as SPIs. Separate
> domains can be useful in case irqchip want to differentiate both of them.
> Since commit unified both the domains there is no way to differentiate.
>
> In preparation to add the second level interrupt controller support where
> GPIO interrupts get latched at PDC (but not direct SPIs) there is a need to
> differentiate between SPIs and GPIOs as SPIs. Reverting above commit do not
> seem a good option either which leads to waste of resources.
>
> PDC HW have the IRQ_PARAM register telling number of direct SPIs and number
> of GPIOs as SPIs. Further PDC allocates direct SPIs at the beginning and
> all GPIOs as SPIs are allocated at the end. This information can be used in
> driver to differentiate them.
>
> Add the support to read this register and keep this information in
> struct pdc_desc. Later change utilizes same.
>
> Signed-off-by: Maulik Shah <maulik.shah@oss.qualcomm.com>
> ---
[...]
> + irq_param = pdc_reg_read(pdc->regs->irq_param_reg, 0);
> + pdc->num_spis = FIELD_GET(GENMASK(7, 0), irq_param);
> + pdc->num_gpios = FIELD_GET(GENMASK(15, 8), irq_param);
num_gpios is not used in this series, please either drop it or
use it to limit the index in the following patches
Konrad
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v3 5/8] irqchip/qcom-pdc: Configure PDC to pass through mode
2026-06-16 9:25 ` [PATCH v3 5/8] irqchip/qcom-pdc: Configure PDC to pass through mode Maulik Shah
@ 2026-06-18 8:18 ` Konrad Dybcio
2026-06-25 9:24 ` Maulik Shah (mkshah)
2026-06-18 8:19 ` Konrad Dybcio
2026-06-30 15:07 ` Thomas Gleixner
2 siblings, 1 reply; 32+ messages in thread
From: Konrad Dybcio @ 2026-06-18 8:18 UTC (permalink / raw)
To: Maulik Shah, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Thomas Gleixner, Linus Walleij
Cc: linux-arm-msm, linux-kernel, devicetree, linux-gpio, Sneh Mankad
On 6/16/26 11:25 AM, Maulik Shah wrote:
> All PDC irqchip supports pass through mode in which both Direct SPIs and
> GPIO IRQs (as SPIs) are sent to GIC without latching at PDC.
>
> Newer PDCs (v3.0 onwards) also support additional secondary controller mode
> where PDC latches GPIO IRQs and sends to GIC as level type IRQ. Direct SPIs
> still works same as pass through mode without latching at PDC even in
> secondary controller mode.
>
> All the SoCs so far default uses pass through mode with the exception of
> x1e. x1e PDC may be set to secondary controller mode for builds on CRD
> boards whereas it may be set to pass through mode for IoT-EVK boards.
> The mode configuration is done in firmware and initially shipped windows
> firmware did not have SCM interface to read or modify the PDC mode.
> Later only write access is opened up for non secure world.
>
> Using the write access available add changes to modify the PDC mode to
> pass through mode via SCM write. When the write fails (on older firmware)
> assume to work in secondary mode.
>
> In secondary mode set the separate irqchip for the GPIOs to perform
> additional operations only for the GPIO irqs.
>
> Co-developed-by: Sneh Mankad <sneh.mankad@oss.qualcomm.com>
> Signed-off-by: Sneh Mankad <sneh.mankad@oss.qualcomm.com>
> Signed-off-by: Maulik Shah <maulik.shah@oss.qualcomm.com>
> ---
[...]
> +static int qcom_pdc_gic_secondary_set_type(struct irq_data *d, unsigned int type)
> +{
> + enum pdc_irq_config_bits pdc_type;
> + enum pdc_irq_config_bits old_pdc_type;
> + int ret;
> +
> + switch (type) {
> + case IRQ_TYPE_EDGE_RISING:
> + pdc_type = PDC_EDGE_RISING;
> + break;
> + case IRQ_TYPE_EDGE_FALLING:
> + pdc_type = PDC_EDGE_FALLING;
> + break;
> + case IRQ_TYPE_EDGE_BOTH:
> + pdc_type = PDC_EDGE_DUAL;
> + break;
> + case IRQ_TYPE_LEVEL_HIGH:
> + pdc_type = PDC_LEVEL_HIGH;
> + break;
> + case IRQ_TYPE_LEVEL_LOW:
> + pdc_type = PDC_LEVEL_LOW;
> + break;
> + default:
> + WARN_ON(1);
> + return -EINVAL;
> + }
> +
> + old_pdc_type = pdc_reg_read(pdc->regs->irq_cfg_reg, d->hwirq);
> + pdc_type |= (old_pdc_type & ~pdc->cfg_fields->irq_type);
> + pdc_reg_write(pdc->regs->irq_cfg_reg, d->hwirq, pdc_type);
> +
> + type = IRQ_TYPE_LEVEL_HIGH;
Please carry your comment from the previous revision:
/*
* PDC forwards GPIOs as level high to GIC in secondary
* mode. Update the type and clear any previously latched
* phantom interrupt at PDC.
*/
> + pdc->clear_gpio(d->hwirq);
> +
> + ret = irq_chip_set_type_parent(d, type);
> + if (ret)
> + return ret;
> +
> + /*
> + * When we change types the PDC can give a phantom interrupt.
> + * Clear it. Specifically the phantom shows up when reconfiguring
> + * polarity of interrupt without changing the state of the signal
> + * but let's be consistent and clear it always.
> + *
> + * Doing this works because we have IRQCHIP_SET_TYPE_MASKED so the
> + * interrupt will be cleared before the rest of the system sees it.
> + */
> + if (old_pdc_type != pdc_type)
> + irq_chip_set_parent_state(d, IRQCHIP_STATE_PENDING, false);
This bit and the switch statement above are common between the two paths..
I'm debating whether we should factor them out as static inline void, but
neither solution is perfect.. so, up to you
[...]
> @@ -385,20 +547,37 @@ static int qcom_pdc_alloc(struct irq_domain *domain, unsigned int virq,
> if (hwirq == GPIO_NO_WAKE_IRQ)
> return irq_domain_disconnect_hierarchy(domain, virq);
>
> - ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq,
> - &qcom_pdc_gic_chip, NULL);
> - if (ret)
> - return ret;
> + /*
> + * PDC secondary chip is only set for the GPIO interrupts as SPIs.
> + * Direct SPI interrupts are still in pass through mode (no latching
> + * at PDC).
> + */
> + if (pdc->mode == PDC_PASS_THROUGH_MODE || !pdc_pin_is_gpio(hwirq)) {
> + ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq,
> + &qcom_pdc_gic_chip,
> + NULL);
> + if (ret)
> + return ret;
>
> - region = get_pin_region(hwirq);
> - if (!region)
> - return irq_domain_disconnect_hierarchy(domain->parent, virq);
> + if (type & IRQ_TYPE_EDGE_BOTH)
> + type = IRQ_TYPE_EDGE_RISING;
>
> - if (type & IRQ_TYPE_EDGE_BOTH)
> - type = IRQ_TYPE_EDGE_RISING;
> + if (type & IRQ_TYPE_LEVEL_MASK)
> + type = IRQ_TYPE_LEVEL_HIGH;
> + } else {
> + ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq,
> + &qcom_pdc_gic_secondary_chip,
> + NULL);
> + if (ret)
> + return ret;
>
> - if (type & IRQ_TYPE_LEVEL_MASK)
> + /* Secondary mode converts all interrupts to LEVEL HIGH type */
> type = IRQ_TYPE_LEVEL_HIGH;
> + }
nit: (pdc->mode == PDC_SECONDARY_MODE && pdc_pin_is_gpio(hwirq))
could be the primary case to better communicate intent
Konrad
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v3 5/8] irqchip/qcom-pdc: Configure PDC to pass through mode
2026-06-16 9:25 ` [PATCH v3 5/8] irqchip/qcom-pdc: Configure PDC to pass through mode Maulik Shah
2026-06-18 8:18 ` Konrad Dybcio
@ 2026-06-18 8:19 ` Konrad Dybcio
2026-06-25 9:25 ` Maulik Shah (mkshah)
2026-06-30 15:07 ` Thomas Gleixner
2 siblings, 1 reply; 32+ messages in thread
From: Konrad Dybcio @ 2026-06-18 8:19 UTC (permalink / raw)
To: Maulik Shah, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Thomas Gleixner, Linus Walleij
Cc: linux-arm-msm, linux-kernel, devicetree, linux-gpio, Sneh Mankad
On 6/16/26 11:25 AM, Maulik Shah wrote:
> All PDC irqchip supports pass through mode in which both Direct SPIs and
> GPIO IRQs (as SPIs) are sent to GIC without latching at PDC.
>
> Newer PDCs (v3.0 onwards) also support additional secondary controller mode
> where PDC latches GPIO IRQs and sends to GIC as level type IRQ. Direct SPIs
> still works same as pass through mode without latching at PDC even in
> secondary controller mode.
>
> All the SoCs so far default uses pass through mode with the exception of
> x1e. x1e PDC may be set to secondary controller mode for builds on CRD
> boards whereas it may be set to pass through mode for IoT-EVK boards.
> The mode configuration is done in firmware and initially shipped windows
> firmware did not have SCM interface to read or modify the PDC mode.
> Later only write access is opened up for non secure world.
>
> Using the write access available add changes to modify the PDC mode to
> pass through mode via SCM write. When the write fails (on older firmware)
> assume to work in secondary mode.
>
> In secondary mode set the separate irqchip for the GPIOs to perform
> additional operations only for the GPIO irqs.
>
> Co-developed-by: Sneh Mankad <sneh.mankad@oss.qualcomm.com>
> Signed-off-by: Sneh Mankad <sneh.mankad@oss.qualcomm.com>
> Signed-off-by: Maulik Shah <maulik.shah@oss.qualcomm.com>
> ---
[...]
> +static void pdc_clear_gpio_cfg(int pin_out)
> +{
> + unsigned long gpio_sts;
> +
> + if (pdc->version < PDC_VERSION_3_0)
> + return;
> +
> + gpio_sts = pdc_reg_read(pdc->regs->irq_cfg_reg, pin_out);
> + __clear_bit(pdc->cfg_fields->gpio_irq_sts, &gpio_sts);
> + pdc_reg_write(pdc->regs->irq_cfg_reg, pin_out, gpio_sts);
> +}
> +
> +static void pdc_unmask_gpio_cfg(int pin_out, bool unmask)
> +{
> + unsigned long gpio_mask;
> +
> + if (pdc->version < PDC_VERSION_3_0)
> + return;
These version checks should be unnecessary now, given the function pointer
is only assigned for hamoa
Konrad
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v3 8/8] arm64: dts: qcom: x1e80100: Add deepest idle state
2026-06-16 9:25 ` [PATCH v3 8/8] arm64: dts: qcom: x1e80100: Add deepest idle state Maulik Shah
@ 2026-06-18 8:25 ` Konrad Dybcio
0 siblings, 0 replies; 32+ messages in thread
From: Konrad Dybcio @ 2026-06-18 8:25 UTC (permalink / raw)
To: Maulik Shah, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Thomas Gleixner, Linus Walleij
Cc: linux-arm-msm, linux-kernel, devicetree, linux-gpio, Sneh Mankad
On 6/16/26 11:25 AM, Maulik Shah wrote:
> Add deepest idle state as GPIO IRQs can work as wakeup capable interrupts
> in deepest idle state.
>
> Signed-off-by: Maulik Shah <maulik.shah@oss.qualcomm.com>
> ---
> arch/arm64/boot/dts/qcom/hamoa.dtsi | 10 +++++++++-
> 1 file changed, 9 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm64/boot/dts/qcom/hamoa.dtsi b/arch/arm64/boot/dts/qcom/hamoa.dtsi
> index 4ba751a65142..47e425003028 100644
> --- a/arch/arm64/boot/dts/qcom/hamoa.dtsi
> +++ b/arch/arm64/boot/dts/qcom/hamoa.dtsi
> @@ -302,6 +302,14 @@ cluster_cl5: cluster-sleep-1 {
> exit-latency-us = <4000>;
> min-residency-us = <7000>;
> };
> +
> + domain_ss3: domain-sleep-0 {
> + compatible = "domain-idle-state";
> + arm,psci-suspend-param = <0x0200c354>;
> + entry-latency-us = <2800>;
> + exit-latency-us = <4400>;
The DSDT has "wake_latency" (presumably the same as exit latency) set
to 5000 us, should we follow?
FWIW, the 2800/4400 numbers here are the exact same as for sm8650..
which doesn't sound very reassuring
> + min-residency-us = <9000>;
This number matches the DSDT
Should the entry latency then be 9000 - 5000 = 4000?
On a separate note, the DSDT also defines:
SS1 (0x02000154, total=7500, exit=500)
SS2 (0x02000254, total=8000, exit=3000)
These are obviously shallower states, but perhaps they could still
be useful?
Konrad
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v3 1/8] irqchip/qcom-pdc: restructure version support
2026-06-17 13:12 ` Konrad Dybcio
@ 2026-06-25 9:19 ` Maulik Shah (mkshah)
0 siblings, 0 replies; 32+ messages in thread
From: Maulik Shah (mkshah) @ 2026-06-25 9:19 UTC (permalink / raw)
To: Konrad Dybcio, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Thomas Gleixner, Linus Walleij
Cc: linux-arm-msm, linux-kernel, devicetree, linux-gpio, Sneh Mankad
On 6/17/2026 6:42 PM, Konrad Dybcio wrote:
> On 6/16/26 11:25 AM, Maulik Shah wrote:
>> PDC irqchip updates IRQ_ENABLE and IRQ_CFG and for three different
>> versions v2.7, v3.0 and v3.2. These registers are organized in H/W
>> as below on various SoCs.
>
> [...]
>
>> - ret = pdc_setup_pin_mapping(node);
>> + ret = pdc_setup_pin_mapping(dev, node);
>
> dev is enough, we can get the np in that function from dev->of_node
>
> otherwise:
>
> Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
>
> Konrad
Sure, Will update in v4 for getting np from dev->of_node.
Thanks,
Maulik
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v3 2/8] irqchip/qcom-pdc: Move all statics to struct pdc_desc
2026-06-17 13:26 ` Konrad Dybcio
@ 2026-06-25 9:19 ` Maulik Shah (mkshah)
2026-06-29 9:56 ` Konrad Dybcio
0 siblings, 1 reply; 32+ messages in thread
From: Maulik Shah (mkshah) @ 2026-06-25 9:19 UTC (permalink / raw)
To: Konrad Dybcio, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Thomas Gleixner, Linus Walleij
Cc: linux-arm-msm, linux-kernel, devicetree, linux-gpio, Sneh Mankad
On 6/17/2026 6:56 PM, Konrad Dybcio wrote:
> On 6/16/26 11:25 AM, Maulik Shah wrote:
>> There are multiple statics used. Move all to struct pdc_desc to better
>> align with versioning support. Document them.
>>
>> No functional impact.
>>
>> Signed-off-by: Maulik Shah <maulik.shah@oss.qualcomm.com>
>> ---
>
> [...]
>
>> static void pdc_enable_intr(struct irq_data *d, bool on)
>> {
>> - unsigned long flags;
>> + guard(raw_spinlock)(&pdc->lock);
>
> tglx suggested to use guard(irq) around "the other callsite"..
> which I'm not sure where it'd be - maybe around __pdc_enable_intr()
> in pdc_setup_pin_mapping()?
>
> Otherwise this patch looks good to me
>
> Konrad
All callers will be from irqchip except pdc_setup_pin_mapping() which was
invoking lock-less because at that time irqchip is not setup and as such
can stay lock less.
Once the patch-3 of this series is applied pdc_setup_pin_mapping() too
will use the lock as it makes direct use of pdc->enable_intr() where the new lock
is kept (only for v2.7 version specific enable function).
Thanks,
Maulik
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v3 4/8] irqchip/qcom-pdc: Differentiate between direct SPI and GPIO as SPI
2026-06-18 8:02 ` Konrad Dybcio
@ 2026-06-25 9:20 ` Maulik Shah (mkshah)
0 siblings, 0 replies; 32+ messages in thread
From: Maulik Shah (mkshah) @ 2026-06-25 9:20 UTC (permalink / raw)
To: Konrad Dybcio, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Thomas Gleixner, Linus Walleij
Cc: linux-arm-msm, linux-kernel, devicetree, linux-gpio, Sneh Mankad
On 6/18/2026 1:32 PM, Konrad Dybcio wrote:
> On 6/16/26 11:25 AM, Maulik Shah wrote:
>> Before commit 4dc70713dc24 ("irqchip/qcom-pdc: Kill non-wakeup irqdomain")
>> there are separate domains for direct SPIs and GPIO used as SPIs. Separate
>> domains can be useful in case irqchip want to differentiate both of them.
>> Since commit unified both the domains there is no way to differentiate.
>>
>> In preparation to add the second level interrupt controller support where
>> GPIO interrupts get latched at PDC (but not direct SPIs) there is a need to
>> differentiate between SPIs and GPIOs as SPIs. Reverting above commit do not
>> seem a good option either which leads to waste of resources.
>>
>> PDC HW have the IRQ_PARAM register telling number of direct SPIs and number
>> of GPIOs as SPIs. Further PDC allocates direct SPIs at the beginning and
>> all GPIOs as SPIs are allocated at the end. This information can be used in
>> driver to differentiate them.
>>
>> Add the support to read this register and keep this information in
>> struct pdc_desc. Later change utilizes same.
>>
>> Signed-off-by: Maulik Shah <maulik.shah@oss.qualcomm.com>
>> ---
>
> [...]
>
>> + irq_param = pdc_reg_read(pdc->regs->irq_param_reg, 0);
>> + pdc->num_spis = FIELD_GET(GENMASK(7, 0), irq_param);
>> + pdc->num_gpios = FIELD_GET(GENMASK(15, 8), irq_param);
>
> num_gpios is not used in this series, please either drop it or
> use it to limit the index in the following patches
>
> Konrad
I will remove unused num_gpios from v4.
Thanks,
Maulik
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v3 5/8] irqchip/qcom-pdc: Configure PDC to pass through mode
2026-06-18 8:18 ` Konrad Dybcio
@ 2026-06-25 9:24 ` Maulik Shah (mkshah)
0 siblings, 0 replies; 32+ messages in thread
From: Maulik Shah (mkshah) @ 2026-06-25 9:24 UTC (permalink / raw)
To: Konrad Dybcio, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Thomas Gleixner, Linus Walleij
Cc: linux-arm-msm, linux-kernel, devicetree, linux-gpio, Sneh Mankad
On 6/18/2026 1:48 PM, Konrad Dybcio wrote:
> On 6/16/26 11:25 AM, Maulik Shah wrote:
[...]
>> + type = IRQ_TYPE_LEVEL_HIGH;
>
>
> Please carry your comment from the previous revision:
>
> /*
> * PDC forwards GPIOs as level high to GIC in secondary
> * mode. Update the type and clear any previously latched
> * phantom interrupt at PDC.
> */
>
I will add back this comment in v4.
[...]
>> + if (pdc->mode == PDC_PASS_THROUGH_MODE || !pdc_pin_is_gpio(hwirq)) {
>> + ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq,
>> + &qcom_pdc_gic_chip,
>> + NULL);
>> + if (ret)
>> + return ret;
>>
>> - region = get_pin_region(hwirq);
>> - if (!region)
>> - return irq_domain_disconnect_hierarchy(domain->parent, virq);
>> + if (type & IRQ_TYPE_EDGE_BOTH)
>> + type = IRQ_TYPE_EDGE_RISING;
>>
>> - if (type & IRQ_TYPE_EDGE_BOTH)
>> - type = IRQ_TYPE_EDGE_RISING;
>> + if (type & IRQ_TYPE_LEVEL_MASK)
>> + type = IRQ_TYPE_LEVEL_HIGH;
>> + } else {
>> + ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq,
>> + &qcom_pdc_gic_secondary_chip,
>> + NULL);
>> + if (ret)
>> + return ret;
>>
>> - if (type & IRQ_TYPE_LEVEL_MASK)
>> + /* Secondary mode converts all interrupts to LEVEL HIGH type */
>> type = IRQ_TYPE_LEVEL_HIGH;
>> + }
>
> nit: (pdc->mode == PDC_SECONDARY_MODE && pdc_pin_is_gpio(hwirq))
> could be the primary case to better communicate intent
>
> Konrad
Made primary case as (pdc->mode == PDC_SECONDARY_MODE && pdc_pin_is_gpio(hwirq) in v4.
Thanks,
Maulik
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v3 5/8] irqchip/qcom-pdc: Configure PDC to pass through mode
2026-06-18 8:19 ` Konrad Dybcio
@ 2026-06-25 9:25 ` Maulik Shah (mkshah)
0 siblings, 0 replies; 32+ messages in thread
From: Maulik Shah (mkshah) @ 2026-06-25 9:25 UTC (permalink / raw)
To: Konrad Dybcio, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Thomas Gleixner, Linus Walleij
Cc: linux-arm-msm, linux-kernel, devicetree, linux-gpio, Sneh Mankad
On 6/18/2026 1:49 PM, Konrad Dybcio wrote:
> On 6/16/26 11:25 AM, Maulik Shah wrote:
[...]
>> +
>> + if (pdc->version < PDC_VERSION_3_0)
>> + return;
>
> These version checks should be unnecessary now, given the function pointer
> is only assigned for hamoa
>
> Konrad
Yes, they are now unnecessary. I will remove in v4.
Thanks,
Maulik
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v3 3/8] irqchip/qcom-pdc: Remove pdc_enable_intr() wrapper
2026-06-16 9:25 ` [PATCH v3 3/8] irqchip/qcom-pdc: Remove pdc_enable_intr() wrapper Maulik Shah
@ 2026-06-28 17:54 ` Val Packett
2026-06-30 3:52 ` Maulik Shah (mkshah)
0 siblings, 1 reply; 32+ messages in thread
From: Val Packett @ 2026-06-28 17:54 UTC (permalink / raw)
To: Maulik Shah, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Thomas Gleixner, Linus Walleij
Cc: linux-arm-msm, linux-kernel, devicetree, linux-gpio, Sneh Mankad
On 6/16/26 6:25 AM, Maulik Shah wrote:
> pdc->enable_intr() function already points to respective version
> specific enable function. pdc_enable_intr() now only kept as wrapper.
> Remove the wrapper and invoke pdc->enable_intr() from caller.
>
> Locking in pdc_enable_intr() applies lock to all pdc->enable_intr()
> however its only required for pdc_enable_intr_bank() which uses
> a shared bank across all interrupts. pdc_enable_intr_cfg() do not
> required locking as IRQ_CFG registers are one per interrupt. Move
> locking accordingly.
>
> Signed-off-by: Maulik Shah <maulik.shah@oss.qualcomm.com>
> ---
> drivers/irqchip/qcom-pdc.c | 13 ++++---------
> 1 file changed, 4 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/irqchip/qcom-pdc.c b/drivers/irqchip/qcom-pdc.c
> index b9acb0f25c9c..6c556464d37c 100644
> --- a/drivers/irqchip/qcom-pdc.c
> +++ b/drivers/irqchip/qcom-pdc.c
> @@ -206,6 +206,8 @@ static void pdc_enable_intr_bank(int pin_out, bool on)
> index = FIELD_GET(IRQ_ENABLE_BANK_INDEX_MASK, pin_out);
> mask = FIELD_GET(IRQ_ENABLE_BANK_BIT_MASK, pin_out);
>
> + guard(raw_spinlock)(&pdc->lock);
> [..]
whoops..
[ 0.197090] BUG: spinlock bad magic on CPU#7, swapper/0/1
[ 0.197104] lock: 0xffff0001022e37b0, .magic: 00000000, .owner:
<none>/-1, .owner_cpu: 0
[ 0.197122] CPU: 7 UID: 0 PID: 1 Comm: swapper/0 Not tainted
7.1.0-next-20260626-uwu+ #128 PREEMPT(full)
[ 0.197129] Hardware name: motorola Motorola Edge 30
(Tianma)/Motorola Edge 30 (Tianma), BIOS 2026.07-rc2-g432bcf301c03-dirty
07/01/2026
[ 0.197133] Call trace:
[ 0.197135] show_stack+0x24/0x38 (C)
[ 0.197148] __dump_stack+0x28/0x38
[ 0.197156] dump_stack_lvl+0x7c/0xa8
[ 0.197165] dump_stack+0x18/0x30
[ 0.197172] spin_dump+0x7c/0x98
[ 0.197179] do_raw_spin_lock+0xa4/0x140
[ 0.197189] _raw_spin_lock+0x2c/0x40
[ 0.197195] pdc_enable_intr_bank+0x40/0x128
[ 0.197201] qcom_pdc_probe+0x3bc/0x520
Gotta also move the spinlock init to before the call to
pdc_setup_pin_mapping..
~val
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v3 0/8] x1e80100: Enable PDC wake GPIOs and deepest idle state
2026-06-16 9:25 [PATCH v3 0/8] x1e80100: Enable PDC wake GPIOs and deepest idle state Maulik Shah
` (7 preceding siblings ...)
2026-06-16 9:25 ` [PATCH v3 8/8] arm64: dts: qcom: x1e80100: Add deepest idle state Maulik Shah
@ 2026-06-28 18:39 ` Val Packett
2026-06-29 9:54 ` Konrad Dybcio
2026-06-30 11:42 ` Linus Walleij
9 siblings, 1 reply; 32+ messages in thread
From: Val Packett @ 2026-06-28 18:39 UTC (permalink / raw)
To: Maulik Shah, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Thomas Gleixner, Linus Walleij
Cc: linux-arm-msm, linux-kernel, devicetree, linux-gpio, Sneh Mankad,
Stephan Gerhold
On 6/16/26 6:25 AM, Maulik Shah wrote:
> [..]
> ---
> Maulik Shah (7):
> irqchip/qcom-pdc: restructure version support
> irqchip/qcom-pdc: Move all statics to struct pdc_desc
> irqchip/qcom-pdc: Remove pdc_enable_intr() wrapper
> irqchip/qcom-pdc: Differentiate between direct SPI and GPIO as SPI
> irqchip/qcom-pdc: Configure PDC to pass through mode
> Revert "pinctrl: qcom: x1e80100: Bypass PDC wakeup parent for now"
> arm64: dts: qcom: x1e80100: Add deepest idle state
>
> Stephan Gerhold (1):
> pinctrl: qcom: Acknowledge IRQs for PDC interrupt controller
>
> [..]
Something about this series breaks the touchscreen interrupt (<&tlmm 81
IRQ_TYPE_LEVEL_LOW>) on sm7325-motorola-dubai :(
With this series, that interrupt only happens once (stuck at 1 in
/proc/interrupts) so events are not reported. Something something level
triggered..??
Thanks,
~val
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v3 0/8] x1e80100: Enable PDC wake GPIOs and deepest idle state
2026-06-28 18:39 ` [PATCH v3 0/8] x1e80100: Enable PDC wake GPIOs and " Val Packett
@ 2026-06-29 9:54 ` Konrad Dybcio
0 siblings, 0 replies; 32+ messages in thread
From: Konrad Dybcio @ 2026-06-29 9:54 UTC (permalink / raw)
To: Val Packett, Maulik Shah, Bjorn Andersson, Konrad Dybcio,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thomas Gleixner,
Linus Walleij
Cc: linux-arm-msm, linux-kernel, devicetree, linux-gpio, Sneh Mankad,
Stephan Gerhold
On 6/28/26 8:39 PM, Val Packett wrote:
>
> On 6/16/26 6:25 AM, Maulik Shah wrote:
>> [..]
>> ---
>> Maulik Shah (7):
>> irqchip/qcom-pdc: restructure version support
>> irqchip/qcom-pdc: Move all statics to struct pdc_desc
>> irqchip/qcom-pdc: Remove pdc_enable_intr() wrapper
>> irqchip/qcom-pdc: Differentiate between direct SPI and GPIO as SPI
>> irqchip/qcom-pdc: Configure PDC to pass through mode
>> Revert "pinctrl: qcom: x1e80100: Bypass PDC wakeup parent for now"
>> arm64: dts: qcom: x1e80100: Add deepest idle state
>>
>> Stephan Gerhold (1):
>> pinctrl: qcom: Acknowledge IRQs for PDC interrupt controller
>>
>> [..]
>
> Something about this series breaks the touchscreen interrupt (<&tlmm 81 IRQ_TYPE_LEVEL_LOW>) on sm7325-motorola-dubai :(
>
> With this series, that interrupt only happens once (stuck at 1 in /proc/interrupts) so events are not reported. Something something level triggered..??
Could you bisect which of the (hopefully first 6) patches cause it?
Konrad
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v3 2/8] irqchip/qcom-pdc: Move all statics to struct pdc_desc
2026-06-25 9:19 ` Maulik Shah (mkshah)
@ 2026-06-29 9:56 ` Konrad Dybcio
0 siblings, 0 replies; 32+ messages in thread
From: Konrad Dybcio @ 2026-06-29 9:56 UTC (permalink / raw)
To: Maulik Shah (mkshah), Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Thomas Gleixner, Linus Walleij
Cc: linux-arm-msm, linux-kernel, devicetree, linux-gpio, Sneh Mankad
On 6/25/26 11:19 AM, Maulik Shah (mkshah) wrote:
>
>
> On 6/17/2026 6:56 PM, Konrad Dybcio wrote:
>> On 6/16/26 11:25 AM, Maulik Shah wrote:
>>> There are multiple statics used. Move all to struct pdc_desc to better
>>> align with versioning support. Document them.
>>>
>>> No functional impact.
>>>
>>> Signed-off-by: Maulik Shah <maulik.shah@oss.qualcomm.com>
>>> ---
>>
>> [...]
>>
>>> static void pdc_enable_intr(struct irq_data *d, bool on)
>>> {
>>> - unsigned long flags;
>>> + guard(raw_spinlock)(&pdc->lock);
>>
>> tglx suggested to use guard(irq) around "the other callsite"..
>> which I'm not sure where it'd be - maybe around __pdc_enable_intr()
>> in pdc_setup_pin_mapping()?
>>
>> Otherwise this patch looks good to me
>>
>> Konrad
>
> All callers will be from irqchip except pdc_setup_pin_mapping() which was
> invoking lock-less because at that time irqchip is not setup and as such
> can stay lock less.
>
> Once the patch-3 of this series is applied pdc_setup_pin_mapping() too
> will use the lock as it makes direct use of pdc->enable_intr() where the new lock
> is kept (only for v2.7 version specific enable function).
Ack, thanks
Konrad
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v3 3/8] irqchip/qcom-pdc: Remove pdc_enable_intr() wrapper
2026-06-28 17:54 ` Val Packett
@ 2026-06-30 3:52 ` Maulik Shah (mkshah)
0 siblings, 0 replies; 32+ messages in thread
From: Maulik Shah (mkshah) @ 2026-06-30 3:52 UTC (permalink / raw)
To: Val Packett, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Thomas Gleixner, Linus Walleij
Cc: linux-arm-msm, linux-kernel, devicetree, linux-gpio, Sneh Mankad
On 6/28/2026 11:24 PM, Val Packett wrote:
>
> On 6/16/26 6:25 AM, Maulik Shah wrote:
[...]
> whoops..
>
> [ 0.197090] BUG: spinlock bad magic on CPU#7, swapper/0/1
> [ 0.197104] lock: 0xffff0001022e37b0, .magic: 00000000, .owner: <none>/-1, .owner_cpu: 0
> [ 0.197122] CPU: 7 UID: 0 PID: 1 Comm: swapper/0 Not tainted 7.1.0-next-20260626-uwu+ #128 PREEMPT(full)
> [ 0.197129] Hardware name: motorola Motorola Edge 30 (Tianma)/Motorola Edge 30 (Tianma), BIOS 2026.07-rc2-g432bcf301c03-dirty 07/01/2026
> [ 0.197133] Call trace:
> [ 0.197135] show_stack+0x24/0x38 (C)
> [ 0.197148] __dump_stack+0x28/0x38
> [ 0.197156] dump_stack_lvl+0x7c/0xa8
> [ 0.197165] dump_stack+0x18/0x30
> [ 0.197172] spin_dump+0x7c/0x98
> [ 0.197179] do_raw_spin_lock+0xa4/0x140
> [ 0.197189] _raw_spin_lock+0x2c/0x40
> [ 0.197195] pdc_enable_intr_bank+0x40/0x128
> [ 0.197201] qcom_pdc_probe+0x3bc/0x520
>
> Gotta also move the spinlock init to before the call to pdc_setup_pin_mapping..
Yes, Moving spinlock will be added in v4 of series.
Thanks,
Maulik
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v3 0/8] x1e80100: Enable PDC wake GPIOs and deepest idle state
2026-06-16 9:25 [PATCH v3 0/8] x1e80100: Enable PDC wake GPIOs and deepest idle state Maulik Shah
` (8 preceding siblings ...)
2026-06-28 18:39 ` [PATCH v3 0/8] x1e80100: Enable PDC wake GPIOs and " Val Packett
@ 2026-06-30 11:42 ` Linus Walleij
2026-06-30 14:34 ` Thomas Gleixner
9 siblings, 1 reply; 32+ messages in thread
From: Linus Walleij @ 2026-06-30 11:42 UTC (permalink / raw)
To: Maulik Shah, Bartosz Golaszewski
Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Thomas Gleixner, linux-arm-msm, linux-kernel,
devicetree, linux-gpio, Sneh Mankad, Stephan Gerhold
On Tue, Jun 16, 2026 at 10:26 AM Maulik Shah
<maulik.shah@oss.qualcomm.com> wrote:
> There are two modes PDC irqchip can work in
> - pass through mode
> - secondary controller mode
>
> Secondary mode is supported depending on SoC using PDC HW Version v3.0
> or higher.
>
> +------------------------------------------------------------------------+
> | SoC | SM8350, SM8450 | SM8550, Hamoa | SM8650, SM8750 |
> |----------------------------------------------------------- ------------|
> | Version | v2.7 | v3.0 | v3.2 |
> |------------------------------------------------------------------------|
> | Pass through | Yes | Yes | Yes |
> |------------------------------------------------------------------------|
> | Secondary | No | Yes | Yes |
> +------------------------------------------------------------------------+
I don't know what to do with this hurdle of pin control and irqchip patches,
luckily it will be Bartosz' problem since he's managing Qualcomm pin
controllers now :D
I'll be fine with brining the irqchip patches through pin control if an
irqchip maintainer ACKs them.
Yours,
Linus Walleij
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v3 0/8] x1e80100: Enable PDC wake GPIOs and deepest idle state
2026-06-30 11:42 ` Linus Walleij
@ 2026-06-30 14:34 ` Thomas Gleixner
0 siblings, 0 replies; 32+ messages in thread
From: Thomas Gleixner @ 2026-06-30 14:34 UTC (permalink / raw)
To: Linus Walleij, Maulik Shah, Bartosz Golaszewski
Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, linux-arm-msm, linux-kernel, devicetree, linux-gpio,
Sneh Mankad, Stephan Gerhold
On Tue, Jun 30 2026 at 12:42, Linus Walleij wrote:
> I don't know what to do with this hurdle of pin control and irqchip patches,
> luckily it will be Bartosz' problem since he's managing Qualcomm pin
> controllers now :D
>
> I'll be fine with brining the irqchip patches through pin control if an
> irqchip maintainer ACKs them.
The irq chip patches are self contained. So once we have a functional
version I can apply them on top of rc1, tag the lot and merge it into
the irqchip branch. Bartosz can then pull the tag into his branch to
apply the rest.
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v3 1/8] irqchip/qcom-pdc: restructure version support
2026-06-16 9:25 ` [PATCH v3 1/8] irqchip/qcom-pdc: restructure version support Maulik Shah
2026-06-17 13:12 ` Konrad Dybcio
@ 2026-06-30 14:38 ` Thomas Gleixner
1 sibling, 0 replies; 32+ messages in thread
From: Thomas Gleixner @ 2026-06-30 14:38 UTC (permalink / raw)
To: Maulik Shah, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Linus Walleij
Cc: linux-arm-msm, linux-kernel, devicetree, linux-gpio, Sneh Mankad,
Maulik Shah
On Tue, Jun 16 2026 at 14:55, Maulik Shah wrote:
> @@ -336,7 +418,8 @@ static int pdc_setup_pin_mapping(struct device_node *np)
> return -EINVAL;
>
> pdc_region_cnt = n / 3;
> - pdc_region = kzalloc_objs(*pdc_region, pdc_region_cnt);
> + pdc_region = devm_kcalloc(dev, pdc_region_cnt, sizeof(*pdc_region),
> + GFP_KERNEL);
No line break required. You have 100 characters
Other than that nit, this looks sane now.
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v3 2/8] irqchip/qcom-pdc: Move all statics to struct pdc_desc
2026-06-16 9:25 ` [PATCH v3 2/8] irqchip/qcom-pdc: Move all statics to struct pdc_desc Maulik Shah
2026-06-17 13:26 ` Konrad Dybcio
@ 2026-06-30 14:46 ` Thomas Gleixner
1 sibling, 0 replies; 32+ messages in thread
From: Thomas Gleixner @ 2026-06-30 14:46 UTC (permalink / raw)
To: Maulik Shah, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Linus Walleij
Cc: linux-arm-msm, linux-kernel, devicetree, linux-gpio, Sneh Mankad,
Maulik Shah
On Tue, Jun 16 2026 at 14:55, Maulik Shah wrote:
> - for (i = 0; i < pdc_region[n].cnt; i++)
> - __pdc_enable_intr(i + pdc_region[n].pin_base, 0);
> + for (int i = 0; i < pdc->region[n].cnt; i++)
> + pdc->enable_intr(i + pdc->region[n].pin_base, 0);
This needs a guard(raw_spinlock_irqsave)() when invoking
pdc->enable_intr(). The probe function is only invoked
with interrupts disabled during early boot. If it's called later, then
this still works, but lockdep will be rightfully upset.
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v3 4/8] irqchip/qcom-pdc: Differentiate between direct SPI and GPIO as SPI
2026-06-16 9:25 ` [PATCH v3 4/8] irqchip/qcom-pdc: Differentiate between direct SPI and GPIO as SPI Maulik Shah
2026-06-18 8:02 ` Konrad Dybcio
@ 2026-06-30 14:57 ` Thomas Gleixner
1 sibling, 0 replies; 32+ messages in thread
From: Thomas Gleixner @ 2026-06-30 14:57 UTC (permalink / raw)
To: Maulik Shah, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Linus Walleij
Cc: linux-arm-msm, linux-kernel, devicetree, linux-gpio, Sneh Mankad,
Maulik Shah
On Tue, Jun 16 2026 at 14:55, Maulik Shah wrote:
> Before commit 4dc70713dc24 ("irqchip/qcom-pdc: Kill non-wakeup irqdomain")
> there are separate domains for direct SPIs and GPIO used as SPIs. Separate
s/are/were/
> domains can be useful in case irqchip want to differentiate both of them.
the irqchip wants
> Since commit unified both the domains there is no way to differentiate.
Since the commit.
> In preparation to add the second level interrupt controller support where
> GPIO interrupts get latched at PDC (but not direct SPIs) there is a need to
> differentiate between SPIs and GPIOs as SPIs. Reverting above commit do not
does not
> seem a good option either which leads to waste of resources.
'either which leads' is not a parseable sentence.
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v3 5/8] irqchip/qcom-pdc: Configure PDC to pass through mode
2026-06-16 9:25 ` [PATCH v3 5/8] irqchip/qcom-pdc: Configure PDC to pass through mode Maulik Shah
2026-06-18 8:18 ` Konrad Dybcio
2026-06-18 8:19 ` Konrad Dybcio
@ 2026-06-30 15:07 ` Thomas Gleixner
2026-06-30 15:09 ` Thomas Gleixner
2 siblings, 1 reply; 32+ messages in thread
From: Thomas Gleixner @ 2026-06-30 15:07 UTC (permalink / raw)
To: Maulik Shah, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Linus Walleij
Cc: linux-arm-msm, linux-kernel, devicetree, linux-gpio, Sneh Mankad,
Maulik Shah
On Tue, Jun 16 2026 at 14:55, Maulik Shah wrote:
> All PDC irqchip supports pass through mode in which both Direct SPIs and
All PDC variants support pass .. ??
> GPIO IRQs (as SPIs) are sent to GIC without latching at PDC.
>
> Newer PDCs (v3.0 onwards) also support additional secondary controller mode
> where PDC latches GPIO IRQs and sends to GIC as level type IRQ. Direct SPIs
latches the GPIO interrupts and sends them to GIC as level type interrupts.
> still works same as pass through mode without latching at PDC even in
SPIs .. work the same as pass-through mode ....
> secondary controller mode.
>
> All the SoCs so far default uses pass through mode with the exception of
SoCs ... use pass-through
> x1e. x1e PDC may be set to secondary controller mode for builds on CRD
> boards whereas it may be set to pass through mode for IoT-EVK boards.
> The mode configuration is done in firmware and initially shipped windows
> firmware did not have SCM interface to read or modify the PDC mode.
> Later only write access is opened up for non secure world.
.. for the non-secure ..
> +/**
> + * qcom_pdc_gic_set_type: Configure PDC for the interrupt
> + *
> + * @d: the interrupt data
> + * @type: the interrupt type
https://docs.kernel.org/process/maintainer-tip.html#struct-declarations-and-initializers
I'm sure I pointed you to that document before.
> + *
> + * All @type are forwarded as Level type to parent GIC
> + */
> +static int qcom_pdc_gic_secondary_set_type(struct irq_data *d, unsigned int type)
> +{
> + enum pdc_irq_config_bits pdc_type;
> + enum pdc_irq_config_bits old_pdc_type;
Chapter before the above ...
> @@ -449,8 +628,13 @@ static int pdc_setup_pin_mapping(struct device *dev, struct device_node *np)
> if (ret)
> return ret;
>
> - for (int i = 0; i < pdc->region[n].cnt; i++)
> - pdc->enable_intr(i + pdc->region[n].pin_base, 0);
> + for (int i = 0; i < pdc->region[n].cnt; i++) {
> + if (pdc_pin_is_gpio(i + pdc->region[n].pin_base) &&
> + pdc->mode == PDC_SECONDARY_MODE)
> + pdc->clear_gpio(i + pdc->region[n].pin_base);
> +
Requires guard(irqsave)(...)
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v3 5/8] irqchip/qcom-pdc: Configure PDC to pass through mode
2026-06-30 15:07 ` Thomas Gleixner
@ 2026-06-30 15:09 ` Thomas Gleixner
0 siblings, 0 replies; 32+ messages in thread
From: Thomas Gleixner @ 2026-06-30 15:09 UTC (permalink / raw)
To: Maulik Shah, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Linus Walleij
Cc: linux-arm-msm, linux-kernel, devicetree, linux-gpio, Sneh Mankad,
Maulik Shah
On Tue, Jun 30 2026 at 17:07, Thomas Gleixner wrote:
> On Tue, Jun 16 2026 at 14:55, Maulik Shah wrote:
>> + for (int i = 0; i < pdc->region[n].cnt; i++) {
>> + if (pdc_pin_is_gpio(i + pdc->region[n].pin_base) &&
>> + pdc->mode == PDC_SECONDARY_MODE)
>> + pdc->clear_gpio(i + pdc->region[n].pin_base);
>> +
>
> Requires guard(irqsave)
before
>>+ pdc->enable_intr(i + pdc->region[n].pin_base, false);
obviously.
^ permalink raw reply [flat|nested] 32+ messages in thread
end of thread, other threads:[~2026-06-30 15:09 UTC | newest]
Thread overview: 32+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-16 9:25 [PATCH v3 0/8] x1e80100: Enable PDC wake GPIOs and deepest idle state Maulik Shah
2026-06-16 9:25 ` [PATCH v3 1/8] irqchip/qcom-pdc: restructure version support Maulik Shah
2026-06-17 13:12 ` Konrad Dybcio
2026-06-25 9:19 ` Maulik Shah (mkshah)
2026-06-30 14:38 ` Thomas Gleixner
2026-06-16 9:25 ` [PATCH v3 2/8] irqchip/qcom-pdc: Move all statics to struct pdc_desc Maulik Shah
2026-06-17 13:26 ` Konrad Dybcio
2026-06-25 9:19 ` Maulik Shah (mkshah)
2026-06-29 9:56 ` Konrad Dybcio
2026-06-30 14:46 ` Thomas Gleixner
2026-06-16 9:25 ` [PATCH v3 3/8] irqchip/qcom-pdc: Remove pdc_enable_intr() wrapper Maulik Shah
2026-06-28 17:54 ` Val Packett
2026-06-30 3:52 ` Maulik Shah (mkshah)
2026-06-16 9:25 ` [PATCH v3 4/8] irqchip/qcom-pdc: Differentiate between direct SPI and GPIO as SPI Maulik Shah
2026-06-18 8:02 ` Konrad Dybcio
2026-06-25 9:20 ` Maulik Shah (mkshah)
2026-06-30 14:57 ` Thomas Gleixner
2026-06-16 9:25 ` [PATCH v3 5/8] irqchip/qcom-pdc: Configure PDC to pass through mode Maulik Shah
2026-06-18 8:18 ` Konrad Dybcio
2026-06-25 9:24 ` Maulik Shah (mkshah)
2026-06-18 8:19 ` Konrad Dybcio
2026-06-25 9:25 ` Maulik Shah (mkshah)
2026-06-30 15:07 ` Thomas Gleixner
2026-06-30 15:09 ` Thomas Gleixner
2026-06-16 9:25 ` [PATCH v3 6/8] pinctrl: qcom: Acknowledge IRQs for PDC interrupt controller Maulik Shah
2026-06-16 9:25 ` [PATCH v3 7/8] Revert "pinctrl: qcom: x1e80100: Bypass PDC wakeup parent for now" Maulik Shah
2026-06-16 9:25 ` [PATCH v3 8/8] arm64: dts: qcom: x1e80100: Add deepest idle state Maulik Shah
2026-06-18 8:25 ` Konrad Dybcio
2026-06-28 18:39 ` [PATCH v3 0/8] x1e80100: Enable PDC wake GPIOs and " Val Packett
2026-06-29 9:54 ` Konrad Dybcio
2026-06-30 11:42 ` Linus Walleij
2026-06-30 14:34 ` Thomas Gleixner
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox