aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/drivers/net/phy/mscc/mscc_main.c
diff options
context:
space:
mode:
authorVladimir Oltean <vladimir.oltean@nxp.com>2020-03-24 16:13:58 +0200
committerDavid S. Miller <davem@davemloft.net>2020-03-24 16:36:37 -0700
commit2283a02b67d41251a80857121e36845161fc57b5 (patch)
treee185ee31e81736c7570bbcc17ac1b7e6be968b05 /drivers/net/phy/mscc/mscc_main.c
parentMerge branch 'axienet-Update-error-handling-and-add-64-bit-DMA-support' (diff)
downloadwireguard-linux-2283a02b67d41251a80857121e36845161fc57b5.tar.xz
wireguard-linux-2283a02b67d41251a80857121e36845161fc57b5.zip
net: phy: mscc: consolidate a common RGMII delay implementation
It looks like the VSC8584 PHY driver is rolling its own RGMII delay configuration code, despite the fact that the logic is mostly the same. In fact only the register layout and position for the RGMII controls has changed. So we need to adapt and parameterize the PHY-dependent bit fields when calling the new generic function. Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Reviewed-by: Andrew Lunn <andrew@lunn.ch> Tested-by: Antoine Tenart <antoine.tenart@bootlin.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/phy/mscc/mscc_main.c')
-rw-r--r--drivers/net/phy/mscc/mscc_main.c78
1 files changed, 40 insertions, 38 deletions
diff --git a/drivers/net/phy/mscc/mscc_main.c b/drivers/net/phy/mscc/mscc_main.c
index 19603081dd14..acddef79f4e8 100644
--- a/drivers/net/phy/mscc/mscc_main.c
+++ b/drivers/net/phy/mscc/mscc_main.c
@@ -520,28 +520,34 @@ out_unlock:
return rc;
}
-static int vsc85xx_default_config(struct phy_device *phydev)
+/* Set the RGMII RX and TX clock skews individually, according to the PHY
+ * interface type, to:
+ * * 0.2 ns (their default, and lowest, hardware value) if delays should
+ * not be enabled
+ * * 2.0 ns (which causes the data to be sampled at exactly half way between
+ * clock transitions at 1000 Mbps) if delays should be enabled
+ */
+static int vsc85xx_rgmii_set_skews(struct phy_device *phydev, u32 rgmii_cntl,
+ u16 rgmii_rx_delay_mask,
+ u16 rgmii_tx_delay_mask)
{
+ u16 rgmii_rx_delay_pos = ffs(rgmii_rx_delay_mask) - 1;
+ u16 rgmii_tx_delay_pos = ffs(rgmii_tx_delay_mask) - 1;
u16 reg_val = 0;
int rc;
- phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
-
- if (!phy_interface_mode_is_rgmii(phydev->interface))
- return 0;
-
mutex_lock(&phydev->lock);
if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID ||
phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
- reg_val |= RGMII_CLK_DELAY_2_0_NS << RGMII_RX_CLK_DELAY_POS;
+ reg_val |= RGMII_CLK_DELAY_2_0_NS << rgmii_rx_delay_pos;
if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID ||
phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
- reg_val |= RGMII_CLK_DELAY_2_0_NS << RGMII_TX_CLK_DELAY_POS;
+ reg_val |= RGMII_CLK_DELAY_2_0_NS << rgmii_tx_delay_pos;
rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED_2,
- MSCC_PHY_RGMII_CNTL,
- RGMII_RX_CLK_DELAY_MASK | RGMII_TX_CLK_DELAY_MASK,
+ rgmii_cntl,
+ rgmii_rx_delay_mask | rgmii_tx_delay_mask,
reg_val);
mutex_unlock(&phydev->lock);
@@ -549,6 +555,23 @@ static int vsc85xx_default_config(struct phy_device *phydev)
return rc;
}
+static int vsc85xx_default_config(struct phy_device *phydev)
+{
+ int rc;
+
+ phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
+
+ if (phy_interface_mode_is_rgmii(phydev->interface)) {
+ rc = vsc85xx_rgmii_set_skews(phydev, VSC8502_RGMII_CNTL,
+ VSC8502_RGMII_RX_DELAY_MASK,
+ VSC8502_RGMII_TX_DELAY_MASK);
+ if (rc)
+ return rc;
+ }
+
+ return 0;
+}
+
static int vsc85xx_get_tunable(struct phy_device *phydev,
struct ethtool_tunable *tuna, void *data)
{
@@ -1301,32 +1324,6 @@ static bool vsc8584_is_pkg_init(struct phy_device *phydev, bool reversed)
return false;
}
-static void vsc8584_rgmii_set_skews(struct phy_device *phydev)
-{
- u32 skew_rx, skew_tx;
-
- /* We first set the Rx and Tx skews to their default value in h/w
- * (0.2 ns).
- */
- skew_rx = VSC8584_RGMII_SKEW_0_2;
- skew_tx = VSC8584_RGMII_SKEW_0_2;
-
- /* We then set the skews based on the interface mode. */
- if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
- phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
- skew_rx = VSC8584_RGMII_SKEW_2_0;
- if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
- phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
- skew_tx = VSC8584_RGMII_SKEW_2_0;
-
- /* Finally we apply the skews configuration. */
- phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED_2,
- MSCC_PHY_RGMII_SETTINGS,
- (0x7 << RGMII_SKEW_RX_POS) | (0x7 << RGMII_SKEW_TX_POS),
- (skew_rx << RGMII_SKEW_RX_POS) |
- (skew_tx << RGMII_SKEW_TX_POS));
-}
-
static int vsc8584_config_init(struct phy_device *phydev)
{
struct vsc8531_private *vsc8531 = phydev->priv;
@@ -1461,8 +1458,13 @@ static int vsc8584_config_init(struct phy_device *phydev)
if (ret)
return ret;
- if (phy_interface_is_rgmii(phydev))
- vsc8584_rgmii_set_skews(phydev);
+ if (phy_interface_is_rgmii(phydev)) {
+ ret = vsc85xx_rgmii_set_skews(phydev, VSC8572_RGMII_CNTL,
+ VSC8572_RGMII_RX_DELAY_MASK,
+ VSC8572_RGMII_TX_DELAY_MASK);
+ if (ret)
+ return ret;
+ }
ret = genphy_soft_reset(phydev);
if (ret)