1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Marvell 88E6xxx SERDES manipulation, via SMI bus
4 *
5 * Copyright (c) 2008 Marvell Semiconductor
6 *
7 * Copyright (c) 2017 Andrew Lunn <andrew@lunn.ch>
8 */
9
10 #include <linux/interrupt.h>
11 #include <linux/irqdomain.h>
12 #include <linux/mii.h>
13
14 #include "chip.h"
15 #include "global2.h"
16 #include "phy.h"
17 #include "port.h"
18 #include "serdes.h"
19
mv88e6352_serdes_read(struct mv88e6xxx_chip * chip,int reg,u16 * val)20 static int mv88e6352_serdes_read(struct mv88e6xxx_chip *chip, int reg,
21 u16 *val)
22 {
23 return mv88e6xxx_phy_page_read(chip, MV88E6352_ADDR_SERDES,
24 MV88E6352_SERDES_PAGE_FIBER,
25 reg, val);
26 }
27
mv88e6390_serdes_read(struct mv88e6xxx_chip * chip,int lane,int device,int reg,u16 * val)28 static int mv88e6390_serdes_read(struct mv88e6xxx_chip *chip,
29 int lane, int device, int reg, u16 *val)
30 {
31 return mv88e6xxx_phy_read_c45(chip, lane, device, reg, val);
32 }
33
mv88e6xxx_pcs_decode_state(struct device * dev,u16 bmsr,u16 lpa,u16 status,struct phylink_link_state * state)34 int mv88e6xxx_pcs_decode_state(struct device *dev, u16 bmsr, u16 lpa,
35 u16 status, struct phylink_link_state *state)
36 {
37 state->link = false;
38
39 /* If the BMSR reports that the link had failed, report this to
40 * phylink.
41 */
42 if (!(bmsr & BMSR_LSTATUS))
43 return 0;
44
45 state->link = !!(status & MV88E6390_SGMII_PHY_STATUS_LINK);
46 state->an_complete = !!(bmsr & BMSR_ANEGCOMPLETE);
47
48 if (status & MV88E6390_SGMII_PHY_STATUS_SPD_DPL_VALID) {
49 /* The Spped and Duplex Resolved register is 1 if AN is enabled
50 * and complete, or if AN is disabled. So with disabled AN we
51 * still get here on link up.
52 */
53 state->duplex = status &
54 MV88E6390_SGMII_PHY_STATUS_DUPLEX_FULL ?
55 DUPLEX_FULL : DUPLEX_HALF;
56
57 if (status & MV88E6390_SGMII_PHY_STATUS_TX_PAUSE)
58 state->pause |= MLO_PAUSE_TX;
59 if (status & MV88E6390_SGMII_PHY_STATUS_RX_PAUSE)
60 state->pause |= MLO_PAUSE_RX;
61
62 switch (status & MV88E6390_SGMII_PHY_STATUS_SPEED_MASK) {
63 case MV88E6390_SGMII_PHY_STATUS_SPEED_1000:
64 if (state->interface == PHY_INTERFACE_MODE_2500BASEX)
65 state->speed = SPEED_2500;
66 else
67 state->speed = SPEED_1000;
68 break;
69 case MV88E6390_SGMII_PHY_STATUS_SPEED_100:
70 state->speed = SPEED_100;
71 break;
72 case MV88E6390_SGMII_PHY_STATUS_SPEED_10:
73 state->speed = SPEED_10;
74 break;
75 default:
76 dev_err(dev, "invalid PHY speed\n");
77 return -EINVAL;
78 }
79 } else if (state->link &&
80 state->interface != PHY_INTERFACE_MODE_SGMII) {
81 /* If Speed and Duplex Resolved register is 0 and link is up, it
82 * means that AN was enabled, but link partner had it disabled
83 * and the PHY invoked the Auto-Negotiation Bypass feature and
84 * linked anyway.
85 */
86 state->duplex = DUPLEX_FULL;
87 if (state->interface == PHY_INTERFACE_MODE_2500BASEX)
88 state->speed = SPEED_2500;
89 else
90 state->speed = SPEED_1000;
91 } else {
92 state->link = false;
93 }
94
95 if (state->interface == PHY_INTERFACE_MODE_2500BASEX)
96 mii_lpa_mod_linkmode_x(state->lp_advertising, lpa,
97 ETHTOOL_LINK_MODE_2500baseX_Full_BIT);
98 else if (state->interface == PHY_INTERFACE_MODE_1000BASEX)
99 mii_lpa_mod_linkmode_x(state->lp_advertising, lpa,
100 ETHTOOL_LINK_MODE_1000baseX_Full_BIT);
101
102 return 0;
103 }
104
105 struct mv88e6352_serdes_hw_stat {
106 char string[ETH_GSTRING_LEN];
107 int sizeof_stat;
108 int reg;
109 };
110
111 static struct mv88e6352_serdes_hw_stat mv88e6352_serdes_hw_stats[] = {
112 { "serdes_fibre_rx_error", 16, 21 },
113 { "serdes_PRBS_error", 32, 24 },
114 };
115
mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip * chip,int port)116 int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port)
117 {
118 int err;
119
120 err = mv88e6352_g2_scratch_port_has_serdes(chip, port);
121 if (err <= 0)
122 return err;
123
124 return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
125 }
126
mv88e6352_serdes_get_strings(struct mv88e6xxx_chip * chip,int port,uint8_t ** data)127 int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip, int port,
128 uint8_t **data)
129 {
130 struct mv88e6352_serdes_hw_stat *stat;
131 int err, i;
132
133 err = mv88e6352_g2_scratch_port_has_serdes(chip, port);
134 if (err <= 0)
135 return err;
136
137 for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_hw_stats); i++) {
138 stat = &mv88e6352_serdes_hw_stats[i];
139 ethtool_puts(data, stat->string);
140 }
141 return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
142 }
143
mv88e6352_serdes_get_stat(struct mv88e6xxx_chip * chip,struct mv88e6352_serdes_hw_stat * stat)144 static uint64_t mv88e6352_serdes_get_stat(struct mv88e6xxx_chip *chip,
145 struct mv88e6352_serdes_hw_stat *stat)
146 {
147 u64 val = 0;
148 u16 reg;
149 int err;
150
151 err = mv88e6352_serdes_read(chip, stat->reg, ®);
152 if (err) {
153 dev_err(chip->dev, "failed to read statistic\n");
154 return 0;
155 }
156
157 val = reg;
158
159 if (stat->sizeof_stat == 32) {
160 err = mv88e6352_serdes_read(chip, stat->reg + 1, ®);
161 if (err) {
162 dev_err(chip->dev, "failed to read statistic\n");
163 return 0;
164 }
165 val = val << 16 | reg;
166 }
167
168 return val;
169 }
170
mv88e6352_serdes_get_stats(struct mv88e6xxx_chip * chip,int port,uint64_t * data)171 size_t mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
172 uint64_t *data)
173 {
174 struct mv88e6xxx_port *mv88e6xxx_port = &chip->ports[port];
175 struct mv88e6352_serdes_hw_stat *stat;
176 int i, err;
177 u64 value;
178
179 err = mv88e6352_g2_scratch_port_has_serdes(chip, port);
180 if (err <= 0)
181 return 0;
182
183 BUILD_BUG_ON(ARRAY_SIZE(mv88e6352_serdes_hw_stats) >
184 ARRAY_SIZE(mv88e6xxx_port->serdes_stats));
185
186 for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_hw_stats); i++) {
187 stat = &mv88e6352_serdes_hw_stats[i];
188 value = mv88e6352_serdes_get_stat(chip, stat);
189 mv88e6xxx_port->serdes_stats[i] += value;
190 data[i] = mv88e6xxx_port->serdes_stats[i];
191 }
192
193 return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
194 }
195
mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip * chip,int port)196 unsigned int mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port)
197 {
198 return irq_find_mapping(chip->g2_irq.domain, MV88E6352_SERDES_IRQ);
199 }
200
mv88e6352_serdes_get_regs_len(struct mv88e6xxx_chip * chip,int port)201 int mv88e6352_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port)
202 {
203 int err;
204
205 mv88e6xxx_reg_lock(chip);
206 err = mv88e6352_g2_scratch_port_has_serdes(chip, port);
207 mv88e6xxx_reg_unlock(chip);
208 if (err <= 0)
209 return err;
210
211 return 32 * sizeof(u16);
212 }
213
mv88e6352_serdes_get_regs(struct mv88e6xxx_chip * chip,int port,void * _p)214 void mv88e6352_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p)
215 {
216 u16 *p = _p;
217 u16 reg;
218 int err;
219 int i;
220
221 err = mv88e6352_g2_scratch_port_has_serdes(chip, port);
222 if (err <= 0)
223 return;
224
225 for (i = 0 ; i < 32; i++) {
226 err = mv88e6352_serdes_read(chip, i, ®);
227 if (!err)
228 p[i] = reg;
229 }
230 }
231
mv88e6341_serdes_get_lane(struct mv88e6xxx_chip * chip,int port)232 int mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
233 {
234 u8 cmode = chip->ports[port].cmode;
235 int lane = -ENODEV;
236
237 switch (port) {
238 case 5:
239 if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
240 cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
241 cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
242 lane = MV88E6341_PORT5_LANE;
243 break;
244 }
245
246 return lane;
247 }
248
mv88e6390_serdes_get_lane(struct mv88e6xxx_chip * chip,int port)249 int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
250 {
251 u8 cmode = chip->ports[port].cmode;
252 int lane = -ENODEV;
253
254 switch (port) {
255 case 9:
256 if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
257 cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
258 cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
259 lane = MV88E6390_PORT9_LANE0;
260 break;
261 case 10:
262 if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
263 cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
264 cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
265 lane = MV88E6390_PORT10_LANE0;
266 break;
267 }
268
269 return lane;
270 }
271
mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip * chip,int port)272 int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
273 {
274 u8 cmode_port = chip->ports[port].cmode;
275 u8 cmode_port10 = chip->ports[10].cmode;
276 u8 cmode_port9 = chip->ports[9].cmode;
277 int lane = -ENODEV;
278
279 switch (port) {
280 case 2:
281 if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
282 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
283 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
284 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
285 lane = MV88E6390_PORT9_LANE1;
286 break;
287 case 3:
288 if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
289 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
290 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
291 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
292 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
293 lane = MV88E6390_PORT9_LANE2;
294 break;
295 case 4:
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_LANE3;
302 break;
303 case 5:
304 if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
305 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
306 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
307 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
308 lane = MV88E6390_PORT10_LANE1;
309 break;
310 case 6:
311 if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
312 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
313 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
314 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
315 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
316 lane = MV88E6390_PORT10_LANE2;
317 break;
318 case 7:
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_LANE3;
325 break;
326 case 9:
327 if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
328 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
329 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
330 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_XAUI ||
331 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
332 lane = MV88E6390_PORT9_LANE0;
333 break;
334 case 10:
335 if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
336 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
337 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
338 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_XAUI ||
339 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
340 lane = MV88E6390_PORT10_LANE0;
341 break;
342 }
343
344 return lane;
345 }
346
347 /* Only Ports 0, 9 and 10 have SERDES lanes. Return the SERDES lane address
348 * a port is using else Returns -ENODEV.
349 */
mv88e6393x_serdes_get_lane(struct mv88e6xxx_chip * chip,int port)350 int mv88e6393x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
351 {
352 u8 cmode = chip->ports[port].cmode;
353 int lane = -ENODEV;
354
355 if (port != 0 && port != 9 && port != 10)
356 return -EOPNOTSUPP;
357
358 if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
359 cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
360 cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
361 cmode == MV88E6393X_PORT_STS_CMODE_5GBASER ||
362 cmode == MV88E6393X_PORT_STS_CMODE_10GBASER ||
363 cmode == MV88E6393X_PORT_STS_CMODE_USXGMII)
364 lane = port;
365
366 return lane;
367 }
368
369 struct mv88e6390_serdes_hw_stat {
370 char string[ETH_GSTRING_LEN];
371 int reg;
372 };
373
374 static struct mv88e6390_serdes_hw_stat mv88e6390_serdes_hw_stats[] = {
375 { "serdes_rx_pkts", 0xf021 },
376 { "serdes_rx_bytes", 0xf024 },
377 { "serdes_rx_pkts_error", 0xf027 },
378 };
379
mv88e6390_serdes_get_sset_count(struct mv88e6xxx_chip * chip,int port)380 int mv88e6390_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port)
381 {
382 if (mv88e6xxx_serdes_get_lane(chip, port) < 0)
383 return 0;
384
385 return ARRAY_SIZE(mv88e6390_serdes_hw_stats);
386 }
387
mv88e6390_serdes_get_strings(struct mv88e6xxx_chip * chip,int port,uint8_t ** data)388 int mv88e6390_serdes_get_strings(struct mv88e6xxx_chip *chip, int port,
389 uint8_t **data)
390 {
391 struct mv88e6390_serdes_hw_stat *stat;
392 int i;
393
394 if (mv88e6xxx_serdes_get_lane(chip, port) < 0)
395 return 0;
396
397 for (i = 0; i < ARRAY_SIZE(mv88e6390_serdes_hw_stats); i++) {
398 stat = &mv88e6390_serdes_hw_stats[i];
399 ethtool_puts(data, stat->string);
400 }
401 return ARRAY_SIZE(mv88e6390_serdes_hw_stats);
402 }
403
mv88e6390_serdes_get_stat(struct mv88e6xxx_chip * chip,int lane,struct mv88e6390_serdes_hw_stat * stat)404 static uint64_t mv88e6390_serdes_get_stat(struct mv88e6xxx_chip *chip, int lane,
405 struct mv88e6390_serdes_hw_stat *stat)
406 {
407 u16 reg[3];
408 int err, i;
409
410 for (i = 0; i < 3; i++) {
411 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
412 stat->reg + i, ®[i]);
413 if (err) {
414 dev_err(chip->dev, "failed to read statistic\n");
415 return 0;
416 }
417 }
418
419 return reg[0] | ((u64)reg[1] << 16) | ((u64)reg[2] << 32);
420 }
421
mv88e6390_serdes_get_stats(struct mv88e6xxx_chip * chip,int port,uint64_t * data)422 size_t mv88e6390_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
423 uint64_t *data)
424 {
425 struct mv88e6390_serdes_hw_stat *stat;
426 int lane;
427 int i;
428
429 lane = mv88e6xxx_serdes_get_lane(chip, port);
430 if (lane < 0)
431 return 0;
432
433 for (i = 0; i < ARRAY_SIZE(mv88e6390_serdes_hw_stats); i++) {
434 stat = &mv88e6390_serdes_hw_stats[i];
435 data[i] = mv88e6390_serdes_get_stat(chip, lane, stat);
436 }
437
438 return ARRAY_SIZE(mv88e6390_serdes_hw_stats);
439 }
440
mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip * chip,int port)441 unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port)
442 {
443 return irq_find_mapping(chip->g2_irq.domain, port);
444 }
445
446 static const u16 mv88e6390_serdes_regs[] = {
447 /* SERDES common registers */
448 0xf00a, 0xf00b, 0xf00c,
449 0xf010, 0xf011, 0xf012, 0xf013,
450 0xf016, 0xf017, 0xf018,
451 0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f,
452 0xf020, 0xf021, 0xf022, 0xf023, 0xf024, 0xf025, 0xf026, 0xf027,
453 0xf028, 0xf029,
454 0xf030, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, 0xf037,
455 0xf038, 0xf039,
456 /* SGMII */
457 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007,
458 0x2008,
459 0x200f,
460 0xa000, 0xa001, 0xa002, 0xa003,
461 /* 10Gbase-X */
462 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006, 0x1007,
463 0x1008,
464 0x100e, 0x100f,
465 0x1018, 0x1019,
466 0x9000, 0x9001, 0x9002, 0x9003, 0x9004,
467 0x9006,
468 0x9010, 0x9011, 0x9012, 0x9013, 0x9014, 0x9015, 0x9016,
469 /* 10Gbase-R */
470 0x1020, 0x1021, 0x1022, 0x1023, 0x1024, 0x1025, 0x1026, 0x1027,
471 0x1028, 0x1029, 0x102a, 0x102b,
472 };
473
mv88e6390_serdes_get_regs_len(struct mv88e6xxx_chip * chip,int port)474 int mv88e6390_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port)
475 {
476 if (mv88e6xxx_serdes_get_lane(chip, port) < 0)
477 return 0;
478
479 return ARRAY_SIZE(mv88e6390_serdes_regs) * sizeof(u16);
480 }
481
mv88e6390_serdes_get_regs(struct mv88e6xxx_chip * chip,int port,void * _p)482 void mv88e6390_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p)
483 {
484 u16 *p = _p;
485 int lane;
486 u16 reg;
487 int err;
488 int i;
489
490 lane = mv88e6xxx_serdes_get_lane(chip, port);
491 if (lane < 0)
492 return;
493
494 for (i = 0 ; i < ARRAY_SIZE(mv88e6390_serdes_regs); i++) {
495 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
496 mv88e6390_serdes_regs[i], ®);
497 if (!err)
498 p[i] = reg;
499 }
500 }
501