pr_err("Can't find FADT\n");
        }
 }
+
+void __init acpi_gic_init(void)
+{
+       struct acpi_table_header *table;
+       acpi_status status;
+       acpi_size tbl_size;
+       int err;
+
+       if (acpi_disabled)
+               return;
+
+       status = acpi_get_table_with_size(ACPI_SIG_MADT, 0, &table, &tbl_size);
+       if (ACPI_FAILURE(status)) {
+               const char *msg = acpi_format_exception(status);
+
+               pr_err("Failed to get MADT table, %s\n", msg);
+               return;
+       }
+
+       err = gic_v2_acpi_init(table);
+       if (err)
+               pr_err("Failed to initialize GIC IRQ controller");
+
+       early_acpi_os_unmap_memory((char *)table, tbl_size);
+}
 
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
+#include <linux/acpi.h>
 #include <linux/irqdomain.h>
 #include <linux/interrupt.h>
 #include <linux/percpu.h>
 #include <linux/slab.h>
 #include <linux/irqchip/chained_irq.h>
 #include <linux/irqchip/arm-gic.h>
+#include <linux/irqchip/arm-gic-acpi.h>
 
 #include <asm/cputype.h>
 #include <asm/irq.h>
 IRQCHIP_DECLARE(msm_qgic2, "qcom,msm-qgic2", gic_of_init);
 
 #endif
+
+#ifdef CONFIG_ACPI
+static phys_addr_t dist_phy_base, cpu_phy_base __initdata;
+
+static int __init
+gic_acpi_parse_madt_cpu(struct acpi_subtable_header *header,
+                       const unsigned long end)
+{
+       struct acpi_madt_generic_interrupt *processor;
+       phys_addr_t gic_cpu_base;
+       static int cpu_base_assigned;
+
+       processor = (struct acpi_madt_generic_interrupt *)header;
+
+       if (BAD_MADT_ENTRY(processor, end))
+               return -EINVAL;
+
+       /*
+        * There is no support for non-banked GICv1/2 register in ACPI spec.
+        * All CPU interface addresses have to be the same.
+        */
+       gic_cpu_base = processor->base_address;
+       if (cpu_base_assigned && gic_cpu_base != cpu_phy_base)
+               return -EINVAL;
+
+       cpu_phy_base = gic_cpu_base;
+       cpu_base_assigned = 1;
+       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;
+
+       dist_phy_base = dist->base_address;
+       return 0;
+}
+
+int __init
+gic_v2_acpi_init(struct acpi_table_header *table)
+{
+       void __iomem *cpu_base, *dist_base;
+       int count;
+
+       /* Collect CPU base addresses */
+       count = acpi_parse_entries(ACPI_SIG_MADT,
+                                  sizeof(struct acpi_table_madt),
+                                  gic_acpi_parse_madt_cpu, table,
+                                  ACPI_MADT_TYPE_GENERIC_INTERRUPT, 0);
+       if (count <= 0) {
+               pr_err("No valid GICC entries exist\n");
+               return -EINVAL;
+       }
+
+       /*
+        * Find distributor base address. We expect one distributor entry since
+        * ACPI 5.1 spec neither support multi-GIC instances nor GIC cascade.
+        */
+       count = acpi_parse_entries(ACPI_SIG_MADT,
+                                  sizeof(struct acpi_table_madt),
+                                  gic_acpi_parse_madt_distributor, table,
+                                  ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR, 0);
+       if (count <= 0) {
+               pr_err("No valid GICD entries exist\n");
+               return -EINVAL;
+       } else if (count > 1) {
+               pr_err("More than one GICD entry detected\n");
+               return -EINVAL;
+       }
+
+       cpu_base = ioremap(cpu_phy_base, ACPI_GIC_CPU_IF_MEM_SIZE);
+       if (!cpu_base) {
+               pr_err("Unable to map GICC registers\n");
+               return -ENOMEM;
+       }
+
+       dist_base = ioremap(dist_phy_base, ACPI_GICV2_DIST_MEM_SIZE);
+       if (!dist_base) {
+               pr_err("Unable to map GICD registers\n");
+               iounmap(cpu_base);
+               return -ENOMEM;
+       }
+
+       /*
+        * Initialize zero GIC instance (no multi-GIC support). Also, set GIC
+        * as default IRQ domain to allow for GSI registration and GSI to IRQ
+        * number translation (see acpi_register_gsi() and acpi_gsi_to_irq()).
+        */
+       gic_init_bases(0, -1, dist_base, cpu_base, 0, NULL);
+       irq_set_default_host(gic_data[0].domain);
+       return 0;
+}
+#endif
 
--- /dev/null
+/*
+ * Copyright (C) 2014, Linaro Ltd.
+ *     Author: Tomasz Nowicki <tomasz.nowicki@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef ARM_GIC_ACPI_H_
+#define ARM_GIC_ACPI_H_
+
+#ifdef CONFIG_ACPI
+
+/*
+ * Hard code here, we can not get memory size from MADT (but FDT does),
+ * Actually no need to do that, because this size can be inferred
+ * from GIC spec.
+ */
+#define ACPI_GICV2_DIST_MEM_SIZE       (SZ_4K)
+#define ACPI_GIC_CPU_IF_MEM_SIZE       (SZ_8K)
+
+struct acpi_table_header;
+
+int gic_v2_acpi_init(struct acpi_table_header *table);
+void acpi_gic_init(void);
+#else
+static inline void acpi_gic_init(void) { }
+#endif
+
+#endif /* ARM_GIC_ACPI_H_ */