1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Marvell 88E6xxx SERDES manipulation, via SMI bus
5 * Copyright (c) 2008 Marvell Semiconductor
7 * Copyright (c) 2017 Andrew Lunn <andrew@lunn.ch>
10 #include <linux/interrupt.h>
11 #include <linux/irqdomain.h>
12 #include <linux/mii.h>
20 static int mv88e6352_serdes_read(struct mv88e6xxx_chip
*chip
, int reg
,
23 return mv88e6xxx_phy_page_read(chip
, MV88E6352_ADDR_SERDES
,
24 MV88E6352_SERDES_PAGE_FIBER
,
28 static int mv88e6352_serdes_write(struct mv88e6xxx_chip
*chip
, int reg
,
31 return mv88e6xxx_phy_page_write(chip
, MV88E6352_ADDR_SERDES
,
32 MV88E6352_SERDES_PAGE_FIBER
,
36 static int mv88e6390_serdes_read(struct mv88e6xxx_chip
*chip
,
37 int lane
, int device
, int reg
, u16
*val
)
39 return mv88e6xxx_phy_read_c45(chip
, lane
, device
, reg
, val
);
42 int mv88e6xxx_pcs_decode_state(struct device
*dev
, u16 bmsr
, u16 lpa
,
43 u16 status
, struct phylink_link_state
*state
)
47 /* If the BMSR reports that the link had failed, report this to
50 if (!(bmsr
& BMSR_LSTATUS
))
53 state
->link
= !!(status
& MV88E6390_SGMII_PHY_STATUS_LINK
);
54 state
->an_complete
= !!(bmsr
& BMSR_ANEGCOMPLETE
);
56 if (status
& MV88E6390_SGMII_PHY_STATUS_SPD_DPL_VALID
) {
57 /* The Spped and Duplex Resolved register is 1 if AN is enabled
58 * and complete, or if AN is disabled. So with disabled AN we
59 * still get here on link up.
61 state
->duplex
= status
&
62 MV88E6390_SGMII_PHY_STATUS_DUPLEX_FULL
?
63 DUPLEX_FULL
: DUPLEX_HALF
;
65 if (status
& MV88E6390_SGMII_PHY_STATUS_TX_PAUSE
)
66 state
->pause
|= MLO_PAUSE_TX
;
67 if (status
& MV88E6390_SGMII_PHY_STATUS_RX_PAUSE
)
68 state
->pause
|= MLO_PAUSE_RX
;
70 switch (status
& MV88E6390_SGMII_PHY_STATUS_SPEED_MASK
) {
71 case MV88E6390_SGMII_PHY_STATUS_SPEED_1000
:
72 if (state
->interface
== PHY_INTERFACE_MODE_2500BASEX
)
73 state
->speed
= SPEED_2500
;
75 state
->speed
= SPEED_1000
;
77 case MV88E6390_SGMII_PHY_STATUS_SPEED_100
:
78 state
->speed
= SPEED_100
;
80 case MV88E6390_SGMII_PHY_STATUS_SPEED_10
:
81 state
->speed
= SPEED_10
;
84 dev_err(dev
, "invalid PHY speed\n");
87 } else if (state
->link
&&
88 state
->interface
!= PHY_INTERFACE_MODE_SGMII
) {
89 /* If Speed and Duplex Resolved register is 0 and link is up, it
90 * means that AN was enabled, but link partner had it disabled
91 * and the PHY invoked the Auto-Negotiation Bypass feature and
94 state
->duplex
= DUPLEX_FULL
;
95 if (state
->interface
== PHY_INTERFACE_MODE_2500BASEX
)
96 state
->speed
= SPEED_2500
;
98 state
->speed
= SPEED_1000
;
103 if (state
->interface
== PHY_INTERFACE_MODE_2500BASEX
)
104 mii_lpa_mod_linkmode_x(state
->lp_advertising
, lpa
,
105 ETHTOOL_LINK_MODE_2500baseX_Full_BIT
);
106 else if (state
->interface
== PHY_INTERFACE_MODE_1000BASEX
)
107 mii_lpa_mod_linkmode_x(state
->lp_advertising
, lpa
,
108 ETHTOOL_LINK_MODE_1000baseX_Full_BIT
);
113 struct mv88e6352_serdes_hw_stat
{
114 char string
[ETH_GSTRING_LEN
];
119 static struct mv88e6352_serdes_hw_stat mv88e6352_serdes_hw_stats
[] = {
120 { "serdes_fibre_rx_error", 16, 21 },
121 { "serdes_PRBS_error", 32, 24 },
124 int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip
*chip
, int port
)
128 err
= mv88e6352_g2_scratch_port_has_serdes(chip
, port
);
132 return ARRAY_SIZE(mv88e6352_serdes_hw_stats
);
135 int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip
*chip
, int port
,
138 struct mv88e6352_serdes_hw_stat
*stat
;
141 err
= mv88e6352_g2_scratch_port_has_serdes(chip
, port
);
145 for (i
= 0; i
< ARRAY_SIZE(mv88e6352_serdes_hw_stats
); i
++) {
146 stat
= &mv88e6352_serdes_hw_stats
[i
];
147 ethtool_puts(data
, stat
->string
);
149 return ARRAY_SIZE(mv88e6352_serdes_hw_stats
);
152 static uint64_t mv88e6352_serdes_get_stat(struct mv88e6xxx_chip
*chip
,
153 struct mv88e6352_serdes_hw_stat
*stat
)
159 err
= mv88e6352_serdes_read(chip
, stat
->reg
, ®
);
161 dev_err(chip
->dev
, "failed to read statistic\n");
167 if (stat
->sizeof_stat
== 32) {
168 err
= mv88e6352_serdes_read(chip
, stat
->reg
+ 1, ®
);
170 dev_err(chip
->dev
, "failed to read statistic\n");
173 val
= val
<< 16 | reg
;
179 size_t mv88e6352_serdes_get_stats(struct mv88e6xxx_chip
*chip
, int port
,
182 struct mv88e6xxx_port
*mv88e6xxx_port
= &chip
->ports
[port
];
183 struct mv88e6352_serdes_hw_stat
*stat
;
187 err
= mv88e6352_g2_scratch_port_has_serdes(chip
, port
);
191 BUILD_BUG_ON(ARRAY_SIZE(mv88e6352_serdes_hw_stats
) >
192 ARRAY_SIZE(mv88e6xxx_port
->serdes_stats
));
194 for (i
= 0; i
< ARRAY_SIZE(mv88e6352_serdes_hw_stats
); i
++) {
195 stat
= &mv88e6352_serdes_hw_stats
[i
];
196 value
= mv88e6352_serdes_get_stat(chip
, stat
);
197 mv88e6xxx_port
->serdes_stats
[i
] += value
;
198 data
[i
] = mv88e6xxx_port
->serdes_stats
[i
];
201 return ARRAY_SIZE(mv88e6352_serdes_hw_stats
);
204 unsigned int mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip
*chip
, int port
)
206 return irq_find_mapping(chip
->g2_irq
.domain
, MV88E6352_SERDES_IRQ
);
209 int mv88e6352_serdes_get_regs_len(struct mv88e6xxx_chip
*chip
, int port
)
213 mv88e6xxx_reg_lock(chip
);
214 err
= mv88e6352_g2_scratch_port_has_serdes(chip
, port
);
215 mv88e6xxx_reg_unlock(chip
);
219 return 32 * sizeof(u16
);
222 void mv88e6352_serdes_get_regs(struct mv88e6xxx_chip
*chip
, int port
, void *_p
)
229 err
= mv88e6352_g2_scratch_port_has_serdes(chip
, port
);
233 for (i
= 0 ; i
< 32; i
++) {
234 err
= mv88e6352_serdes_read(chip
, i
, ®
);
240 int mv88e6341_serdes_get_lane(struct mv88e6xxx_chip
*chip
, int port
)
242 u8 cmode
= chip
->ports
[port
].cmode
;
247 if (cmode
== MV88E6XXX_PORT_STS_CMODE_1000BASEX
||
248 cmode
== MV88E6XXX_PORT_STS_CMODE_SGMII
||
249 cmode
== MV88E6XXX_PORT_STS_CMODE_2500BASEX
)
250 lane
= MV88E6341_PORT5_LANE
;
257 int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip
*chip
, int port
)
259 u8 cmode
= chip
->ports
[port
].cmode
;
264 if (cmode
== MV88E6XXX_PORT_STS_CMODE_1000BASEX
||
265 cmode
== MV88E6XXX_PORT_STS_CMODE_SGMII
||
266 cmode
== MV88E6XXX_PORT_STS_CMODE_2500BASEX
)
267 lane
= MV88E6390_PORT9_LANE0
;
270 if (cmode
== MV88E6XXX_PORT_STS_CMODE_1000BASEX
||
271 cmode
== MV88E6XXX_PORT_STS_CMODE_SGMII
||
272 cmode
== MV88E6XXX_PORT_STS_CMODE_2500BASEX
)
273 lane
= MV88E6390_PORT10_LANE0
;
280 int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip
*chip
, int port
)
282 u8 cmode_port
= chip
->ports
[port
].cmode
;
283 u8 cmode_port10
= chip
->ports
[10].cmode
;
284 u8 cmode_port9
= chip
->ports
[9].cmode
;
289 if (cmode_port9
== MV88E6XXX_PORT_STS_CMODE_1000BASEX
||
290 cmode_port9
== MV88E6XXX_PORT_STS_CMODE_SGMII
||
291 cmode_port9
== MV88E6XXX_PORT_STS_CMODE_2500BASEX
)
292 if (cmode_port
== MV88E6XXX_PORT_STS_CMODE_1000BASEX
)
293 lane
= MV88E6390_PORT9_LANE1
;
296 if (cmode_port9
== MV88E6XXX_PORT_STS_CMODE_1000BASEX
||
297 cmode_port9
== MV88E6XXX_PORT_STS_CMODE_SGMII
||
298 cmode_port9
== MV88E6XXX_PORT_STS_CMODE_2500BASEX
||
299 cmode_port9
== MV88E6XXX_PORT_STS_CMODE_RXAUI
)
300 if (cmode_port
== MV88E6XXX_PORT_STS_CMODE_1000BASEX
)
301 lane
= MV88E6390_PORT9_LANE2
;
304 if (cmode_port9
== MV88E6XXX_PORT_STS_CMODE_1000BASEX
||
305 cmode_port9
== MV88E6XXX_PORT_STS_CMODE_SGMII
||
306 cmode_port9
== MV88E6XXX_PORT_STS_CMODE_2500BASEX
||
307 cmode_port9
== MV88E6XXX_PORT_STS_CMODE_RXAUI
)
308 if (cmode_port
== MV88E6XXX_PORT_STS_CMODE_1000BASEX
)
309 lane
= MV88E6390_PORT9_LANE3
;
312 if (cmode_port10
== MV88E6XXX_PORT_STS_CMODE_1000BASEX
||
313 cmode_port10
== MV88E6XXX_PORT_STS_CMODE_SGMII
||
314 cmode_port10
== MV88E6XXX_PORT_STS_CMODE_2500BASEX
)
315 if (cmode_port
== MV88E6XXX_PORT_STS_CMODE_1000BASEX
)
316 lane
= MV88E6390_PORT10_LANE1
;
319 if (cmode_port10
== MV88E6XXX_PORT_STS_CMODE_1000BASEX
||
320 cmode_port10
== MV88E6XXX_PORT_STS_CMODE_SGMII
||
321 cmode_port10
== MV88E6XXX_PORT_STS_CMODE_2500BASEX
||
322 cmode_port10
== MV88E6XXX_PORT_STS_CMODE_RXAUI
)
323 if (cmode_port
== MV88E6XXX_PORT_STS_CMODE_1000BASEX
)
324 lane
= MV88E6390_PORT10_LANE2
;
327 if (cmode_port10
== MV88E6XXX_PORT_STS_CMODE_1000BASEX
||
328 cmode_port10
== MV88E6XXX_PORT_STS_CMODE_SGMII
||
329 cmode_port10
== MV88E6XXX_PORT_STS_CMODE_2500BASEX
||
330 cmode_port10
== MV88E6XXX_PORT_STS_CMODE_RXAUI
)
331 if (cmode_port
== MV88E6XXX_PORT_STS_CMODE_1000BASEX
)
332 lane
= MV88E6390_PORT10_LANE3
;
335 if (cmode_port9
== MV88E6XXX_PORT_STS_CMODE_1000BASEX
||
336 cmode_port9
== MV88E6XXX_PORT_STS_CMODE_SGMII
||
337 cmode_port9
== MV88E6XXX_PORT_STS_CMODE_2500BASEX
||
338 cmode_port9
== MV88E6XXX_PORT_STS_CMODE_XAUI
||
339 cmode_port9
== MV88E6XXX_PORT_STS_CMODE_RXAUI
)
340 lane
= MV88E6390_PORT9_LANE0
;
343 if (cmode_port10
== MV88E6XXX_PORT_STS_CMODE_1000BASEX
||
344 cmode_port10
== MV88E6XXX_PORT_STS_CMODE_SGMII
||
345 cmode_port10
== MV88E6XXX_PORT_STS_CMODE_2500BASEX
||
346 cmode_port10
== MV88E6XXX_PORT_STS_CMODE_XAUI
||
347 cmode_port10
== MV88E6XXX_PORT_STS_CMODE_RXAUI
)
348 lane
= MV88E6390_PORT10_LANE0
;
355 /* Only Ports 0, 9 and 10 have SERDES lanes. Return the SERDES lane address
356 * a port is using else Returns -ENODEV.
358 int mv88e6393x_serdes_get_lane(struct mv88e6xxx_chip
*chip
, int port
)
360 u8 cmode
= chip
->ports
[port
].cmode
;
363 if (port
!= 0 && port
!= 9 && port
!= 10)
366 if (cmode
== MV88E6XXX_PORT_STS_CMODE_1000BASEX
||
367 cmode
== MV88E6XXX_PORT_STS_CMODE_SGMII
||
368 cmode
== MV88E6XXX_PORT_STS_CMODE_2500BASEX
||
369 cmode
== MV88E6393X_PORT_STS_CMODE_5GBASER
||
370 cmode
== MV88E6393X_PORT_STS_CMODE_10GBASER
||
371 cmode
== MV88E6393X_PORT_STS_CMODE_USXGMII
)
377 struct mv88e6390_serdes_hw_stat
{
378 char string
[ETH_GSTRING_LEN
];
382 static struct mv88e6390_serdes_hw_stat mv88e6390_serdes_hw_stats
[] = {
383 { "serdes_rx_pkts", 0xf021 },
384 { "serdes_rx_bytes", 0xf024 },
385 { "serdes_rx_pkts_error", 0xf027 },
388 int mv88e6390_serdes_get_sset_count(struct mv88e6xxx_chip
*chip
, int port
)
390 if (mv88e6xxx_serdes_get_lane(chip
, port
) < 0)
393 return ARRAY_SIZE(mv88e6390_serdes_hw_stats
);
396 int mv88e6390_serdes_get_strings(struct mv88e6xxx_chip
*chip
, int port
,
399 struct mv88e6390_serdes_hw_stat
*stat
;
402 if (mv88e6xxx_serdes_get_lane(chip
, port
) < 0)
405 for (i
= 0; i
< ARRAY_SIZE(mv88e6390_serdes_hw_stats
); i
++) {
406 stat
= &mv88e6390_serdes_hw_stats
[i
];
407 ethtool_puts(data
, stat
->string
);
409 return ARRAY_SIZE(mv88e6390_serdes_hw_stats
);
412 static uint64_t mv88e6390_serdes_get_stat(struct mv88e6xxx_chip
*chip
, int lane
,
413 struct mv88e6390_serdes_hw_stat
*stat
)
418 for (i
= 0; i
< 3; i
++) {
419 err
= mv88e6390_serdes_read(chip
, lane
, MDIO_MMD_PHYXS
,
420 stat
->reg
+ i
, ®
[i
]);
422 dev_err(chip
->dev
, "failed to read statistic\n");
427 return reg
[0] | ((u64
)reg
[1] << 16) | ((u64
)reg
[2] << 32);
430 size_t mv88e6390_serdes_get_stats(struct mv88e6xxx_chip
*chip
, int port
,
433 struct mv88e6390_serdes_hw_stat
*stat
;
437 lane
= mv88e6xxx_serdes_get_lane(chip
, port
);
441 for (i
= 0; i
< ARRAY_SIZE(mv88e6390_serdes_hw_stats
); i
++) {
442 stat
= &mv88e6390_serdes_hw_stats
[i
];
443 data
[i
] = mv88e6390_serdes_get_stat(chip
, lane
, stat
);
446 return ARRAY_SIZE(mv88e6390_serdes_hw_stats
);
449 unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip
*chip
, int port
)
451 return irq_find_mapping(chip
->g2_irq
.domain
, port
);
454 static const u16 mv88e6390_serdes_regs
[] = {
455 /* SERDES common registers */
456 0xf00a, 0xf00b, 0xf00c,
457 0xf010, 0xf011, 0xf012, 0xf013,
458 0xf016, 0xf017, 0xf018,
459 0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f,
460 0xf020, 0xf021, 0xf022, 0xf023, 0xf024, 0xf025, 0xf026, 0xf027,
462 0xf030, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, 0xf037,
465 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007,
468 0xa000, 0xa001, 0xa002, 0xa003,
470 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006, 0x1007,
474 0x9000, 0x9001, 0x9002, 0x9003, 0x9004,
476 0x9010, 0x9011, 0x9012, 0x9013, 0x9014, 0x9015, 0x9016,
478 0x1020, 0x1021, 0x1022, 0x1023, 0x1024, 0x1025, 0x1026, 0x1027,
479 0x1028, 0x1029, 0x102a, 0x102b,
482 int mv88e6390_serdes_get_regs_len(struct mv88e6xxx_chip
*chip
, int port
)
484 if (mv88e6xxx_serdes_get_lane(chip
, port
) < 0)
487 return ARRAY_SIZE(mv88e6390_serdes_regs
) * sizeof(u16
);
490 void mv88e6390_serdes_get_regs(struct mv88e6xxx_chip
*chip
, int port
, void *_p
)
498 lane
= mv88e6xxx_serdes_get_lane(chip
, port
);
502 for (i
= 0 ; i
< ARRAY_SIZE(mv88e6390_serdes_regs
); i
++) {
503 err
= mv88e6390_serdes_read(chip
, lane
, MDIO_MMD_PHYXS
,
504 mv88e6390_serdes_regs
[i
], ®
);
510 static const int mv88e6352_serdes_p2p_to_reg
[] = {
511 /* Index of value in microvolts corresponds to the register value */
512 14000, 112000, 210000, 308000, 406000, 504000, 602000, 700000,
515 int mv88e6352_serdes_set_tx_amplitude(struct mv88e6xxx_chip
*chip
, int port
,
523 err
= mv88e6352_g2_scratch_port_has_serdes(chip
, port
);
527 for (i
= 0; i
< ARRAY_SIZE(mv88e6352_serdes_p2p_to_reg
); ++i
) {
528 if (mv88e6352_serdes_p2p_to_reg
[i
] == val
) {
538 err
= mv88e6352_serdes_read(chip
, MV88E6352_SERDES_SPEC_CTRL2
, &ctrl
);
542 ctrl
&= ~MV88E6352_SERDES_OUT_AMP_MASK
;
545 return mv88e6352_serdes_write(chip
, MV88E6352_SERDES_SPEC_CTRL2
, ctrl
);