diff options
author | Alex <alex.g@adaptrum.com> | 2016-11-16 04:02:33 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-11-16 17:53:56 -0500 |
commit | 955e16026d08a601d02b961d13b6db9d6c13c8c9 (patch) | |
tree | b78d7f353e0323d970b39e05d20777b5cc0aecca | |
parent | 5f00a8d8a2c2fd99528ab1a3632f0e77f4d25202 (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.c | 34 |
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. */ | ||
121 | static 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 | |||
133 | static 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 | |||
114 | static int vsc824x_ack_interrupt(struct phy_device *phydev) | 146 | static 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, |