[PATCH v3 28/62] arm/gic: Add ACPI support for GIC preinit

shannon.zhao at linaro.org shannon.zhao at linaro.org
Tue Nov 17 01:40:27 PST 2015


From: Shannon Zhao <shannon.zhao at linaro.org>

Since ACPI 6.0 defines that GIC Distributor Structure contains the GIC
version filed, it could get GIC version from that. According to the
version, call different preinit functions.

Signed-off-by: Shannon Zhao <shannon.zhao at linaro.org>
---
 xen/arch/arm/gic.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 51 insertions(+), 4 deletions(-)

diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index 1e1e5ba..ac82588 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -27,6 +27,7 @@
 #include <xen/softirq.h>
 #include <xen/list.h>
 #include <xen/device_tree.h>
+#include <xen/acpi.h>
 #include <asm/p2m.h>
 #include <asm/domain.h>
 #include <asm/platform.h>
@@ -34,6 +35,7 @@
 #include <asm/io.h>
 #include <asm/gic.h>
 #include <asm/vgic.h>
+#include <asm/acpi.h>
 
 static void gic_restore_pending_irqs(struct vcpu *v);
 
@@ -228,10 +230,7 @@ int gic_irq_xlate(const u32 *intspec, unsigned int intsize,
     return 0;
 }
 
-/* Find the interrupt controller and set up the callback to translate
- * device tree IRQ.
- */
-void __init gic_preinit(void)
+void __init dt_gic_preinit(void)
 {
     int rc;
     struct dt_device_node *node;
@@ -261,6 +260,54 @@ void __init gic_preinit(void)
     dt_device_set_used_by(node, DOMID_XEN);
 }
 
+#ifdef CONFIG_ACPI
+static void __init acpi_gic_preinit(void)
+{
+    int rc = 0;
+    acpi_status status;
+    struct acpi_table_header *table;
+    struct acpi_subtable_header * subtable;
+    struct acpi_madt_generic_distributor *dist;
+
+    status = acpi_get_table(ACPI_SIG_MADT, 0, &table);
+    if ( ACPI_FAILURE(status) )
+    {
+        const char *msg = acpi_format_exception(status);
+
+        panic("Failed to get MADT table, %s", msg);
+    }
+
+    subtable = acpi_get_entry(ACPI_SIG_MADT, sizeof(struct acpi_table_madt),
+                              table, ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR, 0);
+    if ( !subtable )
+        panic("No valid GICD entries exists");
+
+    dist = (struct acpi_madt_generic_distributor *)subtable;
+
+    if ( dist->version == ACPI_MADT_GIC_VERSION_V2 )
+        rc = acpi_device_init(DEVICE_GIC, NULL, GIC_V2);
+    else if ( dist->version == ACPI_MADT_GIC_VERSION_V3 )
+        rc = acpi_device_init(DEVICE_GIC, NULL, GIC_V3);
+    else
+        panic("Wrong GIC version or unsupported GIC");
+    if ( rc )
+        panic("Unable to find compatible GIC in the ACPI table");
+}
+#else
+static void __init acpi_gic_preinit(void) {}
+#endif
+
+/* Find the interrupt controller and set up the callback to translate
+ * device tree IRQ.
+ */
+void __init gic_preinit(void)
+{
+    if( acpi_disabled )
+        dt_gic_preinit();
+    else
+        acpi_gic_preinit();
+}
+
 /* Set up the GIC */
 void __init gic_init(void)
 {
-- 
2.1.0




More information about the linux-arm-kernel mailing list