diff --git a/drivers/net/ethernet/ti/prueth.h b/drivers/net/ethernet/ti/prueth.h
index 69ea6affbb1ec848b27a0ed87ff7e5fb88296361..a345f172ac520e84a9a1f82904042e9c53abfa8b 100644
--- a/drivers/net/ethernet/ti/prueth.h
+++ b/drivers/net/ethernet/ti/prueth.h
@@ -46,6 +46,11 @@ enum pruss_ethtype {
 #define PRUETH_IS_PRP(p)	((p)->eth_type == PRUSS_ETHTYPE_PRP)
 #define PRUETH_IS_LRE(p)	(PRUETH_IS_HSR(p) || PRUETH_IS_PRP(p))
 
+#define PRUETH_REG_DUMP_VER		1
+
+/* Encoding: 32-16: Reserved, 16-8: Reg dump version, 8-0: Ethertype  */
+#define PRUETH_REG_DUMP_GET_VER(x)	((PRUETH_REG_DUMP_VER << 8) | ((x)->eth_type))
+
 /**
  * struct prueth_queue_desc - Queue descriptor
  * @rd_ptr:	Read pointer, points to a buffer descriptor in Shared PRU RAM.
diff --git a/drivers/net/ethernet/ti/prueth_core.c b/drivers/net/ethernet/ti/prueth_core.c
index 3b27345a3bb726f241e642d8ef159fd682674626..65fb634f8150225653067a6e1472946a69d2629b 100644
--- a/drivers/net/ethernet/ti/prueth_core.c
+++ b/drivers/net/ethernet/ti/prueth_core.c
@@ -2234,6 +2234,68 @@ static void emac_get_ethtool_stats(struct net_device *ndev,
 	prueth_lre_update_stats(emac->prueth, &data[i]);
 }
 
+static int emac_get_regs_len(struct net_device *ndev)
+{
+	struct prueth_emac *emac = netdev_priv(ndev);
+	struct prueth *prueth = emac->prueth;
+
+	/* VLAN Table at the end of the memory map, after MultiCast
+	 * filter region. So VLAN table base +
+	 * size will give the entire size of reg dump in case of
+	 * Dual-EMAC firmware.
+	 */
+	if (PRUETH_IS_EMAC(prueth)) {
+		return ICSS_EMAC_FW_VLAN_FLTR_TBL_BASE_ADDR +
+		       ICSS_EMAC_FW_VLAN_FILTER_TABLE_SIZE_BYTES;
+	}
+
+	/* MultiCast table and VLAN filter table are in different
+	 * memories in case of HSR/PRP firmware. Therefore add the sizes
+	 * of individual region.
+	 */
+	if (PRUETH_IS_LRE(prueth)) {
+		return ICSS_LRE_FW_VLAN_FLTR_TBL_BASE_ADDR +
+		       ICSS_EMAC_FW_VLAN_FILTER_TABLE_SIZE_BYTES +
+		       ICSS_LRE_FW_MULTICAST_FILTER_TABLE +
+		       ICSS_EMAC_FW_MULTICAST_TABLE_SIZE_BYTES;
+	}
+
+	return 0;
+}
+
+static void emac_get_regs(struct net_device *ndev, struct ethtool_regs *regs,
+			  void *p)
+{
+	struct prueth_emac *emac = netdev_priv(ndev);
+	struct prueth *prueth = emac->prueth;
+	void __iomem *ram;
+	u8 *reg = p;
+
+	regs->version = PRUETH_REG_DUMP_GET_VER(prueth);
+
+	/* Dump firmware's VLAN and MC tables */
+	if (PRUETH_IS_EMAC(prueth)) {
+		ram = prueth->mem[emac->dram].va;
+		memcpy_fromio(reg, ram, emac_get_regs_len(ndev));
+		return;
+	}
+
+	if (PRUETH_IS_LRE(prueth)) {
+		size_t len = ICSS_LRE_FW_VLAN_FLTR_TBL_BASE_ADDR +
+			     ICSS_EMAC_FW_VLAN_FILTER_TABLE_SIZE_BYTES;
+
+		ram =  prueth->mem[PRUETH_MEM_SHARED_RAM].va;
+		memcpy_fromio(reg, ram, len);
+
+		reg += len;
+
+		ram = prueth->mem[PRUETH_MEM_DRAM1].va;
+		len = ICSS_LRE_FW_MULTICAST_FILTER_TABLE +
+		      ICSS_EMAC_FW_MULTICAST_TABLE_SIZE_BYTES;
+		memcpy_fromio(reg, ram, len);
+	}
+}
+
 /* Ethtool support for EMAC adapter */
 static const struct ethtool_ops emac_ethtool_ops = {
 	.get_drvinfo = emac_get_drvinfo,
@@ -2244,6 +2306,8 @@ static const struct ethtool_ops emac_ethtool_ops = {
 	.get_sset_count = emac_get_sset_count,
 	.get_strings = emac_get_strings,
 	.get_ethtool_stats = emac_get_ethtool_stats,
+	.get_regs = emac_get_regs,
+	.get_regs_len = emac_get_regs_len,
 };
 
 /* get emac_port corresponding to eth_node name */