Skip to contentSkip to conversation

net: enetc: add port MDIO support for both i.MX94 and i.MX95

PATCH Applied Wei Fang 6 participants 16 messages Nov 19, 2025 – Mar 2

Subsystems (4)
lore
Share & tools
lore

Wei Fang

author maintainer
#0 lore raw

v3 cover net: enetc: add port MDIO support for both i.MX94 and i.MX95

The NETC IP has one external master MDIO interface (eMDIO) for managing external PHYs, all ENETC ports share this eMDIO. The EMDIO function and the ENETC port MDIO are the virtual ports of this eMDIO, ENETC can use these virtual ports to access their PHYs. The difference is that EMDIO function is a 'global port', it can access all the PHYs on the eMDIO, so it provides a means for different software modules to share a single set of MDIO signals to access their PHYs.

The ENETC port MDIO can only access its own external PHY. Furthermore, its PHY address must be set to its corresponding LaBCR register in IERB module, which is is a 64 KB size page containing registers that are used for pre-boot initialization for all NETC PCIe functions. And this IERB is owned by the host OS and it will be locked after the initialization, so it cannot be configured at running time any more. The port MDIO can only work properly when the PHY address accessed by it matches the value of its corresponding LaBCR[MDIO_PHYAD_PRTAD]. Otherwise, the MDIO access by the port MDIO will not take effect.

Note that the same PHY is either controlled by port MDIO or by the EMDIO function. The netc-blk-ctrl driver will only set the PHY address in the LaBCR register corresponding to the ENETC when the ENETC node contains an mdio child node, and the ENETC driver will only create the port MDIO bus then. An example in DTS is as follows, the EMDIO function will not\
access this PHY.

enetc_port0 {
        phy-handle = <&ethphy0>;
        phy-mode = "rgmii-id";

        mdio {
                #address-cells = <1>;
                #size-cells = <0>;

                ethphy0: ethernet-phy@1 {
                        reg = <1>;
                };
        };
};

If users want to use EMDIO funtion to manage the PHY, they only need to place the PHY node in the emdio node. The same PHY must not be placed simultaneously within the ENETC node. An example in DTS to use EMDIO is as below.

netc_emdio {
        ethphy0: ethernet-phy@1 {
                reg = <1>;
        };

        ethphy2: ethernet-phy@8 {
                reg = <8>;
        };
};

In the host OS, when there are multiple ENETCs, they can all access their PHYs using their own port MDIO, or they can all access their PHYs using the EMDIO function, or they can partially use port MDIO and partially use the EMDIO function.

Another typical use case of port MDIO is the Jailhouse usage. An ENETC is assigned to a guest OS. The EMDIO function will be unavailable in the guest OS because EMDIO is controlled by the host OS. Therefore, the ENETC can use its port MDIO to manage its external PHY in this situation. In this use case, the host OS's root dtb will disable the ENETC node, so the host OS's ENETC driver will not probe the ENETC and its PHY.

In addition, this series also adds the internal MDIO bus support, each ENETC has an internal MDIO interface for managing on-die PHY (PCS) if it has PCS layer.

---
v3 changes:
1. Change the subject, improve the commit message and cover letter
2. Get the PHY address from mdio node not from the phy-handle, so that only the ENETC node contains the mdio child node, its PHY address will be set to LaBCR register in IERB module
3. Add netc_get_emdio_phy_mask() to get PHY address mask from the EMDIO mode, the same PHY address is not allowed to appear in both the ENETC node and the EMDIO node at the same time, ensuring that the EMDIO bus and port MDIO bus are mutually exclusive.
4. Add some error logs
v2 link: https://lore.kernel.org/imx/[email protected]/
v2 changes:
Improve the commit message.
v1 link: https://lore.kernel.org/imx/[email protected]/
---

Wei Fang (3):
net: enetc: set the external PHY address in IERB for port MDIO usage
net: enetc: set external PHY address in IERB for i.MX94 ENETC
net: enetc: update the base address of port MDIO registers for ENETC

    v4
 .../net/ethernet/freescale/enetc/enetc4_hw.h  |   6 +
 .../freescale/enetc/enetc_pf_common.c         |  14 +-
 .../ethernet/freescale/enetc/netc_blk_ctrl.c  | 198 +++++++++++++++++-
 3 files changed, 215 insertions(+), 3 deletions(-)
Signature · 1 line
2.34.1
author maintainer
#1 lore raw

PATCH v3 1/3 net: enetc: set the external PHY address in IERB for port MDIO usage

The ENETC supports managing its own external PHY through its port MDIO functionality. To use this function, the PHY address needs be set in the corresponding LaBCR register in the Integrated Endpoint Register Block (IERB), which is used for pre-boot initialization of NETC PCIe functions. The port MDIO can only work properly when the PHY address accessed by the port MDIO matches the corresponding LaBCR[MDIO_PHYAD_PRTAD] value.

Because the ENETC driver only registers the MDIO bus (port MDIO bus) when it detects an MDIO child node in its node, similarly, the netc-blk-ctrl driver only resolves the PHY address and sets it in the corresponding LaBCR when it detects an MDIO child node in the ENETC node.

---
 .../ethernet/freescale/enetc/netc_blk_ctrl.c  | 141 +++++++++++++++++-
 1 file changed, 140 insertions(+), 1 deletion(-)
drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c +140 -1
index d7aee3c934d3..6dd54b0d9616 100644
@@ -67,6 +67,9 @@
 #define IERB_EMDIOFAUXR			0x344
 #define IERB_T0FAUXR			0x444
 #define IERB_ETBCR(a)			(0x300c + 0x100 * (a))
+#define IERB_LBCR(a)			(0x1010 + 0x40 * (a))
+#define  LBCR_MDIO_PHYAD_PRTAD(addr)	(((addr) & 0x1f) << 8)
+
 #define IERB_EFAUXR(a)			(0x3044 + 0x100 * (a))
 #define IERB_VFAUXR(a)			(0x4004 + 0x40 * (a))
 #define FAUXR_LDID			GENMASK(3, 0)
@@ -322,6 +325,142 @@ static int netc_unlock_ierb_with_warm_reset(struct netc_blk_ctrl *priv)
 				 1000, 100000, true, priv->prb, PRB_NETCRR);
 }
 
+static int netc_get_phy_addr(struct device_node *np)
+{
+	struct device_node *mdio_node, *phy_node;
+	u32 addr = 0;
+	int err = 0;
+
+	mdio_node = of_get_child_by_name(np, "mdio");
+	if (!mdio_node)
+		return 0;
+
+	phy_node = of_get_next_child(mdio_node, NULL);
+	if (!phy_node)
+		goto of_put_mdio_node;
+
+	err = of_property_read_u32(phy_node, "reg", &addr);
+	if (err)
+		goto of_put_phy_node;
+
+	if (addr >= PHY_MAX_ADDR)
+		err = -EINVAL;
+
+of_put_phy_node:
+	of_node_put(phy_node);
+
+of_put_mdio_node:
+	of_node_put(mdio_node);
+
+	return err ? err : addr;
+}
+
+static int netc_parse_emdio_phy_mask(struct device_node *np, u32 *phy_mask)
+{
+	u32 mask = 0;
+
+	for_each_child_of_node_scoped(np, child) {
+		u32 addr;
+		int err;
+
+		err = of_property_read_u32(child, "reg", &addr);
+		if (err)
+			return err;
+
+		if (addr >= PHY_MAX_ADDR)
+			return -EINVAL;
+
+		mask |= BIT(addr);
+	}
+
+	*phy_mask = mask;
+
+	return 0;
+}
+
+static int netc_get_emdio_phy_mask(struct device_node *np, u32 *phy_mask)
+{
+	for_each_child_of_node_scoped(np, child) {
+		for_each_child_of_node_scoped(child, gchild) {
+			if (!of_device_is_compatible(gchild, "pci1131,ee00"))
+				continue;
+
+			return netc_parse_emdio_phy_mask(gchild, phy_mask);
+		}
+	}
+
+	return 0;
+}
+
+static int imx95_enetc_mdio_phyaddr_config(struct platform_device *pdev)
+{
+	struct netc_blk_ctrl *priv = platform_get_drvdata(pdev);
+	struct device_node *np = pdev->dev.of_node;
+	struct device *dev = &pdev->dev;
+	int bus_devfn, addr, err;
+	u32 phy_mask = 0;
+
+	err = netc_get_emdio_phy_mask(np, &phy_mask);
+	if (err) {
+		dev_err(dev, "Failed to get PHY address mask\n");
+		return err;
+	}
+
+	/* Update the port EMDIO PHY address through parsing phy properties.
+	 * This is needed when using the port EMDIO but it's harmless when
+	 * using the central EMDIO. So apply it on all cases.
+	 */
+	for_each_child_of_node_scoped(np, child) {
+		for_each_child_of_node_scoped(child, gchild) {
+			if (!of_device_is_compatible(gchild, "pci1131,e101"))
+				continue;
+
+			bus_devfn = netc_of_pci_get_bus_devfn(gchild);
+			if (bus_devfn < 0) {
+				dev_err(dev, "Failed to get BDF number\n");
+				return bus_devfn;
+			}
+
+			addr = netc_get_phy_addr(gchild);
+			if (addr < 0) {
+				dev_err(dev, "Failed to get PHY address\n");
+				return addr;
+			}
+
+			if (phy_mask & BIT(addr)) {
+				dev_err(dev,
+					"Find same PHY address in EMDIO and ENETC node\n");
+				return -EINVAL;
+			}
+
+			/* The default value of LaBCR[MDIO_PHYAD_PRTAD ] is
+			 * 0, so no need to set the register.
+			 */
+			if (!addr)
+				continue;
+
+			switch (bus_devfn) {
+			case IMX95_ENETC0_BUS_DEVFN:
+				netc_reg_write(priv->ierb, IERB_LBCR(0),
+					       LBCR_MDIO_PHYAD_PRTAD(addr));
+				break;
+			case IMX95_ENETC1_BUS_DEVFN:
+				netc_reg_write(priv->ierb, IERB_LBCR(1),
+					       LBCR_MDIO_PHYAD_PRTAD(addr));
+				break;
+			case IMX95_ENETC2_BUS_DEVFN:
+				netc_reg_write(priv->ierb, IERB_LBCR(2),
+					       LBCR_MDIO_PHYAD_PRTAD(addr));
+				break;
+			default:
+				break;
+			}
+		}
+	}
+
+	return 0;
+}
+
 static int imx95_ierb_init(struct platform_device *pdev)
 {
 	struct netc_blk_ctrl *priv = platform_get_drvdata(pdev);
@@ -349,7 +488,7 @@ static int imx95_ierb_init(struct platform_device *pdev)
 	/* NETC TIMER */
 	netc_reg_write(priv->ierb, IERB_T0FAUXR, 7);
 
-	return 0;
+	return imx95_enetc_mdio_phyaddr_config(pdev);
 }
 
 static int imx94_get_enetc_id(struct device_node *np)
Signature · 1 line
2.34.1
maintainer Reviewed-by on v3 1/3
#2 lore raw

RE: [PATCH v3 net-next 1/3] net: enetc: set the external PHY address in IERB for port MDIO usage

Quoted 3 lines

-----Original Message-----
From: Wei Fang <[email protected]>
Sent: Wednesday, November 19, 2025 12:26 PM

[...]

Quoted 15 lines

Subject: [PATCH v3 net-next 1/3] net: enetc: set the external PHY address in IERB for port MDIO usage

The ENETC supports managing its own external PHY through its port MDIO functionality. To use this function, the PHY address needs be set in the corresponding LaBCR register in the Integrated Endpoint Register Block (IERB), which is used for pre-boot initialization of NETC PCIe functions. The port MDIO can only work properly when the PHY address accessed by the port MDIO matches the corresponding LaBCR[MDIO_PHYAD_PRTAD] value.

Because the ENETC driver only registers the MDIO bus (port MDIO bus) when it detects an MDIO child node in its node, similarly, the netc-blk-ctrl driver only resolves the PHY address and sets it in the corresponding LaBCR when it detects an MDIO child node in the ENETC node.

Quoted 4 lines

---

#3 lore raw

Re: [PATCH v3 net-next 1/3] net: enetc: set the external PHY address in IERB for port MDIO usage

In reply to Wei Fang

Hi,

sorry for the very late reply. I didn't get the chance to boot our i.MX95 based board (TQMa95xxSA) in the meantime.

Am Mittwoch, 19. November 2025, 11:25:55 CET schrieb Wei Fang:

Quoted 36 lines

The ENETC supports managing its own external PHY through its port MDIO functionality. To use this function, the PHY address needs be set in the corresponding LaBCR register in the Integrated Endpoint Register Block (IERB), which is used for pre-boot initialization of NETC PCIe functions. The port MDIO can only work properly when the PHY address accessed by the port MDIO matches the corresponding LaBCR[MDIO_PHYAD_PRTAD] value.

Because the ENETC driver only registers the MDIO bus (port MDIO bus) when it detects an MDIO child node in its node, similarly, the netc-blk-ctrl driver only resolves the PHY address and sets it in the corresponding LaBCR when it detects an MDIO child node in the ENETC node.

---
 .../ethernet/freescale/enetc/netc_blk_ctrl.c  | 141 +++++++++++++++++-
 1 file changed, 140 insertions(+), 1 deletion(-)
drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c +3 -0
index d7aee3c934d3..6dd54b0d9616 100644
@@ -67,6 +67,9 @@
 #define IERB_EMDIOFAUXR			0x344
 #define IERB_T0FAUXR			0x444
 #define IERB_ETBCR(a)			(0x300c + 0x100 * (a))
+#define IERB_LBCR(a)			(0x1010 + 0x40 * (a))
+#define  LBCR_MDIO_PHYAD_PRTAD(addr)	(((addr) & 0x1f) << 8)
+
 #define IERB_EFAUXR(a)			(0x3044 + 0x100 * (a))
 #define IERB_VFAUXR(a)			(0x4004 + 0x40 * (a))
 #define FAUXR_LDID			GENMASK(3, 0)
@@ -322,6 +325,142 @@ static int netc_unlock_ierb_with_warm_reset(struct netc_blk_ctrl *priv)
 				 1000, 100000, true, priv->prb, PRB_NETCRR);
 }

drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c static int netc_unlock_ierb_with_warm_reset(struct netc_blk_ctrl *priv) · line 336

Quoted 10 lines
drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c +9 -0
 
+static int netc_get_phy_addr(struct device_node *np)
+{
+	struct device_node *mdio_node, *phy_node;
+	u32 addr = 0;
+	int err = 0;
+
+	mdio_node = of_get_child_by_name(np, "mdio");
+	if (!mdio_node)
+		return 0;

If there is no 'mdio' node below enetc_portX node, then 0 is returned...

Quoted 84 lines
drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c +84 -0
+
+	phy_node = of_get_next_child(mdio_node, NULL);
+	if (!phy_node)
+		goto of_put_mdio_node;
+
+	err = of_property_read_u32(phy_node, "reg", &addr);
+	if (err)
+		goto of_put_phy_node;
+
+	if (addr >= PHY_MAX_ADDR)
+		err = -EINVAL;
+
+of_put_phy_node:
+	of_node_put(phy_node);
+
+of_put_mdio_node:
+	of_node_put(mdio_node);
+
+	return err ? err : addr;
+}
+
+static int netc_parse_emdio_phy_mask(struct device_node *np, u32 *phy_mask)
+{
+	u32 mask = 0;
+
+	for_each_child_of_node_scoped(np, child) {
+		u32 addr;
+		int err;
+
+		err = of_property_read_u32(child, "reg", &addr);
+		if (err)
+			return err;
+
+		if (addr >= PHY_MAX_ADDR)
+			return -EINVAL;
+
+		mask |= BIT(addr);
+	}
+
+	*phy_mask = mask;
+
+	return 0;
+}
+
+static int netc_get_emdio_phy_mask(struct device_node *np, u32 *phy_mask)
+{
+	for_each_child_of_node_scoped(np, child) {
+		for_each_child_of_node_scoped(child, gchild) {
+			if (!of_device_is_compatible(gchild, "pci1131,ee00"))
+				continue;
+
+			return netc_parse_emdio_phy_mask(gchild, phy_mask);
+		}
+	}
+
+	return 0;
+}
+
+static int imx95_enetc_mdio_phyaddr_config(struct platform_device *pdev)
+{
+	struct netc_blk_ctrl *priv = platform_get_drvdata(pdev);
+	struct device_node *np = pdev->dev.of_node;
+	struct device *dev = &pdev->dev;
+	int bus_devfn, addr, err;
+	u32 phy_mask = 0;
+
+	err = netc_get_emdio_phy_mask(np, &phy_mask);
+	if (err) {
+		dev_err(dev, "Failed to get PHY address mask\n");
+		return err;
+	}
+
+	/* Update the port EMDIO PHY address through parsing phy properties.
+	 * This is needed when using the port EMDIO but it's harmless when
+	 * using the central EMDIO. So apply it on all cases.
+	 */
+	for_each_child_of_node_scoped(np, child) {
+		for_each_child_of_node_scoped(child, gchild) {
+			if (!of_device_is_compatible(gchild, "pci1131,e101"))
+				continue;
+
+			bus_devfn = netc_of_pci_get_bus_devfn(gchild);
+			if (bus_devfn < 0) {
+				dev_err(dev, "Failed to get BDF number\n");

drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c static int netc_unlock_ierb_with_warm_reset(struct netc_blk_ctrl *priv) · line 430

Quoted 10 lines
drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c +10 -0
+				return bus_devfn;
+			}
+
+			addr = netc_get_phy_addr(gchild);
+			if (addr < 0) {
+				dev_err(dev, "Failed to get PHY address\n");
+				return addr;
+			}
+
+			if (phy_mask & BIT(addr)) {

... which will break here if there is an Ethernet PHY using address 0 in 'netc_emdio' node. See arch/arm64/boot/dts/freescale/imx95-tqma9596sa.dtsi node ethernet-phy@0.

Best regards,
Alexander

Quoted 46 lines
drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c +34 -1
+				dev_err(dev,
+					"Find same PHY address in EMDIO and ENETC node\n");
+				return -EINVAL;
+			}
+
+			/* The default value of LaBCR[MDIO_PHYAD_PRTAD ] is
+			 * 0, so no need to set the register.
+			 */
+			if (!addr)
+				continue;
+
+			switch (bus_devfn) {
+			case IMX95_ENETC0_BUS_DEVFN:
+				netc_reg_write(priv->ierb, IERB_LBCR(0),
+					       LBCR_MDIO_PHYAD_PRTAD(addr));
+				break;
+			case IMX95_ENETC1_BUS_DEVFN:
+				netc_reg_write(priv->ierb, IERB_LBCR(1),
+					       LBCR_MDIO_PHYAD_PRTAD(addr));
+				break;
+			case IMX95_ENETC2_BUS_DEVFN:
+				netc_reg_write(priv->ierb, IERB_LBCR(2),
+					       LBCR_MDIO_PHYAD_PRTAD(addr));
+				break;
+			default:
+				break;
+			}
+		}
+	}
+
+	return 0;
+}
+
 static int imx95_ierb_init(struct platform_device *pdev)
 {
 	struct netc_blk_ctrl *priv = platform_get_drvdata(pdev);
@@ -349,7 +488,7 @@ static int imx95_ierb_init(struct platform_device *pdev)
 	/* NETC TIMER */
 	netc_reg_write(priv->ierb, IERB_T0FAUXR, 7);
 
-	return 0;
+	return imx95_enetc_mdio_phyaddr_config(pdev);
 }
 
 static int imx94_get_enetc_id(struct device_node *np)
Signature · 4 lines
TQ-Systems GmbH | Mühlstraße 2, Gut Delling | 82229 Seefeld, Germany
Amtsgericht München, HRB 105018
Geschäftsführer: Detlef Schneider, Rüdiger Stahl, Stefan Schneider
http://www.tq-group.com/
author maintainer
#4 lore raw

RE: [PATCH v3 net-next 1/3] net: enetc: set the external PHY address in IERB for port MDIO usage

Quoted 33 lines
Quoted 33 lines
drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c +33 -0
+static int imx95_enetc_mdio_phyaddr_config(struct platform_device
+*pdev) {
+	struct netc_blk_ctrl *priv = platform_get_drvdata(pdev);
+	struct device_node *np = pdev->dev.of_node;
+	struct device *dev = &pdev->dev;
+	int bus_devfn, addr, err;
+	u32 phy_mask = 0;
+
+	err = netc_get_emdio_phy_mask(np, &phy_mask);
+	if (err) {
+		dev_err(dev, "Failed to get PHY address mask\n");
+		return err;
+	}
+
+	/* Update the port EMDIO PHY address through parsing phy properties.
+	 * This is needed when using the port EMDIO but it's harmless when
+	 * using the central EMDIO. So apply it on all cases.
+	 */
+	for_each_child_of_node_scoped(np, child) {
+		for_each_child_of_node_scoped(child, gchild) {
+			if (!of_device_is_compatible(gchild, "pci1131,e101"))
+				continue;
+
+			bus_devfn = netc_of_pci_get_bus_devfn(gchild);
+			if (bus_devfn < 0) {
+				dev_err(dev, "Failed to get BDF number\n");
+				return bus_devfn;
+			}
+
+			addr = netc_get_phy_addr(gchild);
+			if (addr < 0) {
+				dev_err(dev, "Failed to get PHY address\n");
+				return addr;
Quoted 8 lines

drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c static int netc_unlock_ierb_with_warm_reset(struct netc_blk_ctrl *priv) · line 430

Quoted 3 lines
drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c +3 -0
+			}
+
+			if (phy_mask & BIT(addr)) {

... which will break here if there is an Ethernet PHY using address 0 in 'netc_emdio' node.
See arch/arm64/boot/dts/freescale/imx95-tqma9596sa.dtsi node ethernet-phy@0.

AFAIU, the PHY address 0 is a special address, below is the description of PHYAD from IEEE 802.3 Clause 22.

A PHY that is connected to the station management entity via the mechanical interface defined in 22.6 shall always respond to transactions addressed to PHY Address zero <00000>. A station management entity that is attached to multiple PHYs must have prior knowledge of the appropriate PHY Address for each PHY.

Therefore, for most PHYs, PHY address 0 is typically used as the broadcast address or default response address. In designs that control multiple PHYs via EMDIO, it is recommended to avoid setting a specific PHY to address 0 to prevent bus conflicts.

If the PHY on your board does not use PHY address 0 as the broadcast address or the default response address, then we should check the PHY address first and then check the phy_mask in imx95_enetc_mdio_phyaddr_config(), just the same as imx94_enetc_mdio_phyaddr_config().

#5 lore raw

Re: [PATCH v3 net-next 1/3] net: enetc: set the external PHY address in IERB for port MDIO usage

Hi,

Am Samstag, 28. Februar 2026, 04:52:01 CET schrieb Wei Fang:

Quoted 51 lines
Quoted 33 lines
Quoted 33 lines
drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c +33 -0
+static int imx95_enetc_mdio_phyaddr_config(struct platform_device
+*pdev) {
+	struct netc_blk_ctrl *priv = platform_get_drvdata(pdev);
+	struct device_node *np = pdev->dev.of_node;
+	struct device *dev = &pdev->dev;
+	int bus_devfn, addr, err;
+	u32 phy_mask = 0;
+
+	err = netc_get_emdio_phy_mask(np, &phy_mask);
+	if (err) {
+		dev_err(dev, "Failed to get PHY address mask\n");
+		return err;
+	}
+
+	/* Update the port EMDIO PHY address through parsing phy properties.
+	 * This is needed when using the port EMDIO but it's harmless when
+	 * using the central EMDIO. So apply it on all cases.
+	 */
+	for_each_child_of_node_scoped(np, child) {
+		for_each_child_of_node_scoped(child, gchild) {
+			if (!of_device_is_compatible(gchild, "pci1131,e101"))
+				continue;
+
+			bus_devfn = netc_of_pci_get_bus_devfn(gchild);
+			if (bus_devfn < 0) {
+				dev_err(dev, "Failed to get BDF number\n");
+				return bus_devfn;
+			}
+
+			addr = netc_get_phy_addr(gchild);
+			if (addr < 0) {
+				dev_err(dev, "Failed to get PHY address\n");
+				return addr;
Quoted 8 lines

drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c static int netc_unlock_ierb_with_warm_reset(struct netc_blk_ctrl *priv) · line 430

Quoted 3 lines
drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c +3 -0
+			}
+
+			if (phy_mask & BIT(addr)) {

... which will break here if there is an Ethernet PHY using address 0 in 'netc_emdio' node.
See arch/arm64/boot/dts/freescale/imx95-tqma9596sa.dtsi node ethernet-phy@0.

AFAIU, the PHY address 0 is a special address, below is the description of PHYAD from IEEE 802.3 Clause 22.

A PHY that is connected to the station management entity via the mechanical interface defined in 22.6 shall always respond to transactions addressed to PHY Address zero <00000>. A station management entity that is attached to multiple PHYs must have prior knowledge of the appropriate PHY Address for each PHY.

Quoted 4 lines

Therefore, for most PHYs, PHY address 0 is typically used as the broadcast address or default response address. In designs that control multiple PHYs via EMDIO, it is recommended to avoid setting a specific PHY to address 0 to prevent bus conflicts.

I know about this special meaning, but there are hardware design which do not take this into account.

Quoted 4 lines

If the PHY on your board does not use PHY address 0 as the broadcast address or the default response address, then we should check the PHY address first and then check the phy_mask in imx95_enetc_mdio_phyaddr_config(), just the same as imx94_enetc_mdio_phyaddr_config().

I'm not sure if this is the right fix. What about the case where phy_mask is supposed to be 0, because there are no PHY subnodes of netc_emdio. Instead the PHY with address is a subnode of the enet_portX is supposed to have netc_get_phy_addr() return 0 because that's the actual address. But with the current flow from imx94_enetc_mdio_phyaddr_config() and your suggestion for i.MX95 case we erroneously skip that node.

Best regards,
Alexander

Signature · 4 lines
TQ-Systems GmbH | Mühlstraße 2, Gut Delling | 82229 Seefeld, Germany
Amtsgericht München, HRB 105018
Geschäftsführer: Detlef Schneider, Rüdiger Stahl, Stefan Schneider
http://www.tq-group.com/
author maintainer
#6 lore raw

RE: [PATCH v3 net-next 1/3] net: enetc: set the external PHY address in IERB for port MDIO usage

Quoted 53 lines

Am Samstag, 28. Februar 2026, 04:52:01 CET schrieb Wei Fang:

Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c +7 -0
+static int imx95_enetc_mdio_phyaddr_config(struct platform_device
+*pdev) {
+	struct netc_blk_ctrl *priv = platform_get_drvdata(pdev);
+	struct device_node *np = pdev->dev.of_node;
+	struct device *dev = &pdev->dev;
+	int bus_devfn, addr, err;
+	u32 phy_mask = 0;
Quoted 8 lines
Quoted 8 lines

drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c static int netc_unlock_ierb_with_warm_reset(struct netc_blk_ctrl *priv)

Quoted 8 lines
drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c +8 -0
+
+	err = netc_get_emdio_phy_mask(np, &phy_mask);
+	if (err) {
+		dev_err(dev, "Failed to get PHY address mask\n");
+		return err;
+	}
+
+	/* Update the port EMDIO PHY address through parsing phy

properties.

Quoted 36 lines
Quoted 18 lines
Quoted 18 lines
drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c +18 -0
+	 * This is needed when using the port EMDIO but it's harmless when
+	 * using the central EMDIO. So apply it on all cases.
+	 */
+	for_each_child_of_node_scoped(np, child) {
+		for_each_child_of_node_scoped(child, gchild) {
+			if (!of_device_is_compatible(gchild, "pci1131,e101"))
+				continue;
+
+			bus_devfn = netc_of_pci_get_bus_devfn(gchild);
+			if (bus_devfn < 0) {
+				dev_err(dev, "Failed to get BDF number\n");
+				return bus_devfn;
+			}
+
+			addr = netc_get_phy_addr(gchild);
+			if (addr < 0) {
+				dev_err(dev, "Failed to get PHY address\n");
+				return addr;
Quoted 8 lines

drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c static int netc_unlock_ierb_with_warm_reset(struct netc_blk_ctrl *priv) · line 430

Quoted 3 lines
drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c +3 -0
+			}
+
+			if (phy_mask & BIT(addr)) {

... which will break here if there is an Ethernet PHY using address 0 in 'netc_emdio' node.
See arch/arm64/boot/dts/freescale/imx95-tqma9596sa.dtsi node ethernet-phy@0.

AFAIU, the PHY address 0 is a special address, below is the description of PHYAD from IEEE 802.3 Clause 22.

A PHY that is connected to the station management entity via the mechanical interface defined in 22.6 shall always respond to transactions addressed to PHY Address zero <00000>. A station management entity that is attached to multiple PHYs must have prior knowledge of the appropriate PHY Address for each PHY.

Quoted 7 lines
Quoted 4 lines

Therefore, for most PHYs, PHY address 0 is typically used as the broadcast address or default response address. In designs that control multiple PHYs via EMDIO, it is recommended to avoid setting a specific PHY to address 0 to prevent bus conflicts.

I know about this special meaning, but there are hardware design which do not take this into account.

This might cause potential issues, as all PHYs attached to the same MDIO bus will respond to the accesses to PHY address 0. Is this problem unfixable?

Quoted 6 lines
Quoted 3 lines

If the PHY on your board does not use PHY address 0 as the broadcast address or the default response address, then we should check the PHY address first

and

Quoted 1 line

then check the phy_mask in imx95_enetc_mdio_phyaddr_config(), just the

same

Quoted 9 lines
Quoted 1 line

as imx94_enetc_mdio_phyaddr_config().

I'm not sure if this is the right fix. What about the case where phy_mask is supposed to be 0, because there are no PHY subnodes of netc_emdio. Instead the PHY with address is a subnode of the enet_portX is supposed to have netc_get_phy_addr() return 0 because that's the actual address. But with the current flow from imx94_enetc_mdio_phyaddr_config() and your suggestion for i.MX95 case we erroneously skip that node.

The hardware default value is 0, so no need to configure it. I can send a fix patch this week.

#7 lore raw

Re: [PATCH v3 net-next 1/3] net: enetc: set the external PHY address in IERB for port MDIO usage

Am Montag, 2. März 2026, 10:24:14 CET schrieb Wei Fang:

Quoted 58 lines
Quoted 58 lines

Am Samstag, 28. Februar 2026, 04:52:01 CET schrieb Wei Fang:

Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c +7 -0
+static int imx95_enetc_mdio_phyaddr_config(struct platform_device
+*pdev) {
+	struct netc_blk_ctrl *priv = platform_get_drvdata(pdev);
+	struct device_node *np = pdev->dev.of_node;
+	struct device *dev = &pdev->dev;
+	int bus_devfn, addr, err;
+	u32 phy_mask = 0;
Quoted 8 lines
Quoted 8 lines

drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c static int netc_unlock_ierb_with_warm_reset(struct netc_blk_ctrl *priv)

Quoted 8 lines
drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c +8 -0
+
+	err = netc_get_emdio_phy_mask(np, &phy_mask);
+	if (err) {
+		dev_err(dev, "Failed to get PHY address mask\n");
+		return err;
+	}
+
+	/* Update the port EMDIO PHY address through parsing phy

properties.

Quoted 40 lines
Quoted 18 lines
Quoted 18 lines
drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c +18 -0
+	 * This is needed when using the port EMDIO but it's harmless when
+	 * using the central EMDIO. So apply it on all cases.
+	 */
+	for_each_child_of_node_scoped(np, child) {
+		for_each_child_of_node_scoped(child, gchild) {
+			if (!of_device_is_compatible(gchild, "pci1131,e101"))
+				continue;
+
+			bus_devfn = netc_of_pci_get_bus_devfn(gchild);
+			if (bus_devfn < 0) {
+				dev_err(dev, "Failed to get BDF number\n");
+				return bus_devfn;
+			}
+
+			addr = netc_get_phy_addr(gchild);
+			if (addr < 0) {
+				dev_err(dev, "Failed to get PHY address\n");
+				return addr;
Quoted 8 lines

drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c static int netc_unlock_ierb_with_warm_reset(struct netc_blk_ctrl *priv) · line 430

Quoted 3 lines
drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c +3 -0
+			}
+
+			if (phy_mask & BIT(addr)) {

... which will break here if there is an Ethernet PHY using address 0 in 'netc_emdio' node.
See arch/arm64/boot/dts/freescale/imx95-tqma9596sa.dtsi node ethernet-phy@0.

AFAIU, the PHY address 0 is a special address, below is the description of PHYAD from IEEE 802.3 Clause 22.

A PHY that is connected to the station management entity via the mechanical interface defined in 22.6 shall always respond to transactions addressed to PHY Address zero <00000>. A station management entity that is attached to multiple PHYs must have prior knowledge of the appropriate PHY Address for each PHY.

Therefore, for most PHYs, PHY address 0 is typically used as the broadcast address or default response address. In designs that control multiple PHYs via EMDIO, it is recommended to avoid setting a specific PHY to address 0 to prevent bus conflicts.

Quoted 5 lines
Quoted 2 lines

I know about this special meaning, but there are hardware design which do not take this into account.

This might cause potential issues, as all PHYs attached to the same MDIO bus will respond to the accesses to PHY address 0.

Is that really the case? So far we didn't have any problems with PHYAD 0 and 3 on the same bus. I did a bit of research but couldn't find any information backing that PHYAD 0 is actually a broadcast address. All I could find is the case with just a single PHY on a MDIO bus, defaulting to 0.

Quoted 1 line

Is this problem unfixable?

Right now our problem is that the software doesn't work any more.

Quoted 16 lines
Quoted 6 lines
Quoted 3 lines

If the PHY on your board does not use PHY address 0 as the broadcast address or the default response address, then we should check the PHY address first

and

Quoted 1 line

then check the phy_mask in imx95_enetc_mdio_phyaddr_config(), just the

same

Quoted 9 lines
Quoted 1 line

as imx94_enetc_mdio_phyaddr_config().

I'm not sure if this is the right fix. What about the case where phy_mask is supposed to be 0, because there are no PHY subnodes of netc_emdio. Instead the PHY with address is a subnode of the enet_portX is supposed to have netc_get_phy_addr() return 0 because that's the actual address. But with the current flow from imx94_enetc_mdio_phyaddr_config() and your suggestion for i.MX95 case we erroneously skip that node.

Quoted 2 lines

The hardware default value is 0, so no need to configure it. I can send a fix patch this week.

Okay, thanks.

Best regards,
Alexander

Signature · 4 lines
TQ-Systems GmbH | Mühlstraße 2, Gut Delling | 82229 Seefeld, Germany
Amtsgericht München, HRB 105018
Geschäftsführer: Detlef Schneider, Rüdiger Stahl, Stefan Schneider
http://www.tq-group.com/
author maintainer
#8 lore raw

RE: [PATCH v3 net-next 1/3] net: enetc: set the external PHY address in IERB for port MDIO usage

Quoted 18 lines
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines

AFAIU, the PHY address 0 is a special address, below is the description of PHYAD from IEEE 802.3 Clause 22.

A PHY that is connected to the station management entity via the mechanical interface defined in 22.6 shall always respond to transactions addressed to PHY Address zero <00000>. A station management entity that is attached to multiple PHYs must have prior knowledge of the appropriate PHY Address for each PHY.

Quoted 6 lines
Quoted 6 lines
Quoted 4 lines

Therefore, for most PHYs, PHY address 0 is typically used as the broadcast address or default response address. In designs that control multiple PHYs via EMDIO, it is recommended to avoid setting a specific PHY to address 0 to prevent bus conflicts.

I know about this special meaning, but there are hardware design which do

not

Quoted 2 lines
Quoted 1 line

take this into account.

Quoted 9 lines
Quoted 1 line

This might cause potential issues, as all PHYs attached to the same MDIO bus

will

Quoted 1 line

respond to the accesses to PHY address 0.

Is that really the case? So far we didn't have any problems with PHYAD 0 and 3 on the same bus. I did a bit of research but couldn't find any information backing that PHYAD 0 is actually a broadcast address. All I could find is the case with just a single PHY on a MDIO bus, defaulting to 0.

There is no problem if there is only a single PHY on the bus. But if there are multiple PHYs, as address 0 is the default response address, there PHYs will respond to transactions addressed to PHY address 0.

The reason you didn't see the problem is because the two PHYs on your boards are the same model, so their configurations are identical. However, if you disable the PHY with address 0 via the MDIO bus, both PHYs might be disabled.

Quoted 4 lines
Quoted 1 line

Is this problem unfixable?

Right now our problem is that the software doesn't work any more.

I'm sorry, but I still recommend against using address 0 when there are multiple PHYs on the MDIO bus.

author maintainer
#9 lore raw

PATCH v3 2/3 net: enetc: set external PHY address in IERB for i.MX94 ENETC

In reply to Wei Fang

NETC IP has only one external master MDIO interface (eMDIO) for managing the external PHYs. ENETC can use the interfaces provided by the EMDIO function or its port MDIO to access and manage its external PHY. Both the EMDIO function and the port MDIO are all virtual ports of the eMDIO.

The difference is that the EMDIO function is a 'global port', it can access all the PHYs on the eMDIO, but port MDIO can only access its own PHY. To ensure that ENETC can only access its own PHY through port MDIO, LaBCR[MDIO_PHYAD_PRTAD] needs to be set, which represents the address of the external PHY connected to ENETC. If the accessed PHY address is not consistent with LaBCR[MDIO_PHYAD_PRTAD], then the MDIO access initiated by port MDIO will be invalid.

---
 .../ethernet/freescale/enetc/netc_blk_ctrl.c  | 57 +++++++++++++++++++
 1 file changed, 57 insertions(+)
drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c +57 -0
index 6dd54b0d9616..443983fdecd9 100644
@@ -563,12 +563,64 @@ static int imx94_enetc_update_tid(struct netc_blk_ctrl *priv,
 	return 0;
 }
 
+static int imx94_enetc_mdio_phyaddr_config(struct netc_blk_ctrl *priv,
+					   struct device_node *np,
+					   u32 phy_mask)
+{
+	struct device *dev = &priv->pdev->dev;
+	int bus_devfn, addr;
+
+	bus_devfn = netc_of_pci_get_bus_devfn(np);
+	if (bus_devfn < 0) {
+		dev_err(dev, "Failed to get BDF number\n");
+		return bus_devfn;
+	}
+
+	addr = netc_get_phy_addr(np);
+	if (addr <= 0) {
+		dev_err(dev, "Failed to get PHY address\n");
+		return addr;
+	}
+
+	if (phy_mask & BIT(addr)) {
+		dev_err(dev,
+			"Find same PHY address in EMDIO and ENETC node\n");
+		return -EINVAL;
+	}
+
+	switch (bus_devfn) {
+	case IMX94_ENETC0_BUS_DEVFN:
+		netc_reg_write(priv->ierb, IERB_LBCR(IMX94_ENETC0_LINK),
+			       LBCR_MDIO_PHYAD_PRTAD(addr));
+		break;
+	case IMX94_ENETC1_BUS_DEVFN:
+		netc_reg_write(priv->ierb, IERB_LBCR(IMX94_ENETC1_LINK),
+			       LBCR_MDIO_PHYAD_PRTAD(addr));
+		break;
+	case IMX94_ENETC2_BUS_DEVFN:
+		netc_reg_write(priv->ierb, IERB_LBCR(IMX94_ENETC2_LINK),
+			       LBCR_MDIO_PHYAD_PRTAD(addr));
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
 static int imx94_ierb_init(struct platform_device *pdev)
 {
 	struct netc_blk_ctrl *priv = platform_get_drvdata(pdev);
 	struct device_node *np = pdev->dev.of_node;
+	u32 phy_mask = 0;
 	int err;
 
+	err = netc_get_emdio_phy_mask(np, &phy_mask);
+	if (err) {
+		dev_err(&pdev->dev, "Failed to get PHY address mask\n");
+		return err;
+	}
+
 	for_each_child_of_node_scoped(np, child) {
 		for_each_child_of_node_scoped(child, gchild) {
 			if (!of_device_is_compatible(gchild, "pci1131,e101"))
@@ -577,6 +629,11 @@ static int imx94_ierb_init(struct platform_device *pdev)
 			err = imx94_enetc_update_tid(priv, gchild);
 			if (err)
 				return err;
+
+			err = imx94_enetc_mdio_phyaddr_config(priv, gchild,
+							      phy_mask);
+			if (err)
+				return err;
 		}
 	}
 
Signature · 1 line
2.34.1
maintainer Reviewed-by on v3 2/3
#10 lore raw

RE: [PATCH v3 net-next 2/3] net: enetc: set external PHY address in IERB for i.MX94 ENETC

Quoted 3 lines

-----Original Message-----
From: Wei Fang <[email protected]>
Sent: Wednesday, November 19, 2025 12:26 PM

[...]

Quoted 17 lines

Subject: [PATCH v3 net-next 2/3] net: enetc: set external PHY address in IERB for i.MX94 ENETC

NETC IP has only one external master MDIO interface (eMDIO) for managing the external PHYs. ENETC can use the interfaces provided by the EMDIO function or its port MDIO to access and manage its external PHY. Both the EMDIO function and the port MDIO are all virtual ports of the eMDIO.

The difference is that the EMDIO function is a 'global port', it can access all the PHYs on the eMDIO, but port MDIO can only access its own PHY. To ensure that ENETC can only access its own PHY through port MDIO, LaBCR[MDIO_PHYAD_PRTAD] needs to be set, which represents the address of
the external PHY connected to ENETC. If the accessed PHY address is not consistent with LaBCR[MDIO_PHYAD_PRTAD], then the MDIO access initiated by port MDIO will be invalid.

Quoted 2 lines

---

author maintainer
#11 lore raw

PATCH v3 3/3 net: enetc: update the base address of port MDIO registers for ENETC v4

In reply to Wei Fang

Each ENETC has a set of external MDIO registers to access its external PHY based on its port EMDIO bus, these registers are used for MDIO bus access, such as setting the PHY address, PHY register address and value, read or write operations, C22 or C45 format, etc. The base address of this set of registers has been modified in ENETC v4 and is different from that in ENETC v1. So the base address needs to be updated so that ENETC v4 can use port MDIO to manage its own external PHY.

Additionally, if ENETC has the PCS layer, it also has a set of internal MDIO registers for managing its on-die PHY (PCS/Serdes). The base address of this set of registers is also different from that of ENETC v1, so the base address also needs to be updated so that ENETC v4 can support the management of on-die PHY through the internal MDIO bus.

---
 drivers/net/ethernet/freescale/enetc/enetc4_hw.h   |  6 ++++++
 .../net/ethernet/freescale/enetc/enetc_pf_common.c | 14 ++++++++++++--
 2 files changed, 18 insertions(+), 2 deletions(-)
drivers/net/ethernet/freescale/enetc/enetc4_hw.h +6 -0
index ebea4298791c..3ed0f7a02767 100644
@@ -170,6 +170,9 @@
 /* Port MAC 0/1 Maximum Frame Length Register */
 #define ENETC4_PM_MAXFRM(mac)		(0x5014 + (mac) * 0x400)
 
+/* Port internal MDIO base address, use to access PCS */
+#define ENETC4_PM_IMDIO_BASE		0x5030
+
 /* Port MAC 0/1 Pause Quanta Register */
 #define ENETC4_PM_PAUSE_QUANTA(mac)	(0x5054 + (mac) * 0x400)
 
@@ -198,6 +201,9 @@
 #define   SSP_1G			2
 #define  PM_IF_MODE_ENA			BIT(15)
 
+/* Port external MDIO Base address, use to access off-chip PHY */
+#define ENETC4_EMDIO_BASE		0x5c00
+
 /**********************ENETC Pseudo MAC port registers************************/
 /* Port pseudo MAC receive octets counter (64-bit) */
 #define ENETC4_PPMROCR			0x5080
drivers/net/ethernet/freescale/enetc/enetc_pf_common.c +12 -2
index 9c634205e2a7..76263b8566bb 100644
@@ -176,7 +176,12 @@ static int enetc_mdio_probe(struct enetc_pf *pf, struct device_node *np)
 	bus->parent = dev;
 	mdio_priv = bus->priv;
 	mdio_priv->hw = &pf->si->hw;
-	mdio_priv->mdio_base = ENETC_EMDIO_BASE;
+
+	if (is_enetc_rev1(pf->si))
+		mdio_priv->mdio_base = ENETC_EMDIO_BASE;
+	else
+		mdio_priv->mdio_base = ENETC4_EMDIO_BASE;
+
 	snprintf(bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev));
 
 	err = of_mdiobus_register(bus, np);
@@ -221,7 +226,12 @@ static int enetc_imdio_create(struct enetc_pf *pf)
 	bus->phy_mask = ~0;
 	mdio_priv = bus->priv;
 	mdio_priv->hw = &pf->si->hw;
-	mdio_priv->mdio_base = ENETC_PM_IMDIO_BASE;
+
+	if (is_enetc_rev1(pf->si))
+		mdio_priv->mdio_base = ENETC_PM_IMDIO_BASE;
+	else
+		mdio_priv->mdio_base = ENETC4_PM_IMDIO_BASE;
+
 	snprintf(bus->id, MII_BUS_ID_SIZE, "%s-imdio", dev_name(dev));
 
 	err = mdiobus_register(bus);
Signature · 1 line
2.34.1
maintainer Reviewed-by on v3 3/3
#12 lore raw

RE: [PATCH v3 net-next 3/3] net: enetc: update the base address of port MDIO registers for ENETC v4

Quoted 3 lines

-----Original Message-----
From: Wei Fang <[email protected]>
Sent: Wednesday, November 19, 2025 12:26 PM

[...]

Quoted 11 lines

Subject: [PATCH v3 net-next 3/3] net: enetc: update the base address of port MDIO registers for ENETC v4

Each ENETC has a set of external MDIO registers to access its external PHY based on its port EMDIO bus, these registers are used for MDIO bus access, such as setting the PHY address, PHY register address and value, read or write operations, C22 or C45 format, etc. The base address of this set of registers has been modified in ENETC v4 and is different from that in ENETC v1. So the base address needs to be updated so that ENETC v4 can use port MDIO to manage its own external PHY.

Quoted 8 lines

Additionally, if ENETC has the PCS layer, it also has a set of internal MDIO registers for managing its on-die PHY (PCS/Serdes). The base address of this set of registers is also different from that of ENETC v1, so the base address also needs to be updated so that ENETC v4 can support the management of on-die PHY through the internal MDIO bus.

---

maintainer
#13 lore raw

Re: [PATCH v3 net-next 3/3] net: enetc: update the base address of port MDIO registers for ENETC v4

In reply to Wei Fang
Quoted 8 lines · Wei Fang

Each ENETC has a set of external MDIO registers to access its external PHY based on its port EMDIO bus, these registers are used for MDIO bus access, such as setting the PHY address, PHY register address and value, read or write operations, C22 or C45 format, etc. The base address of this set of registers has been modified in ENETC v4 and is different from that in ENETC v1. So the base address needs to be updated so that ENETC v4 can use port MDIO to manage its own external PHY.

Quoted 7 lines

Additionally, if ENETC has the PCS layer, it also has a set of internal MDIO registers for managing its on-die PHY (PCS/Serdes). The base address of this set of registers is also different from that of ENETC v1, so the base address also needs to be updated so that ENETC v4 can support the management of on-die PHY through the internal MDIO bus.

Andrew, it's not clear to me if you are with the current patch version, could you please chime-in?

Thanks,

Paolo

#14 lore raw

Re: [PATCH v3 net-next 3/3] net: enetc: update the base address of port MDIO registers for ENETC v4

Quoted 15 lines · Paolo Abeni
Quoted 14 lines · Wei Fang

Each ENETC has a set of external MDIO registers to access its external PHY based on its port EMDIO bus, these registers are used for MDIO bus access, such as setting the PHY address, PHY register address and value, read or write operations, C22 or C45 format, etc. The base address of this set of registers has been modified in ENETC v4 and is different from that in ENETC v1. So the base address needs to be updated so that ENETC v4 can use port MDIO to manage its own external PHY.

Additionally, if ENETC has the PCS layer, it also has a set of internal MDIO registers for managing its on-die PHY (PCS/Serdes). The base address of this set of registers is also different from that of ENETC v1, so the base address also needs to be updated so that ENETC v4 can support the management of on-die PHY through the internal MDIO bus.

Quoted 4 lines
Quoted 1 line

Andrew, it's not clear to me if you are with the current patch version, could you please chime-in?

I say merge it. I'm not sure it is the best of architectures, but i don't have time to dig into all the details in order to suggest something better.

Andrew

#15 lore raw
In reply to Wei Fang
This series was applied to netdev/net-next.git (main) by Jakub Kicinski <[email protected]>:

Hello:

This series was applied to netdev/net-next.git (main) by Jakub Kicinski <[email protected]>:

Quoted 9 lines · On Wed, 19 Nov 2025 18:25:54 +0800 you wrote:

The NETC IP has one external master MDIO interface (eMDIO) for managing external PHYs, all ENETC ports share this eMDIO. The EMDIO function and the ENETC port MDIO are the virtual ports of this eMDIO, ENETC can use these virtual ports to access their PHYs. The difference is that EMDIO function is a 'global port', it can access all the PHYs on the eMDIO, so it provides a means for different software modules to share a single set of MDIO signals to access their PHYs.

[...]

Here is the summary with links:
- [v3,net-next,1/3] net: enetc: set the external PHY address in IERB for port MDIO usage

    https://git.kernel.org/netdev/net-next/c/6633df05f3ad
  - [v3,net-next,2/3] net: enetc: set external PHY address in IERB for i.MX94 ENETC
    https://git.kernel.org/netdev/net-next/c/50bfd9c06f0f
  - [v3,net-next,3/3] net: enetc: update the base address of port MDIO registers for ENETC v4
    https://git.kernel.org/netdev/net-next/c/10ba23a7f6cc

You are awesome, thank you!

Signature · 2 lines
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html