diff options
Diffstat (limited to 'drivers/irqchip/irq-ti-sci-intr.c')
| -rw-r--r-- | drivers/irqchip/irq-ti-sci-intr.c | 54 |
1 files changed, 36 insertions, 18 deletions
diff --git a/drivers/irqchip/irq-ti-sci-intr.c b/drivers/irqchip/irq-ti-sci-intr.c index 354613e74ad0..0ea17040e934 100644 --- a/drivers/irqchip/irq-ti-sci-intr.c +++ b/drivers/irqchip/irq-ti-sci-intr.c @@ -61,12 +61,21 @@ static int ti_sci_intr_irq_domain_translate(struct irq_domain *domain, { struct ti_sci_intr_irq_domain *intr = domain->host_data; - if (fwspec->param_count != 1) - return -EINVAL; + if (intr->type) { + /* Global interrupt-type */ + if (fwspec->param_count != 1) + return -EINVAL; - *hwirq = fwspec->param[0]; - *type = intr->type; + *hwirq = fwspec->param[0]; + *type = intr->type; + } else { + /* Per-Line interrupt-type */ + if (fwspec->param_count != 2) + return -EINVAL; + *hwirq = fwspec->param[0]; + *type = fwspec->param[1]; + } return 0; } @@ -128,11 +137,12 @@ static void ti_sci_intr_irq_domain_free(struct irq_domain *domain, * @domain: Pointer to the interrupt router IRQ domain * @virq: Corresponding Linux virtual IRQ number * @hwirq: Corresponding hwirq for the IRQ within this IRQ domain + * @hwirq_type: Corresponding hwirq trigger type for the IRQ within this IRQ domain * * Returns intr output irq if all went well else appropriate error pointer. */ -static int ti_sci_intr_alloc_parent_irq(struct irq_domain *domain, - unsigned int virq, u32 hwirq) +static int ti_sci_intr_alloc_parent_irq(struct irq_domain *domain, unsigned int virq, + u32 hwirq, u32 hwirq_type) { struct ti_sci_intr_irq_domain *intr = domain->host_data; struct device_node *parent_node; @@ -156,11 +166,22 @@ static int ti_sci_intr_alloc_parent_irq(struct irq_domain *domain, fwspec.param_count = 3; fwspec.param[0] = 0; /* SPI */ fwspec.param[1] = p_hwirq - 32; /* SPI offset */ - fwspec.param[2] = intr->type; + fwspec.param[2] = hwirq_type; } else { /* Parent is Interrupt Router */ - fwspec.param_count = 1; - fwspec.param[0] = p_hwirq; + u32 parent_trigger_type; + + if (!of_property_read_u32(parent_node, "ti,intr-trigger-type", + &parent_trigger_type)) { + /* Parent has global trigger type */ + fwspec.param_count = 1; + fwspec.param[0] = p_hwirq; + } else { + /* Parent supports per-line trigger types */ + fwspec.param_count = 2; + fwspec.param[0] = p_hwirq; + fwspec.param[1] = hwirq_type; + } } err = irq_domain_alloc_irqs_parent(domain, virq, 1, &fwspec); @@ -196,15 +217,15 @@ static int ti_sci_intr_irq_domain_alloc(struct irq_domain *domain, void *data) { struct irq_fwspec *fwspec = data; + unsigned int hwirq_type; unsigned long hwirq; - unsigned int flags; int err, out_irq; - err = ti_sci_intr_irq_domain_translate(domain, fwspec, &hwirq, &flags); + err = ti_sci_intr_irq_domain_translate(domain, fwspec, &hwirq, &hwirq_type); if (err) return err; - out_irq = ti_sci_intr_alloc_parent_irq(domain, virq, hwirq); + out_irq = ti_sci_intr_alloc_parent_irq(domain, virq, hwirq, hwirq_type); if (out_irq < 0) return out_irq; @@ -247,12 +268,9 @@ static int ti_sci_intr_irq_domain_probe(struct platform_device *pdev) return -ENOMEM; intr->dev = dev; - ret = of_property_read_u32(dev_of_node(dev), "ti,intr-trigger-type", - &intr->type); - if (ret) { - dev_err(dev, "missing ti,intr-trigger-type property\n"); - return -EINVAL; - } + + if (of_property_read_u32(dev_of_node(dev), "ti,intr-trigger-type", &intr->type)) + intr->type = IRQ_TYPE_NONE; intr->sci = devm_ti_sci_get_by_phandle(dev, "ti,sci"); if (IS_ERR(intr->sci)) |
