Linux Audio

Check our new training course

Linux BSP development engineering services

Need help to port Linux and bootloaders to your hardware?
Loading...
v6.8
  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}
v5.9
   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	int reg_c45 = MII_ADDR_C45 | device << 16 | reg;
  40
  41	return mv88e6xxx_phy_read(chip, lane, reg_c45, val);
  42}
  43
  44static int mv88e6390_serdes_write(struct mv88e6xxx_chip *chip,
  45				  int lane, int device, int reg, u16 val)
  46{
  47	int reg_c45 = MII_ADDR_C45 | device << 16 | reg;
 
 
 
 
 
 
  48
  49	return mv88e6xxx_phy_write(chip, lane, reg_c45, val);
  50}
  51
  52static int mv88e6xxx_serdes_pcs_get_state(struct mv88e6xxx_chip *chip,
  53					  u16 status, u16 lpa,
  54					  struct phylink_link_state *state)
  55{
  56	if (status & MV88E6390_SGMII_PHY_STATUS_SPD_DPL_VALID) {
  57		state->link = !!(status & MV88E6390_SGMII_PHY_STATUS_LINK);
 
 
 
  58		state->duplex = status &
  59				MV88E6390_SGMII_PHY_STATUS_DUPLEX_FULL ?
  60			                         DUPLEX_FULL : DUPLEX_HALF;
  61
  62		if (status & MV88E6390_SGMII_PHY_STATUS_TX_PAUSE)
  63			state->pause |= MLO_PAUSE_TX;
  64		if (status & MV88E6390_SGMII_PHY_STATUS_RX_PAUSE)
  65			state->pause |= MLO_PAUSE_RX;
  66
  67		switch (status & MV88E6390_SGMII_PHY_STATUS_SPEED_MASK) {
  68		case MV88E6390_SGMII_PHY_STATUS_SPEED_1000:
  69			if (state->interface == PHY_INTERFACE_MODE_2500BASEX)
  70				state->speed = SPEED_2500;
  71			else
  72				state->speed = SPEED_1000;
  73			break;
  74		case MV88E6390_SGMII_PHY_STATUS_SPEED_100:
  75			state->speed = SPEED_100;
  76			break;
  77		case MV88E6390_SGMII_PHY_STATUS_SPEED_10:
  78			state->speed = SPEED_10;
  79			break;
  80		default:
  81			dev_err(chip->dev, "invalid PHY speed\n");
  82			return -EINVAL;
  83		}
 
 
 
 
 
 
 
 
 
 
 
 
  84	} else {
  85		state->link = false;
  86	}
  87
  88	if (state->interface == PHY_INTERFACE_MODE_2500BASEX)
  89		mii_lpa_mod_linkmode_x(state->lp_advertising, lpa,
  90				       ETHTOOL_LINK_MODE_2500baseX_Full_BIT);
  91	else if (state->interface == PHY_INTERFACE_MODE_1000BASEX)
  92		mii_lpa_mod_linkmode_x(state->lp_advertising, lpa,
  93				       ETHTOOL_LINK_MODE_1000baseX_Full_BIT);
  94
  95	return 0;
  96}
  97
  98int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, u8 lane,
  99			   bool up)
 100{
 101	u16 val, new_val;
 102	int err;
 103
 104	err = mv88e6352_serdes_read(chip, MII_BMCR, &val);
 105	if (err)
 106		return err;
 107
 108	if (up)
 109		new_val = val & ~BMCR_PDOWN;
 110	else
 111		new_val = val | BMCR_PDOWN;
 112
 113	if (val != new_val)
 114		err = mv88e6352_serdes_write(chip, MII_BMCR, new_val);
 115
 116	return err;
 117}
 118
 119int mv88e6352_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port,
 120				u8 lane, unsigned int mode,
 121				phy_interface_t interface,
 122				const unsigned long *advertise)
 123{
 124	u16 adv, bmcr, val;
 125	bool changed;
 126	int err;
 127
 128	switch (interface) {
 129	case PHY_INTERFACE_MODE_SGMII:
 130		adv = 0x0001;
 131		break;
 132
 133	case PHY_INTERFACE_MODE_1000BASEX:
 134		adv = linkmode_adv_to_mii_adv_x(advertise,
 135					ETHTOOL_LINK_MODE_1000baseX_Full_BIT);
 136		break;
 137
 138	default:
 139		return 0;
 140	}
 141
 142	err = mv88e6352_serdes_read(chip, MII_ADVERTISE, &val);
 143	if (err)
 144		return err;
 145
 146	changed = val != adv;
 147	if (changed) {
 148		err = mv88e6352_serdes_write(chip, MII_ADVERTISE, adv);
 149		if (err)
 150			return err;
 151	}
 152
 153	err = mv88e6352_serdes_read(chip, MII_BMCR, &val);
 154	if (err)
 155		return err;
 156
 157	if (phylink_autoneg_inband(mode))
 158		bmcr = val | BMCR_ANENABLE;
 159	else
 160		bmcr = val & ~BMCR_ANENABLE;
 161
 162	if (bmcr == val)
 163		return changed;
 164
 165	return mv88e6352_serdes_write(chip, MII_BMCR, bmcr);
 166}
 167
 168int mv88e6352_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port,
 169				   u8 lane, struct phylink_link_state *state)
 170{
 171	u16 lpa, status;
 172	int err;
 173
 174	err = mv88e6352_serdes_read(chip, 0x11, &status);
 175	if (err) {
 176		dev_err(chip->dev, "can't read Serdes PHY status: %d\n", err);
 177		return err;
 178	}
 179
 180	err = mv88e6352_serdes_read(chip, MII_LPA, &lpa);
 181	if (err) {
 182		dev_err(chip->dev, "can't read Serdes PHY LPA: %d\n", err);
 183		return err;
 184	}
 185
 186	return mv88e6xxx_serdes_pcs_get_state(chip, status, lpa, state);
 187}
 188
 189int mv88e6352_serdes_pcs_an_restart(struct mv88e6xxx_chip *chip, int port,
 190				    u8 lane)
 191{
 192	u16 bmcr;
 193	int err;
 194
 195	err = mv88e6352_serdes_read(chip, MII_BMCR, &bmcr);
 196	if (err)
 197		return err;
 198
 199	return mv88e6352_serdes_write(chip, MII_BMCR, bmcr | BMCR_ANRESTART);
 200}
 201
 202int mv88e6352_serdes_pcs_link_up(struct mv88e6xxx_chip *chip, int port,
 203				 u8 lane, int speed, int duplex)
 204{
 205	u16 val, bmcr;
 206	int err;
 207
 208	err = mv88e6352_serdes_read(chip, MII_BMCR, &val);
 209	if (err)
 210		return err;
 211
 212	bmcr = val & ~(BMCR_SPEED100 | BMCR_FULLDPLX | BMCR_SPEED1000);
 213	switch (speed) {
 214	case SPEED_1000:
 215		bmcr |= BMCR_SPEED1000;
 216		break;
 217	case SPEED_100:
 218		bmcr |= BMCR_SPEED100;
 219		break;
 220	case SPEED_10:
 221		break;
 222	}
 223
 224	if (duplex == DUPLEX_FULL)
 225		bmcr |= BMCR_FULLDPLX;
 226
 227	if (bmcr == val)
 228		return 0;
 229
 230	return mv88e6352_serdes_write(chip, MII_BMCR, bmcr);
 231}
 232
 233u8 mv88e6352_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
 234{
 235	u8 cmode = chip->ports[port].cmode;
 236	u8 lane = 0;
 237
 238	if ((cmode == MV88E6XXX_PORT_STS_CMODE_100BASEX) ||
 239	    (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX) ||
 240	    (cmode == MV88E6XXX_PORT_STS_CMODE_SGMII))
 241		lane = 0xff; /* Unused */
 242
 243	return lane;
 244}
 245
 246static bool mv88e6352_port_has_serdes(struct mv88e6xxx_chip *chip, int port)
 247{
 248	if (mv88e6xxx_serdes_get_lane(chip, port))
 249		return true;
 250
 251	return false;
 252}
 253
 254struct mv88e6352_serdes_hw_stat {
 255	char string[ETH_GSTRING_LEN];
 256	int sizeof_stat;
 257	int reg;
 258};
 259
 260static struct mv88e6352_serdes_hw_stat mv88e6352_serdes_hw_stats[] = {
 261	{ "serdes_fibre_rx_error", 16, 21 },
 262	{ "serdes_PRBS_error", 32, 24 },
 263};
 264
 265int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port)
 266{
 267	if (mv88e6352_port_has_serdes(chip, port))
 268		return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
 269
 270	return 0;
 
 
 
 
 271}
 272
 273int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip,
 274				 int port, uint8_t *data)
 275{
 276	struct mv88e6352_serdes_hw_stat *stat;
 277	int i;
 278
 279	if (!mv88e6352_port_has_serdes(chip, port))
 280		return 0;
 
 281
 282	for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_hw_stats); i++) {
 283		stat = &mv88e6352_serdes_hw_stats[i];
 284		memcpy(data + i * ETH_GSTRING_LEN, stat->string,
 285		       ETH_GSTRING_LEN);
 286	}
 287	return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
 288}
 289
 290static uint64_t mv88e6352_serdes_get_stat(struct mv88e6xxx_chip *chip,
 291					  struct mv88e6352_serdes_hw_stat *stat)
 292{
 293	u64 val = 0;
 294	u16 reg;
 295	int err;
 296
 297	err = mv88e6352_serdes_read(chip, stat->reg, &reg);
 298	if (err) {
 299		dev_err(chip->dev, "failed to read statistic\n");
 300		return 0;
 301	}
 302
 303	val = reg;
 304
 305	if (stat->sizeof_stat == 32) {
 306		err = mv88e6352_serdes_read(chip, stat->reg + 1, &reg);
 307		if (err) {
 308			dev_err(chip->dev, "failed to read statistic\n");
 309			return 0;
 310		}
 311		val = val << 16 | reg;
 312	}
 313
 314	return val;
 315}
 316
 317int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
 318			       uint64_t *data)
 319{
 320	struct mv88e6xxx_port *mv88e6xxx_port = &chip->ports[port];
 321	struct mv88e6352_serdes_hw_stat *stat;
 
 322	u64 value;
 323	int i;
 324
 325	if (!mv88e6352_port_has_serdes(chip, port))
 
 326		return 0;
 327
 328	BUILD_BUG_ON(ARRAY_SIZE(mv88e6352_serdes_hw_stats) >
 329		     ARRAY_SIZE(mv88e6xxx_port->serdes_stats));
 330
 331	for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_hw_stats); i++) {
 332		stat = &mv88e6352_serdes_hw_stats[i];
 333		value = mv88e6352_serdes_get_stat(chip, stat);
 334		mv88e6xxx_port->serdes_stats[i] += value;
 335		data[i] = mv88e6xxx_port->serdes_stats[i];
 336	}
 337
 338	return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
 339}
 340
 341static void mv88e6352_serdes_irq_link(struct mv88e6xxx_chip *chip, int port)
 342{
 343	u16 bmsr;
 344	int err;
 345
 346	/* If the link has dropped, we want to know about it. */
 347	err = mv88e6352_serdes_read(chip, MII_BMSR, &bmsr);
 348	if (err) {
 349		dev_err(chip->dev, "can't read Serdes BMSR: %d\n", err);
 350		return;
 351	}
 352
 353	dsa_port_phylink_mac_change(chip->ds, port, !!(bmsr & BMSR_LSTATUS));
 354}
 355
 356irqreturn_t mv88e6352_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
 357					u8 lane)
 358{
 359	irqreturn_t ret = IRQ_NONE;
 360	u16 status;
 361	int err;
 362
 363	err = mv88e6352_serdes_read(chip, MV88E6352_SERDES_INT_STATUS, &status);
 364	if (err)
 365		return ret;
 366
 367	if (status & MV88E6352_SERDES_INT_LINK_CHANGE) {
 368		ret = IRQ_HANDLED;
 369		mv88e6352_serdes_irq_link(chip, port);
 370	}
 371
 372	return ret;
 373}
 374
 375int mv88e6352_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, u8 lane,
 376				bool enable)
 377{
 378	u16 val = 0;
 379
 380	if (enable)
 381		val |= MV88E6352_SERDES_INT_LINK_CHANGE;
 382
 383	return mv88e6352_serdes_write(chip, MV88E6352_SERDES_INT_ENABLE, val);
 384}
 385
 386unsigned int mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port)
 387{
 388	return irq_find_mapping(chip->g2_irq.domain, MV88E6352_SERDES_IRQ);
 389}
 390
 391int mv88e6352_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port)
 392{
 393	if (!mv88e6352_port_has_serdes(chip, port))
 394		return 0;
 
 
 
 
 
 395
 396	return 32 * sizeof(u16);
 397}
 398
 399void mv88e6352_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p)
 400{
 401	u16 *p = _p;
 402	u16 reg;
 
 403	int i;
 404
 405	if (!mv88e6352_port_has_serdes(chip, port))
 
 406		return;
 407
 408	for (i = 0 ; i < 32; i++) {
 409		mv88e6352_serdes_read(chip, i, &reg);
 410		p[i] = reg;
 
 411	}
 412}
 413
 414u8 mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
 415{
 416	u8 cmode = chip->ports[port].cmode;
 417	u8 lane = 0;
 418
 419	switch (port) {
 420	case 5:
 421		if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 422		    cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
 423		    cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
 424			lane = MV88E6341_PORT5_LANE;
 425		break;
 426	}
 427
 428	return lane;
 429}
 430
 431u8 mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
 432{
 433	u8 cmode = chip->ports[port].cmode;
 434	u8 lane = 0;
 435
 436	switch (port) {
 437	case 9:
 438		if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 439		    cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
 440		    cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
 441			lane = MV88E6390_PORT9_LANE0;
 442		break;
 443	case 10:
 444		if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 445		    cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
 446		    cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
 447			lane = MV88E6390_PORT10_LANE0;
 448		break;
 449	}
 450
 451	return lane;
 452}
 453
 454u8 mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
 455{
 456	u8 cmode_port = chip->ports[port].cmode;
 457	u8 cmode_port10 = chip->ports[10].cmode;
 458	u8 cmode_port9 = chip->ports[9].cmode;
 459	u8 lane = 0;
 460
 461	switch (port) {
 462	case 2:
 463		if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 464		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
 465		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
 466			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
 467				lane = MV88E6390_PORT9_LANE1;
 468		break;
 469	case 3:
 470		if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 471		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
 472		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
 473		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
 474			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
 475				lane = MV88E6390_PORT9_LANE2;
 476		break;
 477	case 4:
 478		if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 479		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
 480		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
 481		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
 482			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
 483				lane = MV88E6390_PORT9_LANE3;
 484		break;
 485	case 5:
 486		if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 487		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
 488		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
 489			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
 490				lane = MV88E6390_PORT10_LANE1;
 491		break;
 492	case 6:
 493		if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 494		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
 495		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
 496		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
 497			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
 498				lane = MV88E6390_PORT10_LANE2;
 499		break;
 500	case 7:
 501		if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 502		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
 503		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
 504		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
 505			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
 506				lane = MV88E6390_PORT10_LANE3;
 507		break;
 508	case 9:
 509		if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 510		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
 511		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
 512		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_XAUI ||
 513		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
 514			lane = MV88E6390_PORT9_LANE0;
 515		break;
 516	case 10:
 517		if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 518		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
 519		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
 520		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_XAUI ||
 521		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
 522			lane = MV88E6390_PORT10_LANE0;
 523		break;
 524	}
 525
 526	return lane;
 527}
 528
 529/* Set power up/down for 10GBASE-R and 10GBASE-X4/X2 */
 530static int mv88e6390_serdes_power_10g(struct mv88e6xxx_chip *chip, u8 lane,
 531				      bool up)
 
 532{
 533	u16 val, new_val;
 534	int err;
 535
 536	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 537				    MV88E6390_10G_CTRL1, &val);
 538
 539	if (err)
 540		return err;
 
 
 
 
 
 541
 542	if (up)
 543		new_val = val & ~(MDIO_CTRL1_RESET |
 544				  MDIO_PCS_CTRL1_LOOPBACK |
 545				  MDIO_CTRL1_LPOWER);
 546	else
 547		new_val = val | MDIO_CTRL1_LPOWER;
 548
 549	if (val != new_val)
 550		err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
 551					     MV88E6390_10G_CTRL1, new_val);
 552
 553	return err;
 554}
 555
 556/* Set power up/down for SGMII and 1000Base-X */
 557static int mv88e6390_serdes_power_sgmii(struct mv88e6xxx_chip *chip, u8 lane,
 558					bool up)
 559{
 560	u16 val, new_val;
 561	int err;
 562
 563	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 564				    MV88E6390_SGMII_BMCR, &val);
 565	if (err)
 566		return err;
 567
 568	if (up)
 569		new_val = val & ~(BMCR_RESET | BMCR_LOOPBACK | BMCR_PDOWN);
 570	else
 571		new_val = val | BMCR_PDOWN;
 572
 573	if (val != new_val)
 574		err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
 575					     MV88E6390_SGMII_BMCR, new_val);
 576
 577	return err;
 578}
 579
 580struct mv88e6390_serdes_hw_stat {
 581	char string[ETH_GSTRING_LEN];
 582	int reg;
 583};
 584
 585static struct mv88e6390_serdes_hw_stat mv88e6390_serdes_hw_stats[] = {
 586	{ "serdes_rx_pkts", 0xf021 },
 587	{ "serdes_rx_bytes", 0xf024 },
 588	{ "serdes_rx_pkts_error", 0xf027 },
 589};
 590
 591int mv88e6390_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port)
 592{
 593	if (mv88e6390_serdes_get_lane(chip, port) == 0)
 594		return 0;
 595
 596	return ARRAY_SIZE(mv88e6390_serdes_hw_stats);
 597}
 598
 599int mv88e6390_serdes_get_strings(struct mv88e6xxx_chip *chip,
 600				 int port, uint8_t *data)
 601{
 602	struct mv88e6390_serdes_hw_stat *stat;
 603	int i;
 604
 605	if (mv88e6390_serdes_get_lane(chip, port) == 0)
 606		return 0;
 607
 608	for (i = 0; i < ARRAY_SIZE(mv88e6390_serdes_hw_stats); i++) {
 609		stat = &mv88e6390_serdes_hw_stats[i];
 610		memcpy(data + i * ETH_GSTRING_LEN, stat->string,
 611		       ETH_GSTRING_LEN);
 612	}
 613	return ARRAY_SIZE(mv88e6390_serdes_hw_stats);
 614}
 615
 616static uint64_t mv88e6390_serdes_get_stat(struct mv88e6xxx_chip *chip, int lane,
 617					  struct mv88e6390_serdes_hw_stat *stat)
 618{
 619	u16 reg[3];
 620	int err, i;
 621
 622	for (i = 0; i < 3; i++) {
 623		err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 624					    stat->reg + i, &reg[i]);
 625		if (err) {
 626			dev_err(chip->dev, "failed to read statistic\n");
 627			return 0;
 628		}
 629	}
 630
 631	return reg[0] | ((u64)reg[1] << 16) | ((u64)reg[2] << 32);
 632}
 633
 634int mv88e6390_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
 635			       uint64_t *data)
 636{
 637	struct mv88e6390_serdes_hw_stat *stat;
 638	int lane;
 639	int i;
 640
 641	lane = mv88e6390_serdes_get_lane(chip, port);
 642	if (lane == 0)
 643		return 0;
 644
 645	for (i = 0; i < ARRAY_SIZE(mv88e6390_serdes_hw_stats); i++) {
 646		stat = &mv88e6390_serdes_hw_stats[i];
 647		data[i] = mv88e6390_serdes_get_stat(chip, lane, stat);
 648	}
 649
 650	return ARRAY_SIZE(mv88e6390_serdes_hw_stats);
 651}
 652
 653static int mv88e6390_serdes_enable_checker(struct mv88e6xxx_chip *chip, u8 lane)
 654{
 655	u16 reg;
 656	int err;
 657
 658	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 659				    MV88E6390_PG_CONTROL, &reg);
 660	if (err)
 661		return err;
 662
 663	reg |= MV88E6390_PG_CONTROL_ENABLE_PC;
 664	return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
 665				      MV88E6390_PG_CONTROL, reg);
 666}
 667
 668int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, u8 lane,
 669			   bool up)
 670{
 671	u8 cmode = chip->ports[port].cmode;
 672	int err = 0;
 673
 674	switch (cmode) {
 675	case MV88E6XXX_PORT_STS_CMODE_SGMII:
 676	case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
 677	case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
 678		err = mv88e6390_serdes_power_sgmii(chip, lane, up);
 679		break;
 680	case MV88E6XXX_PORT_STS_CMODE_XAUI:
 681	case MV88E6XXX_PORT_STS_CMODE_RXAUI:
 682		err = mv88e6390_serdes_power_10g(chip, lane, up);
 683		break;
 684	}
 685
 686	if (!err && up)
 687		err = mv88e6390_serdes_enable_checker(chip, lane);
 688
 689	return err;
 690}
 691
 692int mv88e6390_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port,
 693				u8 lane, unsigned int mode,
 694				phy_interface_t interface,
 695				const unsigned long *advertise)
 696{
 697	u16 val, bmcr, adv;
 698	bool changed;
 699	int err;
 700
 701	switch (interface) {
 702	case PHY_INTERFACE_MODE_SGMII:
 703		adv = 0x0001;
 704		break;
 705
 706	case PHY_INTERFACE_MODE_1000BASEX:
 707		adv = linkmode_adv_to_mii_adv_x(advertise,
 708					ETHTOOL_LINK_MODE_1000baseX_Full_BIT);
 709		break;
 710
 711	case PHY_INTERFACE_MODE_2500BASEX:
 712		adv = linkmode_adv_to_mii_adv_x(advertise,
 713					ETHTOOL_LINK_MODE_2500baseX_Full_BIT);
 714		break;
 715
 716	default:
 717		return 0;
 718	}
 719
 720	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 721				    MV88E6390_SGMII_ADVERTISE, &val);
 722	if (err)
 723		return err;
 724
 725	changed = val != adv;
 726	if (changed) {
 727		err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
 728					     MV88E6390_SGMII_ADVERTISE, adv);
 729		if (err)
 730			return err;
 731	}
 732
 733	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 734				    MV88E6390_SGMII_BMCR, &val);
 735	if (err)
 736		return err;
 737
 738	if (phylink_autoneg_inband(mode))
 739		bmcr = val | BMCR_ANENABLE;
 740	else
 741		bmcr = val & ~BMCR_ANENABLE;
 742
 743	/* setting ANENABLE triggers a restart of negotiation */
 744	if (bmcr == val)
 745		return changed;
 746
 747	return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
 748				      MV88E6390_SGMII_BMCR, bmcr);
 749}
 750
 751static int mv88e6390_serdes_pcs_get_state_sgmii(struct mv88e6xxx_chip *chip,
 752	int port, u8 lane, struct phylink_link_state *state)
 753{
 754	u16 lpa, status;
 755	int err;
 756
 757	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 758				    MV88E6390_SGMII_PHY_STATUS, &status);
 759	if (err) {
 760		dev_err(chip->dev, "can't read Serdes PHY status: %d\n", err);
 761		return err;
 762	}
 763
 764	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 765				    MV88E6390_SGMII_LPA, &lpa);
 766	if (err) {
 767		dev_err(chip->dev, "can't read Serdes PHY LPA: %d\n", err);
 768		return err;
 769	}
 770
 771	return mv88e6xxx_serdes_pcs_get_state(chip, status, lpa, state);
 772}
 773
 774static int mv88e6390_serdes_pcs_get_state_10g(struct mv88e6xxx_chip *chip,
 775	int port, u8 lane, struct phylink_link_state *state)
 776{
 777	u16 status;
 778	int err;
 779
 780	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 781				    MV88E6390_10G_STAT1, &status);
 782	if (err)
 783		return err;
 784
 785	state->link = !!(status & MDIO_STAT1_LSTATUS);
 786	if (state->link) {
 787		state->speed = SPEED_10000;
 788		state->duplex = DUPLEX_FULL;
 789	}
 790
 791	return 0;
 792}
 793
 794int mv88e6390_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port,
 795				   u8 lane, struct phylink_link_state *state)
 796{
 797	switch (state->interface) {
 798	case PHY_INTERFACE_MODE_SGMII:
 799	case PHY_INTERFACE_MODE_1000BASEX:
 800	case PHY_INTERFACE_MODE_2500BASEX:
 801		return mv88e6390_serdes_pcs_get_state_sgmii(chip, port, lane,
 802							    state);
 803	case PHY_INTERFACE_MODE_XAUI:
 804	case PHY_INTERFACE_MODE_RXAUI:
 805		return mv88e6390_serdes_pcs_get_state_10g(chip, port, lane,
 806							  state);
 807
 808	default:
 809		return -EOPNOTSUPP;
 810	}
 811}
 812
 813int mv88e6390_serdes_pcs_an_restart(struct mv88e6xxx_chip *chip, int port,
 814				    u8 lane)
 815{
 816	u16 bmcr;
 817	int err;
 818
 819	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 820				    MV88E6390_SGMII_BMCR, &bmcr);
 821	if (err)
 822		return err;
 823
 824	return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
 825				      MV88E6390_SGMII_BMCR,
 826				      bmcr | BMCR_ANRESTART);
 827}
 828
 829int mv88e6390_serdes_pcs_link_up(struct mv88e6xxx_chip *chip, int port,
 830				 u8 lane, int speed, int duplex)
 831{
 832	u16 val, bmcr;
 833	int err;
 834
 835	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 836				    MV88E6390_SGMII_BMCR, &val);
 837	if (err)
 838		return err;
 839
 840	bmcr = val & ~(BMCR_SPEED100 | BMCR_FULLDPLX | BMCR_SPEED1000);
 841	switch (speed) {
 842	case SPEED_2500:
 843	case SPEED_1000:
 844		bmcr |= BMCR_SPEED1000;
 845		break;
 846	case SPEED_100:
 847		bmcr |= BMCR_SPEED100;
 848		break;
 849	case SPEED_10:
 850		break;
 851	}
 852
 853	if (duplex == DUPLEX_FULL)
 854		bmcr |= BMCR_FULLDPLX;
 855
 856	if (bmcr == val)
 857		return 0;
 858
 859	return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
 860				      MV88E6390_SGMII_BMCR, bmcr);
 861}
 862
 863static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip,
 864					    int port, u8 lane)
 865{
 866	u16 bmsr;
 867	int err;
 868
 869	/* If the link has dropped, we want to know about it. */
 870	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 871				    MV88E6390_SGMII_BMSR, &bmsr);
 872	if (err) {
 873		dev_err(chip->dev, "can't read Serdes BMSR: %d\n", err);
 874		return;
 875	}
 876
 877	dsa_port_phylink_mac_change(chip->ds, port, !!(bmsr & BMSR_LSTATUS));
 878}
 879
 880static int mv88e6390_serdes_irq_enable_sgmii(struct mv88e6xxx_chip *chip,
 881					     u8 lane, bool enable)
 882{
 883	u16 val = 0;
 884
 885	if (enable)
 886		val |= MV88E6390_SGMII_INT_LINK_DOWN |
 887			MV88E6390_SGMII_INT_LINK_UP;
 888
 889	return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
 890				      MV88E6390_SGMII_INT_ENABLE, val);
 891}
 892
 893int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, u8 lane,
 894				bool enable)
 895{
 896	u8 cmode = chip->ports[port].cmode;
 897
 898	switch (cmode) {
 899	case MV88E6XXX_PORT_STS_CMODE_SGMII:
 900	case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
 901	case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
 902		return mv88e6390_serdes_irq_enable_sgmii(chip, lane, enable);
 903	}
 904
 905	return 0;
 906}
 907
 908static int mv88e6390_serdes_irq_status_sgmii(struct mv88e6xxx_chip *chip,
 909					     u8 lane, u16 *status)
 910{
 911	int err;
 912
 913	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 914				    MV88E6390_SGMII_INT_STATUS, status);
 915
 916	return err;
 917}
 918
 919irqreturn_t mv88e6390_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
 920					u8 lane)
 921{
 922	u8 cmode = chip->ports[port].cmode;
 923	irqreturn_t ret = IRQ_NONE;
 924	u16 status;
 925	int err;
 926
 927	switch (cmode) {
 928	case MV88E6XXX_PORT_STS_CMODE_SGMII:
 929	case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
 930	case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
 931		err = mv88e6390_serdes_irq_status_sgmii(chip, lane, &status);
 932		if (err)
 933			return ret;
 934		if (status & (MV88E6390_SGMII_INT_LINK_DOWN |
 935			      MV88E6390_SGMII_INT_LINK_UP)) {
 936			ret = IRQ_HANDLED;
 937			mv88e6390_serdes_irq_link_sgmii(chip, port, lane);
 938		}
 939	}
 940
 941	return ret;
 942}
 943
 944unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port)
 945{
 946	return irq_find_mapping(chip->g2_irq.domain, port);
 947}
 948
 949static const u16 mv88e6390_serdes_regs[] = {
 950	/* SERDES common registers */
 951	0xf00a, 0xf00b, 0xf00c,
 952	0xf010, 0xf011, 0xf012, 0xf013,
 953	0xf016, 0xf017, 0xf018,
 954	0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f,
 955	0xf020, 0xf021, 0xf022, 0xf023, 0xf024, 0xf025, 0xf026, 0xf027,
 956	0xf028, 0xf029,
 957	0xf030, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, 0xf037,
 958	0xf038, 0xf039,
 959	/* SGMII */
 960	0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007,
 961	0x2008,
 962	0x200f,
 963	0xa000, 0xa001, 0xa002, 0xa003,
 964	/* 10Gbase-X */
 965	0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006, 0x1007,
 966	0x1008,
 967	0x100e, 0x100f,
 968	0x1018, 0x1019,
 969	0x9000, 0x9001, 0x9002, 0x9003, 0x9004,
 970	0x9006,
 971	0x9010, 0x9011, 0x9012, 0x9013, 0x9014, 0x9015, 0x9016,
 972	/* 10Gbase-R */
 973	0x1020, 0x1021, 0x1022, 0x1023, 0x1024, 0x1025, 0x1026, 0x1027,
 974	0x1028, 0x1029, 0x102a, 0x102b,
 975};
 976
 977int mv88e6390_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port)
 978{
 979	if (mv88e6xxx_serdes_get_lane(chip, port) == 0)
 980		return 0;
 981
 982	return ARRAY_SIZE(mv88e6390_serdes_regs) * sizeof(u16);
 983}
 984
 985void mv88e6390_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p)
 986{
 987	u16 *p = _p;
 988	int lane;
 989	u16 reg;
 
 990	int i;
 991
 992	lane = mv88e6xxx_serdes_get_lane(chip, port);
 993	if (lane == 0)
 994		return;
 995
 996	for (i = 0 ; i < ARRAY_SIZE(mv88e6390_serdes_regs); i++) {
 997		mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 998				      mv88e6390_serdes_regs[i], &reg);
 999		p[i] = reg;
 
1000	}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1001}