]> Git Repo - linux.git/blob - drivers/net/phy/smsc.c
Linux 6.14-rc3
[linux.git] / drivers / net / phy / smsc.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * drivers/net/phy/smsc.c
4  *
5  * Driver for SMSC PHYs
6  *
7  * Author: Herbert Valerio Riedel
8  *
9  * Copyright (c) 2006 Herbert Valerio Riedel <[email protected]>
10  *
11  * Support added for SMSC LAN8187 and LAN8700 by [email protected]
12  *
13  */
14
15 #include <linux/clk.h>
16 #include <linux/kernel.h>
17 #include <linux/module.h>
18 #include <linux/mii.h>
19 #include <linux/ethtool.h>
20 #include <linux/of.h>
21 #include <linux/phy.h>
22 #include <linux/netdevice.h>
23 #include <linux/crc16.h>
24 #include <linux/etherdevice.h>
25 #include <linux/smscphy.h>
26
27 /* Vendor-specific PHY Definitions */
28 /* EDPD NLP / crossover time configuration */
29 #define PHY_EDPD_CONFIG                 16
30 #define PHY_EDPD_CONFIG_EXT_CROSSOVER_  0x0001
31
32 /* Control/Status Indication Register */
33 #define SPECIAL_CTRL_STS                27
34 #define SPECIAL_CTRL_STS_OVRRD_AMDIX_   0x8000
35 #define SPECIAL_CTRL_STS_AMDIX_ENABLE_  0x4000
36 #define SPECIAL_CTRL_STS_AMDIX_STATE_   0x2000
37
38 #define EDPD_MAX_WAIT_DFLT_MS           640
39 /* interval between phylib state machine runs in ms */
40 #define PHY_STATE_MACH_MS               1000
41
42 struct smsc_hw_stat {
43         const char *string;
44         u8 reg;
45         u8 bits;
46 };
47
48 static struct smsc_hw_stat smsc_hw_stats[] = {
49         { "phy_symbol_errors", 26, 16},
50 };
51
52 struct smsc_phy_priv {
53         unsigned int edpd_enable:1;
54         unsigned int edpd_mode_set_by_user:1;
55         unsigned int edpd_max_wait_ms;
56         bool wol_arp;
57 };
58
59 static int smsc_phy_ack_interrupt(struct phy_device *phydev)
60 {
61         int rc = phy_read(phydev, MII_LAN83C185_ISF);
62
63         return rc < 0 ? rc : 0;
64 }
65
66 int smsc_phy_config_intr(struct phy_device *phydev)
67 {
68         int rc;
69
70         if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
71                 rc = smsc_phy_ack_interrupt(phydev);
72                 if (rc)
73                         return rc;
74
75                 rc = phy_write(phydev, MII_LAN83C185_IM,
76                                MII_LAN83C185_ISF_INT_PHYLIB_EVENTS);
77         } else {
78                 rc = phy_write(phydev, MII_LAN83C185_IM, 0);
79                 if (rc)
80                         return rc;
81
82                 rc = smsc_phy_ack_interrupt(phydev);
83         }
84
85         return rc < 0 ? rc : 0;
86 }
87 EXPORT_SYMBOL_GPL(smsc_phy_config_intr);
88
89 static int smsc_phy_config_edpd(struct phy_device *phydev)
90 {
91         struct smsc_phy_priv *priv = phydev->priv;
92
93         if (priv->edpd_enable)
94                 return phy_set_bits(phydev, MII_LAN83C185_CTRL_STATUS,
95                                     MII_LAN83C185_EDPWRDOWN);
96         else
97                 return phy_clear_bits(phydev, MII_LAN83C185_CTRL_STATUS,
98                                       MII_LAN83C185_EDPWRDOWN);
99 }
100
101 irqreturn_t smsc_phy_handle_interrupt(struct phy_device *phydev)
102 {
103         int irq_status;
104
105         irq_status = phy_read(phydev, MII_LAN83C185_ISF);
106         if (irq_status < 0) {
107                 if (irq_status != -ENODEV)
108                         phy_error(phydev);
109
110                 return IRQ_NONE;
111         }
112
113         if (!(irq_status & MII_LAN83C185_ISF_INT_PHYLIB_EVENTS))
114                 return IRQ_NONE;
115
116         phy_trigger_machine(phydev);
117
118         return IRQ_HANDLED;
119 }
120 EXPORT_SYMBOL_GPL(smsc_phy_handle_interrupt);
121
122 int smsc_phy_config_init(struct phy_device *phydev)
123 {
124         struct smsc_phy_priv *priv = phydev->priv;
125
126         if (!priv)
127                 return 0;
128
129         /* don't use EDPD in irq mode except overridden by user */
130         if (!priv->edpd_mode_set_by_user && phydev->irq != PHY_POLL)
131                 priv->edpd_enable = false;
132
133         return smsc_phy_config_edpd(phydev);
134 }
135 EXPORT_SYMBOL_GPL(smsc_phy_config_init);
136
137 static int smsc_phy_reset(struct phy_device *phydev)
138 {
139         int rc = phy_read(phydev, MII_LAN83C185_SPECIAL_MODES);
140         if (rc < 0)
141                 return rc;
142
143         /* If the SMSC PHY is in power down mode, then set it
144          * in all capable mode before using it.
145          */
146         if ((rc & MII_LAN83C185_MODE_MASK) == MII_LAN83C185_MODE_POWERDOWN) {
147                 /* set "all capable" mode */
148                 rc |= MII_LAN83C185_MODE_ALL;
149                 phy_write(phydev, MII_LAN83C185_SPECIAL_MODES, rc);
150         }
151
152         /* reset the phy */
153         return genphy_soft_reset(phydev);
154 }
155
156 static int lan87xx_config_aneg(struct phy_device *phydev)
157 {
158         int rc;
159         int val;
160
161         switch (phydev->mdix_ctrl) {
162         case ETH_TP_MDI:
163                 val = SPECIAL_CTRL_STS_OVRRD_AMDIX_;
164                 break;
165         case ETH_TP_MDI_X:
166                 val = SPECIAL_CTRL_STS_OVRRD_AMDIX_ |
167                         SPECIAL_CTRL_STS_AMDIX_STATE_;
168                 break;
169         case ETH_TP_MDI_AUTO:
170                 val = SPECIAL_CTRL_STS_AMDIX_ENABLE_;
171                 break;
172         default:
173                 return genphy_config_aneg(phydev);
174         }
175
176         rc = phy_read(phydev, SPECIAL_CTRL_STS);
177         if (rc < 0)
178                 return rc;
179
180         rc &= ~(SPECIAL_CTRL_STS_OVRRD_AMDIX_ |
181                 SPECIAL_CTRL_STS_AMDIX_ENABLE_ |
182                 SPECIAL_CTRL_STS_AMDIX_STATE_);
183         rc |= val;
184         phy_write(phydev, SPECIAL_CTRL_STS, rc);
185
186         phydev->mdix = phydev->mdix_ctrl;
187         return genphy_config_aneg(phydev);
188 }
189
190 static int lan95xx_config_aneg_ext(struct phy_device *phydev)
191 {
192         if (phydev->phy_id == 0x0007c0f0) { /* LAN9500A or LAN9505A */
193                 /* Extend Manual AutoMDIX timer */
194                 int rc = phy_set_bits(phydev, PHY_EDPD_CONFIG,
195                                       PHY_EDPD_CONFIG_EXT_CROSSOVER_);
196
197                 if (rc < 0)
198                         return rc;
199         }
200
201         return lan87xx_config_aneg(phydev);
202 }
203
204 /*
205  * The LAN87xx suffers from rare absence of the ENERGYON-bit when Ethernet cable
206  * plugs in while LAN87xx is in Energy Detect Power-Down mode. This leads to
207  * unstable detection of plugging in Ethernet cable.
208  * This workaround disables Energy Detect Power-Down mode and waiting for
209  * response on link pulses to detect presence of plugged Ethernet cable.
210  * The Energy Detect Power-Down mode is enabled again in the end of procedure to
211  * save approximately 220 mW of power if cable is unplugged.
212  * The workaround is only applicable to poll mode. Energy Detect Power-Down may
213  * not be used in interrupt mode lest link change detection becomes unreliable.
214  */
215 int lan87xx_read_status(struct phy_device *phydev)
216 {
217         struct smsc_phy_priv *priv = phydev->priv;
218         int err;
219
220         err = genphy_read_status(phydev);
221         if (err)
222                 return err;
223
224         if (!phydev->link && priv && priv->edpd_enable &&
225             priv->edpd_max_wait_ms) {
226                 unsigned int max_wait = priv->edpd_max_wait_ms * 1000;
227                 int rc;
228
229                 /* Disable EDPD to wake up PHY */
230                 rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
231                 if (rc < 0)
232                         return rc;
233
234                 rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS,
235                                rc & ~MII_LAN83C185_EDPWRDOWN);
236                 if (rc < 0)
237                         return rc;
238
239                 /* Wait max 640 ms to detect energy and the timeout is not
240                  * an actual error.
241                  */
242                 read_poll_timeout(phy_read, rc,
243                                   rc & MII_LAN83C185_ENERGYON || rc < 0,
244                                   10000, max_wait, true, phydev,
245                                   MII_LAN83C185_CTRL_STATUS);
246                 if (rc < 0)
247                         return rc;
248
249                 /* Re-enable EDPD */
250                 rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
251                 if (rc < 0)
252                         return rc;
253
254                 rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS,
255                                rc | MII_LAN83C185_EDPWRDOWN);
256                 if (rc < 0)
257                         return rc;
258         }
259
260         return err;
261 }
262 EXPORT_SYMBOL_GPL(lan87xx_read_status);
263
264 static int lan874x_phy_config_init(struct phy_device *phydev)
265 {
266         u16 val;
267         int rc;
268
269         /* Setup LED2/nINT/nPME pin to function as nPME.  May need user option
270          * to use LED1/nINT/nPME.
271          */
272         val = MII_LAN874X_PHY_PME2_SET;
273
274         /* The bits MII_LAN874X_PHY_WOL_PFDA_FR, MII_LAN874X_PHY_WOL_WUFR,
275          * MII_LAN874X_PHY_WOL_MPR, and MII_LAN874X_PHY_WOL_BCAST_FR need to
276          * be cleared to de-assert PME signal after a WoL event happens, but
277          * using PME auto clear gets around that.
278          */
279         val |= MII_LAN874X_PHY_PME_SELF_CLEAR;
280         rc = phy_write_mmd(phydev, MDIO_MMD_PCS, MII_LAN874X_PHY_MMD_WOL_WUCSR,
281                            val);
282         if (rc < 0)
283                 return rc;
284
285         /* set nPME self clear delay time */
286         rc = phy_write_mmd(phydev, MDIO_MMD_PCS, MII_LAN874X_PHY_MMD_MCFGR,
287                            MII_LAN874X_PHY_PME_SELF_CLEAR_DELAY);
288         if (rc < 0)
289                 return rc;
290
291         return smsc_phy_config_init(phydev);
292 }
293
294 static void lan874x_get_wol(struct phy_device *phydev,
295                             struct ethtool_wolinfo *wol)
296 {
297         struct smsc_phy_priv *priv = phydev->priv;
298         int rc;
299
300         wol->supported = (WAKE_UCAST | WAKE_BCAST | WAKE_MAGIC |
301                           WAKE_ARP | WAKE_MCAST);
302         wol->wolopts = 0;
303
304         rc = phy_read_mmd(phydev, MDIO_MMD_PCS, MII_LAN874X_PHY_MMD_WOL_WUCSR);
305         if (rc < 0)
306                 return;
307
308         if (rc & MII_LAN874X_PHY_WOL_PFDAEN)
309                 wol->wolopts |= WAKE_UCAST;
310
311         if (rc & MII_LAN874X_PHY_WOL_BCSTEN)
312                 wol->wolopts |= WAKE_BCAST;
313
314         if (rc & MII_LAN874X_PHY_WOL_MPEN)
315                 wol->wolopts |= WAKE_MAGIC;
316
317         if (rc & MII_LAN874X_PHY_WOL_WUEN) {
318                 if (priv->wol_arp)
319                         wol->wolopts |= WAKE_ARP;
320                 else
321                         wol->wolopts |= WAKE_MCAST;
322         }
323 }
324
325 static u16 smsc_crc16(const u8 *buffer, size_t len)
326 {
327         return bitrev16(crc16(0xFFFF, buffer, len));
328 }
329
330 static int lan874x_chk_wol_pattern(const u8 pattern[], const u16 *mask,
331                                    u8 len, u8 *data, u8 *datalen)
332 {
333         size_t i, j, k;
334         int ret = 0;
335         u16 bits;
336
337         /* Pattern filtering can match up to 128 bytes of frame data.  There
338          * are 8 registers to program the 16-bit masks, where each bit means
339          * the byte will be compared.  The frame data will then go through a
340          * CRC16 calculation for hardware comparison.  This helper function
341          * makes sure only relevant frame data are included in this
342          * calculation.  It provides a warning when the masks and expected
343          * data size do not match.
344          */
345         i = 0;
346         k = 0;
347         while (len > 0) {
348                 bits = *mask;
349                 for (j = 0; j < 16; j++, i++, len--) {
350                         /* No more pattern. */
351                         if (!len) {
352                                 /* The rest of bitmap is not empty. */
353                                 if (bits)
354                                         ret = i + 1;
355                                 break;
356                         }
357                         if (bits & 1)
358                                 data[k++] = pattern[i];
359                         bits >>= 1;
360                 }
361                 mask++;
362         }
363         *datalen = k;
364         return ret;
365 }
366
367 static int lan874x_set_wol_pattern(struct phy_device *phydev, u16 val,
368                                    const u8 data[], u8 datalen,
369                                    const u16 *mask, u8 masklen)
370 {
371         u16 crc, reg;
372         int rc;
373
374         /* Starting pattern offset is set before calling this function. */
375         val |= MII_LAN874X_PHY_WOL_FILTER_EN;
376         rc = phy_write_mmd(phydev, MDIO_MMD_PCS,
377                            MII_LAN874X_PHY_MMD_WOL_WUF_CFGA, val);
378         if (rc < 0)
379                 return rc;
380
381         crc = smsc_crc16(data, datalen);
382         rc = phy_write_mmd(phydev, MDIO_MMD_PCS,
383                            MII_LAN874X_PHY_MMD_WOL_WUF_CFGB, crc);
384         if (rc < 0)
385                 return rc;
386
387         masklen = (masklen + 15) & ~0xf;
388         reg = MII_LAN874X_PHY_MMD_WOL_WUF_MASK7;
389         while (masklen >= 16) {
390                 rc = phy_write_mmd(phydev, MDIO_MMD_PCS, reg, *mask);
391                 if (rc < 0)
392                         return rc;
393                 reg--;
394                 mask++;
395                 masklen -= 16;
396         }
397
398         /* Clear out the rest of mask registers. */
399         while (reg != MII_LAN874X_PHY_MMD_WOL_WUF_MASK0) {
400                 phy_write_mmd(phydev, MDIO_MMD_PCS, reg, 0);
401                 reg--;
402         }
403         return rc;
404 }
405
406 static int lan874x_set_wol(struct phy_device *phydev,
407                            struct ethtool_wolinfo *wol)
408 {
409         struct net_device *ndev = phydev->attached_dev;
410         struct smsc_phy_priv *priv = phydev->priv;
411         u16 val, val_wucsr;
412         u8 data[128];
413         u8 datalen;
414         int rc;
415
416         /* lan874x has only one WoL filter pattern */
417         if ((wol->wolopts & (WAKE_ARP | WAKE_MCAST)) ==
418             (WAKE_ARP | WAKE_MCAST)) {
419                 phydev_info(phydev,
420                             "lan874x WoL supports one of ARP|MCAST at a time\n");
421                 return -EOPNOTSUPP;
422         }
423
424         rc = phy_read_mmd(phydev, MDIO_MMD_PCS, MII_LAN874X_PHY_MMD_WOL_WUCSR);
425         if (rc < 0)
426                 return rc;
427
428         val_wucsr = rc;
429
430         if (wol->wolopts & WAKE_UCAST)
431                 val_wucsr |= MII_LAN874X_PHY_WOL_PFDAEN;
432         else
433                 val_wucsr &= ~MII_LAN874X_PHY_WOL_PFDAEN;
434
435         if (wol->wolopts & WAKE_BCAST)
436                 val_wucsr |= MII_LAN874X_PHY_WOL_BCSTEN;
437         else
438                 val_wucsr &= ~MII_LAN874X_PHY_WOL_BCSTEN;
439
440         if (wol->wolopts & WAKE_MAGIC)
441                 val_wucsr |= MII_LAN874X_PHY_WOL_MPEN;
442         else
443                 val_wucsr &= ~MII_LAN874X_PHY_WOL_MPEN;
444
445         /* Need to use pattern matching */
446         if (wol->wolopts & (WAKE_ARP | WAKE_MCAST))
447                 val_wucsr |= MII_LAN874X_PHY_WOL_WUEN;
448         else
449                 val_wucsr &= ~MII_LAN874X_PHY_WOL_WUEN;
450
451         if (wol->wolopts & WAKE_ARP) {
452                 const u8 pattern[2] = { 0x08, 0x06 };
453                 const u16 mask[1] = { 0x0003 };
454
455                 rc = lan874x_chk_wol_pattern(pattern, mask, 2, data,
456                                              &datalen);
457                 if (rc)
458                         phydev_dbg(phydev, "pattern not valid at %d\n", rc);
459
460                 /* Need to match broadcast destination address and provided
461                  * data pattern at offset 12.
462                  */
463                 val = 12 | MII_LAN874X_PHY_WOL_FILTER_BCSTEN;
464                 rc = lan874x_set_wol_pattern(phydev, val, data, datalen, mask,
465                                              2);
466                 if (rc < 0)
467                         return rc;
468                 priv->wol_arp = true;
469         }
470
471         if (wol->wolopts & WAKE_MCAST) {
472                 /* Need to match multicast destination address. */
473                 val = MII_LAN874X_PHY_WOL_FILTER_MCASTTEN;
474                 rc = lan874x_set_wol_pattern(phydev, val, data, 0, NULL, 0);
475                 if (rc < 0)
476                         return rc;
477                 priv->wol_arp = false;
478         }
479
480         if (wol->wolopts & (WAKE_MAGIC | WAKE_UCAST)) {
481                 const u8 *mac = (const u8 *)ndev->dev_addr;
482                 int i, reg;
483
484                 reg = MII_LAN874X_PHY_MMD_WOL_RX_ADDRC;
485                 for (i = 0; i < 6; i += 2, reg--) {
486                         rc = phy_write_mmd(phydev, MDIO_MMD_PCS, reg,
487                                            ((mac[i + 1] << 8) | mac[i]));
488                         if (rc < 0)
489                                 return rc;
490                 }
491         }
492
493         rc = phy_write_mmd(phydev, MDIO_MMD_PCS, MII_LAN874X_PHY_MMD_WOL_WUCSR,
494                            val_wucsr);
495         if (rc < 0)
496                 return rc;
497
498         return 0;
499 }
500
501 static int smsc_get_sset_count(struct phy_device *phydev)
502 {
503         return ARRAY_SIZE(smsc_hw_stats);
504 }
505
506 static void smsc_get_strings(struct phy_device *phydev, u8 *data)
507 {
508         int i;
509
510         for (i = 0; i < ARRAY_SIZE(smsc_hw_stats); i++)
511                 ethtool_puts(&data, smsc_hw_stats[i].string);
512 }
513
514 static u64 smsc_get_stat(struct phy_device *phydev, int i)
515 {
516         struct smsc_hw_stat stat = smsc_hw_stats[i];
517         int val;
518         u64 ret;
519
520         val = phy_read(phydev, stat.reg);
521         if (val < 0)
522                 ret = U64_MAX;
523         else
524                 ret = val;
525
526         return ret;
527 }
528
529 static void smsc_get_stats(struct phy_device *phydev,
530                            struct ethtool_stats *stats, u64 *data)
531 {
532         int i;
533
534         for (i = 0; i < ARRAY_SIZE(smsc_hw_stats); i++)
535                 data[i] = smsc_get_stat(phydev, i);
536 }
537
538 static int smsc_phy_get_edpd(struct phy_device *phydev, u16 *edpd)
539 {
540         struct smsc_phy_priv *priv = phydev->priv;
541
542         if (!priv)
543                 return -EOPNOTSUPP;
544
545         if (!priv->edpd_enable)
546                 *edpd = ETHTOOL_PHY_EDPD_DISABLE;
547         else if (!priv->edpd_max_wait_ms)
548                 *edpd = ETHTOOL_PHY_EDPD_NO_TX;
549         else
550                 *edpd = PHY_STATE_MACH_MS + priv->edpd_max_wait_ms;
551
552         return 0;
553 }
554
555 static int smsc_phy_set_edpd(struct phy_device *phydev, u16 edpd)
556 {
557         struct smsc_phy_priv *priv = phydev->priv;
558
559         if (!priv)
560                 return -EOPNOTSUPP;
561
562         switch (edpd) {
563         case ETHTOOL_PHY_EDPD_DISABLE:
564                 priv->edpd_enable = false;
565                 break;
566         case ETHTOOL_PHY_EDPD_NO_TX:
567                 priv->edpd_enable = true;
568                 priv->edpd_max_wait_ms = 0;
569                 break;
570         case ETHTOOL_PHY_EDPD_DFLT_TX_MSECS:
571                 edpd = PHY_STATE_MACH_MS + EDPD_MAX_WAIT_DFLT_MS;
572                 fallthrough;
573         default:
574                 if (phydev->irq != PHY_POLL)
575                         return -EOPNOTSUPP;
576                 if (edpd < PHY_STATE_MACH_MS || edpd > PHY_STATE_MACH_MS + 1000)
577                         return -EINVAL;
578                 priv->edpd_enable = true;
579                 priv->edpd_max_wait_ms = edpd - PHY_STATE_MACH_MS;
580         }
581
582         priv->edpd_mode_set_by_user = true;
583
584         return smsc_phy_config_edpd(phydev);
585 }
586
587 int smsc_phy_get_tunable(struct phy_device *phydev,
588                          struct ethtool_tunable *tuna, void *data)
589 {
590         switch (tuna->id) {
591         case ETHTOOL_PHY_EDPD:
592                 return smsc_phy_get_edpd(phydev, data);
593         default:
594                 return -EOPNOTSUPP;
595         }
596 }
597 EXPORT_SYMBOL_GPL(smsc_phy_get_tunable);
598
599 int smsc_phy_set_tunable(struct phy_device *phydev,
600                          struct ethtool_tunable *tuna, const void *data)
601 {
602         switch (tuna->id) {
603         case ETHTOOL_PHY_EDPD:
604                 return smsc_phy_set_edpd(phydev, *(u16 *)data);
605         default:
606                 return -EOPNOTSUPP;
607         }
608 }
609 EXPORT_SYMBOL_GPL(smsc_phy_set_tunable);
610
611 int smsc_phy_probe(struct phy_device *phydev)
612 {
613         struct device *dev = &phydev->mdio.dev;
614         struct smsc_phy_priv *priv;
615         struct clk *refclk;
616
617         priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
618         if (!priv)
619                 return -ENOMEM;
620
621         priv->edpd_enable = true;
622         priv->edpd_max_wait_ms = EDPD_MAX_WAIT_DFLT_MS;
623
624         if (device_property_present(dev, "smsc,disable-energy-detect"))
625                 priv->edpd_enable = false;
626
627         phydev->priv = priv;
628
629         /* Make clk optional to keep DTB backward compatibility. */
630         refclk = devm_clk_get_optional_enabled_with_rate(dev, NULL,
631                                                          50 * 1000 * 1000);
632         if (IS_ERR(refclk))
633                 return dev_err_probe(dev, PTR_ERR(refclk),
634                                      "Failed to request clock\n");
635
636         return 0;
637 }
638 EXPORT_SYMBOL_GPL(smsc_phy_probe);
639
640 static struct phy_driver smsc_phy_driver[] = {
641 {
642         .phy_id         = 0x0007c0a0, /* OUI=0x00800f, Model#=0x0a */
643         .phy_id_mask    = 0xfffffff0,
644         .name           = "SMSC LAN83C185",
645
646         /* PHY_BASIC_FEATURES */
647
648         .probe          = smsc_phy_probe,
649
650         /* basic functions */
651         .config_init    = smsc_phy_config_init,
652         .soft_reset     = smsc_phy_reset,
653
654         /* IRQ related */
655         .config_intr    = smsc_phy_config_intr,
656         .handle_interrupt = smsc_phy_handle_interrupt,
657
658         .suspend        = genphy_suspend,
659         .resume         = genphy_resume,
660 }, {
661         .phy_id         = 0x0007c0b0, /* OUI=0x00800f, Model#=0x0b */
662         .phy_id_mask    = 0xfffffff0,
663         .name           = "SMSC LAN8187",
664
665         /* PHY_BASIC_FEATURES */
666
667         .probe          = smsc_phy_probe,
668
669         /* basic functions */
670         .config_init    = smsc_phy_config_init,
671         .soft_reset     = smsc_phy_reset,
672
673         /* IRQ related */
674         .config_intr    = smsc_phy_config_intr,
675         .handle_interrupt = smsc_phy_handle_interrupt,
676
677         /* Statistics */
678         .get_sset_count = smsc_get_sset_count,
679         .get_strings    = smsc_get_strings,
680         .get_stats      = smsc_get_stats,
681
682         .suspend        = genphy_suspend,
683         .resume         = genphy_resume,
684 }, {
685         /* This covers internal PHY (phy_id: 0x0007C0C3) for
686          * LAN9500 (PID: 0x9500), LAN9514 (PID: 0xec00), LAN9505 (PID: 0x9505)
687          */
688         .phy_id         = 0x0007c0c0, /* OUI=0x00800f, Model#=0x0c */
689         .phy_id_mask    = 0xfffffff0,
690         .name           = "SMSC LAN8700",
691
692         /* PHY_BASIC_FEATURES */
693
694         .probe          = smsc_phy_probe,
695
696         /* basic functions */
697         .read_status    = lan87xx_read_status,
698         .config_init    = smsc_phy_config_init,
699         .soft_reset     = smsc_phy_reset,
700         .config_aneg    = lan87xx_config_aneg,
701
702         /* IRQ related */
703         .config_intr    = smsc_phy_config_intr,
704         .handle_interrupt = smsc_phy_handle_interrupt,
705
706         /* Statistics */
707         .get_sset_count = smsc_get_sset_count,
708         .get_strings    = smsc_get_strings,
709         .get_stats      = smsc_get_stats,
710
711         .get_tunable    = smsc_phy_get_tunable,
712         .set_tunable    = smsc_phy_set_tunable,
713
714         .suspend        = genphy_suspend,
715         .resume         = genphy_resume,
716 }, {
717         .phy_id         = 0x0007c0d0, /* OUI=0x00800f, Model#=0x0d */
718         .phy_id_mask    = 0xfffffff0,
719         .name           = "SMSC LAN911x Internal PHY",
720
721         /* PHY_BASIC_FEATURES */
722
723         .probe          = smsc_phy_probe,
724
725         /* IRQ related */
726         .config_intr    = smsc_phy_config_intr,
727         .handle_interrupt = smsc_phy_handle_interrupt,
728
729         .suspend        = genphy_suspend,
730         .resume         = genphy_resume,
731 }, {
732         /* This covers internal PHY (phy_id: 0x0007C0F0) for
733          * LAN9500A (PID: 0x9E00), LAN9505A (PID: 0x9E01)
734          */
735         .phy_id         = 0x0007c0f0, /* OUI=0x00800f, Model#=0x0f */
736         .phy_id_mask    = 0xfffffff0,
737         .name           = "SMSC LAN8710/LAN8720",
738
739         /* PHY_BASIC_FEATURES */
740
741         .probe          = smsc_phy_probe,
742
743         /* basic functions */
744         .read_status    = lan87xx_read_status,
745         .config_init    = smsc_phy_config_init,
746         .soft_reset     = smsc_phy_reset,
747         .config_aneg    = lan95xx_config_aneg_ext,
748
749         /* IRQ related */
750         .config_intr    = smsc_phy_config_intr,
751         .handle_interrupt = smsc_phy_handle_interrupt,
752
753         /* Statistics */
754         .get_sset_count = smsc_get_sset_count,
755         .get_strings    = smsc_get_strings,
756         .get_stats      = smsc_get_stats,
757
758         .get_tunable    = smsc_phy_get_tunable,
759         .set_tunable    = smsc_phy_set_tunable,
760
761         .suspend        = genphy_suspend,
762         .resume         = genphy_resume,
763 }, {
764         .phy_id         = 0x0007c110,
765         .phy_id_mask    = 0xfffffff0,
766         .name           = "SMSC LAN8740",
767
768         /* PHY_BASIC_FEATURES */
769         .flags          = PHY_RST_AFTER_CLK_EN,
770
771         .probe          = smsc_phy_probe,
772
773         /* basic functions */
774         .read_status    = lan87xx_read_status,
775         .config_init    = lan874x_phy_config_init,
776         .soft_reset     = smsc_phy_reset,
777
778         /* IRQ related */
779         .config_intr    = smsc_phy_config_intr,
780         .handle_interrupt = smsc_phy_handle_interrupt,
781
782         /* Statistics */
783         .get_sset_count = smsc_get_sset_count,
784         .get_strings    = smsc_get_strings,
785         .get_stats      = smsc_get_stats,
786
787         .get_tunable    = smsc_phy_get_tunable,
788         .set_tunable    = smsc_phy_set_tunable,
789
790         /* WoL */
791         .set_wol        = lan874x_set_wol,
792         .get_wol        = lan874x_get_wol,
793
794         .suspend        = genphy_suspend,
795         .resume         = genphy_resume,
796 }, {
797         .phy_id         = 0x0007c130,   /* 0x0007c130 and 0x0007c131 */
798         /* This mask (0xfffffff2) is to differentiate from
799          * LAN88xx (phy_id 0x0007c132)
800          * and allows future phy_id revisions.
801          */
802         .phy_id_mask    = 0xfffffff2,
803         .name           = "Microchip LAN8742",
804
805         /* PHY_BASIC_FEATURES */
806         .flags          = PHY_RST_AFTER_CLK_EN,
807
808         .probe          = smsc_phy_probe,
809
810         /* basic functions */
811         .read_status    = lan87xx_read_status,
812         .config_init    = lan874x_phy_config_init,
813         .soft_reset     = smsc_phy_reset,
814
815         /* IRQ related */
816         .config_intr    = smsc_phy_config_intr,
817         .handle_interrupt = smsc_phy_handle_interrupt,
818
819         /* Statistics */
820         .get_sset_count = smsc_get_sset_count,
821         .get_strings    = smsc_get_strings,
822         .get_stats      = smsc_get_stats,
823
824         .get_tunable    = smsc_phy_get_tunable,
825         .set_tunable    = smsc_phy_set_tunable,
826
827         /* WoL */
828         .set_wol        = lan874x_set_wol,
829         .get_wol        = lan874x_get_wol,
830
831         .suspend        = genphy_suspend,
832         .resume         = genphy_resume,
833 } };
834
835 module_phy_driver(smsc_phy_driver);
836
837 MODULE_DESCRIPTION("SMSC PHY driver");
838 MODULE_AUTHOR("Herbert Valerio Riedel");
839 MODULE_LICENSE("GPL");
840
841 static const struct mdio_device_id __maybe_unused smsc_tbl[] = {
842         { 0x0007c0a0, 0xfffffff0 },
843         { 0x0007c0b0, 0xfffffff0 },
844         { 0x0007c0c0, 0xfffffff0 },
845         { 0x0007c0d0, 0xfffffff0 },
846         { 0x0007c0f0, 0xfffffff0 },
847         { 0x0007c110, 0xfffffff0 },
848         { 0x0007c130, 0xfffffff2 },
849         { }
850 };
851
852 MODULE_DEVICE_TABLE(mdio, smsc_tbl);
This page took 0.137799 seconds and 4 git commands to generate.