diff options
| author | James Morse <james.morse@arm.com> | 2021-04-09 19:12:36 +0100 |
|---|---|---|
| committer | James Morse <james.morse@arm.com> | 2021-11-12 19:01:15 +0000 |
| commit | dcb27679932e5dbe7dbc20cd40bcb4b184ccaee5 (patch) | |
| tree | 3e9a3441405cb0a78158f4df6188f872052804e1 | |
| parent | b88ef5f2a5eddfb0aeca41e498ce74a74d22b2d8 (diff) | |
| download | linux-dcb27679932e5dbe7dbc20cd40bcb4b184ccaee5.tar.gz | |
irqchip/gic, gic-v3: Translate fwspec for DT and ACPI systems in the same way
gic_irq_domain_translate() currently rejects any fwspec for ACPI
systems that has more than 2 paramters.
ACPI only provides a hwirq and type via its fwspec, there isn't an
extra GIC specific field that can be overriden to describe a new
partition as __partition_ppis() does with GIC_IRQ_TYPE_PARTITION.
Enable ACPI_IRQCHIP_FWSPEC_ARG0, to make all calls from
acpi_register_gsi() pass GIC_IRQ_TYPE_GSI as their param[0].
This makes the ACPI format match DT, and allows the irqchip driver
to translate fwspec that aren't from acpi_register_gsi().
its_irq_gic_domain_alloc() is one example of these, it no longer needs
to produce a fwspec in two different layouts.
arm64 systems booting with ACPI only support gicv2 or later, this
doesn't need enabling to support other irqchip drivers.
32bit arm systems support gicv2, but don't use ACPI.
Signed-off-by: James Morse <james.morse@arm.com>
| -rw-r--r-- | arch/arm64/include/asm/irq.h | 4 | ||||
| -rw-r--r-- | drivers/irqchip/Kconfig | 1 | ||||
| -rw-r--r-- | drivers/irqchip/irq-gic-v3-its.c | 21 | ||||
| -rw-r--r-- | drivers/irqchip/irq-gic-v3.c | 16 | ||||
| -rw-r--r-- | drivers/irqchip/irq-gic.c | 18 |
5 files changed, 22 insertions, 38 deletions
diff --git a/arch/arm64/include/asm/irq.h b/arch/arm64/include/asm/irq.h index dc1e73509e1ce..688f61121bd0b 100644 --- a/arch/arm64/include/asm/irq.h +++ b/arch/arm64/include/asm/irq.h @@ -12,6 +12,10 @@ */ #define GIC_IRQ_TYPE_LPI 0xa110c8ed #define GIC_IRQ_TYPE_PARTITION (GIC_IRQ_TYPE_LPI + 1) +#define GIC_IRQ_TYPE_GSI (GIC_IRQ_TYPE_LPI + 2) + +#define ACPI_IRQCHIP_FWSPEC_ARG0 GIC_IRQ_TYPE_GSI + struct pt_regs; diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index aca7b595c4c78..5fffad0f71b82 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -9,6 +9,7 @@ config ARM_GIC bool select IRQ_DOMAIN_HIERARCHY select GENERIC_IRQ_EFFECTIVE_AFF_MASK + select ACPI_IRQCHIP_FWSPEC_ARG0 if ACPI config ARM_GIC_PM bool diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index eb0882d153666..f1610189bdfef 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -3512,20 +3512,15 @@ static int its_irq_gic_domain_alloc(struct irq_domain *domain, { struct irq_fwspec fwspec; - if (irq_domain_get_of_node(domain->parent)) { - fwspec.fwnode = domain->parent->fwnode; - fwspec.param_count = 3; - fwspec.param[0] = GIC_IRQ_TYPE_LPI; - fwspec.param[1] = hwirq; - fwspec.param[2] = IRQ_TYPE_EDGE_RISING; - } else if (is_fwnode_irqchip(domain->parent->fwnode)) { - fwspec.fwnode = domain->parent->fwnode; - fwspec.param_count = 2; - fwspec.param[0] = hwirq; - fwspec.param[1] = IRQ_TYPE_EDGE_RISING; - } else { + if (!irq_domain_get_of_node(domain->parent) && + !is_fwnode_irqchip(domain->parent->fwnode)) return -EINVAL; - } + + fwspec.fwnode = domain->parent->fwnode; + fwspec.param_count = 3; + fwspec.param[0] = GIC_IRQ_TYPE_LPI; + fwspec.param[1] = hwirq; + fwspec.param[2] = IRQ_TYPE_EDGE_RISING; return irq_domain_alloc_irqs_parent(domain, virq, 1, &fwspec); } diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index e13492b194881..8e89c396234ef 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -1402,7 +1402,8 @@ static int gic_irq_domain_translate(struct irq_domain *d, return 0; } - if (is_of_node(fwspec->fwnode)) { + if (is_of_node(fwspec->fwnode) || + is_fwnode_irqchip(fwspec->fwnode)) { if (fwspec->param_count < 3) return -EINVAL; @@ -1419,6 +1420,7 @@ static int gic_irq_domain_translate(struct irq_domain *d, case 3: /* EPPI */ *hwirq = fwspec->param[1] + EPPI_BASE_INTID; break; + case GIC_IRQ_TYPE_GSI: /* GSI */ case GIC_IRQ_TYPE_LPI: /* LPI */ *hwirq = fwspec->param[1]; break; @@ -1434,7 +1436,6 @@ static int gic_irq_domain_translate(struct irq_domain *d, } *type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK; - /* * Make it clear that broken DTs are... broken. * Partitioned PPIs are an unfortunate exception. @@ -1444,17 +1445,6 @@ static int gic_irq_domain_translate(struct irq_domain *d, return 0; } - if (is_fwnode_irqchip(fwspec->fwnode)) { - if(fwspec->param_count != 2) - return -EINVAL; - - *hwirq = fwspec->param[0]; - *type = fwspec->param[1]; - - WARN_ON(*type == IRQ_TYPE_NONE); - return 0; - } - return -EINVAL; } diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 5f22c9d65e578..ef2bda5ed7c5e 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -1059,7 +1059,9 @@ static int gic_irq_domain_translate(struct irq_domain *d, return 0; } - if (is_of_node(fwspec->fwnode)) { + + if (is_of_node(fwspec->fwnode) || + is_fwnode_irqchip(fwspec->fwnode)) { if (fwspec->param_count < 3) return -EINVAL; @@ -1070,6 +1072,9 @@ static int gic_irq_domain_translate(struct irq_domain *d, case 1: /* PPI */ *hwirq = fwspec->param[1] + 16; break; + case GIC_IRQ_TYPE_GSI: /* GSI */ + *hwirq = fwspec->param[1]; + break; default: return -EINVAL; } @@ -1081,17 +1086,6 @@ static int gic_irq_domain_translate(struct irq_domain *d, return 0; } - if (is_fwnode_irqchip(fwspec->fwnode)) { - if(fwspec->param_count != 2) - return -EINVAL; - - *hwirq = fwspec->param[0]; - *type = fwspec->param[1]; - - WARN_ON(*type == IRQ_TYPE_NONE); - return 0; - } - return -EINVAL; } |
