1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Marvell 88E6352 family SERDES PCS support
5 * Copyright (c) 2008 Marvell Semiconductor
7 * Copyright (c) 2017 Andrew Lunn <andrew@lunn.ch>
9 #include <linux/interrupt.h>
10 #include <linux/irqdomain.h>
11 #include <linux/mii.h>
19 struct mv88e639x_pcs
{
20 struct mdio_device mdio
;
21 struct phylink_pcs sgmii_pcs
;
22 struct phylink_pcs xg_pcs
;
25 phy_interface_t interface
;
28 irqreturn_t (*handle_irq
)(struct mv88e639x_pcs
*mpcs
);
31 static int mv88e639x_read(struct mv88e639x_pcs
*mpcs
, u16 regnum
, u16
*val
)
35 err
= mdiodev_c45_read(&mpcs
->mdio
, MDIO_MMD_PHYXS
, regnum
);
44 static int mv88e639x_write(struct mv88e639x_pcs
*mpcs
, u16 regnum
, u16 val
)
46 return mdiodev_c45_write(&mpcs
->mdio
, MDIO_MMD_PHYXS
, regnum
, val
);
49 static int mv88e639x_modify(struct mv88e639x_pcs
*mpcs
, u16 regnum
, u16 mask
,
52 return mdiodev_c45_modify(&mpcs
->mdio
, MDIO_MMD_PHYXS
, regnum
, mask
,
56 static int mv88e639x_modify_changed(struct mv88e639x_pcs
*mpcs
, u16 regnum
,
59 return mdiodev_c45_modify_changed(&mpcs
->mdio
, MDIO_MMD_PHYXS
, regnum
,
63 static struct mv88e639x_pcs
*
64 mv88e639x_pcs_alloc(struct device
*dev
, struct mii_bus
*bus
, unsigned int addr
,
67 struct mv88e639x_pcs
*mpcs
;
69 mpcs
= kzalloc(sizeof(*mpcs
), GFP_KERNEL
);
73 mpcs
->mdio
.dev
.parent
= dev
;
75 mpcs
->mdio
.addr
= addr
;
77 snprintf(mpcs
->name
, sizeof(mpcs
->name
),
78 "mv88e6xxx-%s-serdes-%d", dev_name(dev
), port
);
83 static irqreturn_t
mv88e639x_pcs_handle_irq(int irq
, void *dev_id
)
85 struct mv88e639x_pcs
*mpcs
= dev_id
;
86 irqreturn_t (*handler
)(struct mv88e639x_pcs
*);
88 handler
= READ_ONCE(mpcs
->handle_irq
);
95 static int mv88e639x_pcs_setup_irq(struct mv88e639x_pcs
*mpcs
,
96 struct mv88e6xxx_chip
*chip
, int port
)
100 irq
= mv88e6xxx_serdes_irq_mapping(chip
, port
);
102 /* Use polling mode */
103 mpcs
->sgmii_pcs
.poll
= true;
104 mpcs
->xg_pcs
.poll
= true;
110 return request_threaded_irq(irq
, NULL
, mv88e639x_pcs_handle_irq
,
111 IRQF_ONESHOT
, mpcs
->name
, mpcs
);
114 static void mv88e639x_pcs_teardown(struct mv88e6xxx_chip
*chip
, int port
)
116 struct mv88e639x_pcs
*mpcs
= chip
->ports
[port
].pcs_private
;
122 free_irq(mpcs
->irq
, mpcs
);
126 chip
->ports
[port
].pcs_private
= NULL
;
129 static struct mv88e639x_pcs
*sgmii_pcs_to_mv88e639x_pcs(struct phylink_pcs
*pcs
)
131 return container_of(pcs
, struct mv88e639x_pcs
, sgmii_pcs
);
134 static irqreturn_t
mv88e639x_sgmii_handle_irq(struct mv88e639x_pcs
*mpcs
)
139 err
= mv88e639x_read(mpcs
, MV88E6390_SGMII_INT_STATUS
, &int_status
);
143 if (int_status
& (MV88E6390_SGMII_INT_LINK_DOWN
|
144 MV88E6390_SGMII_INT_LINK_UP
)) {
145 phylink_pcs_change(&mpcs
->sgmii_pcs
,
146 int_status
& MV88E6390_SGMII_INT_LINK_UP
);
154 static int mv88e639x_sgmii_pcs_control_irq(struct mv88e639x_pcs
*mpcs
,
160 val
|= MV88E6390_SGMII_INT_LINK_DOWN
|
161 MV88E6390_SGMII_INT_LINK_UP
;
163 return mv88e639x_modify(mpcs
, MV88E6390_SGMII_INT_ENABLE
,
164 MV88E6390_SGMII_INT_LINK_DOWN
|
165 MV88E6390_SGMII_INT_LINK_UP
, val
);
168 static int mv88e639x_sgmii_pcs_control_pwr(struct mv88e639x_pcs
*mpcs
,
174 mask
= BMCR_RESET
| BMCR_LOOPBACK
| BMCR_PDOWN
;
177 mask
= val
= BMCR_PDOWN
;
180 return mv88e639x_modify(mpcs
, MV88E6390_SGMII_BMCR
, mask
, val
);
183 static int mv88e639x_sgmii_pcs_enable(struct phylink_pcs
*pcs
)
185 struct mv88e639x_pcs
*mpcs
= sgmii_pcs_to_mv88e639x_pcs(pcs
);
187 /* power enable done in post_config */
188 mpcs
->handle_irq
= mv88e639x_sgmii_handle_irq
;
190 return mv88e639x_sgmii_pcs_control_irq(mpcs
, !!mpcs
->irq
);
193 static void mv88e639x_sgmii_pcs_disable(struct phylink_pcs
*pcs
)
195 struct mv88e639x_pcs
*mpcs
= sgmii_pcs_to_mv88e639x_pcs(pcs
);
197 mv88e639x_sgmii_pcs_control_irq(mpcs
, false);
198 mv88e639x_sgmii_pcs_control_pwr(mpcs
, false);
201 static void mv88e639x_sgmii_pcs_pre_config(struct phylink_pcs
*pcs
,
202 phy_interface_t interface
)
204 struct mv88e639x_pcs
*mpcs
= sgmii_pcs_to_mv88e639x_pcs(pcs
);
206 mv88e639x_sgmii_pcs_control_pwr(mpcs
, false);
209 static int mv88e6390_erratum_3_14(struct mv88e639x_pcs
*mpcs
)
211 static const int lanes
[] = { MV88E6390_PORT9_LANE0
, MV88E6390_PORT9_LANE1
,
212 MV88E6390_PORT9_LANE2
, MV88E6390_PORT9_LANE3
,
213 MV88E6390_PORT10_LANE0
, MV88E6390_PORT10_LANE1
,
214 MV88E6390_PORT10_LANE2
, MV88E6390_PORT10_LANE3
};
217 /* 88e6190x and 88e6390x errata 3.14:
218 * After chip reset, SERDES reconfiguration or SERDES core
219 * Software Reset, the SERDES lanes may not be properly aligned
220 * resulting in CRC errors
223 for (i
= 0; i
< ARRAY_SIZE(lanes
); i
++) {
224 err
= mdiobus_c45_write(mpcs
->mdio
.bus
, lanes
[i
],
230 err
= mdiobus_c45_write(mpcs
->mdio
.bus
, lanes
[i
],
240 static int mv88e639x_sgmii_pcs_post_config(struct phylink_pcs
*pcs
,
241 phy_interface_t interface
)
243 struct mv88e639x_pcs
*mpcs
= sgmii_pcs_to_mv88e639x_pcs(pcs
);
246 mv88e639x_sgmii_pcs_control_pwr(mpcs
, true);
248 if (mpcs
->erratum_3_14
) {
249 err
= mv88e6390_erratum_3_14(mpcs
);
251 dev_err(mpcs
->mdio
.dev
.parent
,
252 "failed to apply erratum 3.14: %pe\n",
259 static void mv88e639x_sgmii_pcs_get_state(struct phylink_pcs
*pcs
,
260 struct phylink_link_state
*state
)
262 struct mv88e639x_pcs
*mpcs
= sgmii_pcs_to_mv88e639x_pcs(pcs
);
263 u16 bmsr
, lpa
, status
;
266 err
= mv88e639x_read(mpcs
, MV88E6390_SGMII_BMSR
, &bmsr
);
268 dev_err(mpcs
->mdio
.dev
.parent
,
269 "can't read Serdes PHY %s: %pe\n",
270 "BMSR", ERR_PTR(err
));
275 err
= mv88e639x_read(mpcs
, MV88E6390_SGMII_LPA
, &lpa
);
277 dev_err(mpcs
->mdio
.dev
.parent
,
278 "can't read Serdes PHY %s: %pe\n",
279 "LPA", ERR_PTR(err
));
284 err
= mv88e639x_read(mpcs
, MV88E6390_SGMII_PHY_STATUS
, &status
);
286 dev_err(mpcs
->mdio
.dev
.parent
,
287 "can't read Serdes PHY %s: %pe\n",
288 "status", ERR_PTR(err
));
293 mv88e6xxx_pcs_decode_state(mpcs
->mdio
.dev
.parent
, bmsr
, lpa
, status
,
297 static int mv88e639x_sgmii_pcs_config(struct phylink_pcs
*pcs
,
298 unsigned int neg_mode
,
299 phy_interface_t interface
,
300 const unsigned long *advertising
,
301 bool permit_pause_to_mac
)
303 struct mv88e639x_pcs
*mpcs
= sgmii_pcs_to_mv88e639x_pcs(pcs
);
308 adv
= phylink_mii_c22_pcs_encode_advertisement(interface
, advertising
);
312 mpcs
->interface
= interface
;
314 err
= mv88e639x_modify_changed(mpcs
, MV88E6390_SGMII_ADVERTISE
,
321 err
= mv88e639x_read(mpcs
, MV88E6390_SGMII_BMCR
, &val
);
325 if (neg_mode
== PHYLINK_PCS_NEG_INBAND_ENABLED
)
326 bmcr
= val
| BMCR_ANENABLE
;
328 bmcr
= val
& ~BMCR_ANENABLE
;
330 /* setting ANENABLE triggers a restart of negotiation */
334 return mv88e639x_write(mpcs
, MV88E6390_SGMII_BMCR
, bmcr
);
337 static void mv88e639x_sgmii_pcs_an_restart(struct phylink_pcs
*pcs
)
339 struct mv88e639x_pcs
*mpcs
= sgmii_pcs_to_mv88e639x_pcs(pcs
);
341 mv88e639x_modify(mpcs
, MV88E6390_SGMII_BMCR
,
342 BMCR_ANRESTART
, BMCR_ANRESTART
);
345 static void mv88e639x_sgmii_pcs_link_up(struct phylink_pcs
*pcs
,
347 phy_interface_t interface
,
348 int speed
, int duplex
)
350 struct mv88e639x_pcs
*mpcs
= sgmii_pcs_to_mv88e639x_pcs(pcs
);
354 if (phylink_autoneg_inband(mode
))
357 bmcr
= mii_bmcr_encode_fixed(speed
, duplex
);
359 err
= mv88e639x_modify(mpcs
, MV88E6390_SGMII_BMCR
,
360 BMCR_SPEED1000
| BMCR_SPEED100
| BMCR_FULLDPLX
,
363 dev_err(mpcs
->mdio
.dev
.parent
,
364 "can't access Serdes PHY %s: %pe\n",
365 "BMCR", ERR_PTR(err
));
368 static const struct phylink_pcs_ops mv88e639x_sgmii_pcs_ops
= {
369 .pcs_enable
= mv88e639x_sgmii_pcs_enable
,
370 .pcs_disable
= mv88e639x_sgmii_pcs_disable
,
371 .pcs_pre_config
= mv88e639x_sgmii_pcs_pre_config
,
372 .pcs_post_config
= mv88e639x_sgmii_pcs_post_config
,
373 .pcs_get_state
= mv88e639x_sgmii_pcs_get_state
,
374 .pcs_an_restart
= mv88e639x_sgmii_pcs_an_restart
,
375 .pcs_config
= mv88e639x_sgmii_pcs_config
,
376 .pcs_link_up
= mv88e639x_sgmii_pcs_link_up
,
379 static struct mv88e639x_pcs
*xg_pcs_to_mv88e639x_pcs(struct phylink_pcs
*pcs
)
381 return container_of(pcs
, struct mv88e639x_pcs
, xg_pcs
);
384 static int mv88e639x_xg_pcs_enable(struct mv88e639x_pcs
*mpcs
)
386 return mv88e639x_modify(mpcs
, MV88E6390_10G_CTRL1
,
387 MDIO_CTRL1_RESET
| MDIO_PCS_CTRL1_LOOPBACK
|
388 MDIO_CTRL1_LPOWER
, 0);
391 static void mv88e639x_xg_pcs_disable(struct mv88e639x_pcs
*mpcs
)
393 mv88e639x_modify(mpcs
, MV88E6390_10G_CTRL1
, MDIO_CTRL1_LPOWER
,
397 static void mv88e639x_xg_pcs_get_state(struct phylink_pcs
*pcs
,
398 struct phylink_link_state
*state
)
400 struct mv88e639x_pcs
*mpcs
= xg_pcs_to_mv88e639x_pcs(pcs
);
406 err
= mv88e639x_read(mpcs
, MV88E6390_10G_STAT1
, &status
);
408 dev_err(mpcs
->mdio
.dev
.parent
,
409 "can't read Serdes PHY %s: %pe\n",
410 "STAT1", ERR_PTR(err
));
414 state
->link
= !!(status
& MDIO_STAT1_LSTATUS
);
416 switch (state
->interface
) {
417 case PHY_INTERFACE_MODE_5GBASER
:
418 state
->speed
= SPEED_5000
;
421 case PHY_INTERFACE_MODE_10GBASER
:
422 case PHY_INTERFACE_MODE_RXAUI
:
423 case PHY_INTERFACE_MODE_XAUI
:
424 state
->speed
= SPEED_10000
;
432 state
->duplex
= DUPLEX_FULL
;
436 static int mv88e639x_xg_pcs_config(struct phylink_pcs
*pcs
,
437 unsigned int neg_mode
,
438 phy_interface_t interface
,
439 const unsigned long *advertising
,
440 bool permit_pause_to_mac
)
445 static struct phylink_pcs
*
446 mv88e639x_pcs_select(struct mv88e6xxx_chip
*chip
, int port
,
447 phy_interface_t mode
)
449 struct mv88e639x_pcs
*mpcs
;
451 mpcs
= chip
->ports
[port
].pcs_private
;
456 case PHY_INTERFACE_MODE_SGMII
:
457 case PHY_INTERFACE_MODE_1000BASEX
:
458 case PHY_INTERFACE_MODE_2500BASEX
:
459 return &mpcs
->sgmii_pcs
;
461 case PHY_INTERFACE_MODE_5GBASER
:
462 if (!mpcs
->supports_5g
)
465 case PHY_INTERFACE_MODE_10GBASER
:
466 case PHY_INTERFACE_MODE_XAUI
:
467 case PHY_INTERFACE_MODE_RXAUI
:
468 case PHY_INTERFACE_MODE_USXGMII
:
469 return &mpcs
->xg_pcs
;
476 /* Marvell 88E6390 Specific support */
478 static irqreturn_t
mv88e6390_xg_handle_irq(struct mv88e639x_pcs
*mpcs
)
483 err
= mv88e639x_read(mpcs
, MV88E6390_10G_INT_STATUS
, &int_status
);
487 if (int_status
& (MV88E6390_10G_INT_LINK_DOWN
|
488 MV88E6390_10G_INT_LINK_UP
)) {
489 phylink_pcs_change(&mpcs
->xg_pcs
,
490 int_status
& MV88E6390_10G_INT_LINK_UP
);
498 static int mv88e6390_xg_control_irq(struct mv88e639x_pcs
*mpcs
, bool enable
)
503 val
= MV88E6390_10G_INT_LINK_DOWN
| MV88E6390_10G_INT_LINK_UP
;
505 return mv88e639x_modify(mpcs
, MV88E6390_10G_INT_ENABLE
,
506 MV88E6390_10G_INT_LINK_DOWN
|
507 MV88E6390_10G_INT_LINK_UP
, val
);
510 static int mv88e6390_xg_pcs_enable(struct phylink_pcs
*pcs
)
512 struct mv88e639x_pcs
*mpcs
= xg_pcs_to_mv88e639x_pcs(pcs
);
515 err
= mv88e639x_xg_pcs_enable(mpcs
);
519 mpcs
->handle_irq
= mv88e6390_xg_handle_irq
;
521 return mv88e6390_xg_control_irq(mpcs
, !!mpcs
->irq
);
524 static void mv88e6390_xg_pcs_disable(struct phylink_pcs
*pcs
)
526 struct mv88e639x_pcs
*mpcs
= xg_pcs_to_mv88e639x_pcs(pcs
);
528 mv88e6390_xg_control_irq(mpcs
, false);
529 mv88e639x_xg_pcs_disable(mpcs
);
532 static const struct phylink_pcs_ops mv88e6390_xg_pcs_ops
= {
533 .pcs_enable
= mv88e6390_xg_pcs_enable
,
534 .pcs_disable
= mv88e6390_xg_pcs_disable
,
535 .pcs_get_state
= mv88e639x_xg_pcs_get_state
,
536 .pcs_config
= mv88e639x_xg_pcs_config
,
539 static int mv88e6390_pcs_enable_checker(struct mv88e639x_pcs
*mpcs
)
541 return mv88e639x_modify(mpcs
, MV88E6390_PG_CONTROL
,
542 MV88E6390_PG_CONTROL_ENABLE_PC
,
543 MV88E6390_PG_CONTROL_ENABLE_PC
);
546 static int mv88e6390_pcs_init(struct mv88e6xxx_chip
*chip
, int port
)
548 struct mv88e639x_pcs
*mpcs
;
553 lane
= mv88e6xxx_serdes_get_lane(chip
, port
);
557 bus
= mv88e6xxx_default_mdio_bus(chip
);
560 mpcs
= mv88e639x_pcs_alloc(dev
, bus
, lane
, port
);
564 mpcs
->sgmii_pcs
.ops
= &mv88e639x_sgmii_pcs_ops
;
565 mpcs
->sgmii_pcs
.neg_mode
= true;
566 mpcs
->xg_pcs
.ops
= &mv88e6390_xg_pcs_ops
;
567 mpcs
->xg_pcs
.neg_mode
= true;
569 if (chip
->info
->prod_num
== MV88E6XXX_PORT_SWITCH_ID_PROD_6190X
||
570 chip
->info
->prod_num
== MV88E6XXX_PORT_SWITCH_ID_PROD_6390X
)
571 mpcs
->erratum_3_14
= true;
573 err
= mv88e639x_pcs_setup_irq(mpcs
, chip
, port
);
577 /* 6390 and 6390x has the checker, 6393x doesn't appear to? */
578 /* This is to enable gathering the statistics. Maybe this
579 * should call out to a helper? Or we could do this at init time.
581 err
= mv88e6390_pcs_enable_checker(mpcs
);
585 chip
->ports
[port
].pcs_private
= mpcs
;
594 const struct mv88e6xxx_pcs_ops mv88e6390_pcs_ops
= {
595 .pcs_init
= mv88e6390_pcs_init
,
596 .pcs_teardown
= mv88e639x_pcs_teardown
,
597 .pcs_select
= mv88e639x_pcs_select
,
600 /* Marvell 88E6393X Specific support */
602 static int mv88e6393x_power_lane(struct mv88e639x_pcs
*mpcs
, bool enable
)
604 u16 val
= MV88E6393X_SERDES_CTRL1_TX_PDOWN
|
605 MV88E6393X_SERDES_CTRL1_RX_PDOWN
;
607 return mv88e639x_modify(mpcs
, MV88E6393X_SERDES_CTRL1
, val
,
611 /* mv88e6393x family errata 4.6:
612 * Cannot clear PwrDn bit on SERDES if device is configured CPU_MGD mode or
613 * P0_mode is configured for [x]MII.
614 * Workaround: Set SERDES register 4.F002 bit 5=0 and bit 15=1.
616 * It seems that after this workaround the SERDES is automatically powered up
617 * (the bit is cleared), so power it down.
619 static int mv88e6393x_erratum_4_6(struct mv88e639x_pcs
*mpcs
)
623 err
= mv88e639x_modify(mpcs
, MV88E6393X_SERDES_POC
,
624 MV88E6393X_SERDES_POC_PDOWN
|
625 MV88E6393X_SERDES_POC_RESET
,
626 MV88E6393X_SERDES_POC_RESET
);
630 err
= mv88e639x_modify(mpcs
, MV88E6390_SGMII_BMCR
,
631 BMCR_PDOWN
, BMCR_PDOWN
);
635 err
= mv88e639x_sgmii_pcs_control_pwr(mpcs
, false);
639 return mv88e6393x_power_lane(mpcs
, false);
642 /* mv88e6393x family errata 4.8:
643 * When a SERDES port is operating in 1000BASE-X or SGMII mode link may not
644 * come up after hardware reset or software reset of SERDES core. Workaround
645 * is to write SERDES register 4.F074.14=1 for only those modes and 0 in all
648 static int mv88e6393x_erratum_4_8(struct mv88e639x_pcs
*mpcs
)
653 err
= mv88e639x_read(mpcs
, MV88E6393X_SERDES_POC
, &poc
);
657 poc
&= MV88E6393X_SERDES_POC_PCS_MASK
;
658 if (poc
== MV88E6393X_SERDES_POC_PCS_1000BASEX
||
659 poc
== MV88E6393X_SERDES_POC_PCS_SGMII_PHY
||
660 poc
== MV88E6393X_SERDES_POC_PCS_SGMII_MAC
)
661 reg
= MV88E6393X_ERRATA_4_8_BIT
;
665 return mv88e639x_modify(mpcs
, MV88E6393X_ERRATA_4_8_REG
,
666 MV88E6393X_ERRATA_4_8_BIT
, reg
);
669 /* mv88e6393x family errata 5.2:
670 * For optimal signal integrity the following sequence should be applied to
671 * SERDES operating in 10G mode. These registers only apply to 10G operation
672 * and have no effect on other speeds.
674 static int mv88e6393x_erratum_5_2(struct mv88e639x_pcs
*mpcs
)
676 static const struct {
677 u16 dev
, reg
, val
, mask
;
679 { MDIO_MMD_VEND1
, 0x8093, 0xcb5a, 0xffff },
680 { MDIO_MMD_VEND1
, 0x8171, 0x7088, 0xffff },
681 { MDIO_MMD_VEND1
, 0x80c9, 0x311a, 0xffff },
682 { MDIO_MMD_VEND1
, 0x80a2, 0x8000, 0xff7f },
683 { MDIO_MMD_VEND1
, 0x80a9, 0x0000, 0xfff0 },
684 { MDIO_MMD_VEND1
, 0x80a3, 0x0000, 0xf8ff },
685 { MDIO_MMD_PHYXS
, MV88E6393X_SERDES_POC
,
686 MV88E6393X_SERDES_POC_RESET
, MV88E6393X_SERDES_POC_RESET
},
690 for (i
= 0; i
< ARRAY_SIZE(fixes
); ++i
) {
691 err
= mdiodev_c45_modify(&mpcs
->mdio
, fixes
[i
].dev
,
692 fixes
[i
].reg
, fixes
[i
].mask
,
701 /* Inband AN is broken on Amethyst in 2500base-x mode when set by standard
702 * mechanism (via cmode).
703 * We can get around this by configuring the PCS mode to 1000base-x and then
704 * writing value 0x58 to register 1e.8000. (This must be done while SerDes
705 * receiver and transmitter are disabled, which is, when this function is
707 * It seem that when we do this configuration to 2500base-x mode (by changing
708 * PCS mode to 1000base-x and frequency to 3.125 GHz from 1.25 GHz) and then
709 * configure to sgmii or 1000base-x, the device thinks that it already has
710 * SerDes at 1.25 GHz and does not change the 1e.8000 register, leaving SerDes
712 * To avoid this, change PCS mode back to 2500base-x when disabling SerDes from
715 static int mv88e6393x_fix_2500basex_an(struct mv88e639x_pcs
*mpcs
, bool on
)
721 reg
= MV88E6393X_SERDES_POC_PCS_1000BASEX
|
722 MV88E6393X_SERDES_POC_AN
;
724 reg
= MV88E6393X_SERDES_POC_PCS_2500BASEX
;
726 reg
|= MV88E6393X_SERDES_POC_RESET
;
728 err
= mv88e639x_modify(mpcs
, MV88E6393X_SERDES_POC
,
729 MV88E6393X_SERDES_POC_PCS_MASK
|
730 MV88E6393X_SERDES_POC_AN
|
731 MV88E6393X_SERDES_POC_RESET
, reg
);
735 return mdiodev_c45_write(&mpcs
->mdio
, MDIO_MMD_VEND1
, 0x8000, 0x58);
738 static int mv88e6393x_sgmii_apply_2500basex_an(struct mv88e639x_pcs
*mpcs
,
739 phy_interface_t interface
,
744 if (interface
!= PHY_INTERFACE_MODE_2500BASEX
)
747 err
= mv88e6393x_fix_2500basex_an(mpcs
, enable
);
749 dev_err(mpcs
->mdio
.dev
.parent
,
750 "failed to %s 2500basex fix: %pe\n",
751 enable
? "enable" : "disable", ERR_PTR(err
));
756 static void mv88e6393x_sgmii_pcs_disable(struct phylink_pcs
*pcs
)
758 struct mv88e639x_pcs
*mpcs
= sgmii_pcs_to_mv88e639x_pcs(pcs
);
760 mv88e639x_sgmii_pcs_disable(pcs
);
761 mv88e6393x_power_lane(mpcs
, false);
762 mv88e6393x_sgmii_apply_2500basex_an(mpcs
, mpcs
->interface
, false);
765 static void mv88e6393x_sgmii_pcs_pre_config(struct phylink_pcs
*pcs
,
766 phy_interface_t interface
)
768 struct mv88e639x_pcs
*mpcs
= sgmii_pcs_to_mv88e639x_pcs(pcs
);
770 mv88e639x_sgmii_pcs_pre_config(pcs
, interface
);
771 mv88e6393x_power_lane(mpcs
, false);
772 mv88e6393x_sgmii_apply_2500basex_an(mpcs
, mpcs
->interface
, false);
775 static int mv88e6393x_sgmii_pcs_post_config(struct phylink_pcs
*pcs
,
776 phy_interface_t interface
)
778 struct mv88e639x_pcs
*mpcs
= sgmii_pcs_to_mv88e639x_pcs(pcs
);
781 err
= mv88e6393x_erratum_4_8(mpcs
);
785 err
= mv88e6393x_sgmii_apply_2500basex_an(mpcs
, interface
, true);
789 err
= mv88e6393x_power_lane(mpcs
, true);
793 return mv88e639x_sgmii_pcs_post_config(pcs
, interface
);
796 static const struct phylink_pcs_ops mv88e6393x_sgmii_pcs_ops
= {
797 .pcs_enable
= mv88e639x_sgmii_pcs_enable
,
798 .pcs_disable
= mv88e6393x_sgmii_pcs_disable
,
799 .pcs_pre_config
= mv88e6393x_sgmii_pcs_pre_config
,
800 .pcs_post_config
= mv88e6393x_sgmii_pcs_post_config
,
801 .pcs_get_state
= mv88e639x_sgmii_pcs_get_state
,
802 .pcs_an_restart
= mv88e639x_sgmii_pcs_an_restart
,
803 .pcs_config
= mv88e639x_sgmii_pcs_config
,
804 .pcs_link_up
= mv88e639x_sgmii_pcs_link_up
,
807 static irqreturn_t
mv88e6393x_xg_handle_irq(struct mv88e639x_pcs
*mpcs
)
809 u16 int_status
, stat1
;
813 err
= mv88e639x_read(mpcs
, MV88E6393X_10G_INT_STATUS
, &int_status
);
817 if (int_status
& MV88E6393X_10G_INT_LINK_CHANGE
) {
818 err
= mv88e639x_read(mpcs
, MV88E6390_10G_STAT1
, &stat1
);
822 link_down
= !(stat1
& MDIO_STAT1_LSTATUS
);
824 phylink_pcs_change(&mpcs
->xg_pcs
, !link_down
);
832 static int mv88e6393x_xg_control_irq(struct mv88e639x_pcs
*mpcs
, bool enable
)
837 val
= MV88E6393X_10G_INT_LINK_CHANGE
;
839 return mv88e639x_modify(mpcs
, MV88E6393X_10G_INT_ENABLE
,
840 MV88E6393X_10G_INT_LINK_CHANGE
, val
);
843 static int mv88e6393x_xg_pcs_enable(struct phylink_pcs
*pcs
)
845 struct mv88e639x_pcs
*mpcs
= xg_pcs_to_mv88e639x_pcs(pcs
);
847 mpcs
->handle_irq
= mv88e6393x_xg_handle_irq
;
849 return mv88e6393x_xg_control_irq(mpcs
, !!mpcs
->irq
);
852 static void mv88e6393x_xg_pcs_disable(struct phylink_pcs
*pcs
)
854 struct mv88e639x_pcs
*mpcs
= xg_pcs_to_mv88e639x_pcs(pcs
);
856 mv88e6393x_xg_control_irq(mpcs
, false);
857 mv88e639x_xg_pcs_disable(mpcs
);
858 mv88e6393x_power_lane(mpcs
, false);
861 /* The PCS has to be powered down while CMODE is changed */
862 static void mv88e6393x_xg_pcs_pre_config(struct phylink_pcs
*pcs
,
863 phy_interface_t interface
)
865 struct mv88e639x_pcs
*mpcs
= xg_pcs_to_mv88e639x_pcs(pcs
);
867 mv88e639x_xg_pcs_disable(mpcs
);
868 mv88e6393x_power_lane(mpcs
, false);
871 static int mv88e6393x_xg_pcs_post_config(struct phylink_pcs
*pcs
,
872 phy_interface_t interface
)
874 struct mv88e639x_pcs
*mpcs
= xg_pcs_to_mv88e639x_pcs(pcs
);
877 if (interface
== PHY_INTERFACE_MODE_10GBASER
||
878 interface
== PHY_INTERFACE_MODE_USXGMII
) {
879 err
= mv88e6393x_erratum_5_2(mpcs
);
884 err
= mv88e6393x_power_lane(mpcs
, true);
888 return mv88e639x_xg_pcs_enable(mpcs
);
891 static void mv88e6393x_xg_pcs_get_state(struct phylink_pcs
*pcs
,
892 struct phylink_link_state
*state
)
894 struct mv88e639x_pcs
*mpcs
= xg_pcs_to_mv88e639x_pcs(pcs
);
895 u16 status
, lp_status
;
898 if (state
->interface
!= PHY_INTERFACE_MODE_USXGMII
)
899 return mv88e639x_xg_pcs_get_state(pcs
, state
);
903 err
= mv88e639x_read(mpcs
, MV88E6390_USXGMII_PHY_STATUS
, &status
);
904 err
= err
? : mv88e639x_read(mpcs
, MV88E6390_USXGMII_LP_STATUS
, &lp_status
);
906 dev_err(mpcs
->mdio
.dev
.parent
,
907 "can't read USXGMII status: %pe\n", ERR_PTR(err
));
911 state
->link
= !!(status
& MDIO_USXGMII_LINK
);
912 state
->an_complete
= state
->link
;
913 phylink_decode_usxgmii_word(state
, lp_status
);
916 static const struct phylink_pcs_ops mv88e6393x_xg_pcs_ops
= {
917 .pcs_enable
= mv88e6393x_xg_pcs_enable
,
918 .pcs_disable
= mv88e6393x_xg_pcs_disable
,
919 .pcs_pre_config
= mv88e6393x_xg_pcs_pre_config
,
920 .pcs_post_config
= mv88e6393x_xg_pcs_post_config
,
921 .pcs_get_state
= mv88e6393x_xg_pcs_get_state
,
922 .pcs_config
= mv88e639x_xg_pcs_config
,
925 static int mv88e6393x_pcs_init(struct mv88e6xxx_chip
*chip
, int port
)
927 struct mv88e639x_pcs
*mpcs
;
932 lane
= mv88e6xxx_serdes_get_lane(chip
, port
);
936 bus
= mv88e6xxx_default_mdio_bus(chip
);
939 mpcs
= mv88e639x_pcs_alloc(dev
, bus
, lane
, port
);
943 mpcs
->sgmii_pcs
.ops
= &mv88e6393x_sgmii_pcs_ops
;
944 mpcs
->sgmii_pcs
.neg_mode
= true;
945 mpcs
->xg_pcs
.ops
= &mv88e6393x_xg_pcs_ops
;
946 mpcs
->xg_pcs
.neg_mode
= true;
947 mpcs
->supports_5g
= true;
949 err
= mv88e6393x_erratum_4_6(mpcs
);
953 err
= mv88e639x_pcs_setup_irq(mpcs
, chip
, port
);
957 chip
->ports
[port
].pcs_private
= mpcs
;
966 const struct mv88e6xxx_pcs_ops mv88e6393x_pcs_ops
= {
967 .pcs_init
= mv88e6393x_pcs_init
,
968 .pcs_teardown
= mv88e639x_pcs_teardown
,
969 .pcs_select
= mv88e639x_pcs_select
,