>From 7f19f32d3074c9990e46349b76ae13dc9c1133d6 Mon Sep 17 00:00:00 2001 From: Marc Gonzalez Date: Wed, 13 Feb 2019 18:29:02 +0100 Subject: [PATCH] net: phy: at803x: Fix RGMII RX and TX clock delays setup The current code supports enabling RGMII RX and TX clock delays. The unstated assumption is that these settings are disabled by default at reset, which is not the case. RX clock delay is enabled at reset. And TX clock delay "survives" across SW resets. Thus, if the bootloader enables TX clock delay, it will remain enabled at reset in Linux. Provide disable functions to configure the RGMII clock delays exactly as specified in the fwspec. Fixes: cd28d1d6e52e: ("net: phy: at803x: Disable phy delay for RGMII mode") Reported-by: Peter Ujfalusi Signed-off-by: Marc Gonzalez Signed-off-by: Niklas Cassel --- drivers/net/phy/at803x.c | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c index 90dc62c15fc5..700c1e4d34ad 100644 --- a/drivers/net/phy/at803x.c +++ b/drivers/net/phy/at803x.c @@ -103,12 +103,24 @@ static int at803x_debug_reg_mask(struct phy_device *phydev, u16 reg, return phy_write(phydev, AT803X_DEBUG_DATA, val); } +static inline int at803x_enable_rx_delay(struct phy_device *phydev) +{ + return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_0, 0, + AT803X_DEBUG_RX_CLK_DLY_EN); +} + static inline int at803x_disable_rx_delay(struct phy_device *phydev) { return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_0, AT803X_DEBUG_RX_CLK_DLY_EN, 0); } +static inline int at803x_enable_tx_delay(struct phy_device *phydev) +{ + return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_5, 0, + AT803X_DEBUG_TX_CLK_DLY_EN); +} + static inline int at803x_disable_tx_delay(struct phy_device *phydev) { return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_5, @@ -242,20 +254,22 @@ static int at803x_config_init(struct phy_device *phydev) return ret; if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID || - phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || - phydev->interface == PHY_INTERFACE_MODE_RGMII) { + phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) + ret = at803x_enable_rx_delay(phydev); + else ret = at803x_disable_rx_delay(phydev); - if (ret < 0) - return ret; - } + + if (ret < 0) + return ret; if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID || - phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || - phydev->interface == PHY_INTERFACE_MODE_RGMII) { + phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) + ret = at803x_enable_tx_delay(phydev); + else ret = at803x_disable_tx_delay(phydev); - if (ret < 0) - return ret; - } + + if (ret < 0) + return ret; return 0; } -- 2.20.1