mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2026-06-13 15:03:58 +03:00
Merge patch series "am65-cpsw-nuss phy_interface_t fixup for fixed TX delay"
Matthias Schiffer <matthias.schiffer@ew.tq-group.com> says: Following a discussion on the LKML [1], there has been a clarification of the correct use of the rgmii(/-rxid/-txid/-it) phy-modes [2] - namely, that they don't describe the interface at the MAC or PHY boundary, but whether the PCB traces add delays or not (where it is implementation-defined whether the delays are added on the MAC or PHY side in the latter case). Accordingly, a fixup has been implemented in the am65-cpsw-nuss driver to make it follow the clarified rules [3]; apply the same change to U-Boot. Backwards compatibility is preserved: using an old DTB with the wrong phy-mode only results in a warning message, but keeps the Ethernet working. With a new DTB from Linux 6.17+ that sets the mode to rgmii-id, these changes are necessary to avoid using an unsupported/ reserved configuration. See the commit message of patch 2/2 for some additional detail. [1] https://lore.kernel.org/lkml/d25b1447-c28b-4998-b238-92672434dc28@lunn.ch/ [2] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c360eb0c3ccb95306704fd221442283ee82f1f58 [3] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ca13b249f291f4920466638d1adbfb3f9c8db6e9 Link: https://lore.kernel.org/r/cover.1759218200.git.matthias.schiffer@ew.tq-group.com
This commit is contained in:
@@ -234,14 +234,11 @@ out:
|
||||
#define AM65_GMII_SEL_MODE_RGMII 2
|
||||
#define AM65_GMII_SEL_MODE_SGMII 3
|
||||
|
||||
#define AM65_GMII_SEL_RGMII_IDMODE BIT(4)
|
||||
|
||||
static int am65_cpsw_gmii_sel_k3(struct am65_cpsw_priv *priv,
|
||||
phy_interface_t phy_mode)
|
||||
{
|
||||
struct udevice *dev = priv->dev;
|
||||
u32 offset, reg, phandle;
|
||||
bool rgmii_id = false;
|
||||
fdt_addr_t gmii_sel;
|
||||
u32 mode = 0;
|
||||
ofnode node;
|
||||
@@ -278,12 +275,6 @@ static int am65_cpsw_gmii_sel_k3(struct am65_cpsw_priv *priv,
|
||||
mode = AM65_GMII_SEL_MODE_RGMII;
|
||||
break;
|
||||
|
||||
case PHY_INTERFACE_MODE_RGMII_ID:
|
||||
case PHY_INTERFACE_MODE_RGMII_TXID:
|
||||
mode = AM65_GMII_SEL_MODE_RGMII;
|
||||
rgmii_id = true;
|
||||
break;
|
||||
|
||||
case PHY_INTERFACE_MODE_SGMII:
|
||||
mode = AM65_GMII_SEL_MODE_SGMII;
|
||||
break;
|
||||
@@ -298,9 +289,6 @@ static int am65_cpsw_gmii_sel_k3(struct am65_cpsw_priv *priv,
|
||||
break;
|
||||
};
|
||||
|
||||
if (rgmii_id)
|
||||
mode |= AM65_GMII_SEL_RGMII_IDMODE;
|
||||
|
||||
reg = mode;
|
||||
dev_dbg(dev, "gmii_sel PHY mode: %u, new gmii_sel: %08x\n",
|
||||
phy_mode, reg);
|
||||
@@ -630,7 +618,7 @@ static int am65_cpsw_phy_init(struct udevice *dev)
|
||||
u32 supported = PHY_GBIT_FEATURES;
|
||||
int ret = 0;
|
||||
|
||||
phydev = dm_eth_phy_connect(dev);
|
||||
phydev = dm_eth_phy_connect_interface(dev, pdata->phy_interface);
|
||||
if (!phydev) {
|
||||
dev_err(dev, "phy_connect() failed\n");
|
||||
return -ENODEV;
|
||||
@@ -657,9 +645,28 @@ static int am65_cpsw_ofdata_parse_phy(struct udevice *dev)
|
||||
dev_read_u32(dev, "reg", &priv->port_id);
|
||||
|
||||
pdata->phy_interface = dev_read_phy_mode(dev);
|
||||
if (pdata->phy_interface == PHY_INTERFACE_MODE_NA) {
|
||||
|
||||
/* CPSW controllers supported by this driver have a fixed internal TX
|
||||
* delay in RGMII mode. Fix up PHY mode to account for this and warn
|
||||
* about Device Trees that claim to have a TX delay on the PCB.
|
||||
*/
|
||||
switch (pdata->phy_interface) {
|
||||
case PHY_INTERFACE_MODE_RGMII_ID:
|
||||
pdata->phy_interface = PHY_INTERFACE_MODE_RGMII_RXID;
|
||||
break;
|
||||
case PHY_INTERFACE_MODE_RGMII_TXID:
|
||||
pdata->phy_interface = PHY_INTERFACE_MODE_RGMII;
|
||||
break;
|
||||
case PHY_INTERFACE_MODE_RGMII:
|
||||
case PHY_INTERFACE_MODE_RGMII_RXID:
|
||||
dev_warn(dev,
|
||||
"RGMII mode without internal TX delay unsupported; please fix your Device Tree\n");
|
||||
break;
|
||||
case PHY_INTERFACE_MODE_NA:
|
||||
dev_err(dev, "Invalid PHY mode, port %u\n", priv->port_id);
|
||||
return -EINVAL;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
dev_read_u32(dev, "max-speed", (u32 *)&pdata->max_speed);
|
||||
|
||||
@@ -192,6 +192,21 @@ struct phy_device *dm_mdio_phy_connect(struct udevice *mdiodev, int phyaddr,
|
||||
struct udevice *ethdev,
|
||||
phy_interface_t interface);
|
||||
|
||||
/**
|
||||
* dm_eth_phy_connect_interface - Connect an Eth device to a PHY based on device
|
||||
* tree with custom PHY interface
|
||||
*
|
||||
* Picks up the DT phy-handle and from ethernet device node and connects the
|
||||
* ethernet device to the linked PHY, while allowing the caller to specify
|
||||
* the phy-mode to use.
|
||||
*
|
||||
* @ethdev: ethernet device
|
||||
* @interface: MAC-PHY protocol
|
||||
*
|
||||
* Return: pointer to phy_device, or 0 on error
|
||||
*/
|
||||
struct phy_device *dm_eth_phy_connect_interface(struct udevice *ethdev,
|
||||
phy_interface_t interface);
|
||||
/**
|
||||
* dm_eth_phy_connect - Connect an Eth device to a PHY based on device tree
|
||||
*
|
||||
|
||||
@@ -242,8 +242,8 @@ struct phy_device *dm_mdio_phy_connect(struct udevice *mdiodev, int phyaddr,
|
||||
return phy_connect(pdata->mii_bus, phyaddr, ethdev, interface);
|
||||
}
|
||||
|
||||
static struct phy_device *dm_eth_connect_phy_handle(struct udevice *ethdev,
|
||||
phy_interface_t interface)
|
||||
struct phy_device *dm_eth_phy_connect_interface(struct udevice *ethdev,
|
||||
phy_interface_t interface)
|
||||
{
|
||||
u32 phy_addr;
|
||||
struct udevice *mdiodev;
|
||||
@@ -282,8 +282,10 @@ static struct phy_device *dm_eth_connect_phy_handle(struct udevice *ethdev,
|
||||
phy = dm_mdio_phy_connect(mdiodev, phy_addr, ethdev, interface);
|
||||
|
||||
out:
|
||||
if (phy)
|
||||
if (phy) {
|
||||
phy->node = phynode;
|
||||
phy->interface = interface;
|
||||
}
|
||||
|
||||
return phy;
|
||||
}
|
||||
@@ -292,7 +294,6 @@ out:
|
||||
struct phy_device *dm_eth_phy_connect(struct udevice *ethdev)
|
||||
{
|
||||
phy_interface_t interface;
|
||||
struct phy_device *phy;
|
||||
|
||||
if (!dev_has_ofnode(ethdev)) {
|
||||
debug("%s: supplied eth dev has no DT node!\n", ethdev->name);
|
||||
@@ -303,14 +304,7 @@ struct phy_device *dm_eth_phy_connect(struct udevice *ethdev)
|
||||
if (interface == PHY_INTERFACE_MODE_NA)
|
||||
dev_dbg(ethdev, "can't find interface mode, default to NA\n");
|
||||
|
||||
phy = dm_eth_connect_phy_handle(ethdev, interface);
|
||||
|
||||
if (!phy)
|
||||
return NULL;
|
||||
|
||||
phy->interface = interface;
|
||||
|
||||
return phy;
|
||||
return dm_eth_phy_connect_interface(ethdev, interface);
|
||||
}
|
||||
|
||||
UCLASS_DRIVER(mdio) = {
|
||||
|
||||
Reference in New Issue
Block a user