* along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/acpi.h>
 #include <linux/bitmap.h>
 #include <linux/cpu.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
+#include <linux/irqdomain.h>
+#include <linux/acpi_iort.h>
 #include <linux/log2.h>
 #include <linux/mm.h>
 #include <linux/msi.h>
                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 {
                return -EINVAL;
        }
        return 0;
 }
 
+#ifdef CONFIG_ACPI
+
+#define ACPI_GICV3_ITS_MEM_SIZE (SZ_128K)
+
+static int __init gic_acpi_parse_madt_its(struct acpi_subtable_header *header,
+                                         const unsigned long end)
+{
+       struct acpi_madt_generic_translator *its_entry;
+       struct fwnode_handle *dom_handle;
+       struct resource res;
+       int err;
+
+       its_entry = (struct acpi_madt_generic_translator *)header;
+       memset(&res, 0, sizeof(res));
+       res.start = its_entry->base_address;
+       res.end = its_entry->base_address + ACPI_GICV3_ITS_MEM_SIZE - 1;
+       res.flags = IORESOURCE_MEM;
+
+       dom_handle = irq_domain_alloc_fwnode((void *)its_entry->base_address);
+       if (!dom_handle) {
+               pr_err("ITS@%pa: Unable to allocate GICv3 ITS domain token\n",
+                      &res.start);
+               return -ENOMEM;
+       }
+
+       err = iort_register_domain_token(its_entry->translation_id, dom_handle);
+       if (err) {
+               pr_err("ITS@%pa: Unable to register GICv3 ITS domain token (ITS ID %d) to IORT\n",
+                      &res.start, its_entry->translation_id);
+               goto dom_err;
+       }
+
+       err = its_probe_one(&res, dom_handle, NUMA_NO_NODE);
+       if (!err)
+               return 0;
+
+       iort_deregister_domain_token(its_entry->translation_id);
+dom_err:
+       irq_domain_free_fwnode(dom_handle);
+       return err;
+}
+
+static void __init its_acpi_probe(void)
+{
+       acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_TRANSLATOR,
+                             gic_acpi_parse_madt_its, 0);
+}
+#else
+static void __init its_acpi_probe(void) { }
+#endif
+
 int __init its_init(struct fwnode_handle *handle, struct rdists *rdists,
                    struct irq_domain *parent_domain)
 {
        if (of_node)
                its_of_probe(of_node);
        else
-               return -ENODEV;
+               its_acpi_probe();
 
        if (list_empty(&its_nodes)) {
                pr_warn("ITS: No ITS available, not enabling LPIs\n");