diff --git a/drivers/soc/ti/Kconfig b/drivers/soc/ti/Kconfig
index be4570baad96..7640490c2a6a 100644
--- a/drivers/soc/ti/Kconfig
+++ b/drivers/soc/ti/Kconfig
@@ -73,4 +73,10 @@ config TI_SCI_PM_DOMAINS
 	  called ti_sci_pm_domains. Note this is needed early in boot before
 	  rootfs may be available.
 
+config K3_INTA_MSI_DOMAIN
+	bool
+	select GENERIC_MSI_IRQ_DOMAIN
+	help
+	  Driver to enable Interrupt Aggregator specific MSI Domain.
+
 endif # SOC_TI
diff --git a/drivers/soc/ti/Makefile b/drivers/soc/ti/Makefile
index a22edc0b258a..152b195273ee 100644
--- a/drivers/soc/ti/Makefile
+++ b/drivers/soc/ti/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_KEYSTONE_NAVIGATOR_DMA)	+= knav_dma.o
 obj-$(CONFIG_AMX3_PM)			+= pm33xx.o
 obj-$(CONFIG_WKUP_M3_IPC)		+= wkup_m3_ipc.o
 obj-$(CONFIG_TI_SCI_PM_DOMAINS)		+= ti_sci_pm_domains.o
+obj-$(CONFIG_K3_INTA_MSI_DOMAIN)	+= k3_inta_msi.o
diff --git a/drivers/soc/ti/k3_inta_msi.c b/drivers/soc/ti/k3_inta_msi.c
new file mode 100644
index 000000000000..0236d836d7f6
--- /dev/null
+++ b/drivers/soc/ti/k3_inta_msi.c
@@ -0,0 +1,163 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Texas Instruments' K3 Interrupt Aggregator driver MSI support
+ *
+ * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+ *	Lokesh Vutla <lokeshvutla@ti.com>
+ */
+
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/msi.h>
+#include <linux/soc/ti/k3_inta_msi.h>
+
+#ifdef GENERIC_MSI_DOMAIN_OPS
+
+#define TI_SCI_DEV_ID_MASK	0xffff
+#define TI_SCI_DEV_ID_SHIFT	16
+#define TI_SCI_IRQ_ID_MASK	0xffff
+#define TI_SCI_IRQ_ID_SHIFT	0
+
+#define TO_HWIRQ(id, index)	(((id & TI_SCI_DEV_ID_MASK) << \
+				 TI_SCI_DEV_ID_SHIFT) | \
+				(index & TI_SCI_IRQ_ID_MASK))
+static void inta_msi_set_desc(msi_alloc_info_t *arg, struct msi_desc *desc)
+{
+	arg->desc = desc;
+	arg->hwirq = TO_HWIRQ(desc->inta.dev_id, desc->inta.msi_index);
+}
+#else
+#define inta_msi_set_desc NULL
+#endif
+
+static void inta_msi_update_dom_ops(struct msi_domain_info *info)
+{
+	struct msi_domain_ops *ops = info->ops;
+
+	BUG_ON(!ops);
+
+	if (ops->set_desc == NULL)
+		ops->set_desc = inta_msi_set_desc;
+}
+
+static void inta_msi_update_chip_ops(struct msi_domain_info *info)
+{
+	struct irq_chip *chip = info->chip;
+
+	BUG_ON(!chip);
+	if (!chip->irq_mask)
+		chip->irq_mask = irq_chip_mask_parent;
+	if (!chip->irq_unmask)
+		chip->irq_unmask = irq_chip_unmask_parent;
+	if (!chip->irq_eoi)
+		chip->irq_eoi = irq_chip_eoi_parent;
+	if (!chip->irq_set_affinity)
+		chip->irq_set_affinity = msi_domain_set_affinity;
+}
+
+struct irq_domain *inta_msi_create_irq_domain(struct fwnode_handle *fwnode,
+					      struct msi_domain_info *info,
+					      struct irq_domain *parent)
+{
+	struct irq_domain *domain;
+
+	if (info->flags & MSI_FLAG_USE_DEF_DOM_OPS)
+		inta_msi_update_dom_ops(info);
+	if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS)
+		inta_msi_update_chip_ops(info);
+
+	domain = msi_create_irq_domain(fwnode, info, parent);
+	if (domain)
+		irq_domain_update_bus_token(domain, DOMAIN_BUS_K3_INTA_MSI);
+
+	return domain;
+}
+EXPORT_SYMBOL_GPL(inta_msi_create_irq_domain);
+
+static struct msi_desc *inta_msi_alloc_desc(struct device *dev, u32 dev_id,
+					    u32 index)
+{
+	struct msi_desc *msi_desc;
+
+	msi_desc = alloc_msi_entry(dev, 1, NULL);
+	if (!msi_desc) {
+		dev_err(dev, "Failed to allocate msi entry\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	msi_desc->inta.msi_index = index;
+	msi_desc->inta.dev_id = dev_id;
+	INIT_LIST_HEAD(&msi_desc->list);
+	list_add_tail(&msi_desc->list, dev_to_msi_list(dev));
+
+	return msi_desc;
+}
+
+void inta_msi_domain_free_group_irqs(struct device *dev, u32 *arr_index,
+				     int nr_irqs)
+{
+	struct irq_domain *msi_domain;
+	struct msi_desc *desc, *tmp;
+	unsigned int i, virq = 0;
+
+	msi_domain = dev_get_msi_domain(dev);
+
+	list_for_each_entry_safe(desc, tmp, dev_to_msi_list(dev), list) {
+		for (i = 0; i < nr_irqs; i++) {
+			if (desc->inta.msi_index == arr_index[i]) {
+				msi_domain_free_irq(desc);
+				/* HACK to get parent IRQ. Any elegant solution? */
+				if (!virq)
+					virq = desc->msg.data;
+				list_del(&desc->list);
+				free_msi_entry(desc);
+			}
+		}
+	}
+
+	msi_domain_unprepare_irqs(msi_domain, nr_irqs, (void *)&virq);
+}
+EXPORT_SYMBOL_GPL(inta_msi_domain_free_group_irqs);
+
+int inta_msi_domain_alloc_group_irqs(struct device *dev, u32 dev_id,
+				     int nr_irqs, u32 *arr_index)
+{
+	struct irq_domain *msi_domain;
+	struct msi_desc *msi_desc;
+	msi_alloc_info_t arg;
+	int ret, i;
+
+	msi_domain = dev_get_msi_domain(dev);
+	if (!msi_domain)
+		return -EINVAL;
+
+	if (nr_irqs < 1)
+		return -EINVAL;
+
+	ret = msi_domain_prepare_irqs(msi_domain, dev, nr_irqs, &arg);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < nr_irqs; i++) {
+		msi_desc = inta_msi_alloc_desc(dev, dev_id, arr_index[i]);
+		if (IS_ERR(msi_desc)) {
+			ret = PTR_ERR(msi_desc);
+			goto cleanup;
+		}
+
+		ret = msi_domain_alloc_irq(msi_domain, dev, msi_desc, &arg);
+		if (ret) {
+			dev_err(dev, "Failed to allocate IRQs\n");
+			goto cleanup;
+		}
+	}
+	return 0;
+
+cleanup:
+	inta_msi_domain_free_group_irqs(dev, arr_index, i);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(inta_msi_domain_alloc_group_irqs);
diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index 068aa46f0d55..47bb695e1067 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -81,6 +81,7 @@ enum irq_domain_bus_token {
 	DOMAIN_BUS_NEXUS,
 	DOMAIN_BUS_IPI,
 	DOMAIN_BUS_FSL_MC_MSI,
+	DOMAIN_BUS_K3_INTA_MSI,
 };
 
 /**
diff --git a/include/linux/msi.h b/include/linux/msi.h
index 1e37aa569a3c..acc2873bb197 100644
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -47,6 +47,11 @@ struct fsl_mc_msi_desc {
 	u16				msi_index;
 };
 
+struct inta_msi_desc {
+	u16	dev_id;
+	u16	msi_index;
+};
+
 /**
  * struct msi_desc - Descriptor structure for MSI based interrupts
  * @list:	List head for management
@@ -106,6 +111,7 @@ struct msi_desc {
 		 */
 		struct platform_msi_desc platform;
 		struct fsl_mc_msi_desc fsl_mc;
+		struct inta_msi_desc inta;
 	};
 };
 
diff --git a/include/linux/soc/ti/k3_inta_msi.h b/include/linux/soc/ti/k3_inta_msi.h
new file mode 100644
index 000000000000..42c6202f044d
--- /dev/null
+++ b/include/linux/soc/ti/k3_inta_msi.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Texas Instruments' K3 INTA MSI helper
+ *
+ * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+ *	Lokesh Vutla <lokeshvutla@ti.com>
+ */
+
+#ifndef __INCLUDE_LINUX_K3_INTA_MSI_H
+#define __INCLUDE_LINUX_K3_INTA_MSI_H
+
+#include <linux/msi.h>
+
+struct irq_domain *inta_msi_create_irq_domain(struct fwnode_handle *fwnode,
+					      struct msi_domain_info *info,
+					      struct irq_domain *parent);
+int inta_msi_domain_alloc_group_irqs(struct device *dev, u32 dev_id,
+				     int nr_irqs, u32 *arr_index);
+void inta_msi_domain_free_group_irqs(struct device *dev, u32 *arr_index,
+				     int nr_irqs);
+#endif /* __INCLUDE_LINUX_IRQCHIP_TI_SCI_INTA_H */
