1 // SPDX-License-Identifier: GPL-2.0+
3 * Marvell 10G 88x3310 PHY driver
5 * Based upon the ID registers, this PHY appears to be a mixture of IPs
6 * from two different companies.
8 * There appears to be several different data paths through the PHY which
9 * are automatically managed by the PHY. The following has been determined
10 * via observation and experimentation for a setup using single-lane Serdes:
12 * SGMII PHYXS -- BASE-T PCS -- 10G PMA -- AN -- Copper (for <= 1G)
13 * 10GBASE-KR PHYXS -- BASE-T PCS -- 10G PMA -- AN -- Copper (for 10G)
14 * 10GBASE-KR PHYXS -- BASE-R PCS -- Fiber
16 * With XAUI, observation shows:
18 * XAUI PHYXS -- <appropriate PCS as above>
20 * and no switching of the host interface mode occurs.
22 * If both the fiber and copper ports are connected, the first to gain
23 * link takes priority and the other port is completely locked out.
25 #include <linux/ctype.h>
26 #include <linux/delay.h>
27 #include <linux/hwmon.h>
28 #include <linux/marvell_phy.h>
29 #include <linux/phy.h>
30 #include <linux/sfp.h>
32 #define MV_PHY_ALASKA_NBT_QUIRK_MASK 0xfffffffe
33 #define MV_PHY_ALASKA_NBT_QUIRK_REV (MARVELL_PHY_ID_88X3310 | 0xa)
36 MV_PMA_FW_VER0
= 0xc011,
37 MV_PMA_FW_VER1
= 0xc012,
39 MV_PMA_BOOT_FATAL
= BIT(0),
41 MV_PCS_BASE_T
= 0x0000,
42 MV_PCS_BASE_R
= 0x1000,
43 MV_PCS_1000BASEX
= 0x2000,
45 MV_PCS_CSCR1
= 0x8000,
46 MV_PCS_CSCR1_ED_MASK
= 0x0300,
47 MV_PCS_CSCR1_ED_OFF
= 0x0000,
48 MV_PCS_CSCR1_ED_RX
= 0x0200,
49 MV_PCS_CSCR1_ED_NLP
= 0x0300,
50 MV_PCS_CSCR1_MDIX_MASK
= 0x0060,
51 MV_PCS_CSCR1_MDIX_MDI
= 0x0000,
52 MV_PCS_CSCR1_MDIX_MDIX
= 0x0020,
53 MV_PCS_CSCR1_MDIX_AUTO
= 0x0060,
55 MV_PCS_CSSR1
= 0x8008,
56 MV_PCS_CSSR1_SPD1_MASK
= 0xc000,
57 MV_PCS_CSSR1_SPD1_SPD2
= 0xc000,
58 MV_PCS_CSSR1_SPD1_1000
= 0x8000,
59 MV_PCS_CSSR1_SPD1_100
= 0x4000,
60 MV_PCS_CSSR1_SPD1_10
= 0x0000,
61 MV_PCS_CSSR1_DUPLEX_FULL
= BIT(13),
62 MV_PCS_CSSR1_RESOLVED
= BIT(11),
63 MV_PCS_CSSR1_MDIX
= BIT(6),
64 MV_PCS_CSSR1_SPD2_MASK
= 0x000c,
65 MV_PCS_CSSR1_SPD2_5000
= 0x0008,
66 MV_PCS_CSSR1_SPD2_2500
= 0x0004,
67 MV_PCS_CSSR1_SPD2_10000
= 0x0000,
69 /* Temperature read register (88E2110 only) */
72 /* These registers appear at 0x800X and 0xa00X - the 0xa00X control
73 * registers appear to set themselves to the 0x800X when AN is
74 * restarted, but status registers appear readable from either.
76 MV_AN_CTRL1000
= 0x8000, /* 1000base-T control register */
77 MV_AN_STAT1000
= 0x8001, /* 1000base-T status register */
79 /* Vendor2 MMD registers */
80 MV_V2_PORT_CTRL
= 0xf001,
81 MV_V2_PORT_CTRL_SWRST
= BIT(15),
82 MV_V2_PORT_CTRL_PWRDOWN
= BIT(11),
83 MV_V2_PORT_MAC_TYPE_MASK
= 0x7,
84 MV_V2_PORT_MAC_TYPE_RATE_MATCH
= 0x6,
85 /* Temperature control/read registers (88X3310 only) */
86 MV_V2_TEMP_CTRL
= 0xf08a,
87 MV_V2_TEMP_CTRL_MASK
= 0xc000,
88 MV_V2_TEMP_CTRL_SAMPLE
= 0x0000,
89 MV_V2_TEMP_CTRL_DISABLE
= 0xc000,
91 MV_V2_TEMP_UNKNOWN
= 0x9600, /* unknown function */
98 struct device
*hwmon_dev
;
103 static umode_t
mv3310_hwmon_is_visible(const void *data
,
104 enum hwmon_sensor_types type
,
105 u32 attr
, int channel
)
107 if (type
== hwmon_chip
&& attr
== hwmon_chip_update_interval
)
109 if (type
== hwmon_temp
&& attr
== hwmon_temp_input
)
114 static int mv3310_hwmon_read_temp_reg(struct phy_device
*phydev
)
116 return phy_read_mmd(phydev
, MDIO_MMD_VEND2
, MV_V2_TEMP
);
119 static int mv2110_hwmon_read_temp_reg(struct phy_device
*phydev
)
121 return phy_read_mmd(phydev
, MDIO_MMD_PCS
, MV_PCS_TEMP
);
124 static int mv10g_hwmon_read_temp_reg(struct phy_device
*phydev
)
126 if (phydev
->drv
->phy_id
== MARVELL_PHY_ID_88X3310
)
127 return mv3310_hwmon_read_temp_reg(phydev
);
128 else /* MARVELL_PHY_ID_88E2110 */
129 return mv2110_hwmon_read_temp_reg(phydev
);
132 static int mv3310_hwmon_read(struct device
*dev
, enum hwmon_sensor_types type
,
133 u32 attr
, int channel
, long *value
)
135 struct phy_device
*phydev
= dev_get_drvdata(dev
);
138 if (type
== hwmon_chip
&& attr
== hwmon_chip_update_interval
) {
139 *value
= MSEC_PER_SEC
;
143 if (type
== hwmon_temp
&& attr
== hwmon_temp_input
) {
144 temp
= mv10g_hwmon_read_temp_reg(phydev
);
148 *value
= ((temp
& 0xff) - 75) * 1000;
156 static const struct hwmon_ops mv3310_hwmon_ops
= {
157 .is_visible
= mv3310_hwmon_is_visible
,
158 .read
= mv3310_hwmon_read
,
161 static u32 mv3310_hwmon_chip_config
[] = {
162 HWMON_C_REGISTER_TZ
| HWMON_C_UPDATE_INTERVAL
,
166 static const struct hwmon_channel_info mv3310_hwmon_chip
= {
168 .config
= mv3310_hwmon_chip_config
,
171 static u32 mv3310_hwmon_temp_config
[] = {
176 static const struct hwmon_channel_info mv3310_hwmon_temp
= {
178 .config
= mv3310_hwmon_temp_config
,
181 static const struct hwmon_channel_info
*mv3310_hwmon_info
[] = {
187 static const struct hwmon_chip_info mv3310_hwmon_chip_info
= {
188 .ops
= &mv3310_hwmon_ops
,
189 .info
= mv3310_hwmon_info
,
192 static int mv3310_hwmon_config(struct phy_device
*phydev
, bool enable
)
197 if (phydev
->drv
->phy_id
!= MARVELL_PHY_ID_88X3310
)
200 ret
= phy_write_mmd(phydev
, MDIO_MMD_VEND2
, MV_V2_TEMP
,
205 val
= enable
? MV_V2_TEMP_CTRL_SAMPLE
: MV_V2_TEMP_CTRL_DISABLE
;
207 return phy_modify_mmd(phydev
, MDIO_MMD_VEND2
, MV_V2_TEMP_CTRL
,
208 MV_V2_TEMP_CTRL_MASK
, val
);
211 static int mv3310_hwmon_probe(struct phy_device
*phydev
)
213 struct device
*dev
= &phydev
->mdio
.dev
;
214 struct mv3310_priv
*priv
= dev_get_drvdata(&phydev
->mdio
.dev
);
217 priv
->hwmon_name
= devm_kstrdup(dev
, dev_name(dev
), GFP_KERNEL
);
218 if (!priv
->hwmon_name
)
221 for (i
= j
= 0; priv
->hwmon_name
[i
]; i
++) {
222 if (isalnum(priv
->hwmon_name
[i
])) {
224 priv
->hwmon_name
[j
] = priv
->hwmon_name
[i
];
228 priv
->hwmon_name
[j
] = '\0';
230 ret
= mv3310_hwmon_config(phydev
, true);
234 priv
->hwmon_dev
= devm_hwmon_device_register_with_info(dev
,
235 priv
->hwmon_name
, phydev
,
236 &mv3310_hwmon_chip_info
, NULL
);
238 return PTR_ERR_OR_ZERO(priv
->hwmon_dev
);
241 static inline int mv3310_hwmon_config(struct phy_device
*phydev
, bool enable
)
246 static int mv3310_hwmon_probe(struct phy_device
*phydev
)
252 static int mv3310_power_down(struct phy_device
*phydev
)
254 return phy_set_bits_mmd(phydev
, MDIO_MMD_VEND2
, MV_V2_PORT_CTRL
,
255 MV_V2_PORT_CTRL_PWRDOWN
);
258 static int mv3310_power_up(struct phy_device
*phydev
)
260 struct mv3310_priv
*priv
= dev_get_drvdata(&phydev
->mdio
.dev
);
263 ret
= phy_clear_bits_mmd(phydev
, MDIO_MMD_VEND2
, MV_V2_PORT_CTRL
,
264 MV_V2_PORT_CTRL_PWRDOWN
);
266 if (phydev
->drv
->phy_id
!= MARVELL_PHY_ID_88X3310
||
267 priv
->firmware_ver
< 0x00030000)
270 return phy_set_bits_mmd(phydev
, MDIO_MMD_VEND2
, MV_V2_PORT_CTRL
,
271 MV_V2_PORT_CTRL_SWRST
);
274 static int mv3310_reset(struct phy_device
*phydev
, u32 unit
)
278 err
= phy_modify_mmd(phydev
, MDIO_MMD_PCS
, unit
+ MDIO_CTRL1
,
279 MDIO_CTRL1_RESET
, MDIO_CTRL1_RESET
);
283 return phy_read_mmd_poll_timeout(phydev
, MDIO_MMD_PCS
,
284 unit
+ MDIO_CTRL1
, val
,
285 !(val
& MDIO_CTRL1_RESET
),
289 static int mv3310_get_edpd(struct phy_device
*phydev
, u16
*edpd
)
293 val
= phy_read_mmd(phydev
, MDIO_MMD_PCS
, MV_PCS_CSCR1
);
297 switch (val
& MV_PCS_CSCR1_ED_MASK
) {
298 case MV_PCS_CSCR1_ED_NLP
:
301 case MV_PCS_CSCR1_ED_RX
:
302 *edpd
= ETHTOOL_PHY_EDPD_NO_TX
;
305 *edpd
= ETHTOOL_PHY_EDPD_DISABLE
;
311 static int mv3310_set_edpd(struct phy_device
*phydev
, u16 edpd
)
318 case ETHTOOL_PHY_EDPD_DFLT_TX_MSECS
:
319 val
= MV_PCS_CSCR1_ED_NLP
;
322 case ETHTOOL_PHY_EDPD_NO_TX
:
323 val
= MV_PCS_CSCR1_ED_RX
;
326 case ETHTOOL_PHY_EDPD_DISABLE
:
327 val
= MV_PCS_CSCR1_ED_OFF
;
334 err
= phy_modify_mmd_changed(phydev
, MDIO_MMD_PCS
, MV_PCS_CSCR1
,
335 MV_PCS_CSCR1_ED_MASK
, val
);
337 err
= mv3310_reset(phydev
, MV_PCS_BASE_T
);
342 static int mv3310_sfp_insert(void *upstream
, const struct sfp_eeprom_id
*id
)
344 struct phy_device
*phydev
= upstream
;
345 __ETHTOOL_DECLARE_LINK_MODE_MASK(support
) = { 0, };
346 phy_interface_t iface
;
348 sfp_parse_support(phydev
->sfp_bus
, id
, support
);
349 iface
= sfp_select_interface(phydev
->sfp_bus
, support
);
351 if (iface
!= PHY_INTERFACE_MODE_10GBASER
) {
352 dev_err(&phydev
->mdio
.dev
, "incompatible SFP module inserted\n");
358 static const struct sfp_upstream_ops mv3310_sfp_ops
= {
359 .attach
= phy_sfp_attach
,
360 .detach
= phy_sfp_detach
,
361 .module_insert
= mv3310_sfp_insert
,
364 static int mv3310_probe(struct phy_device
*phydev
)
366 struct mv3310_priv
*priv
;
367 u32 mmd_mask
= MDIO_DEVS_PMAPMD
| MDIO_DEVS_AN
;
370 if (!phydev
->is_c45
||
371 (phydev
->c45_ids
.devices_in_package
& mmd_mask
) != mmd_mask
)
374 ret
= phy_read_mmd(phydev
, MDIO_MMD_PMAPMD
, MV_PMA_BOOT
);
378 if (ret
& MV_PMA_BOOT_FATAL
) {
379 dev_warn(&phydev
->mdio
.dev
,
380 "PHY failed to boot firmware, status=%04x\n", ret
);
384 priv
= devm_kzalloc(&phydev
->mdio
.dev
, sizeof(*priv
), GFP_KERNEL
);
388 dev_set_drvdata(&phydev
->mdio
.dev
, priv
);
390 ret
= phy_read_mmd(phydev
, MDIO_MMD_PMAPMD
, MV_PMA_FW_VER0
);
394 priv
->firmware_ver
= ret
<< 16;
396 ret
= phy_read_mmd(phydev
, MDIO_MMD_PMAPMD
, MV_PMA_FW_VER1
);
400 priv
->firmware_ver
|= ret
;
402 phydev_info(phydev
, "Firmware version %u.%u.%u.%u\n",
403 priv
->firmware_ver
>> 24, (priv
->firmware_ver
>> 16) & 255,
404 (priv
->firmware_ver
>> 8) & 255, priv
->firmware_ver
& 255);
406 /* Powering down the port when not in use saves about 600mW */
407 ret
= mv3310_power_down(phydev
);
411 ret
= mv3310_hwmon_probe(phydev
);
415 return phy_sfp_probe(phydev
, &mv3310_sfp_ops
);
418 static void mv3310_remove(struct phy_device
*phydev
)
420 mv3310_hwmon_config(phydev
, false);
423 static int mv3310_suspend(struct phy_device
*phydev
)
425 return mv3310_power_down(phydev
);
428 static int mv3310_resume(struct phy_device
*phydev
)
432 ret
= mv3310_power_up(phydev
);
436 return mv3310_hwmon_config(phydev
, true);
439 /* Some PHYs in the Alaska family such as the 88X3310 and the 88E2010
440 * don't set bit 14 in PMA Extended Abilities (1.11), although they do
441 * support 2.5GBASET and 5GBASET. For these models, we can still read their
442 * 2.5G/5G extended abilities register (1.21). We detect these models based on
443 * the PMA device identifier, with a mask matching models known to have this
446 static bool mv3310_has_pma_ngbaset_quirk(struct phy_device
*phydev
)
448 if (!(phydev
->c45_ids
.devices_in_package
& MDIO_DEVS_PMAPMD
))
451 /* Only some revisions of the 88X3310 family PMA seem to be impacted */
452 return (phydev
->c45_ids
.device_ids
[MDIO_MMD_PMAPMD
] &
453 MV_PHY_ALASKA_NBT_QUIRK_MASK
) == MV_PHY_ALASKA_NBT_QUIRK_REV
;
456 static int mv3310_config_init(struct phy_device
*phydev
)
458 struct mv3310_priv
*priv
= dev_get_drvdata(&phydev
->mdio
.dev
);
462 /* Check that the PHY interface type is compatible */
463 if (phydev
->interface
!= PHY_INTERFACE_MODE_SGMII
&&
464 phydev
->interface
!= PHY_INTERFACE_MODE_2500BASEX
&&
465 phydev
->interface
!= PHY_INTERFACE_MODE_XAUI
&&
466 phydev
->interface
!= PHY_INTERFACE_MODE_RXAUI
&&
467 phydev
->interface
!= PHY_INTERFACE_MODE_10GBASER
)
470 phydev
->mdix_ctrl
= ETH_TP_MDI_AUTO
;
472 /* Power up so reset works */
473 err
= mv3310_power_up(phydev
);
477 val
= phy_read_mmd(phydev
, MDIO_MMD_VEND2
, MV_V2_PORT_CTRL
);
480 priv
->rate_match
= ((val
& MV_V2_PORT_MAC_TYPE_MASK
) ==
481 MV_V2_PORT_MAC_TYPE_RATE_MATCH
);
483 /* Enable EDPD mode - saving 600mW */
484 return mv3310_set_edpd(phydev
, ETHTOOL_PHY_EDPD_DFLT_TX_MSECS
);
487 static int mv3310_get_features(struct phy_device
*phydev
)
491 ret
= genphy_c45_pma_read_abilities(phydev
);
495 if (mv3310_has_pma_ngbaset_quirk(phydev
)) {
496 val
= phy_read_mmd(phydev
, MDIO_MMD_PMAPMD
,
497 MDIO_PMA_NG_EXTABLE
);
501 linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT
,
503 val
& MDIO_PMA_NG_EXTABLE_2_5GBT
);
505 linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT
,
507 val
& MDIO_PMA_NG_EXTABLE_5GBT
);
513 static int mv3310_config_mdix(struct phy_device
*phydev
)
518 switch (phydev
->mdix_ctrl
) {
519 case ETH_TP_MDI_AUTO
:
520 val
= MV_PCS_CSCR1_MDIX_AUTO
;
523 val
= MV_PCS_CSCR1_MDIX_MDIX
;
526 val
= MV_PCS_CSCR1_MDIX_MDI
;
532 err
= phy_modify_mmd_changed(phydev
, MDIO_MMD_PCS
, MV_PCS_CSCR1
,
533 MV_PCS_CSCR1_MDIX_MASK
, val
);
535 err
= mv3310_reset(phydev
, MV_PCS_BASE_T
);
540 static int mv3310_config_aneg(struct phy_device
*phydev
)
542 bool changed
= false;
546 ret
= mv3310_config_mdix(phydev
);
550 if (phydev
->autoneg
== AUTONEG_DISABLE
)
551 return genphy_c45_pma_setup_forced(phydev
);
553 ret
= genphy_c45_an_config_aneg(phydev
);
559 /* Clause 45 has no standardized support for 1000BaseT, therefore
560 * use vendor registers for this mode.
562 reg
= linkmode_adv_to_mii_ctrl1000_t(phydev
->advertising
);
563 ret
= phy_modify_mmd_changed(phydev
, MDIO_MMD_AN
, MV_AN_CTRL1000
,
564 ADVERTISE_1000FULL
| ADVERTISE_1000HALF
, reg
);
570 return genphy_c45_check_and_restart_aneg(phydev
, changed
);
573 static int mv3310_aneg_done(struct phy_device
*phydev
)
577 val
= phy_read_mmd(phydev
, MDIO_MMD_PCS
, MV_PCS_BASE_R
+ MDIO_STAT1
);
581 if (val
& MDIO_STAT1_LSTATUS
)
584 return genphy_c45_aneg_done(phydev
);
587 static void mv3310_update_interface(struct phy_device
*phydev
)
589 struct mv3310_priv
*priv
= dev_get_drvdata(&phydev
->mdio
.dev
);
591 /* In "XFI with Rate Matching" mode the PHY interface is fixed at
592 * 10Gb. The PHY adapts the rate to actual wire speed with help of
593 * internal 16KB buffer.
595 if (priv
->rate_match
) {
596 phydev
->interface
= PHY_INTERFACE_MODE_10GBASER
;
600 if ((phydev
->interface
== PHY_INTERFACE_MODE_SGMII
||
601 phydev
->interface
== PHY_INTERFACE_MODE_2500BASEX
||
602 phydev
->interface
== PHY_INTERFACE_MODE_10GBASER
) &&
604 /* The PHY automatically switches its serdes interface (and
605 * active PHYXS instance) between Cisco SGMII, 10GBase-R and
606 * 2500BaseX modes according to the speed. Florian suggests
607 * setting phydev->interface to communicate this to the MAC.
608 * Only do this if we are already in one of the above modes.
610 switch (phydev
->speed
) {
612 phydev
->interface
= PHY_INTERFACE_MODE_10GBASER
;
615 phydev
->interface
= PHY_INTERFACE_MODE_2500BASEX
;
620 phydev
->interface
= PHY_INTERFACE_MODE_SGMII
;
628 /* 10GBASE-ER,LR,LRM,SR do not support autonegotiation. */
629 static int mv3310_read_status_10gbaser(struct phy_device
*phydev
)
632 phydev
->speed
= SPEED_10000
;
633 phydev
->duplex
= DUPLEX_FULL
;
638 static int mv3310_read_status_copper(struct phy_device
*phydev
)
640 int cssr1
, speed
, val
;
642 val
= genphy_c45_read_link(phydev
);
646 val
= phy_read_mmd(phydev
, MDIO_MMD_AN
, MDIO_STAT1
);
650 cssr1
= phy_read_mmd(phydev
, MDIO_MMD_PCS
, MV_PCS_CSSR1
);
654 /* If the link settings are not resolved, mark the link down */
655 if (!(cssr1
& MV_PCS_CSSR1_RESOLVED
)) {
660 /* Read the copper link settings */
661 speed
= cssr1
& MV_PCS_CSSR1_SPD1_MASK
;
662 if (speed
== MV_PCS_CSSR1_SPD1_SPD2
)
663 speed
|= cssr1
& MV_PCS_CSSR1_SPD2_MASK
;
666 case MV_PCS_CSSR1_SPD1_SPD2
| MV_PCS_CSSR1_SPD2_10000
:
667 phydev
->speed
= SPEED_10000
;
670 case MV_PCS_CSSR1_SPD1_SPD2
| MV_PCS_CSSR1_SPD2_5000
:
671 phydev
->speed
= SPEED_5000
;
674 case MV_PCS_CSSR1_SPD1_SPD2
| MV_PCS_CSSR1_SPD2_2500
:
675 phydev
->speed
= SPEED_2500
;
678 case MV_PCS_CSSR1_SPD1_1000
:
679 phydev
->speed
= SPEED_1000
;
682 case MV_PCS_CSSR1_SPD1_100
:
683 phydev
->speed
= SPEED_100
;
686 case MV_PCS_CSSR1_SPD1_10
:
687 phydev
->speed
= SPEED_10
;
691 phydev
->duplex
= cssr1
& MV_PCS_CSSR1_DUPLEX_FULL
?
692 DUPLEX_FULL
: DUPLEX_HALF
;
693 phydev
->mdix
= cssr1
& MV_PCS_CSSR1_MDIX
?
694 ETH_TP_MDI_X
: ETH_TP_MDI
;
696 if (val
& MDIO_AN_STAT1_COMPLETE
) {
697 val
= genphy_c45_read_lpa(phydev
);
701 /* Read the link partner's 1G advertisement */
702 val
= phy_read_mmd(phydev
, MDIO_MMD_AN
, MV_AN_STAT1000
);
706 mii_stat1000_mod_linkmode_lpa_t(phydev
->lp_advertising
, val
);
708 /* Update the pause status */
709 phy_resolve_aneg_pause(phydev
);
715 static int mv3310_read_status(struct phy_device
*phydev
)
719 phydev
->speed
= SPEED_UNKNOWN
;
720 phydev
->duplex
= DUPLEX_UNKNOWN
;
721 linkmode_zero(phydev
->lp_advertising
);
724 phydev
->asym_pause
= 0;
725 phydev
->mdix
= ETH_TP_MDI_INVALID
;
727 val
= phy_read_mmd(phydev
, MDIO_MMD_PCS
, MV_PCS_BASE_R
+ MDIO_STAT1
);
731 if (val
& MDIO_STAT1_LSTATUS
)
732 err
= mv3310_read_status_10gbaser(phydev
);
734 err
= mv3310_read_status_copper(phydev
);
739 mv3310_update_interface(phydev
);
744 static int mv3310_get_tunable(struct phy_device
*phydev
,
745 struct ethtool_tunable
*tuna
, void *data
)
748 case ETHTOOL_PHY_EDPD
:
749 return mv3310_get_edpd(phydev
, data
);
755 static int mv3310_set_tunable(struct phy_device
*phydev
,
756 struct ethtool_tunable
*tuna
, const void *data
)
759 case ETHTOOL_PHY_EDPD
:
760 return mv3310_set_edpd(phydev
, *(u16
*)data
);
766 static struct phy_driver mv3310_drivers
[] = {
768 .phy_id
= MARVELL_PHY_ID_88X3310
,
769 .phy_id_mask
= MARVELL_PHY_ID_MASK
,
771 .get_features
= mv3310_get_features
,
772 .config_init
= mv3310_config_init
,
773 .probe
= mv3310_probe
,
774 .suspend
= mv3310_suspend
,
775 .resume
= mv3310_resume
,
776 .config_aneg
= mv3310_config_aneg
,
777 .aneg_done
= mv3310_aneg_done
,
778 .read_status
= mv3310_read_status
,
779 .get_tunable
= mv3310_get_tunable
,
780 .set_tunable
= mv3310_set_tunable
,
781 .remove
= mv3310_remove
,
784 .phy_id
= MARVELL_PHY_ID_88E2110
,
785 .phy_id_mask
= MARVELL_PHY_ID_MASK
,
787 .probe
= mv3310_probe
,
788 .suspend
= mv3310_suspend
,
789 .resume
= mv3310_resume
,
790 .config_init
= mv3310_config_init
,
791 .config_aneg
= mv3310_config_aneg
,
792 .aneg_done
= mv3310_aneg_done
,
793 .read_status
= mv3310_read_status
,
794 .get_tunable
= mv3310_get_tunable
,
795 .set_tunable
= mv3310_set_tunable
,
796 .remove
= mv3310_remove
,
800 module_phy_driver(mv3310_drivers
);
802 static struct mdio_device_id __maybe_unused mv3310_tbl
[] = {
803 { MARVELL_PHY_ID_88X3310
, MARVELL_PHY_ID_MASK
},
804 { MARVELL_PHY_ID_88E2110
, MARVELL_PHY_ID_MASK
},
807 MODULE_DEVICE_TABLE(mdio
, mv3310_tbl
);
808 MODULE_DESCRIPTION("Marvell Alaska X 10Gigabit Ethernet PHY driver (MV88X3310)");
809 MODULE_LICENSE("GPL");