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
20static 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
28static 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
36static 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
42int 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
113struct mv88e6352_serdes_hw_stat {
114	char string[ETH_GSTRING_LEN];
115	int sizeof_stat;
116	int reg;
117};
118
119static struct mv88e6352_serdes_hw_stat mv88e6352_serdes_hw_stats[] = {
120	{ "serdes_fibre_rx_error", 16, 21 },
121	{ "serdes_PRBS_error", 32, 24 },
122};
123
124int 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
135int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip,
136				 int port, 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		memcpy(data + i * ETH_GSTRING_LEN, stat->string,
148		       ETH_GSTRING_LEN);
149	}
150	return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
151}
152
153static uint64_t mv88e6352_serdes_get_stat(struct mv88e6xxx_chip *chip,
154					  struct mv88e6352_serdes_hw_stat *stat)
155{
156	u64 val = 0;
157	u16 reg;
158	int err;
159
160	err = mv88e6352_serdes_read(chip, stat->reg, &reg);
161	if (err) {
162		dev_err(chip->dev, "failed to read statistic\n");
163		return 0;
164	}
165
166	val = reg;
167
168	if (stat->sizeof_stat == 32) {
169		err = mv88e6352_serdes_read(chip, stat->reg + 1, &reg);
170		if (err) {
171			dev_err(chip->dev, "failed to read statistic\n");
172			return 0;
173		}
174		val = val << 16 | reg;
175	}
176
177	return val;
178}
179
180size_t mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
181				  uint64_t *data)
182{
183	struct mv88e6xxx_port *mv88e6xxx_port = &chip->ports[port];
184	struct mv88e6352_serdes_hw_stat *stat;
185	int i, err;
186	u64 value;
187
188	err = mv88e6352_g2_scratch_port_has_serdes(chip, port);
189	if (err <= 0)
190		return 0;
191
192	BUILD_BUG_ON(ARRAY_SIZE(mv88e6352_serdes_hw_stats) >
193		     ARRAY_SIZE(mv88e6xxx_port->serdes_stats));
194
195	for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_hw_stats); i++) {
196		stat = &mv88e6352_serdes_hw_stats[i];
197		value = mv88e6352_serdes_get_stat(chip, stat);
198		mv88e6xxx_port->serdes_stats[i] += value;
199		data[i] = mv88e6xxx_port->serdes_stats[i];
200	}
201
202	return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
203}
204
205unsigned int mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port)
206{
207	return irq_find_mapping(chip->g2_irq.domain, MV88E6352_SERDES_IRQ);
208}
209
210int mv88e6352_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port)
211{
212	int err;
213
214	mv88e6xxx_reg_lock(chip);
215	err = mv88e6352_g2_scratch_port_has_serdes(chip, port);
216	mv88e6xxx_reg_unlock(chip);
217	if (err <= 0)
218		return err;
219
220	return 32 * sizeof(u16);
221}
222
223void mv88e6352_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p)
224{
225	u16 *p = _p;
226	u16 reg;
227	int err;
228	int i;
229
230	err = mv88e6352_g2_scratch_port_has_serdes(chip, port);
231	if (err <= 0)
232		return;
233
234	for (i = 0 ; i < 32; i++) {
235		err = mv88e6352_serdes_read(chip, i, &reg);
236		if (!err)
237			p[i] = reg;
238	}
239}
240
241int mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
242{
243	u8 cmode = chip->ports[port].cmode;
244	int lane = -ENODEV;
245
246	switch (port) {
247	case 5:
248		if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
249		    cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
250		    cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
251			lane = MV88E6341_PORT5_LANE;
252		break;
253	}
254
255	return lane;
256}
257
258int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
259{
260	u8 cmode = chip->ports[port].cmode;
261	int lane = -ENODEV;
262
263	switch (port) {
264	case 9:
265		if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
266		    cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
267		    cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
268			lane = MV88E6390_PORT9_LANE0;
269		break;
270	case 10:
271		if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
272		    cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
273		    cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
274			lane = MV88E6390_PORT10_LANE0;
275		break;
276	}
277
278	return lane;
279}
280
281int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
282{
283	u8 cmode_port = chip->ports[port].cmode;
284	u8 cmode_port10 = chip->ports[10].cmode;
285	u8 cmode_port9 = chip->ports[9].cmode;
286	int lane = -ENODEV;
287
288	switch (port) {
289	case 2:
290		if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
291		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
292		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
293			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
294				lane = MV88E6390_PORT9_LANE1;
295		break;
296	case 3:
297		if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
298		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
299		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
300		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
301			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
302				lane = MV88E6390_PORT9_LANE2;
303		break;
304	case 4:
305		if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
306		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
307		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
308		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
309			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
310				lane = MV88E6390_PORT9_LANE3;
311		break;
312	case 5:
313		if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
314		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
315		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
316			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
317				lane = MV88E6390_PORT10_LANE1;
318		break;
319	case 6:
320		if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
321		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
322		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
323		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
324			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
325				lane = MV88E6390_PORT10_LANE2;
326		break;
327	case 7:
328		if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
329		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
330		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
331		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
332			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
333				lane = MV88E6390_PORT10_LANE3;
334		break;
335	case 9:
336		if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
337		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
338		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
339		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_XAUI ||
340		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
341			lane = MV88E6390_PORT9_LANE0;
342		break;
343	case 10:
344		if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
345		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
346		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
347		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_XAUI ||
348		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
349			lane = MV88E6390_PORT10_LANE0;
350		break;
351	}
352
353	return lane;
354}
355
356/* Only Ports 0, 9 and 10 have SERDES lanes. Return the SERDES lane address
357 * a port is using else Returns -ENODEV.
358 */
359int mv88e6393x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
360{
361	u8 cmode = chip->ports[port].cmode;
362	int lane = -ENODEV;
363
364	if (port != 0 && port != 9 && port != 10)
365		return -EOPNOTSUPP;
366
367	if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
368	    cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
369	    cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
370	    cmode == MV88E6393X_PORT_STS_CMODE_5GBASER ||
371	    cmode == MV88E6393X_PORT_STS_CMODE_10GBASER ||
372	    cmode == MV88E6393X_PORT_STS_CMODE_USXGMII)
373		lane = port;
374
375	return lane;
376}
377
378struct mv88e6390_serdes_hw_stat {
379	char string[ETH_GSTRING_LEN];
380	int reg;
381};
382
383static struct mv88e6390_serdes_hw_stat mv88e6390_serdes_hw_stats[] = {
384	{ "serdes_rx_pkts", 0xf021 },
385	{ "serdes_rx_bytes", 0xf024 },
386	{ "serdes_rx_pkts_error", 0xf027 },
387};
388
389int mv88e6390_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port)
390{
391	if (mv88e6xxx_serdes_get_lane(chip, port) < 0)
392		return 0;
393
394	return ARRAY_SIZE(mv88e6390_serdes_hw_stats);
395}
396
397int mv88e6390_serdes_get_strings(struct mv88e6xxx_chip *chip,
398				 int port, uint8_t *data)
399{
400	struct mv88e6390_serdes_hw_stat *stat;
401	int i;
402
403	if (mv88e6xxx_serdes_get_lane(chip, port) < 0)
404		return 0;
405
406	for (i = 0; i < ARRAY_SIZE(mv88e6390_serdes_hw_stats); i++) {
407		stat = &mv88e6390_serdes_hw_stats[i];
408		memcpy(data + i * ETH_GSTRING_LEN, stat->string,
409		       ETH_GSTRING_LEN);
410	}
411	return ARRAY_SIZE(mv88e6390_serdes_hw_stats);
412}
413
414static uint64_t mv88e6390_serdes_get_stat(struct mv88e6xxx_chip *chip, int lane,
415					  struct mv88e6390_serdes_hw_stat *stat)
416{
417	u16 reg[3];
418	int err, i;
419
420	for (i = 0; i < 3; i++) {
421		err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
422					    stat->reg + i, &reg[i]);
423		if (err) {
424			dev_err(chip->dev, "failed to read statistic\n");
425			return 0;
426		}
427	}
428
429	return reg[0] | ((u64)reg[1] << 16) | ((u64)reg[2] << 32);
430}
431
432size_t mv88e6390_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
433				  uint64_t *data)
434{
435	struct mv88e6390_serdes_hw_stat *stat;
436	int lane;
437	int i;
438
439	lane = mv88e6xxx_serdes_get_lane(chip, port);
440	if (lane < 0)
441		return 0;
442
443	for (i = 0; i < ARRAY_SIZE(mv88e6390_serdes_hw_stats); i++) {
444		stat = &mv88e6390_serdes_hw_stats[i];
445		data[i] = mv88e6390_serdes_get_stat(chip, lane, stat);
446	}
447
448	return ARRAY_SIZE(mv88e6390_serdes_hw_stats);
449}
450
451unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port)
452{
453	return irq_find_mapping(chip->g2_irq.domain, port);
454}
455
456static const u16 mv88e6390_serdes_regs[] = {
457	/* SERDES common registers */
458	0xf00a, 0xf00b, 0xf00c,
459	0xf010, 0xf011, 0xf012, 0xf013,
460	0xf016, 0xf017, 0xf018,
461	0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f,
462	0xf020, 0xf021, 0xf022, 0xf023, 0xf024, 0xf025, 0xf026, 0xf027,
463	0xf028, 0xf029,
464	0xf030, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, 0xf037,
465	0xf038, 0xf039,
466	/* SGMII */
467	0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007,
468	0x2008,
469	0x200f,
470	0xa000, 0xa001, 0xa002, 0xa003,
471	/* 10Gbase-X */
472	0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006, 0x1007,
473	0x1008,
474	0x100e, 0x100f,
475	0x1018, 0x1019,
476	0x9000, 0x9001, 0x9002, 0x9003, 0x9004,
477	0x9006,
478	0x9010, 0x9011, 0x9012, 0x9013, 0x9014, 0x9015, 0x9016,
479	/* 10Gbase-R */
480	0x1020, 0x1021, 0x1022, 0x1023, 0x1024, 0x1025, 0x1026, 0x1027,
481	0x1028, 0x1029, 0x102a, 0x102b,
482};
483
484int mv88e6390_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port)
485{
486	if (mv88e6xxx_serdes_get_lane(chip, port) < 0)
487		return 0;
488
489	return ARRAY_SIZE(mv88e6390_serdes_regs) * sizeof(u16);
490}
491
492void mv88e6390_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p)
493{
494	u16 *p = _p;
495	int lane;
496	u16 reg;
497	int err;
498	int i;
499
500	lane = mv88e6xxx_serdes_get_lane(chip, port);
501	if (lane < 0)
502		return;
503
504	for (i = 0 ; i < ARRAY_SIZE(mv88e6390_serdes_regs); i++) {
505		err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
506					    mv88e6390_serdes_regs[i], &reg);
507		if (!err)
508			p[i] = reg;
509	}
510}
511
512static const int mv88e6352_serdes_p2p_to_reg[] = {
513	/* Index of value in microvolts corresponds to the register value */
514	14000, 112000, 210000, 308000, 406000, 504000, 602000, 700000,
515};
516
517int mv88e6352_serdes_set_tx_amplitude(struct mv88e6xxx_chip *chip, int port,
518				      int val)
519{
520	bool found = false;
521	u16 ctrl, reg;
522	int err;
523	int i;
524
525	err = mv88e6352_g2_scratch_port_has_serdes(chip, port);
526	if (err <= 0)
527		return err;
528
529	for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_p2p_to_reg); ++i) {
530		if (mv88e6352_serdes_p2p_to_reg[i] == val) {
531			reg = i;
532			found = true;
533			break;
534		}
535	}
536
537	if (!found)
538		return -EINVAL;
539
540	err = mv88e6352_serdes_read(chip, MV88E6352_SERDES_SPEC_CTRL2, &ctrl);
541	if (err)
542		return err;
543
544	ctrl &= ~MV88E6352_SERDES_OUT_AMP_MASK;
545	ctrl |= reg;
546
547	return mv88e6352_serdes_write(chip, MV88E6352_SERDES_SPEC_CTRL2, ctrl);
548}
549