diff --git a/xen/arch/arm/gic-v2.c b/xen/arch/arm/gic-v2.c
index 7276951..fcdcd19 100644
--- a/xen/arch/arm/gic-v2.c
+++ b/xen/arch/arm/gic-v2.c
@@ -28,6 +28,8 @@
 #include <xen/list.h>
 #include <xen/device_tree.h>
 #include <xen/libfdt/libfdt.h>
+#include <xen/acpi.h>
+#include <acpi/actables.h>
 #include <asm/p2m.h>
 #include <asm/domain.h>
 #include <asm/platform.h>
@@ -35,6 +37,7 @@
 
 #include <asm/io.h>
 #include <asm/gic.h>
+#include <asm/acpi.h>
 
 /*
  * LR register definitions are GIC v2 specific.
@@ -692,9 +695,122 @@ static int __init dt_gicv2_init(void)
     return 0;
 }
 
+#ifdef CONFIG_ACPI
+static int __init
+gic_acpi_parse_madt_cpu(struct acpi_subtable_header *header,
+                        const unsigned long end)
+{
+        struct acpi_madt_generic_interrupt *processor;
+
+        processor = (struct acpi_madt_generic_interrupt *)header;
+
+        if (BAD_MADT_ENTRY(processor, end))
+                return -EINVAL;
+
+        /* Read from APIC table and fill up the GIC variables */
+
+        gicv2.cbase = processor->base_address;
+        gicv2.hbase = processor->gich_base_address;
+        gicv2.vbase = processor->gicv_base_address;
+        gicv2_info.maintenance_irq = processor->vgic_maintenance_interrupt;
+        if( processor->flags & ACPI_MADT_ENABLED )
+        {
+            if( processor->flags & ACPI_MADT_VGIC )
+                set_irq_type(gicv2_info.maintenance_irq, ACPI_IRQ_TYPE_EDGE_BOTH);
+            else
+                set_irq_type(gicv2_info.maintenance_irq, ACPI_IRQ_TYPE_LEVEL_MASK);
+        }
+
+        processor->gich_base_address = 0;
+        processor->gicv_base_address = 0;
+        processor->vgic_maintenance_interrupt = 0;
+        clean_dcache_va_range(processor, sizeof(struct acpi_madt_generic_interrupt));
+
+        return 0;
+}
+
+static int __init
+gic_acpi_parse_madt_distributor(struct acpi_subtable_header *header,
+                                const unsigned long end)
+{
+        struct acpi_madt_generic_distributor *dist;
+
+        dist = (struct acpi_madt_generic_distributor *)header;
+
+        if (BAD_MADT_ENTRY(dist, end))
+                return -EINVAL;
+
+        gicv2.dbase = dist->base_address;
+
+        return 0;
+}
+
+static int __init acpi_gicv2_init(void)
+{
+    acpi_status status;
+    struct acpi_table_header *table;
+    u8 checksum;
+    int res;
+
+    status = acpi_get_table(ACPI_SIG_MADT, 0, &table);
+
+    if ( ACPI_FAILURE(status) )
+    {
+              const char *msg = acpi_format_exception(status);
+              printk("\nFailed to get MADT table, %s\n", msg);
+              return 1;
+    }
+
+    /* Collect CPU base addresses */
+    res = acpi_parse_entries(ACPI_SIG_MADT,
+                                sizeof(struct acpi_table_madt),
+                                gic_acpi_parse_madt_cpu, table,
+                                ACPI_MADT_TYPE_GENERIC_INTERRUPT,
+                                0);
+    if ( res < 0 )
+    {
+        printk("Error during GICC entries parsing\n");
+        printk("\nFailed to initialize GIC IRQ controller\n");
+        return -EINVAL;
+    }
+
+    /*
+     * Find distributor base address. We expect one distributor entry since
+     * ACPI 5.0 spec neither support multi-GIC instances nor GIC cascade.
+     */
+    res = acpi_parse_entries(ACPI_SIG_MADT,
+                                sizeof(struct acpi_table_madt),
+                                gic_acpi_parse_madt_distributor, table,
+                                ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR,
+                                0);
+
+    if ( res < 0 )
+    {
+        printk("Error during GICD entries parsing\n");
+        printk("\nFailed to initialize GIC IRQ controller\n");
+        return -EINVAL;
+    }
+
+    checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, table), table->length);
+    table->checksum -= checksum;
+    clean_dcache_va_range(table, sizeof(struct acpi_table_header));
+
+    return 0;
+}
+#else
+static int __init acpi_gicv2_init(void)
+{
+/* Should never reach here */
+    return -EINVAL;
+}
+#endif
+
 static int gicv2_init(void)
 {
-     dt_gicv2_init();
+    if( acpi_disabled )
+        dt_gicv2_init();
+    else
+        acpi_gicv2_init();
 
     /* TODO: Add check on distributor, cpu size */
 
@@ -790,7 +906,21 @@ DT_DEVICE_START(gicv2, "GICv2", DEVICE_GIC)
         .dt_match = gicv2_dt_match,
         .init = dt_gicv2_preinit,
 DT_DEVICE_END
+#ifdef CONFIG_ACPI
+/* Set up the GIC */
+static int __init acpi_gicv2_preinit(const void *data)
+{
+    gicv2_info.hw_version = GIC_V2;
+    register_gic_ops(&gicv2_ops);
+
+    return 0;
+}
 
+ACPI_DEVICE_START(agicv2, "GICv2", DEVICE_GIC)
+        .class_type = GIC_V2,
+        .init = acpi_gicv2_preinit,
+ACPI_DEVICE_END
+#endif
 /*
  * Local variables:
  * mode: C
diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index 701c306..e33bfd7 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);
 
@@ -261,9 +263,23 @@ void __init dt_gic_preinit(void)
     dt_device_set_used_by(node, DOMID_XEN);
 }
 
+static void __init acpi_gic_init(void)
+{
+    int rc;
+
+    /* NOTE: Only one GIC is supported */
+    /* hardcode to gic v2 for now */
+    rc = acpi_device_init(DEVICE_GIC, NULL, GIC_V2);
+    if ( rc )
+        panic("Unable to find compatible GIC in the ACPI table");
+}
+
 void __init gic_preinit(void)
 {
-    dt_gic_preinit();
+    if( acpi_disabled )
+        dt_gic_preinit();
+    else
+        acpi_gic_init();
 }
 
 /* Set up the GIC */
diff --git a/xen/drivers/char/arm-uart.c b/xen/drivers/char/arm-uart.c
new file mode 100644
index 0000000..2603508
--- /dev/null
+++ b/xen/drivers/char/arm-uart.c
@@ -0,0 +1,136 @@
+/*
+ * xen/drivers/char/dt-uart.c
+ *
+ * Generic uart retrieved via the device tree
+ *
+ * Julien Grall <julien.grall@linaro.org>
+ * Copyright (c) 2013 Linaro Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <asm/device.h>
+#include <asm/types.h>
+#include <xen/console.h>
+#include <xen/device_tree.h>
+#include <xen/serial.h>
+#include <xen/errno.h>
+#include <xen/acpi.h>
+
+/*
+ * Configure UART port with a string:
+ * path:options
+ *
+ * @path: full path used in the device tree for the UART. If the path
+ * doesn't start with '/', we assuming that it's an alias.
+ * @options: UART speficic options (see in each UART driver)
+ */
+static char __initdata opt_dtuart[256] = "";
+string_param("dtuart", opt_dtuart);
+
+static void __init dt_uart_init(void)
+{
+    struct dt_device_node *dev;
+    int ret;
+    const char *devpath = opt_dtuart;
+    char *options;
+
+    if ( !console_has("dtuart") )
+        return; /* Not for us */
+
+    if ( !strcmp(opt_dtuart, "") )
+    {
+        const struct dt_device_node *chosen = dt_find_node_by_path("/chosen");
+
+        if ( chosen )
+        {
+            const char *stdout;
+
+            ret = dt_property_read_string(chosen, "stdout-path", &stdout);
+            if ( ret >= 0 )
+            {
+                printk("Taking dtuart configuration from /chosen/stdout-path\n");
+                if ( strlcpy(opt_dtuart, stdout, sizeof(opt_dtuart))
+                     >= sizeof(opt_dtuart) )
+                    printk("WARNING: /chosen/stdout-path too long, truncated\n");
+            }
+            else if ( ret != -EINVAL /* Not present */ )
+                printk("Failed to read /chosen/stdout-path (%d)\n", ret);
+        }
+    }
+
+    if ( !strcmp(opt_dtuart, "") )
+    {
+        printk("No dtuart path configured\n");
+        return;
+    }
+
+    options = strchr(opt_dtuart, ':');
+    if ( options != NULL )
+        *(options++) = '\0';
+    else
+        options = "";
+
+    printk("Looking for dtuart at \"%s\", options \"%s\"\n", devpath, options);
+    if ( *devpath == '/' )
+        dev = dt_find_node_by_path(devpath);
+    else
+        dev = dt_find_node_by_alias(devpath);
+
+    if ( !dev )
+    {
+        printk("Unable to find device \"%s\"\n", devpath);
+        return;
+    }
+
+    ret = device_init(dev, DEVICE_SERIAL, options);
+
+    if ( ret )
+        printk("Unable to initialize dtuart: %d\n", ret);
+}
+
+static void __init acpi_uart_init(void)
+{
+#ifdef CONFIG_ACPI
+    struct acpi_table_spcr *spcr=NULL;
+    int ret;
+
+    acpi_get_table(ACPI_SIG_SPCR, 0,(struct acpi_table_header **)&spcr);
+
+    if ( spcr == NULL )
+        printk("Unable to get spcr table\n");
+    else
+    {
+        ret = acpi_device_init(DEVICE_SERIAL, NULL, spcr->interface_type);
+
+        if ( ret )
+            printk("Unable to initialize acpi uart: %d\n", ret);
+    }
+#endif
+}
+
+void __init uart_init(void)
+{
+    if ( acpi_disabled )
+        dt_uart_init();
+    else
+        acpi_uart_init();
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
