diff options
Diffstat (limited to 'drivers/net/phy/ti_phy_init.c')
-rw-r--r-- | drivers/net/phy/ti_phy_init.c | 48 |
1 files changed, 47 insertions, 1 deletions
diff --git a/drivers/net/phy/ti_phy_init.c b/drivers/net/phy/ti_phy_init.c index a0878193ac0..850c0cbec96 100644 --- a/drivers/net/phy/ti_phy_init.c +++ b/drivers/net/phy/ti_phy_init.c @@ -10,12 +10,58 @@ #include <phy.h> #include "ti_phy_init.h" +#define DP83822_DEVADDR 0x1f + +#define MII_DP83822_RCSR 0x17 + +/* RCSR bits */ +#define DP83822_RX_CLK_SHIFT BIT(12) +#define DP83822_TX_CLK_SHIFT BIT(11) + +/* DP83822 specific RGMII RX/TX delay configuration. */ +static int dp83822_config(struct phy_device *phydev) +{ + ofnode node = phy_get_ofnode(phydev); + u32 rgmii_delay = 0; + u32 rx_delay = 0; + u32 tx_delay = 0; + int ret; + + ret = ofnode_read_u32(node, "rx-internal-delay-ps", &rx_delay); + if (ret) { + rx_delay = phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || + phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID; + } + + ret = ofnode_read_u32(node, "tx-internal-delay-ps", &tx_delay); + if (ret) { + tx_delay = phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || + phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID; + } + + /* Bit set means Receive path internal clock shift is ENABLED */ + if (rx_delay) + rgmii_delay |= DP83822_RX_CLK_SHIFT; + + /* Bit set means Transmit path internal clock shift is DISABLED */ + if (!tx_delay) + rgmii_delay |= DP83822_TX_CLK_SHIFT; + + ret = phy_modify_mmd(phydev, DP83822_DEVADDR, MII_DP83822_RCSR, + DP83822_RX_CLK_SHIFT | DP83822_TX_CLK_SHIFT, + rgmii_delay); + if (ret) + return ret; + + return genphy_config_aneg(phydev); +} + U_BOOT_PHY_DRIVER(dp83822) = { .name = "TI DP83822", .uid = 0x2000a240, .mask = 0xfffffff0, .features = PHY_BASIC_FEATURES, - .config = &genphy_config_aneg, + .config = &dp83822_config, .startup = &genphy_startup, .shutdown = &genphy_shutdown, }; |