summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex <alex.g@adaptrum.com>2016-11-16 04:02:33 -0500
committerDavid S. Miller <davem@davemloft.net>2016-11-16 17:53:56 -0500
commit955e16026d08a601d02b961d13b6db9d6c13c8c9 (patch)
treeb78d7f353e0323d970b39e05d20777b5cc0aecca
parent5f00a8d8a2c2fd99528ab1a3632f0e77f4d25202 (diff)
net/phy/vitesse: Configure RGMII skew on VSC8601, if needed
With RGMII, we need a 1.5 to 2ns skew between clock and data lines. The VSC8601 can handle this internally. While the VSC8601 can set more fine-grained delays, the standard skew settings work out of the box. The same heuristic is used to determine when this skew should be enabled as in vsc824x_config_init(). Tested on custom board with AM3352 SOC and VSC801 PHY. Signed-off-by: Alexandru Gagniuc <alex.g@adaptrum.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/phy/vitesse.c34
1 files changed, 33 insertions, 1 deletions
diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c
index 2e37eb337d48..24b4a09468dd 100644
--- a/drivers/net/phy/vitesse.c
+++ b/drivers/net/phy/vitesse.c
@@ -62,6 +62,10 @@
62/* Vitesse Extended Page Access Register */ 62/* Vitesse Extended Page Access Register */
63#define MII_VSC82X4_EXT_PAGE_ACCESS 0x1f 63#define MII_VSC82X4_EXT_PAGE_ACCESS 0x1f
64 64
65/* Vitesse VSC8601 Extended PHY Control Register 1 */
66#define MII_VSC8601_EPHY_CTL 0x17
67#define MII_VSC8601_EPHY_CTL_RGMII_SKEW (1 << 8)
68
65#define PHY_ID_VSC8234 0x000fc620 69#define PHY_ID_VSC8234 0x000fc620
66#define PHY_ID_VSC8244 0x000fc6c0 70#define PHY_ID_VSC8244 0x000fc6c0
67#define PHY_ID_VSC8514 0x00070670 71#define PHY_ID_VSC8514 0x00070670
@@ -111,6 +115,34 @@ static int vsc824x_config_init(struct phy_device *phydev)
111 return err; 115 return err;
112} 116}
113 117
118/* This adds a skew for both TX and RX clocks, so the skew should only be
119 * applied to "rgmii-id" interfaces. It may not work as expected
120 * on "rgmii-txid", "rgmii-rxid" or "rgmii" interfaces. */
121static int vsc8601_add_skew(struct phy_device *phydev)
122{
123 int ret;
124
125 ret = phy_read(phydev, MII_VSC8601_EPHY_CTL);
126 if (ret < 0)
127 return ret;
128
129 ret |= MII_VSC8601_EPHY_CTL_RGMII_SKEW;
130 return phy_write(phydev, MII_VSC8601_EPHY_CTL, ret);
131}
132
133static int vsc8601_config_init(struct phy_device *phydev)
134{
135 int ret = 0;
136
137 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
138 ret = vsc8601_add_skew(phydev);
139
140 if (ret < 0)
141 return ret;
142
143 return genphy_config_init(phydev);
144}
145
114static int vsc824x_ack_interrupt(struct phy_device *phydev) 146static int vsc824x_ack_interrupt(struct phy_device *phydev)
115{ 147{
116 int err = 0; 148 int err = 0;
@@ -275,7 +307,7 @@ static struct phy_driver vsc82xx_driver[] = {
275 .phy_id_mask = 0x000ffff0, 307 .phy_id_mask = 0x000ffff0,
276 .features = PHY_GBIT_FEATURES, 308 .features = PHY_GBIT_FEATURES,
277 .flags = PHY_HAS_INTERRUPT, 309 .flags = PHY_HAS_INTERRUPT,
278 .config_init = &genphy_config_init, 310 .config_init = &vsc8601_config_init,
279 .config_aneg = &genphy_config_aneg, 311 .config_aneg = &genphy_config_aneg,
280 .read_status = &genphy_read_status, 312 .read_status = &genphy_read_status,
281 .ack_interrupt = &vsc824x_ack_interrupt, 313 .ack_interrupt = &vsc824x_ack_interrupt,