net: fsl_enetc: Add support for i.MX952
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@nxp.com> Signed-off-by: Alice Guo <alice.guo@nxp.com> Reviewed-by: Peng Fan <peng.fan@nxp.com>
This commit is contained in:
+2
-2
@@ -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
|
||||
|
||||
+27
-1
@@ -75,10 +75,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 = dev_read_u32_array(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));
|
||||
|
||||
|
||||
@@ -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 },
|
||||
{},
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user