Skip to content

Commit 05b35e7

Browse files
Andre Edichdavem330
authored andcommitted
smsc95xx: add phylib support
Generally, each PHY has their own configuration and it can be done through an external PHY driver. The smsc95xx driver uses only the hard-coded internal PHY configuration. This patch adds phylib support to probe external PHY drivers for configuring external PHYs. The MDI-X configuration for the internal PHYs moves from drivers/net/usb/smsc95xx.c to drivers/net/phy/smsc.c. Signed-off-by: Andre Edich <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent ad90a73 commit 05b35e7

File tree

3 files changed

+203
-265
lines changed

3 files changed

+203
-265
lines changed

drivers/net/phy/smsc.c

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,17 @@
2121
#include <linux/netdevice.h>
2222
#include <linux/smscphy.h>
2323

24+
/* Vendor-specific PHY Definitions */
25+
/* EDPD NLP / crossover time configuration */
26+
#define PHY_EDPD_CONFIG 16
27+
#define PHY_EDPD_CONFIG_EXT_CROSSOVER_ 0x0001
28+
29+
/* Control/Status Indication Register */
30+
#define SPECIAL_CTRL_STS 27
31+
#define SPECIAL_CTRL_STS_OVRRD_AMDIX_ 0x8000
32+
#define SPECIAL_CTRL_STS_AMDIX_ENABLE_ 0x4000
33+
#define SPECIAL_CTRL_STS_AMDIX_STATE_ 0x2000
34+
2435
struct smsc_hw_stat {
2536
const char *string;
2637
u8 reg;
@@ -96,6 +107,54 @@ static int lan911x_config_init(struct phy_device *phydev)
96107
return smsc_phy_ack_interrupt(phydev);
97108
}
98109

110+
static int lan87xx_config_aneg(struct phy_device *phydev)
111+
{
112+
int rc;
113+
int val;
114+
115+
switch (phydev->mdix_ctrl) {
116+
case ETH_TP_MDI:
117+
val = SPECIAL_CTRL_STS_OVRRD_AMDIX_;
118+
break;
119+
case ETH_TP_MDI_X:
120+
val = SPECIAL_CTRL_STS_OVRRD_AMDIX_ |
121+
SPECIAL_CTRL_STS_AMDIX_STATE_;
122+
break;
123+
case ETH_TP_MDI_AUTO:
124+
val = SPECIAL_CTRL_STS_AMDIX_ENABLE_;
125+
break;
126+
default:
127+
return genphy_config_aneg(phydev);
128+
}
129+
130+
rc = phy_read(phydev, SPECIAL_CTRL_STS);
131+
if (rc < 0)
132+
return rc;
133+
134+
rc &= ~(SPECIAL_CTRL_STS_OVRRD_AMDIX_ |
135+
SPECIAL_CTRL_STS_AMDIX_ENABLE_ |
136+
SPECIAL_CTRL_STS_AMDIX_STATE_);
137+
rc |= val;
138+
phy_write(phydev, SPECIAL_CTRL_STS, rc);
139+
140+
phydev->mdix = phydev->mdix_ctrl;
141+
return genphy_config_aneg(phydev);
142+
}
143+
144+
static int lan87xx_config_aneg_ext(struct phy_device *phydev)
145+
{
146+
int rc;
147+
148+
/* Extend Manual AutoMDIX timer */
149+
rc = phy_read(phydev, PHY_EDPD_CONFIG);
150+
if (rc < 0)
151+
return rc;
152+
153+
rc |= PHY_EDPD_CONFIG_EXT_CROSSOVER_;
154+
phy_write(phydev, PHY_EDPD_CONFIG, rc);
155+
return lan87xx_config_aneg(phydev);
156+
}
157+
99158
/*
100159
* The LAN87xx suffers from rare absence of the ENERGYON-bit when Ethernet cable
101160
* plugs in while LAN87xx is in Energy Detect Power-Down mode. This leads to
@@ -250,6 +309,9 @@ static struct phy_driver smsc_phy_driver[] = {
250309
.suspend = genphy_suspend,
251310
.resume = genphy_resume,
252311
}, {
312+
/* This covers internal PHY (phy_id: 0x0007C0C3) for
313+
* LAN9500 (PID: 0x9500), LAN9514 (PID: 0xec00), LAN9505 (PID: 0x9505)
314+
*/
253315
.phy_id = 0x0007c0c0, /* OUI=0x00800f, Model#=0x0c */
254316
.phy_id_mask = 0xfffffff0,
255317
.name = "SMSC LAN8700",
@@ -262,6 +324,7 @@ static struct phy_driver smsc_phy_driver[] = {
262324
.read_status = lan87xx_read_status,
263325
.config_init = smsc_phy_config_init,
264326
.soft_reset = smsc_phy_reset,
327+
.config_aneg = lan87xx_config_aneg,
265328

266329
/* IRQ related */
267330
.ack_interrupt = smsc_phy_ack_interrupt,
@@ -293,6 +356,9 @@ static struct phy_driver smsc_phy_driver[] = {
293356
.suspend = genphy_suspend,
294357
.resume = genphy_resume,
295358
}, {
359+
/* This covers internal PHY (phy_id: 0x0007C0F0) for
360+
* LAN9500A (PID: 0x9E00), LAN9505A (PID: 0x9E01)
361+
*/
296362
.phy_id = 0x0007c0f0, /* OUI=0x00800f, Model#=0x0f */
297363
.phy_id_mask = 0xfffffff0,
298364
.name = "SMSC LAN8710/LAN8720",
@@ -306,6 +372,7 @@ static struct phy_driver smsc_phy_driver[] = {
306372
.read_status = lan87xx_read_status,
307373
.config_init = smsc_phy_config_init,
308374
.soft_reset = smsc_phy_reset,
375+
.config_aneg = lan87xx_config_aneg_ext,
309376

310377
/* IRQ related */
311378
.ack_interrupt = smsc_phy_ack_interrupt,

drivers/net/usb/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,8 @@ config USB_NET_SMSC75XX
345345
config USB_NET_SMSC95XX
346346
tristate "SMSC LAN95XX based USB 2.0 10/100 ethernet devices"
347347
depends on USB_USBNET
348+
select PHYLIB
349+
select SMSC_PHY
348350
select BITREVERSE
349351
select CRC16
350352
select CRC32

0 commit comments

Comments
 (0)