1 // SPDX-License-Identifier: GPL-2.0+
3 * drivers/net/phy/smsc.c
7 * Author: Herbert Valerio Riedel
9 * Copyright (c) 2006 Herbert Valerio Riedel <hvr@gnu.org>
11 * Support added for SMSC LAN8187 and LAN8700 by steve.glendinning@shawell.net
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>
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>
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
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
38 #define EDPD_MAX_WAIT_DFLT_MS 640
39 /* interval between phylib state machine runs in ms */
40 #define PHY_STATE_MACH_MS 1000
48 static struct smsc_hw_stat smsc_hw_stats
[] = {
49 { "phy_symbol_errors", 26, 16},
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
;
59 static int smsc_phy_ack_interrupt(struct phy_device
*phydev
)
61 int rc
= phy_read(phydev
, MII_LAN83C185_ISF
);
63 return rc
< 0 ? rc
: 0;
66 int smsc_phy_config_intr(struct phy_device
*phydev
)
70 if (phydev
->interrupts
== PHY_INTERRUPT_ENABLED
) {
71 rc
= smsc_phy_ack_interrupt(phydev
);
75 rc
= phy_write(phydev
, MII_LAN83C185_IM
,
76 MII_LAN83C185_ISF_INT_PHYLIB_EVENTS
);
78 rc
= phy_write(phydev
, MII_LAN83C185_IM
, 0);
82 rc
= smsc_phy_ack_interrupt(phydev
);
85 return rc
< 0 ? rc
: 0;
87 EXPORT_SYMBOL_GPL(smsc_phy_config_intr
);
89 static int smsc_phy_config_edpd(struct phy_device
*phydev
)
91 struct smsc_phy_priv
*priv
= phydev
->priv
;
93 if (priv
->edpd_enable
)
94 return phy_set_bits(phydev
, MII_LAN83C185_CTRL_STATUS
,
95 MII_LAN83C185_EDPWRDOWN
);
97 return phy_clear_bits(phydev
, MII_LAN83C185_CTRL_STATUS
,
98 MII_LAN83C185_EDPWRDOWN
);
101 irqreturn_t
smsc_phy_handle_interrupt(struct phy_device
*phydev
)
105 irq_status
= phy_read(phydev
, MII_LAN83C185_ISF
);
106 if (irq_status
< 0) {
107 if (irq_status
!= -ENODEV
)
113 if (!(irq_status
& MII_LAN83C185_ISF_INT_PHYLIB_EVENTS
))
116 phy_trigger_machine(phydev
);
120 EXPORT_SYMBOL_GPL(smsc_phy_handle_interrupt
);
122 int smsc_phy_config_init(struct phy_device
*phydev
)
124 struct smsc_phy_priv
*priv
= phydev
->priv
;
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;
133 return smsc_phy_config_edpd(phydev
);
135 EXPORT_SYMBOL_GPL(smsc_phy_config_init
);
137 static int smsc_phy_reset(struct phy_device
*phydev
)
139 int rc
= phy_read(phydev
, MII_LAN83C185_SPECIAL_MODES
);
143 /* If the SMSC PHY is in power down mode, then set it
144 * in all capable mode before using it.
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
);
153 return genphy_soft_reset(phydev
);
156 static int lan87xx_config_aneg(struct phy_device
*phydev
)
161 switch (phydev
->mdix_ctrl
) {
163 val
= SPECIAL_CTRL_STS_OVRRD_AMDIX_
;
166 val
= SPECIAL_CTRL_STS_OVRRD_AMDIX_
|
167 SPECIAL_CTRL_STS_AMDIX_STATE_
;
169 case ETH_TP_MDI_AUTO
:
170 val
= SPECIAL_CTRL_STS_AMDIX_ENABLE_
;
173 return genphy_config_aneg(phydev
);
176 rc
= phy_read(phydev
, SPECIAL_CTRL_STS
);
180 rc
&= ~(SPECIAL_CTRL_STS_OVRRD_AMDIX_
|
181 SPECIAL_CTRL_STS_AMDIX_ENABLE_
|
182 SPECIAL_CTRL_STS_AMDIX_STATE_
);
184 phy_write(phydev
, SPECIAL_CTRL_STS
, rc
);
186 phydev
->mdix
= phydev
->mdix_ctrl
;
187 return genphy_config_aneg(phydev
);
190 static int lan95xx_config_aneg_ext(struct phy_device
*phydev
)
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_
);
201 return lan87xx_config_aneg(phydev
);
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.
215 int lan87xx_read_status(struct phy_device
*phydev
)
217 struct smsc_phy_priv
*priv
= phydev
->priv
;
220 err
= genphy_read_status(phydev
);
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;
229 /* Disable EDPD to wake up PHY */
230 rc
= phy_read(phydev
, MII_LAN83C185_CTRL_STATUS
);
234 rc
= phy_write(phydev
, MII_LAN83C185_CTRL_STATUS
,
235 rc
& ~MII_LAN83C185_EDPWRDOWN
);
239 /* Wait max 640 ms to detect energy and the timeout is not
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
);
250 rc
= phy_read(phydev
, MII_LAN83C185_CTRL_STATUS
);
254 rc
= phy_write(phydev
, MII_LAN83C185_CTRL_STATUS
,
255 rc
| MII_LAN83C185_EDPWRDOWN
);
262 EXPORT_SYMBOL_GPL(lan87xx_read_status
);
264 static int lan874x_phy_config_init(struct phy_device
*phydev
)
269 /* Setup LED2/nINT/nPME pin to function as nPME. May need user option
270 * to use LED1/nINT/nPME.
272 val
= MII_LAN874X_PHY_PME2_SET
;
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.
279 val
|= MII_LAN874X_PHY_PME_SELF_CLEAR
;
280 rc
= phy_write_mmd(phydev
, MDIO_MMD_PCS
, MII_LAN874X_PHY_MMD_WOL_WUCSR
,
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
);
291 return smsc_phy_config_init(phydev
);
294 static void lan874x_get_wol(struct phy_device
*phydev
,
295 struct ethtool_wolinfo
*wol
)
297 struct smsc_phy_priv
*priv
= phydev
->priv
;
300 wol
->supported
= (WAKE_UCAST
| WAKE_BCAST
| WAKE_MAGIC
|
301 WAKE_ARP
| WAKE_MCAST
);
304 rc
= phy_read_mmd(phydev
, MDIO_MMD_PCS
, MII_LAN874X_PHY_MMD_WOL_WUCSR
);
308 if (rc
& MII_LAN874X_PHY_WOL_PFDAEN
)
309 wol
->wolopts
|= WAKE_UCAST
;
311 if (rc
& MII_LAN874X_PHY_WOL_BCSTEN
)
312 wol
->wolopts
|= WAKE_BCAST
;
314 if (rc
& MII_LAN874X_PHY_WOL_MPEN
)
315 wol
->wolopts
|= WAKE_MAGIC
;
317 if (rc
& MII_LAN874X_PHY_WOL_WUEN
) {
319 wol
->wolopts
|= WAKE_ARP
;
321 wol
->wolopts
|= WAKE_MCAST
;
325 static u16
smsc_crc16(const u8
*buffer
, size_t len
)
327 return bitrev16(crc16(0xFFFF, buffer
, len
));
330 static int lan874x_chk_wol_pattern(const u8 pattern
[], const u16
*mask
,
331 u8 len
, u8
*data
, u8
*datalen
)
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.
349 for (j
= 0; j
< 16; j
++, i
++, len
--) {
350 /* No more pattern. */
352 /* The rest of bitmap is not empty. */
358 data
[k
++] = pattern
[i
];
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
)
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
);
381 crc
= smsc_crc16(data
, datalen
);
382 rc
= phy_write_mmd(phydev
, MDIO_MMD_PCS
,
383 MII_LAN874X_PHY_MMD_WOL_WUF_CFGB
, crc
);
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
);
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);
406 static int lan874x_set_wol(struct phy_device
*phydev
,
407 struct ethtool_wolinfo
*wol
)
409 struct net_device
*ndev
= phydev
->attached_dev
;
410 struct smsc_phy_priv
*priv
= phydev
->priv
;
416 /* lan874x has only one WoL filter pattern */
417 if ((wol
->wolopts
& (WAKE_ARP
| WAKE_MCAST
)) ==
418 (WAKE_ARP
| WAKE_MCAST
)) {
420 "lan874x WoL supports one of ARP|MCAST at a time\n");
424 rc
= phy_read_mmd(phydev
, MDIO_MMD_PCS
, MII_LAN874X_PHY_MMD_WOL_WUCSR
);
430 if (wol
->wolopts
& WAKE_UCAST
)
431 val_wucsr
|= MII_LAN874X_PHY_WOL_PFDAEN
;
433 val_wucsr
&= ~MII_LAN874X_PHY_WOL_PFDAEN
;
435 if (wol
->wolopts
& WAKE_BCAST
)
436 val_wucsr
|= MII_LAN874X_PHY_WOL_BCSTEN
;
438 val_wucsr
&= ~MII_LAN874X_PHY_WOL_BCSTEN
;
440 if (wol
->wolopts
& WAKE_MAGIC
)
441 val_wucsr
|= MII_LAN874X_PHY_WOL_MPEN
;
443 val_wucsr
&= ~MII_LAN874X_PHY_WOL_MPEN
;
445 /* Need to use pattern matching */
446 if (wol
->wolopts
& (WAKE_ARP
| WAKE_MCAST
))
447 val_wucsr
|= MII_LAN874X_PHY_WOL_WUEN
;
449 val_wucsr
&= ~MII_LAN874X_PHY_WOL_WUEN
;
451 if (wol
->wolopts
& WAKE_ARP
) {
452 const u8 pattern
[2] = { 0x08, 0x06 };
453 const u16 mask
[1] = { 0x0003 };
455 rc
= lan874x_chk_wol_pattern(pattern
, mask
, 2, data
,
458 phydev_dbg(phydev
, "pattern not valid at %d\n", rc
);
460 /* Need to match broadcast destination address and provided
461 * data pattern at offset 12.
463 val
= 12 | MII_LAN874X_PHY_WOL_FILTER_BCSTEN
;
464 rc
= lan874x_set_wol_pattern(phydev
, val
, data
, datalen
, mask
,
468 priv
->wol_arp
= true;
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);
477 priv
->wol_arp
= false;
480 if (wol
->wolopts
& (WAKE_MAGIC
| WAKE_UCAST
)) {
481 const u8
*mac
= (const u8
*)ndev
->dev_addr
;
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
]));
493 rc
= phy_write_mmd(phydev
, MDIO_MMD_PCS
, MII_LAN874X_PHY_MMD_WOL_WUCSR
,
501 static int smsc_get_sset_count(struct phy_device
*phydev
)
503 return ARRAY_SIZE(smsc_hw_stats
);
506 static void smsc_get_strings(struct phy_device
*phydev
, u8
*data
)
510 for (i
= 0; i
< ARRAY_SIZE(smsc_hw_stats
); i
++)
511 ethtool_puts(&data
, smsc_hw_stats
[i
].string
);
514 static u64
smsc_get_stat(struct phy_device
*phydev
, int i
)
516 struct smsc_hw_stat stat
= smsc_hw_stats
[i
];
520 val
= phy_read(phydev
, stat
.reg
);
529 static void smsc_get_stats(struct phy_device
*phydev
,
530 struct ethtool_stats
*stats
, u64
*data
)
534 for (i
= 0; i
< ARRAY_SIZE(smsc_hw_stats
); i
++)
535 data
[i
] = smsc_get_stat(phydev
, i
);
538 static int smsc_phy_get_edpd(struct phy_device
*phydev
, u16
*edpd
)
540 struct smsc_phy_priv
*priv
= phydev
->priv
;
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
;
550 *edpd
= PHY_STATE_MACH_MS
+ priv
->edpd_max_wait_ms
;
555 static int smsc_phy_set_edpd(struct phy_device
*phydev
, u16 edpd
)
557 struct smsc_phy_priv
*priv
= phydev
->priv
;
563 case ETHTOOL_PHY_EDPD_DISABLE
:
564 priv
->edpd_enable
= false;
566 case ETHTOOL_PHY_EDPD_NO_TX
:
567 priv
->edpd_enable
= true;
568 priv
->edpd_max_wait_ms
= 0;
570 case ETHTOOL_PHY_EDPD_DFLT_TX_MSECS
:
571 edpd
= PHY_STATE_MACH_MS
+ EDPD_MAX_WAIT_DFLT_MS
;
574 if (phydev
->irq
!= PHY_POLL
)
576 if (edpd
< PHY_STATE_MACH_MS
|| edpd
> PHY_STATE_MACH_MS
+ 1000)
578 priv
->edpd_enable
= true;
579 priv
->edpd_max_wait_ms
= edpd
- PHY_STATE_MACH_MS
;
582 priv
->edpd_mode_set_by_user
= true;
584 return smsc_phy_config_edpd(phydev
);
587 int smsc_phy_get_tunable(struct phy_device
*phydev
,
588 struct ethtool_tunable
*tuna
, void *data
)
591 case ETHTOOL_PHY_EDPD
:
592 return smsc_phy_get_edpd(phydev
, data
);
597 EXPORT_SYMBOL_GPL(smsc_phy_get_tunable
);
599 int smsc_phy_set_tunable(struct phy_device
*phydev
,
600 struct ethtool_tunable
*tuna
, const void *data
)
603 case ETHTOOL_PHY_EDPD
:
604 return smsc_phy_set_edpd(phydev
, *(u16
*)data
);
609 EXPORT_SYMBOL_GPL(smsc_phy_set_tunable
);
611 int smsc_phy_probe(struct phy_device
*phydev
)
613 struct device
*dev
= &phydev
->mdio
.dev
;
614 struct smsc_phy_priv
*priv
;
617 priv
= devm_kzalloc(dev
, sizeof(*priv
), GFP_KERNEL
);
621 priv
->edpd_enable
= true;
622 priv
->edpd_max_wait_ms
= EDPD_MAX_WAIT_DFLT_MS
;
624 if (device_property_present(dev
, "smsc,disable-energy-detect"))
625 priv
->edpd_enable
= false;
629 /* Make clk optional to keep DTB backward compatibility. */
630 refclk
= devm_clk_get_optional_enabled_with_rate(dev
, NULL
,
633 return dev_err_probe(dev
, PTR_ERR(refclk
),
634 "Failed to request clock\n");
638 EXPORT_SYMBOL_GPL(smsc_phy_probe
);
640 static struct phy_driver smsc_phy_driver
[] = {
642 .phy_id
= 0x0007c0a0, /* OUI=0x00800f, Model#=0x0a */
643 .phy_id_mask
= 0xfffffff0,
644 .name
= "SMSC LAN83C185",
646 /* PHY_BASIC_FEATURES */
648 .probe
= smsc_phy_probe
,
650 /* basic functions */
651 .config_init
= smsc_phy_config_init
,
652 .soft_reset
= smsc_phy_reset
,
655 .config_intr
= smsc_phy_config_intr
,
656 .handle_interrupt
= smsc_phy_handle_interrupt
,
658 .suspend
= genphy_suspend
,
659 .resume
= genphy_resume
,
661 .phy_id
= 0x0007c0b0, /* OUI=0x00800f, Model#=0x0b */
662 .phy_id_mask
= 0xfffffff0,
663 .name
= "SMSC LAN8187",
665 /* PHY_BASIC_FEATURES */
667 .probe
= smsc_phy_probe
,
669 /* basic functions */
670 .config_init
= smsc_phy_config_init
,
671 .soft_reset
= smsc_phy_reset
,
674 .config_intr
= smsc_phy_config_intr
,
675 .handle_interrupt
= smsc_phy_handle_interrupt
,
678 .get_sset_count
= smsc_get_sset_count
,
679 .get_strings
= smsc_get_strings
,
680 .get_stats
= smsc_get_stats
,
682 .suspend
= genphy_suspend
,
683 .resume
= genphy_resume
,
685 /* This covers internal PHY (phy_id: 0x0007C0C3) for
686 * LAN9500 (PID: 0x9500), LAN9514 (PID: 0xec00), LAN9505 (PID: 0x9505)
688 .phy_id
= 0x0007c0c0, /* OUI=0x00800f, Model#=0x0c */
689 .phy_id_mask
= 0xfffffff0,
690 .name
= "SMSC LAN8700",
692 /* PHY_BASIC_FEATURES */
694 .probe
= smsc_phy_probe
,
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
,
703 .config_intr
= smsc_phy_config_intr
,
704 .handle_interrupt
= smsc_phy_handle_interrupt
,
707 .get_sset_count
= smsc_get_sset_count
,
708 .get_strings
= smsc_get_strings
,
709 .get_stats
= smsc_get_stats
,
711 .get_tunable
= smsc_phy_get_tunable
,
712 .set_tunable
= smsc_phy_set_tunable
,
714 .suspend
= genphy_suspend
,
715 .resume
= genphy_resume
,
717 .phy_id
= 0x0007c0d0, /* OUI=0x00800f, Model#=0x0d */
718 .phy_id_mask
= 0xfffffff0,
719 .name
= "SMSC LAN911x Internal PHY",
721 /* PHY_BASIC_FEATURES */
723 .probe
= smsc_phy_probe
,
726 .config_intr
= smsc_phy_config_intr
,
727 .handle_interrupt
= smsc_phy_handle_interrupt
,
729 .suspend
= genphy_suspend
,
730 .resume
= genphy_resume
,
732 /* This covers internal PHY (phy_id: 0x0007C0F0) for
733 * LAN9500A (PID: 0x9E00), LAN9505A (PID: 0x9E01)
735 .phy_id
= 0x0007c0f0, /* OUI=0x00800f, Model#=0x0f */
736 .phy_id_mask
= 0xfffffff0,
737 .name
= "SMSC LAN8710/LAN8720",
739 /* PHY_BASIC_FEATURES */
741 .probe
= smsc_phy_probe
,
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
,
750 .config_intr
= smsc_phy_config_intr
,
751 .handle_interrupt
= smsc_phy_handle_interrupt
,
754 .get_sset_count
= smsc_get_sset_count
,
755 .get_strings
= smsc_get_strings
,
756 .get_stats
= smsc_get_stats
,
758 .get_tunable
= smsc_phy_get_tunable
,
759 .set_tunable
= smsc_phy_set_tunable
,
761 .suspend
= genphy_suspend
,
762 .resume
= genphy_resume
,
764 .phy_id
= 0x0007c110,
765 .phy_id_mask
= 0xfffffff0,
766 .name
= "SMSC LAN8740",
768 /* PHY_BASIC_FEATURES */
769 .flags
= PHY_RST_AFTER_CLK_EN
,
771 .probe
= smsc_phy_probe
,
773 /* basic functions */
774 .read_status
= lan87xx_read_status
,
775 .config_init
= lan874x_phy_config_init
,
776 .soft_reset
= smsc_phy_reset
,
779 .config_intr
= smsc_phy_config_intr
,
780 .handle_interrupt
= smsc_phy_handle_interrupt
,
783 .get_sset_count
= smsc_get_sset_count
,
784 .get_strings
= smsc_get_strings
,
785 .get_stats
= smsc_get_stats
,
787 .get_tunable
= smsc_phy_get_tunable
,
788 .set_tunable
= smsc_phy_set_tunable
,
791 .set_wol
= lan874x_set_wol
,
792 .get_wol
= lan874x_get_wol
,
794 .suspend
= genphy_suspend
,
795 .resume
= genphy_resume
,
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.
802 .phy_id_mask
= 0xfffffff2,
803 .name
= "Microchip LAN8742",
805 /* PHY_BASIC_FEATURES */
806 .flags
= PHY_RST_AFTER_CLK_EN
,
808 .probe
= smsc_phy_probe
,
810 /* basic functions */
811 .read_status
= lan87xx_read_status
,
812 .config_init
= lan874x_phy_config_init
,
813 .soft_reset
= smsc_phy_reset
,
816 .config_intr
= smsc_phy_config_intr
,
817 .handle_interrupt
= smsc_phy_handle_interrupt
,
820 .get_sset_count
= smsc_get_sset_count
,
821 .get_strings
= smsc_get_strings
,
822 .get_stats
= smsc_get_stats
,
824 .get_tunable
= smsc_phy_get_tunable
,
825 .set_tunable
= smsc_phy_set_tunable
,
828 .set_wol
= lan874x_set_wol
,
829 .get_wol
= lan874x_get_wol
,
831 .suspend
= genphy_suspend
,
832 .resume
= genphy_resume
,
835 module_phy_driver(smsc_phy_driver
);
837 MODULE_DESCRIPTION("SMSC PHY driver");
838 MODULE_AUTHOR("Herbert Valerio Riedel");
839 MODULE_LICENSE("GPL");
841 static 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 },
852 MODULE_DEVICE_TABLE(mdio
, smsc_tbl
);