[PATCH v4 3/7] irqchip/qcom-pdc: Differentiate between direct SPI and GPIO as SPI
From: Maulik Shah
Date: Tue Jul 07 2026 - 05:26:11 EST
Before commit 4dc70713dc24 ("irqchip/qcom-pdc: Kill non-wakeup irqdomain")
there were separate domains for direct SPIs and GPIOs used as SPIs.
Separate domains can be useful in case the irqchip wants to differentiate
both of them. Since the 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 does
not seem a good option 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@xxxxxxxxxxxxxxxx>
---
drivers/irqchip/qcom-pdc.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/drivers/irqchip/qcom-pdc.c b/drivers/irqchip/qcom-pdc.c
index 764f7965cfb8..53a477aa9765 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,7 @@ 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
* @region: PDC interrupt continuous range
* @region_cnt: Total PDC ranges
* @x1e_quirk: x1e H/W Bug handling
@@ -104,6 +112,7 @@ struct pdc_desc {
void __iomem *base;
void __iomem *prev_base;
u32 version;
+ u32 num_spis;
struct pdc_pin_region *region;
int region_cnt;
@@ -120,6 +129,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 +140,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 +150,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 = {
@@ -445,6 +457,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 */
@@ -501,6 +514,9 @@ 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);
+
parent_domain = irq_find_host(parent);
if (!parent_domain) {
pr_err("%pOF: unable to find PDC's parent domain\n", node);
--
2.43.0