/* 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
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;
if (ret)
return ret;
+ if (phy_interface_is_rgmii(phydev))
+ vsc8584_rgmii_set_skews(phydev);
+
ret = genphy_soft_reset(phydev);
if (ret)
return ret;