21
21
#include <linux/netdevice.h>
22
22
#include <linux/smscphy.h>
23
23
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
+
24
35
struct smsc_hw_stat {
25
36
const char * string ;
26
37
u8 reg ;
@@ -96,6 +107,54 @@ static int lan911x_config_init(struct phy_device *phydev)
96
107
return smsc_phy_ack_interrupt (phydev );
97
108
}
98
109
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
+
99
158
/*
100
159
* The LAN87xx suffers from rare absence of the ENERGYON-bit when Ethernet cable
101
160
* 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[] = {
250
309
.suspend = genphy_suspend ,
251
310
.resume = genphy_resume ,
252
311
}, {
312
+ /* This covers internal PHY (phy_id: 0x0007C0C3) for
313
+ * LAN9500 (PID: 0x9500), LAN9514 (PID: 0xec00), LAN9505 (PID: 0x9505)
314
+ */
253
315
.phy_id = 0x0007c0c0 , /* OUI=0x00800f, Model#=0x0c */
254
316
.phy_id_mask = 0xfffffff0 ,
255
317
.name = "SMSC LAN8700" ,
@@ -262,6 +324,7 @@ static struct phy_driver smsc_phy_driver[] = {
262
324
.read_status = lan87xx_read_status ,
263
325
.config_init = smsc_phy_config_init ,
264
326
.soft_reset = smsc_phy_reset ,
327
+ .config_aneg = lan87xx_config_aneg ,
265
328
266
329
/* IRQ related */
267
330
.ack_interrupt = smsc_phy_ack_interrupt ,
@@ -293,6 +356,9 @@ static struct phy_driver smsc_phy_driver[] = {
293
356
.suspend = genphy_suspend ,
294
357
.resume = genphy_resume ,
295
358
}, {
359
+ /* This covers internal PHY (phy_id: 0x0007C0F0) for
360
+ * LAN9500A (PID: 0x9E00), LAN9505A (PID: 0x9E01)
361
+ */
296
362
.phy_id = 0x0007c0f0 , /* OUI=0x00800f, Model#=0x0f */
297
363
.phy_id_mask = 0xfffffff0 ,
298
364
.name = "SMSC LAN8710/LAN8720" ,
@@ -306,6 +372,7 @@ static struct phy_driver smsc_phy_driver[] = {
306
372
.read_status = lan87xx_read_status ,
307
373
.config_init = smsc_phy_config_init ,
308
374
.soft_reset = smsc_phy_reset ,
375
+ .config_aneg = lan87xx_config_aneg_ext ,
309
376
310
377
/* IRQ related */
311
378
.ack_interrupt = smsc_phy_ack_interrupt ,
0 commit comments