summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2020-03-20 07:14:46 +0300
committerDavid S. Miller <davem@davemloft.net>2020-03-20 07:14:46 +0300
commit5c9a9fce3a0a32a68cc54b44ce1dc2004f7eec23 (patch)
treee1baded556e97c18dc3a7a86fd239ac4b40995fb
parent9096a03f3cbbf9eb57b94abbd08f2fa018cedce4 (diff)
parentdee48f78d02e159f96f2f261695fd98068d9e6a3 (diff)
downloadlinux-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.h15
-rw-r--r--drivers/net/phy/mscc/mscc_main.c61
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;