@@ -1899,6 +1899,20 @@ static int tegra_pmc_irq_alloc(struct irq_domain *domain, unsigned int virq,
event->id,
&pmc->irq, pmc);
+ /*
+ * GPIOs don't have an equivalent interrupt in the
+ * parent controller (GIC). However some code, such
+ * as the one in irq_get_irqchip_state(), require a
+ * valid IRQ chip to be set. Make sure that's the
+ * case by passing NULL here, which will install a
+ * dummy IRQ chip for the interrupt in the parent
+ * domain.
+ */
+ if (domain->parent)
+ irq_domain_set_hwirq_and_chip(domain->parent,
+ virq, 0, NULL,
+ NULL);
+
break;
}
}
@@ -1908,10 +1922,22 @@ static int tegra_pmc_irq_alloc(struct irq_domain *domain, unsigned int virq,
* dummy hardware IRQ number. This is used in the ->irq_set_type()
* and ->irq_set_wake() callbacks to return early for these IRQs.
*/
- if (i == soc->num_wake_events)
+ if (i == soc->num_wake_events) {
err = irq_domain_set_hwirq_and_chip(domain, virq, ULONG_MAX,
&pmc->irq, pmc);
+ /*
+ * Interrupts without a wake event don't have a corresponding
+ * interrupt in the parent controller (GIC). Pass NULL for the
+ * chip here, which causes a dummy IRQ chip to be installed
+ * for the interrupt in the parent domain, to make this
+ * explicit.
+ */
+ if (domain->parent)
+ irq_domain_set_hwirq_and_chip(domain->parent, virq, 0,
+ NULL, NULL);
+ }
+
return err;
}