aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMadalin Bucur <madalin.bucur@freescale.com>2013-11-20 17:38:19 -0500
committerDavid S. Miller <davem@davemloft.net>2013-11-20 22:09:19 -0500
commit3fb69bcadda6263b92dbf8dd74717cba27c77ed9 (patch)
tree63c40467c4237dbf3f402d97df9a2be5aba62b8d
parent06ae4f848fe69ebd3c3a00d2ecbb8af22fb75418 (diff)
net/phy: Add the autocross feature for forced links on VSC82x4
Add auto-MDI/MDI-X capability for forced (autonegotiation disabled) 10/100 Mbps speeds on Vitesse VSC82x4 PHYs. Exported previously static function genphy_setup_forced() required by the new config_aneg handler in the Vitesse PHY module. Signed-off-by: Madalin Bucur <madalin.bucur@freescale.com> Signed-off-by: Shruti Kanetkar <Shruti@freescale.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/phy/phy_device.c4
-rw-r--r--drivers/net/phy/vitesse.c75
-rw-r--r--include/linux/phy.h1
3 files changed, 73 insertions, 7 deletions
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 74630e94fa3b..d6447b3f7409 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -697,7 +697,7 @@ static int genphy_config_advert(struct phy_device *phydev)
697 * to the values in phydev. Assumes that the values are valid. 697 * to the values in phydev. Assumes that the values are valid.
698 * Please see phy_sanitize_settings(). 698 * Please see phy_sanitize_settings().
699 */ 699 */
700static int genphy_setup_forced(struct phy_device *phydev) 700int genphy_setup_forced(struct phy_device *phydev)
701{ 701{
702 int err; 702 int err;
703 int ctl = 0; 703 int ctl = 0;
@@ -716,7 +716,7 @@ static int genphy_setup_forced(struct phy_device *phydev)
716 716
717 return err; 717 return err;
718} 718}
719 719EXPORT_SYMBOL(genphy_setup_forced);
720 720
721/** 721/**
722 * genphy_restart_aneg - Enable and Restart Autonegotiation 722 * genphy_restart_aneg - Enable and Restart Autonegotiation
diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c
index 40406bc2f8af..508e4359338b 100644
--- a/drivers/net/phy/vitesse.c
+++ b/drivers/net/phy/vitesse.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * Author: Kriston Carson 4 * Author: Kriston Carson
5 * 5 *
6 * Copyright (c) 2005, 2009 Freescale Semiconductor, Inc. 6 * Copyright (c) 2005, 2009, 2011 Freescale Semiconductor, Inc.
7 * 7 *
8 * This program is free software; you can redistribute it and/or modify it 8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the 9 * under the terms of the GNU General Public License as published by the
@@ -18,6 +18,11 @@
18#include <linux/ethtool.h> 18#include <linux/ethtool.h>
19#include <linux/phy.h> 19#include <linux/phy.h>
20 20
21/* Vitesse Extended Page Magic Register(s) */
22#define MII_VSC82X4_EXT_PAGE_16E 0x10
23#define MII_VSC82X4_EXT_PAGE_17E 0x11
24#define MII_VSC82X4_EXT_PAGE_18E 0x12
25
21/* Vitesse Extended Control Register 1 */ 26/* Vitesse Extended Control Register 1 */
22#define MII_VSC8244_EXT_CON1 0x17 27#define MII_VSC8244_EXT_CON1 0x17
23#define MII_VSC8244_EXTCON1_INIT 0x0000 28#define MII_VSC8244_EXTCON1_INIT 0x0000
@@ -54,6 +59,9 @@
54#define MII_VSC8221_AUXCONSTAT_INIT 0x0004 /* need to set this bit? */ 59#define MII_VSC8221_AUXCONSTAT_INIT 0x0004 /* need to set this bit? */
55#define MII_VSC8221_AUXCONSTAT_RESERVED 0x0004 60#define MII_VSC8221_AUXCONSTAT_RESERVED 0x0004
56 61
62/* Vitesse Extended Page Access Register */
63#define MII_VSC82X4_EXT_PAGE_ACCESS 0x1f
64
57#define PHY_ID_VSC8234 0x000fc620 65#define PHY_ID_VSC8234 0x000fc620
58#define PHY_ID_VSC8244 0x000fc6c0 66#define PHY_ID_VSC8244 0x000fc6c0
59#define PHY_ID_VSC8574 0x000704a0 67#define PHY_ID_VSC8574 0x000704a0
@@ -154,6 +162,63 @@ static int vsc8221_config_init(struct phy_device *phydev)
154 */ 162 */
155} 163}
156 164
165/* vsc82x4_config_autocross_enable - Enable auto MDI/MDI-X for forced links
166 * @phydev: target phy_device struct
167 *
168 * Enable auto MDI/MDI-X when in 10/100 forced link speeds by writing
169 * special values in the VSC8234/VSC8244 extended reserved registers
170 */
171static int vsc82x4_config_autocross_enable(struct phy_device *phydev)
172{
173 int ret;
174
175 if (phydev->autoneg == AUTONEG_ENABLE || phydev->speed > SPEED_100)
176 return 0;
177
178 /* map extended registers set 0x10 - 0x1e */
179 ret = phy_write(phydev, MII_VSC82X4_EXT_PAGE_ACCESS, 0x52b5);
180 if (ret >= 0)
181 ret = phy_write(phydev, MII_VSC82X4_EXT_PAGE_18E, 0x0012);
182 if (ret >= 0)
183 ret = phy_write(phydev, MII_VSC82X4_EXT_PAGE_17E, 0x2803);
184 if (ret >= 0)
185 ret = phy_write(phydev, MII_VSC82X4_EXT_PAGE_16E, 0x87fa);
186 /* map standard registers set 0x10 - 0x1e */
187 if (ret >= 0)
188 ret = phy_write(phydev, MII_VSC82X4_EXT_PAGE_ACCESS, 0x0000);
189 else
190 phy_write(phydev, MII_VSC82X4_EXT_PAGE_ACCESS, 0x0000);
191
192 return ret;
193}
194
195/* vsc82x4_config_aneg - restart auto-negotiation or write BMCR
196 * @phydev: target phy_device struct
197 *
198 * Description: If auto-negotiation is enabled, we configure the
199 * advertising, and then restart auto-negotiation. If it is not
200 * enabled, then we write the BMCR and also start the auto
201 * MDI/MDI-X feature
202 */
203static int vsc82x4_config_aneg(struct phy_device *phydev)
204{
205 int ret;
206
207 /* Enable auto MDI/MDI-X when in 10/100 forced link speeds by
208 * writing special values in the VSC8234 extended reserved registers
209 */
210 if (phydev->autoneg != AUTONEG_ENABLE && phydev->speed <= SPEED_100) {
211 ret = genphy_setup_forced(phydev);
212
213 if (ret < 0) /* error */
214 return ret;
215
216 return vsc82x4_config_autocross_enable(phydev);
217 }
218
219 return genphy_config_aneg(phydev);
220}
221
157/* Vitesse 82xx */ 222/* Vitesse 82xx */
158static struct phy_driver vsc82xx_driver[] = { 223static struct phy_driver vsc82xx_driver[] = {
159{ 224{
@@ -163,7 +228,7 @@ static struct phy_driver vsc82xx_driver[] = {
163 .features = PHY_GBIT_FEATURES, 228 .features = PHY_GBIT_FEATURES,
164 .flags = PHY_HAS_INTERRUPT, 229 .flags = PHY_HAS_INTERRUPT,
165 .config_init = &vsc824x_config_init, 230 .config_init = &vsc824x_config_init,
166 .config_aneg = &genphy_config_aneg, 231 .config_aneg = &vsc82x4_config_aneg,
167 .read_status = &genphy_read_status, 232 .read_status = &genphy_read_status,
168 .ack_interrupt = &vsc824x_ack_interrupt, 233 .ack_interrupt = &vsc824x_ack_interrupt,
169 .config_intr = &vsc82xx_config_intr, 234 .config_intr = &vsc82xx_config_intr,
@@ -175,7 +240,7 @@ static struct phy_driver vsc82xx_driver[] = {
175 .features = PHY_GBIT_FEATURES, 240 .features = PHY_GBIT_FEATURES,
176 .flags = PHY_HAS_INTERRUPT, 241 .flags = PHY_HAS_INTERRUPT,
177 .config_init = &vsc824x_config_init, 242 .config_init = &vsc824x_config_init,
178 .config_aneg = &genphy_config_aneg, 243 .config_aneg = &vsc82x4_config_aneg,
179 .read_status = &genphy_read_status, 244 .read_status = &genphy_read_status,
180 .ack_interrupt = &vsc824x_ack_interrupt, 245 .ack_interrupt = &vsc824x_ack_interrupt,
181 .config_intr = &vsc82xx_config_intr, 246 .config_intr = &vsc82xx_config_intr,
@@ -187,7 +252,7 @@ static struct phy_driver vsc82xx_driver[] = {
187 .features = PHY_GBIT_FEATURES, 252 .features = PHY_GBIT_FEATURES,
188 .flags = PHY_HAS_INTERRUPT, 253 .flags = PHY_HAS_INTERRUPT,
189 .config_init = &vsc824x_config_init, 254 .config_init = &vsc824x_config_init,
190 .config_aneg = &genphy_config_aneg, 255 .config_aneg = &vsc82x4_config_aneg,
191 .read_status = &genphy_read_status, 256 .read_status = &genphy_read_status,
192 .ack_interrupt = &vsc824x_ack_interrupt, 257 .ack_interrupt = &vsc824x_ack_interrupt,
193 .config_intr = &vsc82xx_config_intr, 258 .config_intr = &vsc82xx_config_intr,
@@ -199,7 +264,7 @@ static struct phy_driver vsc82xx_driver[] = {
199 .features = PHY_GBIT_FEATURES, 264 .features = PHY_GBIT_FEATURES,
200 .flags = PHY_HAS_INTERRUPT, 265 .flags = PHY_HAS_INTERRUPT,
201 .config_init = &vsc824x_config_init, 266 .config_init = &vsc824x_config_init,
202 .config_aneg = &genphy_config_aneg, 267 .config_aneg = &vsc82x4_config_aneg,
203 .read_status = &genphy_read_status, 268 .read_status = &genphy_read_status,
204 .ack_interrupt = &vsc824x_ack_interrupt, 269 .ack_interrupt = &vsc824x_ack_interrupt,
205 .config_intr = &vsc82xx_config_intr, 270 .config_intr = &vsc82xx_config_intr,
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 64ab823f7b74..48a4dc3cb8cf 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -559,6 +559,7 @@ static inline int phy_read_status(struct phy_device *phydev) {
559 return phydev->drv->read_status(phydev); 559 return phydev->drv->read_status(phydev);
560} 560}
561 561
562int genphy_setup_forced(struct phy_device *phydev);
562int genphy_restart_aneg(struct phy_device *phydev); 563int genphy_restart_aneg(struct phy_device *phydev);
563int genphy_config_aneg(struct phy_device *phydev); 564int genphy_config_aneg(struct phy_device *phydev);
564int genphy_update_link(struct phy_device *phydev); 565int genphy_update_link(struct phy_device *phydev);