[PATCH v1 2/3] net: fsl_enetc: Add support for i.MX952
alice.guo at oss.nxp.com
alice.guo at oss.nxp.com
Fri Apr 3 11:41:27 CEST 2026
From: Ye Li <ye.li at nxp.com>
Extend ENETC driver to support i.MX952 platform where 2 ENETC
controllers are located on different PCIe buses.
Key changes:
- Add enetc_dev_id_imx() to derive device ID from device tree "reg"
property for i.MX952, mapping bus_devfn values 0x0 and 0x100 to device
IDs 0 and 1 respectively
- Implement imx952_netcmix_init() to configure MII protocol and PCS
settings based on PHY mode parsed from device tree
- Add i.MX952 to FSL_ENETC_NETC_BLK_CTRL Kconfig dependencies
Signed-off-by: Ye Li <ye.li at nxp.com>
Signed-off-by: Alice Guo <alice.guo at nxp.com>
---
drivers/net/Kconfig | 4 +-
drivers/net/fsl_enetc.c | 28 +++++++++++++-
drivers/net/fsl_enetc_netc_blk_ctrl.c | 72 +++++++++++++++++++++++++++++++++++
3 files changed, 101 insertions(+), 3 deletions(-)
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index ed07e286676..4da10ed1289 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1018,8 +1018,8 @@ config FSL_ENETC
config FSL_ENETC_NETC_BLK_CTRL
bool "NXP ENETC NETC blocks control driver"
depends on FSL_ENETC
- depends on IMX95 || IMX94
- default y if IMX95 || IMX94
+ depends on IMX95 || IMX94 || IMX952
+ default y if IMX95 || IMX94 || IMX952
help
This driver configures Integrated Endpoint Register Block (IERB) and
Privileged Register Block (PRB) of NETC. For i.MX platforms, it also
diff --git a/drivers/net/fsl_enetc.c b/drivers/net/fsl_enetc.c
index 766aea035d3..a1569b9d989 100644
--- a/drivers/net/fsl_enetc.c
+++ b/drivers/net/fsl_enetc.c
@@ -67,10 +67,36 @@ static int enetc_is_ls1028a(struct udevice *dev)
pplat->vendor == PCI_VENDOR_ID_FREESCALE;
}
+static int enetc_dev_id_imx(struct udevice *dev)
+{
+ if (IS_ENABLED(CONFIG_IMX952)) {
+ int bus_devfn;
+ u32 reg[5];
+ int error;
+
+ error = ofnode_read_u32_array(dev_ofnode(dev), "reg", reg, ARRAY_SIZE(reg));
+ if (error)
+ return error;
+
+ bus_devfn = (reg[0] >> 8) & 0xffff;
+
+ switch (bus_devfn) {
+ case 0:
+ return 0;
+ case 0x100:
+ return 1;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ return PCI_DEV(pci_get_devfn(dev)) >> 3;
+}
+
static int enetc_dev_id(struct udevice *dev)
{
if (enetc_is_imx95(dev))
- return PCI_DEV(pci_get_devfn(dev)) >> 3;
+ return enetc_dev_id_imx(dev);
if (enetc_is_ls1028a(dev))
return PCI_FUNC(pci_get_devfn(dev));
diff --git a/drivers/net/fsl_enetc_netc_blk_ctrl.c b/drivers/net/fsl_enetc_netc_blk_ctrl.c
index 8577bb75632..0c87d80ea5c 100644
--- a/drivers/net/fsl_enetc_netc_blk_ctrl.c
+++ b/drivers/net/fsl_enetc_netc_blk_ctrl.c
@@ -35,6 +35,7 @@
#define MII_PROT_RGMII 0x2
#define MII_PROT_SERIAL 0x3
#define MII_PROT(port, prot) (((prot) & 0xf) << ((port) << 2))
+#define MII_PROT_GET(reg, port) (((reg) >> ((port) << 2)) & 0xf)
#define IMX95_CFG_LINK_PCS_PROT(a) (0x8 + (a) * 4)
#define PCS_PROT_1G_SGMII BIT(0)
@@ -97,6 +98,9 @@
#define IMX94_TIMER1_ID 1
#define IMX94_TIMER2_ID 2
+#define IMX952_ENETC0_BUS_DEVFN 0x0
+#define IMX952_ENETC1_BUS_DEVFN 0x100
+
/* Flags for different platforms */
#define NETC_HAS_NETCMIX BIT(0)
@@ -567,6 +571,69 @@ static int netc_prb_check_error(struct netc_blk_ctrl *priv)
return 0;
}
+static int imx952_netcmix_init(struct udevice *dev)
+{
+ struct netc_blk_ctrl *priv = dev_get_priv(dev);
+ ofnode child, gchild;
+ phy_interface_t interface;
+ int bus_devfn, mii_proto;
+ u32 val;
+
+ /* Default setting */
+ val = MII_PROT(0, MII_PROT_RGMII) | MII_PROT(1, MII_PROT_RGMII);
+
+ /* Update the link MII protocol through parsing phy-mode */
+ dev_for_each_subnode(child, dev) {
+ if (!ofnode_is_enabled(child))
+ continue;
+
+ ofnode_for_each_subnode(gchild, child) {
+ if (!ofnode_is_enabled(gchild))
+ continue;
+
+ if (!ofnode_device_is_compatible(gchild, "pci1131,e101"))
+ continue;
+
+ bus_devfn = netc_of_pci_get_bus_devfn(gchild);
+ if (bus_devfn < 0)
+ return -EINVAL;
+
+ interface = ofnode_read_phy_mode(gchild);
+ if (interface == -1)
+ continue;
+
+ mii_proto = netc_get_link_mii_protocol(interface);
+ if (mii_proto < 0)
+ return -EINVAL;
+
+ switch (bus_devfn) {
+ case IMX952_ENETC0_BUS_DEVFN:
+ val &= ~CFG_LINK_MII_PORT_0;
+ val |= FIELD_PREP(CFG_LINK_MII_PORT_0, mii_proto);
+ break;
+ case IMX952_ENETC1_BUS_DEVFN:
+ val &= ~CFG_LINK_MII_PORT_1;
+ val |= FIELD_PREP(CFG_LINK_MII_PORT_1, mii_proto);
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+ }
+
+ if (MII_PROT_GET(val, 1) == MII_PROT_SERIAL) {
+ /* Configure Link I/O variant */
+ netc_reg_write(priv->netcmix, IMX95_CFG_LINK_IO_VAR,
+ IO_VAR(1, IO_VAR_16FF_16G_SERDES));
+ /* Configure Link 2 PCS protocol */
+ netc_reg_write(priv->netcmix, IMX95_CFG_LINK_PCS_PROT(1),
+ PCS_PROT_2500M_SGMII);
+ }
+ netc_reg_write(priv->netcmix, IMX95_CFG_LINK_MII_PROT, val);
+
+ return 0;
+}
+
static const struct netc_devinfo imx95_devinfo = {
.netcmix_init = imx95_netcmix_init,
.ierb_init = imx95_ierb_init,
@@ -578,9 +645,14 @@ static const struct netc_devinfo imx94_devinfo = {
.xpcs_port_init = imx94_netc_xpcs_port_init,
};
+static const struct netc_devinfo imx952_devinfo = {
+ .netcmix_init = imx952_netcmix_init,
+};
+
static const struct udevice_id netc_blk_ctrl_match[] = {
{ .compatible = "nxp,imx95-netc-blk-ctrl", .data = (ulong)&imx95_devinfo },
{ .compatible = "nxp,imx94-netc-blk-ctrl", .data = (ulong)&imx94_devinfo },
+ { .compatible = "nxp,imx952-netc-blk-ctrl", .data = (ulong)&imx952_devinfo },
{},
};
--
2.43.0
More information about the U-Boot
mailing list