diff options
| author | Julien Blanc <julien.blanc@sprinte.eu> | 2026-10-09 08:08:33 +0000 |
|---|---|---|
| committer | Jakub Kicinski <kuba@kernel.org> | 2026-10-15 17:36:39 -0700 |
| commit | b8aa6bedc5fb16bad28b7f7665d184e94e40ad6e (patch) | |
| tree | 8c86c12a6783567fc52e34a628bfbee299a1db3d | |
| parent | 01b99e9d0d6260846e4256abb0d500d7985a8215 (diff) | |
net: phy: dp83td510: Add config phase
Add a config phase for the Texas Instruments DP83TD510E ethernet PHY
The config phase currently sets the following properties from the
device tree:
* RMII / RGMII mode (note : RMII master / slave can only be set
by straps and cannot be changed at runtime)
* RGMII delays. These delays can be enabled on the phy side, only
as a boolean. Delays are enabled if phy-mode is rgmii-id, or
rgmii-[rx|tx]id which enables only the corresponding delay.
* In case another mode is encountered, do nothing and return
success (keep old behavior)
Note on RCSR: unlike the DP83822, on the DS83TD510E both
delays are active-high (ie, rgmii internal delays are enabled
when the corresponding bit is set to 1 in the configuration
register).
Signed-off-by: Julien Blanc <julien.blanc@sprinte.eu>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://patch.msgid.link/e9e0499a28a49e489fb623429c7487b8ece78d12.camel@sprinte.eu
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
| -rw-r--r-- | drivers/net/phy/dp83td510.c | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/drivers/net/phy/dp83td510.c b/drivers/net/phy/dp83td510.c index 9e9a41bf6457..31c139bef076 100644 --- a/drivers/net/phy/dp83td510.c +++ b/drivers/net/phy/dp83td510.c @@ -30,6 +30,12 @@ #define DP83TD510E_INT1_LINK BIT(13) #define DP83TD510E_INT1_LINK_EN BIT(5) +#define DP83TD510E_RCSR 0x17 +#define DP83TD510E_RMII_MODE_EN BIT(5) +#define DP83TD510E_RGMII_MODE_EN BIT(9) +#define DP83TD510E_TX_CLK_SHIFT BIT(11) +#define DP83TD510E_RX_CLK_SHIFT BIT(12) + #define DP83TD510E_CTRL 0x1f #define DP83TD510E_CTRL_HW_RESET BIT(15) #define DP83TD510E_CTRL_SW_RESET BIT(14) @@ -649,6 +655,71 @@ static int dp83td510_config_aneg(struct phy_device *phydev) return genphy_c45_check_and_restart_aneg(phydev, changed); } +static bool dp83td510_config_rgmii_rx_delay(struct phy_device *phydev) +{ + return phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || + phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID; +} + +static bool dp83td510_config_rgmii_tx_delay(struct phy_device *phydev) +{ + return phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || + phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID; +} + +static int dp83td510_config_init(struct phy_device *phydev) +{ + int rgmii_delay = 0; + bool rx_int_delay; + bool tx_int_delay; + int ret; + + if (phy_interface_is_rgmii(phydev)) { + rx_int_delay = dp83td510_config_rgmii_rx_delay(phydev); + if (rx_int_delay) + rgmii_delay |= DP83TD510E_RX_CLK_SHIFT; + + tx_int_delay = dp83td510_config_rgmii_tx_delay(phydev); + + if (tx_int_delay) + rgmii_delay |= DP83TD510E_TX_CLK_SHIFT; + + ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, DP83TD510E_RCSR, + DP83TD510E_RX_CLK_SHIFT | + DP83TD510E_TX_CLK_SHIFT, + rgmii_delay); + if (ret) + return ret; + + ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, + DP83TD510E_RCSR, DP83TD510E_RGMII_MODE_EN); + + if (ret) + return ret; + + } else if (phydev->interface == PHY_INTERFACE_MODE_RMII) { + /* set RMII_MODE_EN, clear RGMII_MODE_EN. We need to clear RGMII + * here because otherwise, RMII/MII configuration would be + * ignored as RGMII would be selected. + */ + ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, DP83TD510E_RCSR, + DP83TD510E_RMII_MODE_EN | + DP83TD510E_RGMII_MODE_EN, + DP83TD510E_RMII_MODE_EN); + if (ret) + return ret; + } else { + /* may be MII, which is supported, or something else. Just + * return success to keep the old behavior and not break + * anything. Configuration may have been done by straps so + * it's better to not touch it. + */ + ret = 0; + } + + return ret; +} + static int dp83td510_get_sqi(struct phy_device *phydev) { int sqi, ret; @@ -942,6 +1013,7 @@ static struct phy_driver dp83td510_driver[] = { .name = "TI DP83TD510E", .flags = PHY_POLL_CABLE_TEST, + .config_init = dp83td510_config_init, .probe = dp83td510_probe, .config_aneg = dp83td510_config_aneg, .read_status = dp83td510_read_status, |
