xref: /linux/drivers/net/dsa/mv88e6xxx/serdes.c (revision f72aa1b276281b4e4f75261af8425bc99d903f3e)
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 
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 
28 static int mv88e6352_serdes_write(struct mv88e6xxx_chip *chip, int reg,
29 				  u16 val)
30 {
31 	return mv88e6xxx_phy_page_write(chip, MV88E6352_ADDR_SERDES,
32 					MV88E6352_SERDES_PAGE_FIBER,
33 					reg, val);
34 }
35 
36 static int mv88e6390_serdes_read(struct mv88e6xxx_chip *chip,
37 				 int lane, int device, int reg, u16 *val)
38 {
39 	return mv88e6xxx_phy_read_c45(chip, lane, device, reg, val);
40 }
41 
42 int mv88e6xxx_pcs_decode_state(struct device *dev, u16 bmsr, u16 lpa,
43 			       u16 status, struct phylink_link_state *state)
44 {
45 	state->link = false;
46 
47 	/* If the BMSR reports that the link had failed, report this to
48 	 * phylink.
49 	 */
50 	if (!(bmsr & BMSR_LSTATUS))
51 		return 0;
52 
53 	state->link = !!(status & MV88E6390_SGMII_PHY_STATUS_LINK);
54 	state->an_complete = !!(bmsr & BMSR_ANEGCOMPLETE);
55 
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.
60 		 */
61 		state->duplex = status &
62 				MV88E6390_SGMII_PHY_STATUS_DUPLEX_FULL ?
63 			                         DUPLEX_FULL : DUPLEX_HALF;
64 
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;
69 
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;
74 			else
75 				state->speed = SPEED_1000;
76 			break;
77 		case MV88E6390_SGMII_PHY_STATUS_SPEED_100:
78 			state->speed = SPEED_100;
79 			break;
80 		case MV88E6390_SGMII_PHY_STATUS_SPEED_10:
81 			state->speed = SPEED_10;
82 			break;
83 		default:
84 			dev_err(dev, "invalid PHY speed\n");
85 			return -EINVAL;
86 		}
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
92 		 * linked anyway.
93 		 */
94 		state->duplex = DUPLEX_FULL;
95 		if (state->interface == PHY_INTERFACE_MODE_2500BASEX)
96 			state->speed = SPEED_2500;
97 		else
98 			state->speed = SPEED_1000;
99 	} else {
100 		state->link = false;
101 	}
102 
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);
109 
110 	return 0;
111 }
112 
113 struct mv88e6352_serdes_hw_stat {
114 	char string[ETH_GSTRING_LEN];
115 	int sizeof_stat;
116 	int reg;
117 };
118 
119 static struct mv88e6352_serdes_hw_stat mv88e6352_serdes_hw_stats[] = {
120 	{ "serdes_fibre_rx_error", 16, 21 },
121 	{ "serdes_PRBS_error", 32, 24 },
122 };
123 
124 int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port)
125 {
126 	int err;
127 
128 	err = mv88e6352_g2_scratch_port_has_serdes(chip, port);
129 	if (err <= 0)
130 		return err;
131 
132 	return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
133 }
134 
135 int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip, int port,
136 				 uint8_t **data)
137 {
138 	struct mv88e6352_serdes_hw_stat *stat;
139 	int err, i;
140 
141 	err = mv88e6352_g2_scratch_port_has_serdes(chip, port);
142 	if (err <= 0)
143 		return err;
144 
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);
148 	}
149 	return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
150 }
151 
152 static uint64_t mv88e6352_serdes_get_stat(struct mv88e6xxx_chip *chip,
153 					  struct mv88e6352_serdes_hw_stat *stat)
154 {
155 	u64 val = 0;
156 	u16 reg;
157 	int err;
158 
159 	err = mv88e6352_serdes_read(chip, stat->reg, &reg);
160 	if (err) {
161 		dev_err(chip->dev, "failed to read statistic\n");
162 		return 0;
163 	}
164 
165 	val = reg;
166 
167 	if (stat->sizeof_stat == 32) {
168 		err = mv88e6352_serdes_read(chip, stat->reg + 1, &reg);
169 		if (err) {
170 			dev_err(chip->dev, "failed to read statistic\n");
171 			return 0;
172 		}
173 		val = val << 16 | reg;
174 	}
175 
176 	return val;
177 }
178 
179 size_t mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
180 				  uint64_t *data)
181 {
182 	struct mv88e6xxx_port *mv88e6xxx_port = &chip->ports[port];
183 	struct mv88e6352_serdes_hw_stat *stat;
184 	int i, err;
185 	u64 value;
186 
187 	err = mv88e6352_g2_scratch_port_has_serdes(chip, port);
188 	if (err <= 0)
189 		return 0;
190 
191 	BUILD_BUG_ON(ARRAY_SIZE(mv88e6352_serdes_hw_stats) >
192 		     ARRAY_SIZE(mv88e6xxx_port->serdes_stats));
193 
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];
199 	}
200 
201 	return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
202 }
203 
204 unsigned int mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port)
205 {
206 	return irq_find_mapping(chip->g2_irq.domain, MV88E6352_SERDES_IRQ);
207 }
208 
209 int mv88e6352_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port)
210 {
211 	int err;
212 
213 	mv88e6xxx_reg_lock(chip);
214 	err = mv88e6352_g2_scratch_port_has_serdes(chip, port);
215 	mv88e6xxx_reg_unlock(chip);
216 	if (err <= 0)
217 		return err;
218 
219 	return 32 * sizeof(u16);
220 }
221 
222 void mv88e6352_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p)
223 {
224 	u16 *p = _p;
225 	u16 reg;
226 	int err;
227 	int i;
228 
229 	err = mv88e6352_g2_scratch_port_has_serdes(chip, port);
230 	if (err <= 0)
231 		return;
232 
233 	for (i = 0 ; i < 32; i++) {
234 		err = mv88e6352_serdes_read(chip, i, &reg);
235 		if (!err)
236 			p[i] = reg;
237 	}
238 }
239 
240 int mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
241 {
242 	u8 cmode = chip->ports[port].cmode;
243 	int lane = -ENODEV;
244 
245 	switch (port) {
246 	case 5:
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;
251 		break;
252 	}
253 
254 	return lane;
255 }
256 
257 int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
258 {
259 	u8 cmode = chip->ports[port].cmode;
260 	int lane = -ENODEV;
261 
262 	switch (port) {
263 	case 9:
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;
268 		break;
269 	case 10:
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;
274 		break;
275 	}
276 
277 	return lane;
278 }
279 
280 int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
281 {
282 	u8 cmode_port = chip->ports[port].cmode;
283 	u8 cmode_port10 = chip->ports[10].cmode;
284 	u8 cmode_port9 = chip->ports[9].cmode;
285 	int lane = -ENODEV;
286 
287 	switch (port) {
288 	case 2:
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;
294 		break;
295 	case 3:
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;
302 		break;
303 	case 4:
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;
310 		break;
311 	case 5:
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;
317 		break;
318 	case 6:
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;
325 		break;
326 	case 7:
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;
333 		break;
334 	case 9:
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;
341 		break;
342 	case 10:
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;
349 		break;
350 	}
351 
352 	return lane;
353 }
354 
355 /* Only Ports 0, 9 and 10 have SERDES lanes. Return the SERDES lane address
356  * a port is using else Returns -ENODEV.
357  */
358 int mv88e6393x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
359 {
360 	u8 cmode = chip->ports[port].cmode;
361 	int lane = -ENODEV;
362 
363 	if (port != 0 && port != 9 && port != 10)
364 		return -EOPNOTSUPP;
365 
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)
372 		lane = port;
373 
374 	return lane;
375 }
376 
377 struct mv88e6390_serdes_hw_stat {
378 	char string[ETH_GSTRING_LEN];
379 	int reg;
380 };
381 
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 },
386 };
387 
388 int mv88e6390_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port)
389 {
390 	if (mv88e6xxx_serdes_get_lane(chip, port) < 0)
391 		return 0;
392 
393 	return ARRAY_SIZE(mv88e6390_serdes_hw_stats);
394 }
395 
396 int mv88e6390_serdes_get_strings(struct mv88e6xxx_chip *chip, int port,
397 				 uint8_t **data)
398 {
399 	struct mv88e6390_serdes_hw_stat *stat;
400 	int i;
401 
402 	if (mv88e6xxx_serdes_get_lane(chip, port) < 0)
403 		return 0;
404 
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);
408 	}
409 	return ARRAY_SIZE(mv88e6390_serdes_hw_stats);
410 }
411 
412 static uint64_t mv88e6390_serdes_get_stat(struct mv88e6xxx_chip *chip, int lane,
413 					  struct mv88e6390_serdes_hw_stat *stat)
414 {
415 	u16 reg[3];
416 	int err, i;
417 
418 	for (i = 0; i < 3; i++) {
419 		err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
420 					    stat->reg + i, &reg[i]);
421 		if (err) {
422 			dev_err(chip->dev, "failed to read statistic\n");
423 			return 0;
424 		}
425 	}
426 
427 	return reg[0] | ((u64)reg[1] << 16) | ((u64)reg[2] << 32);
428 }
429 
430 size_t mv88e6390_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
431 				  uint64_t *data)
432 {
433 	struct mv88e6390_serdes_hw_stat *stat;
434 	int lane;
435 	int i;
436 
437 	lane = mv88e6xxx_serdes_get_lane(chip, port);
438 	if (lane < 0)
439 		return 0;
440 
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);
444 	}
445 
446 	return ARRAY_SIZE(mv88e6390_serdes_hw_stats);
447 }
448 
449 unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port)
450 {
451 	return irq_find_mapping(chip->g2_irq.domain, port);
452 }
453 
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,
461 	0xf028, 0xf029,
462 	0xf030, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, 0xf037,
463 	0xf038, 0xf039,
464 	/* SGMII */
465 	0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007,
466 	0x2008,
467 	0x200f,
468 	0xa000, 0xa001, 0xa002, 0xa003,
469 	/* 10Gbase-X */
470 	0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006, 0x1007,
471 	0x1008,
472 	0x100e, 0x100f,
473 	0x1018, 0x1019,
474 	0x9000, 0x9001, 0x9002, 0x9003, 0x9004,
475 	0x9006,
476 	0x9010, 0x9011, 0x9012, 0x9013, 0x9014, 0x9015, 0x9016,
477 	/* 10Gbase-R */
478 	0x1020, 0x1021, 0x1022, 0x1023, 0x1024, 0x1025, 0x1026, 0x1027,
479 	0x1028, 0x1029, 0x102a, 0x102b,
480 };
481 
482 int mv88e6390_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port)
483 {
484 	if (mv88e6xxx_serdes_get_lane(chip, port) < 0)
485 		return 0;
486 
487 	return ARRAY_SIZE(mv88e6390_serdes_regs) * sizeof(u16);
488 }
489 
490 void mv88e6390_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p)
491 {
492 	u16 *p = _p;
493 	int lane;
494 	u16 reg;
495 	int err;
496 	int i;
497 
498 	lane = mv88e6xxx_serdes_get_lane(chip, port);
499 	if (lane < 0)
500 		return;
501 
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], &reg);
505 		if (!err)
506 			p[i] = reg;
507 	}
508 }
509 
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,
513 };
514 
515 int mv88e6352_serdes_set_tx_amplitude(struct mv88e6xxx_chip *chip, int port,
516 				      int val)
517 {
518 	bool found = false;
519 	u16 ctrl, reg;
520 	int err;
521 	int i;
522 
523 	err = mv88e6352_g2_scratch_port_has_serdes(chip, port);
524 	if (err <= 0)
525 		return err;
526 
527 	for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_p2p_to_reg); ++i) {
528 		if (mv88e6352_serdes_p2p_to_reg[i] == val) {
529 			reg = i;
530 			found = true;
531 			break;
532 		}
533 	}
534 
535 	if (!found)
536 		return -EINVAL;
537 
538 	err = mv88e6352_serdes_read(chip, MV88E6352_SERDES_SPEC_CTRL2, &ctrl);
539 	if (err)
540 		return err;
541 
542 	ctrl &= ~MV88E6352_SERDES_OUT_AMP_MASK;
543 	ctrl |= reg;
544 
545 	return mv88e6352_serdes_write(chip, MV88E6352_SERDES_SPEC_CTRL2, ctrl);
546 }
547