aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Morse <james.morse@arm.com>2021-04-09 19:12:36 +0100
committerJames Morse <james.morse@arm.com>2021-11-12 19:01:15 +0000
commitdcb27679932e5dbe7dbc20cd40bcb4b184ccaee5 (patch)
tree3e9a3441405cb0a78158f4df6188f872052804e1
parentb88ef5f2a5eddfb0aeca41e498ce74a74d22b2d8 (diff)
downloadlinux-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.h4
-rw-r--r--drivers/irqchip/Kconfig1
-rw-r--r--drivers/irqchip/irq-gic-v3-its.c21
-rw-r--r--drivers/irqchip/irq-gic-v3.c16
-rw-r--r--drivers/irqchip/irq-gic.c18
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;
}