Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

irqchip/ti-sci-intr: Allow parsing interrupt-types per-line

Some INTR router instances act as simple passthroughs that preserve the
source interrupt type unchanged at the output line, rather than
converting all interrupts to a fixed type.

When interrupt sources are not homogeneous with respect to trigger type,
the driver needs to read each source's interrupt type from DT and pass
it unchanged to its interrupt parent.

Add support to check for absence of "ti,intr-trigger-type" to indicate
passthrough mode. When this property is absent, parse interrupt type
per-line from the DT fwspec provided by the interrupt source. Else, use
the global setting for all interrupt lines.

Signed-off-by: Aniket Limaye <a-limaye@ti.com>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Link: https://patch.msgid.link/20260123-ul-driver-i2c-j722s-v4-2-b08625c487d5@ti.com

authored by

Aniket Limaye and committed by
Thomas Gleixner
3d9617ea 7a30a7a6

+36 -18
+36 -18
drivers/irqchip/irq-ti-sci-intr.c
··· 61 61 { 62 62 struct ti_sci_intr_irq_domain *intr = domain->host_data; 63 63 64 - if (fwspec->param_count != 1) 65 - return -EINVAL; 64 + if (intr->type) { 65 + /* Global interrupt-type */ 66 + if (fwspec->param_count != 1) 67 + return -EINVAL; 66 68 67 - *hwirq = fwspec->param[0]; 68 - *type = intr->type; 69 + *hwirq = fwspec->param[0]; 70 + *type = intr->type; 71 + } else { 72 + /* Per-Line interrupt-type */ 73 + if (fwspec->param_count != 2) 74 + return -EINVAL; 69 75 76 + *hwirq = fwspec->param[0]; 77 + *type = fwspec->param[1]; 78 + } 70 79 return 0; 71 80 } 72 81 ··· 137 128 * @domain: Pointer to the interrupt router IRQ domain 138 129 * @virq: Corresponding Linux virtual IRQ number 139 130 * @hwirq: Corresponding hwirq for the IRQ within this IRQ domain 131 + * @hwirq_type: Corresponding hwirq trigger type for the IRQ within this IRQ domain 140 132 * 141 133 * Returns intr output irq if all went well else appropriate error pointer. 142 134 */ 143 - static int ti_sci_intr_alloc_parent_irq(struct irq_domain *domain, 144 - unsigned int virq, u32 hwirq) 135 + static int ti_sci_intr_alloc_parent_irq(struct irq_domain *domain, unsigned int virq, 136 + u32 hwirq, u32 hwirq_type) 145 137 { 146 138 struct ti_sci_intr_irq_domain *intr = domain->host_data; 147 139 struct device_node *parent_node; ··· 166 156 fwspec.param_count = 3; 167 157 fwspec.param[0] = 0; /* SPI */ 168 158 fwspec.param[1] = p_hwirq - 32; /* SPI offset */ 169 - fwspec.param[2] = intr->type; 159 + fwspec.param[2] = hwirq_type; 170 160 } else { 171 161 /* Parent is Interrupt Router */ 172 - fwspec.param_count = 1; 173 - fwspec.param[0] = p_hwirq; 162 + u32 parent_trigger_type; 163 + 164 + if (!of_property_read_u32(parent_node, "ti,intr-trigger-type", 165 + &parent_trigger_type)) { 166 + /* Parent has global trigger type */ 167 + fwspec.param_count = 1; 168 + fwspec.param[0] = p_hwirq; 169 + } else { 170 + /* Parent supports per-line trigger types */ 171 + fwspec.param_count = 2; 172 + fwspec.param[0] = p_hwirq; 173 + fwspec.param[1] = hwirq_type; 174 + } 174 175 } 175 176 176 177 err = irq_domain_alloc_irqs_parent(domain, virq, 1, &fwspec); ··· 217 196 void *data) 218 197 { 219 198 struct irq_fwspec *fwspec = data; 199 + unsigned int hwirq_type; 220 200 unsigned long hwirq; 221 - unsigned int flags; 222 201 int err, out_irq; 223 202 224 - err = ti_sci_intr_irq_domain_translate(domain, fwspec, &hwirq, &flags); 203 + err = ti_sci_intr_irq_domain_translate(domain, fwspec, &hwirq, &hwirq_type); 225 204 if (err) 226 205 return err; 227 206 228 - out_irq = ti_sci_intr_alloc_parent_irq(domain, virq, hwirq); 207 + out_irq = ti_sci_intr_alloc_parent_irq(domain, virq, hwirq, hwirq_type); 229 208 if (out_irq < 0) 230 209 return out_irq; 231 210 ··· 268 247 return -ENOMEM; 269 248 270 249 intr->dev = dev; 271 - ret = of_property_read_u32(dev_of_node(dev), "ti,intr-trigger-type", 272 - &intr->type); 273 - if (ret) { 274 - dev_err(dev, "missing ti,intr-trigger-type property\n"); 275 - return -EINVAL; 276 - } 250 + 251 + if (of_property_read_u32(dev_of_node(dev), "ti,intr-trigger-type", &intr->type)) 252 + intr->type = IRQ_TYPE_NONE; 277 253 278 254 intr->sci = devm_ti_sci_get_by_phandle(dev, "ti,sci"); 279 255 if (IS_ERR(intr->sci))