diff options
author | David S. Miller <davem@davemloft.net> | 2020-03-20 07:14:46 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2020-03-20 07:14:46 +0300 |
commit | 5c9a9fce3a0a32a68cc54b44ce1dc2004f7eec23 (patch) | |
tree | e1baded556e97c18dc3a7a86fd239ac4b40995fb | |
parent | 9096a03f3cbbf9eb57b94abbd08f2fa018cedce4 (diff) | |
parent | dee48f78d02e159f96f2f261695fd98068d9e6a3 (diff) | |
download | linux-5c9a9fce3a0a32a68cc54b44ce1dc2004f7eec23.tar.xz |
Merge branch 'mscc-RGMII'
Antoine Tenart says:
====================
net: phy: mscc: add support for RGMII MAC mode
This series adds support for the RGMII MAC mode for the VSC8584 PHY
family and for RGMII_ID modes (Tx and/or Rx).
I decided to drop the custom delay for now. I made some tests and it
seemed to be working quite well. If we find out we really need to lower
the delay, which I doubt, I'll send support for it.
Since v2:
- Dropped support for custom dt bindings.
- Add the 2ns delay based on the interface mode.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/phy/mscc/mscc.h | 15 | ||||
-rw-r--r-- | drivers/net/phy/mscc/mscc_main.c | 61 |
2 files changed, 64 insertions, 12 deletions
diff --git a/drivers/net/phy/mscc/mscc.h b/drivers/net/phy/mscc/mscc.h index 29ccb2c9c095..25729302714c 100644 --- a/drivers/net/phy/mscc/mscc.h +++ b/drivers/net/phy/mscc/mscc.h @@ -161,6 +161,20 @@ enum rgmii_rx_clock_delay { /* Extended Page 2 Registers */ #define MSCC_PHY_CU_PMD_TX_CNTL 16 +#define MSCC_PHY_RGMII_SETTINGS 18 +#define RGMII_SKEW_RX_POS 1 +#define RGMII_SKEW_TX_POS 4 + +/* RGMII skew values, in ns */ +#define VSC8584_RGMII_SKEW_0_2 0 +#define VSC8584_RGMII_SKEW_0_8 1 +#define VSC8584_RGMII_SKEW_1_1 2 +#define VSC8584_RGMII_SKEW_1_7 3 +#define VSC8584_RGMII_SKEW_2_0 4 +#define VSC8584_RGMII_SKEW_2_3 5 +#define VSC8584_RGMII_SKEW_2_6 6 +#define VSC8584_RGMII_SKEW_3_4 7 + #define MSCC_PHY_RGMII_CNTL 20 #define RGMII_RX_CLK_DELAY_MASK 0x0070 #define RGMII_RX_CLK_DELAY_POS 4 @@ -241,6 +255,7 @@ enum rgmii_rx_clock_delay { #define MAC_CFG_MASK 0xc000 #define MAC_CFG_SGMII 0x0000 #define MAC_CFG_QSGMII 0x4000 +#define MAC_CFG_RGMII 0x8000 /* Test page Registers */ #define MSCC_PHY_TEST_PAGE_5 5 diff --git a/drivers/net/phy/mscc/mscc_main.c b/drivers/net/phy/mscc/mscc_main.c index bc6beec8aff0..5d78732de702 100644 --- a/drivers/net/phy/mscc/mscc_main.c +++ b/drivers/net/phy/mscc/mscc_main.c @@ -1288,6 +1288,32 @@ 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; @@ -1360,27 +1386,35 @@ static int vsc8584_config_init(struct phy_device *phydev) val = phy_base_read(phydev, MSCC_PHY_MAC_CFG_FASTLINK); val &= ~MAC_CFG_MASK; - if (phydev->interface == PHY_INTERFACE_MODE_QSGMII) + if (phydev->interface == PHY_INTERFACE_MODE_QSGMII) { val |= MAC_CFG_QSGMII; - else + } else if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { val |= MAC_CFG_SGMII; + } else if (phy_interface_is_rgmii(phydev)) { + val |= MAC_CFG_RGMII; + } else { + ret = -EINVAL; + goto err; + } ret = phy_base_write(phydev, MSCC_PHY_MAC_CFG_FASTLINK, val); if (ret) goto err; - val = PROC_CMD_MCB_ACCESS_MAC_CONF | PROC_CMD_RST_CONF_PORT | - PROC_CMD_READ_MOD_WRITE_PORT; - if (phydev->interface == PHY_INTERFACE_MODE_QSGMII) - val |= PROC_CMD_QSGMII_MAC; - else - val |= PROC_CMD_SGMII_MAC; + if (!phy_interface_is_rgmii(phydev)) { + val = PROC_CMD_MCB_ACCESS_MAC_CONF | PROC_CMD_RST_CONF_PORT | + PROC_CMD_READ_MOD_WRITE_PORT; + if (phydev->interface == PHY_INTERFACE_MODE_QSGMII) + val |= PROC_CMD_QSGMII_MAC; + else + val |= PROC_CMD_SGMII_MAC; - ret = vsc8584_cmd(phydev, val); - if (ret) - goto err; + ret = vsc8584_cmd(phydev, val); + if (ret) + goto err; - usleep_range(10000, 20000); + usleep_range(10000, 20000); + } /* Disable SerDes for 100Base-FX */ ret = vsc8584_cmd(phydev, PROC_CMD_FIBER_MEDIA_CONF | @@ -1414,6 +1448,9 @@ static int vsc8584_config_init(struct phy_device *phydev) if (ret) return ret; + if (phy_interface_is_rgmii(phydev)) + vsc8584_rgmii_set_skews(phydev); + ret = genphy_soft_reset(phydev); if (ret) return ret; |