1 // SPDX-License-Identifier: GPL-2.0+
3 * Marvell 88x2222 dual-port multi-speed ethernet transceiver.
6 * XAUI on the host side.
7 * 1000Base-X or 10GBase-R on the line side.
8 * SGMII over 1000Base-X.
10 #include <linux/module.h>
11 #include <linux/phy.h>
12 #include <linux/delay.h>
13 #include <linux/mdio.h>
14 #include <linux/marvell_phy.h>
16 #include <linux/sfp.h>
17 #include <linux/netdevice.h>
19 /* Port PCS Configuration */
20 #define MV_PCS_CONFIG 0xF002
21 #define MV_PCS_HOST_XAUI 0x73
22 #define MV_PCS_LINE_10GBR (0x71 << 8)
23 #define MV_PCS_LINE_1GBX_AN (0x7B << 8)
24 #define MV_PCS_LINE_SGMII_AN (0x7F << 8)
26 /* Port Reset and Power Down */
27 #define MV_PORT_RST 0xF003
28 #define MV_LINE_RST_SW BIT(15)
29 #define MV_HOST_RST_SW BIT(7)
30 #define MV_PORT_RST_SW (MV_LINE_RST_SW | MV_HOST_RST_SW)
32 /* PMD Receive Signal Detect */
33 #define MV_RX_SIGNAL_DETECT 0x000A
34 #define MV_RX_SIGNAL_DETECT_GLOBAL BIT(0)
36 /* 1000Base-X/SGMII Control Register */
37 #define MV_1GBX_CTRL (0x2000 + MII_BMCR)
39 /* 1000BASE-X/SGMII Status Register */
40 #define MV_1GBX_STAT (0x2000 + MII_BMSR)
42 /* 1000Base-X Auto-Negotiation Advertisement Register */
43 #define MV_1GBX_ADVERTISE (0x2000 + MII_ADVERTISE)
45 /* 1000Base-X PHY Specific Status Register */
46 #define MV_1GBX_PHY_STAT 0xA003
47 #define MV_1GBX_PHY_STAT_AN_RESOLVED BIT(11)
48 #define MV_1GBX_PHY_STAT_DUPLEX BIT(13)
49 #define MV_1GBX_PHY_STAT_SPEED100 BIT(14)
50 #define MV_1GBX_PHY_STAT_SPEED1000 BIT(15)
52 #define AUTONEG_TIMEOUT 3
55 phy_interface_t line_interface
;
56 __ETHTOOL_DECLARE_LINK_MODE_MASK(supported
);
60 /* SFI PMA transmit enable */
61 static int mv2222_tx_enable(struct phy_device
*phydev
)
63 return phy_clear_bits_mmd(phydev
, MDIO_MMD_PMAPMD
, MDIO_PMA_TXDIS
,
64 MDIO_PMD_TXDIS_GLOBAL
);
67 /* SFI PMA transmit disable */
68 static int mv2222_tx_disable(struct phy_device
*phydev
)
70 return phy_set_bits_mmd(phydev
, MDIO_MMD_PMAPMD
, MDIO_PMA_TXDIS
,
71 MDIO_PMD_TXDIS_GLOBAL
);
74 static int mv2222_soft_reset(struct phy_device
*phydev
)
78 ret
= phy_write_mmd(phydev
, MDIO_MMD_VEND2
, MV_PORT_RST
,
83 return phy_read_mmd_poll_timeout(phydev
, MDIO_MMD_VEND2
, MV_PORT_RST
,
84 val
, !(val
& MV_PORT_RST_SW
),
88 static int mv2222_disable_aneg(struct phy_device
*phydev
)
90 int ret
= phy_clear_bits_mmd(phydev
, MDIO_MMD_PCS
, MV_1GBX_CTRL
,
91 BMCR_ANENABLE
| BMCR_ANRESTART
);
95 return mv2222_soft_reset(phydev
);
98 static int mv2222_enable_aneg(struct phy_device
*phydev
)
100 int ret
= phy_set_bits_mmd(phydev
, MDIO_MMD_PCS
, MV_1GBX_CTRL
,
101 BMCR_ANENABLE
| BMCR_RESET
);
105 return mv2222_soft_reset(phydev
);
108 static int mv2222_set_sgmii_speed(struct phy_device
*phydev
)
110 struct mv2222_data
*priv
= phydev
->priv
;
112 switch (phydev
->speed
) {
115 if ((linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT
,
117 linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT
,
119 return phy_modify_mmd(phydev
, MDIO_MMD_PCS
,
121 BMCR_SPEED1000
| BMCR_SPEED100
,
126 if ((linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT
,
128 linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT
,
130 return phy_modify_mmd(phydev
, MDIO_MMD_PCS
,
132 BMCR_SPEED1000
| BMCR_SPEED100
,
136 if ((linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT
,
138 linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT
,
140 return phy_modify_mmd(phydev
, MDIO_MMD_PCS
,
142 BMCR_SPEED1000
| BMCR_SPEED100
,
149 static bool mv2222_is_10g_capable(struct phy_device
*phydev
)
151 struct mv2222_data
*priv
= phydev
->priv
;
153 return (linkmode_test_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT
,
155 linkmode_test_bit(ETHTOOL_LINK_MODE_10000baseCR_Full_BIT
,
157 linkmode_test_bit(ETHTOOL_LINK_MODE_10000baseSR_Full_BIT
,
159 linkmode_test_bit(ETHTOOL_LINK_MODE_10000baseLR_Full_BIT
,
161 linkmode_test_bit(ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT
,
163 linkmode_test_bit(ETHTOOL_LINK_MODE_10000baseER_Full_BIT
,
167 static bool mv2222_is_1gbx_capable(struct phy_device
*phydev
)
169 struct mv2222_data
*priv
= phydev
->priv
;
171 return linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT
,
175 static bool mv2222_is_sgmii_capable(struct phy_device
*phydev
)
177 struct mv2222_data
*priv
= phydev
->priv
;
179 return (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT
,
181 linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT
,
183 linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT
,
185 linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT
,
187 linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT
,
189 linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT
,
193 static int mv2222_config_line(struct phy_device
*phydev
)
195 struct mv2222_data
*priv
= phydev
->priv
;
197 switch (priv
->line_interface
) {
198 case PHY_INTERFACE_MODE_10GBASER
:
199 return phy_write_mmd(phydev
, MDIO_MMD_VEND2
, MV_PCS_CONFIG
,
200 MV_PCS_HOST_XAUI
| MV_PCS_LINE_10GBR
);
201 case PHY_INTERFACE_MODE_1000BASEX
:
202 return phy_write_mmd(phydev
, MDIO_MMD_VEND2
, MV_PCS_CONFIG
,
203 MV_PCS_HOST_XAUI
| MV_PCS_LINE_1GBX_AN
);
204 case PHY_INTERFACE_MODE_SGMII
:
205 return phy_write_mmd(phydev
, MDIO_MMD_VEND2
, MV_PCS_CONFIG
,
206 MV_PCS_HOST_XAUI
| MV_PCS_LINE_SGMII_AN
);
212 /* Switch between 1G (1000Base-X/SGMII) and 10G (10GBase-R) modes */
213 static int mv2222_swap_line_type(struct phy_device
*phydev
)
215 struct mv2222_data
*priv
= phydev
->priv
;
216 bool changed
= false;
219 switch (priv
->line_interface
) {
220 case PHY_INTERFACE_MODE_10GBASER
:
221 if (mv2222_is_1gbx_capable(phydev
)) {
222 priv
->line_interface
= PHY_INTERFACE_MODE_1000BASEX
;
226 if (mv2222_is_sgmii_capable(phydev
)) {
227 priv
->line_interface
= PHY_INTERFACE_MODE_SGMII
;
232 case PHY_INTERFACE_MODE_1000BASEX
:
233 case PHY_INTERFACE_MODE_SGMII
:
234 if (mv2222_is_10g_capable(phydev
)) {
235 priv
->line_interface
= PHY_INTERFACE_MODE_10GBASER
;
245 ret
= mv2222_config_line(phydev
);
253 static int mv2222_setup_forced(struct phy_device
*phydev
)
255 struct mv2222_data
*priv
= phydev
->priv
;
258 if (priv
->line_interface
== PHY_INTERFACE_MODE_10GBASER
) {
259 if (phydev
->speed
< SPEED_10000
&&
260 phydev
->speed
!= SPEED_UNKNOWN
) {
261 ret
= mv2222_swap_line_type(phydev
);
267 if (priv
->line_interface
== PHY_INTERFACE_MODE_SGMII
) {
268 ret
= mv2222_set_sgmii_speed(phydev
);
273 return mv2222_disable_aneg(phydev
);
276 static int mv2222_config_aneg(struct phy_device
*phydev
)
278 struct mv2222_data
*priv
= phydev
->priv
;
281 /* SFP is not present, do nothing */
282 if (priv
->line_interface
== PHY_INTERFACE_MODE_NA
)
285 if (phydev
->autoneg
== AUTONEG_DISABLE
||
286 priv
->line_interface
== PHY_INTERFACE_MODE_10GBASER
)
287 return mv2222_setup_forced(phydev
);
289 adv
= linkmode_adv_to_mii_adv_x(priv
->supported
,
290 ETHTOOL_LINK_MODE_1000baseX_Full_BIT
);
292 ret
= phy_modify_mmd(phydev
, MDIO_MMD_PCS
, MV_1GBX_ADVERTISE
,
293 ADVERTISE_1000XFULL
|
294 ADVERTISE_1000XPAUSE
| ADVERTISE_1000XPSE_ASYM
,
299 return mv2222_enable_aneg(phydev
);
302 static int mv2222_aneg_done(struct phy_device
*phydev
)
306 if (mv2222_is_10g_capable(phydev
)) {
307 ret
= phy_read_mmd(phydev
, MDIO_MMD_PCS
, MDIO_STAT1
);
311 if (ret
& MDIO_STAT1_LSTATUS
)
315 ret
= phy_read_mmd(phydev
, MDIO_MMD_PCS
, MV_1GBX_STAT
);
319 return (ret
& BMSR_ANEGCOMPLETE
);
322 /* Returns negative on error, 0 if link is down, 1 if link is up */
323 static int mv2222_read_status_10g(struct phy_device
*phydev
)
328 val
= phy_read_mmd(phydev
, MDIO_MMD_PCS
, MDIO_STAT1
);
332 if (val
& MDIO_STAT1_LSTATUS
) {
335 /* 10GBASE-R do not support auto-negotiation */
336 phydev
->autoneg
= AUTONEG_DISABLE
;
337 phydev
->speed
= SPEED_10000
;
338 phydev
->duplex
= DUPLEX_FULL
;
340 if (phydev
->autoneg
== AUTONEG_ENABLE
) {
343 if (timeout
> AUTONEG_TIMEOUT
) {
346 val
= mv2222_swap_line_type(phydev
);
350 return mv2222_config_aneg(phydev
);
358 /* Returns negative on error, 0 if link is down, 1 if link is up */
359 static int mv2222_read_status_1g(struct phy_device
*phydev
)
364 val
= phy_read_mmd(phydev
, MDIO_MMD_PCS
, MV_1GBX_STAT
);
368 if (phydev
->autoneg
== AUTONEG_ENABLE
&&
369 !(val
& BMSR_ANEGCOMPLETE
)) {
372 if (timeout
> AUTONEG_TIMEOUT
) {
375 val
= mv2222_swap_line_type(phydev
);
379 return mv2222_config_aneg(phydev
);
385 if (!(val
& BMSR_LSTATUS
))
390 val
= phy_read_mmd(phydev
, MDIO_MMD_PCS
, MV_1GBX_PHY_STAT
);
394 if (val
& MV_1GBX_PHY_STAT_AN_RESOLVED
) {
395 if (val
& MV_1GBX_PHY_STAT_DUPLEX
)
396 phydev
->duplex
= DUPLEX_FULL
;
398 phydev
->duplex
= DUPLEX_HALF
;
400 if (val
& MV_1GBX_PHY_STAT_SPEED1000
)
401 phydev
->speed
= SPEED_1000
;
402 else if (val
& MV_1GBX_PHY_STAT_SPEED100
)
403 phydev
->speed
= SPEED_100
;
405 phydev
->speed
= SPEED_10
;
411 static bool mv2222_link_is_operational(struct phy_device
*phydev
)
413 struct mv2222_data
*priv
= phydev
->priv
;
416 val
= phy_read_mmd(phydev
, MDIO_MMD_PMAPMD
, MV_RX_SIGNAL_DETECT
);
417 if (val
< 0 || !(val
& MV_RX_SIGNAL_DETECT_GLOBAL
))
420 if (phydev
->sfp_bus
&& !priv
->sfp_link
)
426 static int mv2222_read_status(struct phy_device
*phydev
)
428 struct mv2222_data
*priv
= phydev
->priv
;
432 phydev
->speed
= SPEED_UNKNOWN
;
433 phydev
->duplex
= DUPLEX_UNKNOWN
;
435 if (!mv2222_link_is_operational(phydev
))
438 if (priv
->line_interface
== PHY_INTERFACE_MODE_10GBASER
)
439 link
= mv2222_read_status_10g(phydev
);
441 link
= mv2222_read_status_1g(phydev
);
451 static int mv2222_resume(struct phy_device
*phydev
)
453 return mv2222_tx_enable(phydev
);
456 static int mv2222_suspend(struct phy_device
*phydev
)
458 return mv2222_tx_disable(phydev
);
461 static int mv2222_get_features(struct phy_device
*phydev
)
463 /* All supported linkmodes are set at probe */
468 static int mv2222_config_init(struct phy_device
*phydev
)
470 if (phydev
->interface
!= PHY_INTERFACE_MODE_XAUI
)
476 static int mv2222_sfp_insert(void *upstream
, const struct sfp_eeprom_id
*id
)
478 DECLARE_PHY_INTERFACE_MASK(interfaces
);
479 struct phy_device
*phydev
= upstream
;
480 phy_interface_t sfp_interface
;
481 struct mv2222_data
*priv
;
485 __ETHTOOL_DECLARE_LINK_MODE_MASK(sfp_supported
) = { 0, };
488 dev
= &phydev
->mdio
.dev
;
490 sfp_parse_support(phydev
->sfp_bus
, id
, sfp_supported
, interfaces
);
491 phydev
->port
= sfp_parse_port(phydev
->sfp_bus
, id
, sfp_supported
);
492 sfp_interface
= sfp_select_interface(phydev
->sfp_bus
, sfp_supported
);
494 dev_info(dev
, "%s SFP module inserted\n", phy_modes(sfp_interface
));
496 if (sfp_interface
!= PHY_INTERFACE_MODE_10GBASER
&&
497 sfp_interface
!= PHY_INTERFACE_MODE_1000BASEX
&&
498 sfp_interface
!= PHY_INTERFACE_MODE_SGMII
) {
499 dev_err(dev
, "Incompatible SFP module inserted\n");
504 priv
->line_interface
= sfp_interface
;
505 linkmode_and(priv
->supported
, phydev
->supported
, sfp_supported
);
507 ret
= mv2222_config_line(phydev
);
511 if (mutex_trylock(&phydev
->lock
)) {
512 ret
= mv2222_config_aneg(phydev
);
513 mutex_unlock(&phydev
->lock
);
519 static void mv2222_sfp_remove(void *upstream
)
521 struct phy_device
*phydev
= upstream
;
522 struct mv2222_data
*priv
;
526 priv
->line_interface
= PHY_INTERFACE_MODE_NA
;
527 linkmode_zero(priv
->supported
);
528 phydev
->port
= PORT_NONE
;
531 static void mv2222_sfp_link_up(void *upstream
)
533 struct phy_device
*phydev
= upstream
;
534 struct mv2222_data
*priv
;
537 priv
->sfp_link
= true;
540 static void mv2222_sfp_link_down(void *upstream
)
542 struct phy_device
*phydev
= upstream
;
543 struct mv2222_data
*priv
;
546 priv
->sfp_link
= false;
549 static const struct sfp_upstream_ops sfp_phy_ops
= {
550 .module_insert
= mv2222_sfp_insert
,
551 .module_remove
= mv2222_sfp_remove
,
552 .link_up
= mv2222_sfp_link_up
,
553 .link_down
= mv2222_sfp_link_down
,
554 .attach
= phy_sfp_attach
,
555 .detach
= phy_sfp_detach
,
556 .connect_phy
= phy_sfp_connect_phy
,
557 .disconnect_phy
= phy_sfp_disconnect_phy
,
560 static int mv2222_probe(struct phy_device
*phydev
)
562 struct device
*dev
= &phydev
->mdio
.dev
;
563 struct mv2222_data
*priv
= NULL
;
565 __ETHTOOL_DECLARE_LINK_MODE_MASK(supported
) = { 0, };
567 linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT
, supported
);
568 linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT
, supported
);
569 linkmode_set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT
, supported
);
570 linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT
, supported
);
571 linkmode_set_bit(ETHTOOL_LINK_MODE_TP_BIT
, supported
);
572 linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT
, supported
);
573 linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT
, supported
);
574 linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT
, supported
);
575 linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT
, supported
);
576 linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT
, supported
);
577 linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT
, supported
);
578 linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT
, supported
);
579 linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT
, supported
);
580 linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseCR_Full_BIT
, supported
);
581 linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseSR_Full_BIT
, supported
);
582 linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseLR_Full_BIT
, supported
);
583 linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT
, supported
);
584 linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseER_Full_BIT
, supported
);
586 linkmode_copy(phydev
->supported
, supported
);
588 priv
= devm_kzalloc(dev
, sizeof(*priv
), GFP_KERNEL
);
592 priv
->line_interface
= PHY_INTERFACE_MODE_NA
;
595 return phy_sfp_probe(phydev
, &sfp_phy_ops
);
598 static struct phy_driver mv2222_drivers
[] = {
600 .phy_id
= MARVELL_PHY_ID_88X2222
,
601 .phy_id_mask
= MARVELL_PHY_ID_MASK
,
602 .name
= "Marvell 88X2222",
603 .get_features
= mv2222_get_features
,
604 .soft_reset
= mv2222_soft_reset
,
605 .config_init
= mv2222_config_init
,
606 .config_aneg
= mv2222_config_aneg
,
607 .aneg_done
= mv2222_aneg_done
,
608 .probe
= mv2222_probe
,
609 .suspend
= mv2222_suspend
,
610 .resume
= mv2222_resume
,
611 .read_status
= mv2222_read_status
,
614 module_phy_driver(mv2222_drivers
);
616 static struct mdio_device_id __maybe_unused mv2222_tbl
[] = {
617 { MARVELL_PHY_ID_88X2222
, MARVELL_PHY_ID_MASK
},
620 MODULE_DEVICE_TABLE(mdio
, mv2222_tbl
);
622 MODULE_DESCRIPTION("Marvell 88x2222 ethernet transceiver driver");
623 MODULE_LICENSE("GPL");