diff --git a/Documentation/riscv/acpi.rst b/Documentation/riscv/acpi.rst
index 9870a282815b..e2406546bc16 100644
--- a/Documentation/riscv/acpi.rst
+++ b/Documentation/riscv/acpi.rst
@@ -8,3 +8,24 @@ The ISA string parsing rules for ACPI are defined by `Version ASCIIDOC
 Conversion, 12/2022 of the RISC-V specifications, as defined by tag
 "riscv-isa-release-1239329-2023-05-23" (commit 1239329
 ) <https://github.com/riscv/riscv-isa-manual/releases/tag/riscv-isa-release-1239329-2023-05-23>`_
+
+Interrupt Controller Drivers
+=======
+
+ACPI drivers for RISC-V interrupt controllers use software node framework to
+create the fwnode for the interrupt controllers. Below properties are
+additionally required for some firmware nodes apart from the properties
+defined by the device tree bindings for these interrupt controllers. The
+properties are created using the data in MADT table.
+
+1) RISC-V Interrupt Controller (INTC)
+-----------
+``hartid`` - Hart ID of the hart this interrupt controller belongs to.
+
+``riscv,imsic-addr`` - Physical base address of the Incoming MSI Controller
+(IMSIC) MMIO region of this hart.
+
+``riscv,imsic-size`` - Size in bytes of the IMSIC MMIO region of this hart.
+
+``riscv,ext-intc-id`` - The unique ID of the external interrupts connected
+to this hart.
diff --git a/arch/riscv/include/asm/acpi.h b/arch/riscv/include/asm/acpi.h
index 0c4e8b35103e..0ac2df2dd194 100644
--- a/arch/riscv/include/asm/acpi.h
+++ b/arch/riscv/include/asm/acpi.h
@@ -68,6 +68,7 @@ int acpi_get_riscv_isa(struct acpi_table_header *table,
 static inline int acpi_numa_get_nid(unsigned int cpu) { return NUMA_NO_NODE; }
 int acpi_get_cbo_block_size(struct acpi_table_header *table, unsigned int cpu, u32 *cbom_size,
 			    u32 *cboz_size, u32 *cbop_size);
+struct fwnode_handle *acpi_rintc_create_irqchip_fwnode(struct acpi_madt_rintc *rintc);
 #else
 static inline void acpi_init_rintc_map(void) { }
 static inline struct acpi_madt_rintc *acpi_cpu_get_madt_rintc(int cpu)
diff --git a/drivers/acpi/riscv/Makefile b/drivers/acpi/riscv/Makefile
index 8b3b126e0b94..8b664190d172 100644
--- a/drivers/acpi/riscv/Makefile
+++ b/drivers/acpi/riscv/Makefile
@@ -1,2 +1,2 @@
 # SPDX-License-Identifier: GPL-2.0-only
-obj-y 	+= rhct.o
+obj-y 	+= rhct.o irqchip.o
diff --git a/drivers/acpi/riscv/irqchip.c b/drivers/acpi/riscv/irqchip.c
new file mode 100644
index 000000000000..36f066a2cad5
--- /dev/null
+++ b/drivers/acpi/riscv/irqchip.c
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2023, Ventana Micro Systems Inc
+ *	Author: Sunil V L <sunilvl@ventanamicro.com>
+ *
+ */
+
+#include <linux/acpi.h>
+#include <linux/fwnode.h>
+#include <linux/irqdomain.h>
+#include <linux/list.h>
+#include <linux/property.h>
+
+struct riscv_irqchip_list {
+	struct fwnode_handle *fwnode;
+	struct list_head list;
+};
+
+LIST_HEAD(rintc_list);
+
+struct fwnode_handle *acpi_rintc_create_irqchip_fwnode(struct acpi_madt_rintc *rintc)
+{
+	struct property_entry props[6] = {};
+	struct fwnode_handle *fwnode;
+	struct riscv_irqchip_list *rintc_element;
+
+	props[0] = PROPERTY_ENTRY_U64("hartid", rintc->hart_id);
+	props[1] = PROPERTY_ENTRY_U32("riscv,ext-intc-id", rintc->ext_intc_id);
+	props[2] = PROPERTY_ENTRY_U64("riscv,imsic-addr", rintc->imsic_addr);
+	props[3] = PROPERTY_ENTRY_U32("riscv,imsic-size", rintc->imsic_size);
+	props[4] = PROPERTY_ENTRY_U32("#interrupt-cells", 1);
+
+	fwnode = fwnode_create_software_node_early(props, NULL);
+	if (fwnode) {
+		rintc_element = kzalloc(sizeof(*rintc_element), GFP_KERNEL);
+		if (!rintc_element) {
+			fwnode_remove_software_node(fwnode);
+			return NULL;
+		}
+
+		rintc_element->fwnode = fwnode;
+		list_add_tail(&rintc_element->list, &rintc_list);
+	}
+
+	return fwnode;
+}
diff --git a/drivers/irqchip/irq-riscv-intc.c b/drivers/irqchip/irq-riscv-intc.c
index 1a0fc87152c5..1ef9cada1ed3 100644
--- a/drivers/irqchip/irq-riscv-intc.c
+++ b/drivers/irqchip/irq-riscv-intc.c
@@ -203,6 +203,12 @@ static int __init riscv_intc_acpi_init(union acpi_subtable_headers *header,
 
 	rintc = (struct acpi_madt_rintc *)header;
 
+	fn = acpi_rintc_create_irqchip_fwnode(rintc);
+	if (!fn) {
+		pr_err("unable to create INTC FW node\n");
+		return -ENOMEM;
+	}
+
 	/*
 	 * The ACPI MADT will have one INTC for each CPU (or HART)
 	 * so riscv_intc_acpi_init() function will be called once
@@ -212,12 +218,6 @@ static int __init riscv_intc_acpi_init(union acpi_subtable_headers *header,
 	if (riscv_hartid_to_cpuid(rintc->hart_id) != smp_processor_id())
 		return 0;
 
-	fn = irq_domain_alloc_named_fwnode("RISCV-INTC");
-	if (!fn) {
-		pr_err("unable to allocate INTC FW node\n");
-		return -ENOMEM;
-	}
-
 	return riscv_intc_init_common(fn);
 }
 
