54
54
#define USB_PRODUCT_ID_LAN7500 (0x7500)
55
55
#define USB_PRODUCT_ID_LAN7505 (0x7505)
56
56
#define RXW_PADDING 2
57
- #define SUPPORTED_WAKE (WAKE_UCAST | WAKE_BCAST | \
57
+ #define SUPPORTED_WAKE (WAKE_PHY | WAKE_UCAST | WAKE_BCAST | \
58
58
WAKE_MCAST | WAKE_ARP | WAKE_MAGIC)
59
59
60
60
#define check_warn (ret , fmt , args ...) \
@@ -185,14 +185,15 @@ static int smsc75xx_clear_feature(struct usbnet *dev, u32 feature)
185
185
186
186
/* Loop until the read is completed with timeout
187
187
* called with phy_mutex held */
188
- static int smsc75xx_phy_wait_not_busy (struct usbnet * dev )
188
+ static __must_check int __smsc75xx_phy_wait_not_busy (struct usbnet * dev ,
189
+ int in_pm )
189
190
{
190
191
unsigned long start_time = jiffies ;
191
192
u32 val ;
192
193
int ret ;
193
194
194
195
do {
195
- ret = smsc75xx_read_reg (dev , MII_ACCESS , & val );
196
+ ret = __smsc75xx_read_reg (dev , MII_ACCESS , & val , in_pm );
196
197
check_warn_return (ret , "Error reading MII_ACCESS\n" );
197
198
198
199
if (!(val & MII_ACCESS_BUSY ))
@@ -202,7 +203,8 @@ static int smsc75xx_phy_wait_not_busy(struct usbnet *dev)
202
203
return - EIO ;
203
204
}
204
205
205
- static int smsc75xx_mdio_read (struct net_device * netdev , int phy_id , int idx )
206
+ static int __smsc75xx_mdio_read (struct net_device * netdev , int phy_id , int idx ,
207
+ int in_pm )
206
208
{
207
209
struct usbnet * dev = netdev_priv (netdev );
208
210
u32 val , addr ;
@@ -211,7 +213,7 @@ static int smsc75xx_mdio_read(struct net_device *netdev, int phy_id, int idx)
211
213
mutex_lock (& dev -> phy_mutex );
212
214
213
215
/* confirm MII not busy */
214
- ret = smsc75xx_phy_wait_not_busy (dev );
216
+ ret = __smsc75xx_phy_wait_not_busy (dev , in_pm );
215
217
check_warn_goto_done (ret , "MII is busy in smsc75xx_mdio_read\n" );
216
218
217
219
/* set the address, index & direction (read from PHY) */
@@ -220,13 +222,13 @@ static int smsc75xx_mdio_read(struct net_device *netdev, int phy_id, int idx)
220
222
addr = ((phy_id << MII_ACCESS_PHY_ADDR_SHIFT ) & MII_ACCESS_PHY_ADDR )
221
223
| ((idx << MII_ACCESS_REG_ADDR_SHIFT ) & MII_ACCESS_REG_ADDR )
222
224
| MII_ACCESS_READ | MII_ACCESS_BUSY ;
223
- ret = smsc75xx_write_reg (dev , MII_ACCESS , addr );
225
+ ret = __smsc75xx_write_reg (dev , MII_ACCESS , addr , in_pm );
224
226
check_warn_goto_done (ret , "Error writing MII_ACCESS\n" );
225
227
226
- ret = smsc75xx_phy_wait_not_busy (dev );
228
+ ret = __smsc75xx_phy_wait_not_busy (dev , in_pm );
227
229
check_warn_goto_done (ret , "Timed out reading MII reg %02X\n" , idx );
228
230
229
- ret = smsc75xx_read_reg (dev , MII_DATA , & val );
231
+ ret = __smsc75xx_read_reg (dev , MII_DATA , & val , in_pm );
230
232
check_warn_goto_done (ret , "Error reading MII_DATA\n" );
231
233
232
234
ret = (u16 )(val & 0xFFFF );
@@ -236,8 +238,8 @@ static int smsc75xx_mdio_read(struct net_device *netdev, int phy_id, int idx)
236
238
return ret ;
237
239
}
238
240
239
- static void smsc75xx_mdio_write (struct net_device * netdev , int phy_id , int idx ,
240
- int regval )
241
+ static void __smsc75xx_mdio_write (struct net_device * netdev , int phy_id ,
242
+ int idx , int regval , int in_pm )
241
243
{
242
244
struct usbnet * dev = netdev_priv (netdev );
243
245
u32 val , addr ;
@@ -246,11 +248,11 @@ static void smsc75xx_mdio_write(struct net_device *netdev, int phy_id, int idx,
246
248
mutex_lock (& dev -> phy_mutex );
247
249
248
250
/* confirm MII not busy */
249
- ret = smsc75xx_phy_wait_not_busy (dev );
251
+ ret = __smsc75xx_phy_wait_not_busy (dev , in_pm );
250
252
check_warn_goto_done (ret , "MII is busy in smsc75xx_mdio_write\n" );
251
253
252
254
val = regval ;
253
- ret = smsc75xx_write_reg (dev , MII_DATA , val );
255
+ ret = __smsc75xx_write_reg (dev , MII_DATA , val , in_pm );
254
256
check_warn_goto_done (ret , "Error writing MII_DATA\n" );
255
257
256
258
/* set the address, index & direction (write to PHY) */
@@ -259,16 +261,39 @@ static void smsc75xx_mdio_write(struct net_device *netdev, int phy_id, int idx,
259
261
addr = ((phy_id << MII_ACCESS_PHY_ADDR_SHIFT ) & MII_ACCESS_PHY_ADDR )
260
262
| ((idx << MII_ACCESS_REG_ADDR_SHIFT ) & MII_ACCESS_REG_ADDR )
261
263
| MII_ACCESS_WRITE | MII_ACCESS_BUSY ;
262
- ret = smsc75xx_write_reg (dev , MII_ACCESS , addr );
264
+ ret = __smsc75xx_write_reg (dev , MII_ACCESS , addr , in_pm );
263
265
check_warn_goto_done (ret , "Error writing MII_ACCESS\n" );
264
266
265
- ret = smsc75xx_phy_wait_not_busy (dev );
267
+ ret = __smsc75xx_phy_wait_not_busy (dev , in_pm );
266
268
check_warn_goto_done (ret , "Timed out writing MII reg %02X\n" , idx );
267
269
268
270
done :
269
271
mutex_unlock (& dev -> phy_mutex );
270
272
}
271
273
274
+ static int smsc75xx_mdio_read_nopm (struct net_device * netdev , int phy_id ,
275
+ int idx )
276
+ {
277
+ return __smsc75xx_mdio_read (netdev , phy_id , idx , 1 );
278
+ }
279
+
280
+ static void smsc75xx_mdio_write_nopm (struct net_device * netdev , int phy_id ,
281
+ int idx , int regval )
282
+ {
283
+ __smsc75xx_mdio_write (netdev , phy_id , idx , regval , 1 );
284
+ }
285
+
286
+ static int smsc75xx_mdio_read (struct net_device * netdev , int phy_id , int idx )
287
+ {
288
+ return __smsc75xx_mdio_read (netdev , phy_id , idx , 0 );
289
+ }
290
+
291
+ static void smsc75xx_mdio_write (struct net_device * netdev , int phy_id , int idx ,
292
+ int regval )
293
+ {
294
+ __smsc75xx_mdio_write (netdev , phy_id , idx , regval , 0 );
295
+ }
296
+
272
297
static int smsc75xx_wait_eeprom (struct usbnet * dev )
273
298
{
274
299
unsigned long start_time = jiffies ;
@@ -1233,6 +1258,32 @@ static int smsc75xx_enter_suspend0(struct usbnet *dev)
1233
1258
return 0 ;
1234
1259
}
1235
1260
1261
+ static int smsc75xx_enter_suspend1 (struct usbnet * dev )
1262
+ {
1263
+ u32 val ;
1264
+ int ret ;
1265
+
1266
+ ret = smsc75xx_read_reg_nopm (dev , PMT_CTL , & val );
1267
+ check_warn_return (ret , "Error reading PMT_CTL\n" );
1268
+
1269
+ val &= ~(PMT_CTL_SUS_MODE | PMT_CTL_WUPS | PMT_CTL_PHY_RST );
1270
+ val |= PMT_CTL_SUS_MODE_1 ;
1271
+
1272
+ ret = smsc75xx_write_reg_nopm (dev , PMT_CTL , val );
1273
+ check_warn_return (ret , "Error writing PMT_CTL\n" );
1274
+
1275
+ /* clear wol status, enable energy detection */
1276
+ val &= ~PMT_CTL_WUPS ;
1277
+ val |= (PMT_CTL_WUPS_ED | PMT_CTL_ED_EN );
1278
+
1279
+ ret = smsc75xx_write_reg_nopm (dev , PMT_CTL , val );
1280
+ check_warn_return (ret , "Error writing PMT_CTL\n" );
1281
+
1282
+ smsc75xx_set_feature (dev , USB_DEVICE_REMOTE_WAKEUP );
1283
+
1284
+ return 0 ;
1285
+ }
1286
+
1236
1287
static int smsc75xx_enter_suspend2 (struct usbnet * dev )
1237
1288
{
1238
1289
u32 val ;
@@ -1250,18 +1301,61 @@ static int smsc75xx_enter_suspend2(struct usbnet *dev)
1250
1301
return 0 ;
1251
1302
}
1252
1303
1304
+ static int smsc75xx_enable_phy_wakeup_interrupts (struct usbnet * dev , u16 mask )
1305
+ {
1306
+ struct mii_if_info * mii = & dev -> mii ;
1307
+ int ret ;
1308
+
1309
+ netdev_dbg (dev -> net , "enabling PHY wakeup interrupts\n" );
1310
+
1311
+ /* read to clear */
1312
+ ret = smsc75xx_mdio_read_nopm (dev -> net , mii -> phy_id , PHY_INT_SRC );
1313
+ check_warn_return (ret , "Error reading PHY_INT_SRC\n" );
1314
+
1315
+ /* enable interrupt source */
1316
+ ret = smsc75xx_mdio_read_nopm (dev -> net , mii -> phy_id , PHY_INT_MASK );
1317
+ check_warn_return (ret , "Error reading PHY_INT_MASK\n" );
1318
+
1319
+ ret |= mask ;
1320
+
1321
+ smsc75xx_mdio_write_nopm (dev -> net , mii -> phy_id , PHY_INT_MASK , ret );
1322
+
1323
+ return 0 ;
1324
+ }
1325
+
1326
+ static int smsc75xx_link_ok_nopm (struct usbnet * dev )
1327
+ {
1328
+ struct mii_if_info * mii = & dev -> mii ;
1329
+ int ret ;
1330
+
1331
+ /* first, a dummy read, needed to latch some MII phys */
1332
+ ret = smsc75xx_mdio_read_nopm (dev -> net , mii -> phy_id , MII_BMSR );
1333
+ check_warn_return (ret , "Error reading MII_BMSR\n" );
1334
+
1335
+ ret = smsc75xx_mdio_read_nopm (dev -> net , mii -> phy_id , MII_BMSR );
1336
+ check_warn_return (ret , "Error reading MII_BMSR\n" );
1337
+
1338
+ return !!(ret & BMSR_LSTATUS );
1339
+ }
1340
+
1253
1341
static int smsc75xx_suspend (struct usb_interface * intf , pm_message_t message )
1254
1342
{
1255
1343
struct usbnet * dev = usb_get_intfdata (intf );
1256
1344
struct smsc75xx_priv * pdata = (struct smsc75xx_priv * )(dev -> data [0 ]);
1345
+ u32 val , link_up ;
1257
1346
int ret ;
1258
- u32 val ;
1259
1347
1260
1348
ret = usbnet_suspend (intf , message );
1261
1349
check_warn_return (ret , "usbnet_suspend error\n" );
1262
1350
1263
- /* if no wol options set, enter lowest power SUSPEND2 mode */
1264
- if (!(pdata -> wolopts & SUPPORTED_WAKE )) {
1351
+ /* determine if link is up using only _nopm functions */
1352
+ link_up = smsc75xx_link_ok_nopm (dev );
1353
+
1354
+ /* if no wol options set, or if link is down and we're not waking on
1355
+ * PHY activity, enter lowest power SUSPEND2 mode
1356
+ */
1357
+ if (!(pdata -> wolopts & SUPPORTED_WAKE ) ||
1358
+ !(link_up || (pdata -> wolopts & WAKE_PHY ))) {
1265
1359
netdev_info (dev -> net , "entering SUSPEND2 mode\n" );
1266
1360
1267
1361
/* disable energy detect (link up) & wake up events */
@@ -1284,6 +1378,33 @@ static int smsc75xx_suspend(struct usb_interface *intf, pm_message_t message)
1284
1378
return smsc75xx_enter_suspend2 (dev );
1285
1379
}
1286
1380
1381
+ if (pdata -> wolopts & WAKE_PHY ) {
1382
+ ret = smsc75xx_enable_phy_wakeup_interrupts (dev ,
1383
+ (PHY_INT_MASK_ANEG_COMP | PHY_INT_MASK_LINK_DOWN ));
1384
+ check_warn_return (ret , "error enabling PHY wakeup ints\n" );
1385
+
1386
+ /* if link is down then configure EDPD and enter SUSPEND1,
1387
+ * otherwise enter SUSPEND0 below
1388
+ */
1389
+ if (!link_up ) {
1390
+ struct mii_if_info * mii = & dev -> mii ;
1391
+ netdev_info (dev -> net , "entering SUSPEND1 mode\n" );
1392
+
1393
+ /* enable energy detect power-down mode */
1394
+ ret = smsc75xx_mdio_read_nopm (dev -> net , mii -> phy_id ,
1395
+ PHY_MODE_CTRL_STS );
1396
+ check_warn_return (ret , "Error reading PHY_MODE_CTRL_STS\n" );
1397
+
1398
+ ret |= MODE_CTRL_STS_EDPWRDOWN ;
1399
+
1400
+ smsc75xx_mdio_write_nopm (dev -> net , mii -> phy_id ,
1401
+ PHY_MODE_CTRL_STS , ret );
1402
+
1403
+ /* enter SUSPEND1 mode */
1404
+ return smsc75xx_enter_suspend1 (dev );
1405
+ }
1406
+ }
1407
+
1287
1408
if (pdata -> wolopts & (WAKE_MCAST | WAKE_ARP )) {
1288
1409
int i , filter = 0 ;
1289
1410
@@ -1350,6 +1471,20 @@ static int smsc75xx_suspend(struct usb_interface *intf, pm_message_t message)
1350
1471
ret = smsc75xx_write_reg_nopm (dev , WUCSR , val );
1351
1472
check_warn_return (ret , "Error writing WUCSR\n" );
1352
1473
1474
+ if (pdata -> wolopts & WAKE_PHY ) {
1475
+ netdev_info (dev -> net , "enabling PHY wakeup\n" );
1476
+
1477
+ ret = smsc75xx_read_reg_nopm (dev , PMT_CTL , & val );
1478
+ check_warn_return (ret , "Error reading PMT_CTL\n" );
1479
+
1480
+ /* clear wol status, enable energy detection */
1481
+ val &= ~PMT_CTL_WUPS ;
1482
+ val |= (PMT_CTL_WUPS_ED | PMT_CTL_ED_EN );
1483
+
1484
+ ret = smsc75xx_write_reg_nopm (dev , PMT_CTL , val );
1485
+ check_warn_return (ret , "Error writing PMT_CTL\n" );
1486
+ }
1487
+
1353
1488
if (pdata -> wolopts & WAKE_MAGIC ) {
1354
1489
netdev_info (dev -> net , "enabling magic packet wakeup\n" );
1355
1490
ret = smsc75xx_read_reg_nopm (dev , WUCSR , & val );
0 commit comments