Linux Audio

Check our new training course

Loading...
v4.17
 
  1/*
  2 * Marvell 88E6xxx SERDES manipulation, via SMI bus
  3 *
  4 * Copyright (c) 2008 Marvell Semiconductor
  5 *
  6 * Copyright (c) 2017 Andrew Lunn <andrew@lunn.ch>
  7 *
  8 * This program is free software; you can redistribute it and/or modify
  9 * it under the terms of the GNU General Public License as published by
 10 * the Free Software Foundation; either version 2 of the License, or
 11 * (at your option) any later version.
 12 */
 13
 
 
 14#include <linux/mii.h>
 15
 16#include "chip.h"
 17#include "global2.h"
 18#include "phy.h"
 19#include "port.h"
 20#include "serdes.h"
 21
 22static int mv88e6352_serdes_read(struct mv88e6xxx_chip *chip, int reg,
 23				 u16 *val)
 24{
 25	return mv88e6xxx_phy_page_read(chip, MV88E6352_ADDR_SERDES,
 26				       MV88E6352_SERDES_PAGE_FIBER,
 27				       reg, val);
 28}
 29
 30static int mv88e6352_serdes_write(struct mv88e6xxx_chip *chip, int reg,
 31				  u16 val)
 32{
 33	return mv88e6xxx_phy_page_write(chip, MV88E6352_ADDR_SERDES,
 34					MV88E6352_SERDES_PAGE_FIBER,
 35					reg, val);
 36}
 37
 38static int mv88e6352_serdes_power_set(struct mv88e6xxx_chip *chip, bool on)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 39{
 40	u16 val, new_val;
 41	int err;
 42
 43	err = mv88e6352_serdes_read(chip, MII_BMCR, &val);
 44	if (err)
 45		return err;
 46
 47	if (on)
 48		new_val = val & ~BMCR_PDOWN;
 49	else
 50		new_val = val | BMCR_PDOWN;
 51
 52	if (val != new_val)
 53		err = mv88e6352_serdes_write(chip, MII_BMCR, new_val);
 54
 55	return err;
 56}
 57
 58static bool mv88e6352_port_has_serdes(struct mv88e6xxx_chip *chip, int port)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 59{
 60	u8 cmode;
 61	int err;
 62
 63	err = mv88e6xxx_port_get_cmode(chip, port, &cmode);
 64	if (err) {
 65		dev_err(chip->dev, "failed to read cmode\n");
 66		return false;
 67	}
 68
 69	if ((cmode == MV88E6XXX_PORT_STS_CMODE_100BASE_X) ||
 70	    (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X) ||
 71	    (cmode == MV88E6XXX_PORT_STS_CMODE_SGMII))
 72		return true;
 
 
 
 
 
 
 
 73
 74	return false;
 75}
 76
 77int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
 
 78{
 
 79	int err;
 80
 81	if (mv88e6352_port_has_serdes(chip, port)) {
 82		err = mv88e6352_serdes_power_set(chip, on);
 83		if (err < 0)
 84			return err;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 85	}
 86
 87	return 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 88}
 89
 90struct mv88e6352_serdes_hw_stat {
 91	char string[ETH_GSTRING_LEN];
 92	int sizeof_stat;
 93	int reg;
 94};
 95
 96static struct mv88e6352_serdes_hw_stat mv88e6352_serdes_hw_stats[] = {
 97	{ "serdes_fibre_rx_error", 16, 21 },
 98	{ "serdes_PRBS_error", 32, 24 },
 99};
100
101int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port)
102{
103	if (mv88e6352_port_has_serdes(chip, port))
104		return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
105
106	return 0;
 
 
 
 
107}
108
109int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip,
110				 int port, uint8_t *data)
111{
112	struct mv88e6352_serdes_hw_stat *stat;
113	int i;
114
115	if (!mv88e6352_port_has_serdes(chip, port))
116		return 0;
 
117
118	for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_hw_stats); i++) {
119		stat = &mv88e6352_serdes_hw_stats[i];
120		memcpy(data + i * ETH_GSTRING_LEN, stat->string,
121		       ETH_GSTRING_LEN);
122	}
123	return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
124}
125
126static uint64_t mv88e6352_serdes_get_stat(struct mv88e6xxx_chip *chip,
127					  struct mv88e6352_serdes_hw_stat *stat)
128{
129	u64 val = 0;
130	u16 reg;
131	int err;
132
133	err = mv88e6352_serdes_read(chip, stat->reg, &reg);
134	if (err) {
135		dev_err(chip->dev, "failed to read statistic\n");
136		return 0;
137	}
138
139	val = reg;
140
141	if (stat->sizeof_stat == 32) {
142		err = mv88e6352_serdes_read(chip, stat->reg + 1, &reg);
143		if (err) {
144			dev_err(chip->dev, "failed to read statistic\n");
145			return 0;
146		}
147		val = val << 16 | reg;
148	}
149
150	return val;
151}
152
153int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
154			       uint64_t *data)
155{
156	struct mv88e6xxx_port *mv88e6xxx_port = &chip->ports[port];
157	struct mv88e6352_serdes_hw_stat *stat;
 
158	u64 value;
159	int i;
160
161	if (!mv88e6352_port_has_serdes(chip, port))
162		return 0;
 
163
164	BUILD_BUG_ON(ARRAY_SIZE(mv88e6352_serdes_hw_stats) >
165		     ARRAY_SIZE(mv88e6xxx_port->serdes_stats));
166
167	for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_hw_stats); i++) {
168		stat = &mv88e6352_serdes_hw_stats[i];
169		value = mv88e6352_serdes_get_stat(chip, stat);
170		mv88e6xxx_port->serdes_stats[i] += value;
171		data[i] = mv88e6xxx_port->serdes_stats[i];
172	}
173
174	return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
175}
176
177/* Set the power on/off for 10GBASE-R and 10GBASE-X4/X2 */
178static int mv88e6390_serdes_10g(struct mv88e6xxx_chip *chip, int addr, bool on)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
179{
180	u16 val, new_val;
181	int reg_c45;
182	int err;
183
184	reg_c45 = MII_ADDR_C45 | MV88E6390_SERDES_DEVICE |
185		MV88E6390_PCS_CONTROL_1;
186	err = mv88e6xxx_phy_read(chip, addr, reg_c45, &val);
187	if (err)
188		return err;
189
190	if (on)
191		new_val = val & ~(MV88E6390_PCS_CONTROL_1_RESET |
192				  MV88E6390_PCS_CONTROL_1_LOOPBACK |
193				  MV88E6390_PCS_CONTROL_1_PDOWN);
194	else
195		new_val = val | MV88E6390_PCS_CONTROL_1_PDOWN;
196
197	if (val != new_val)
198		err = mv88e6xxx_phy_write(chip, addr, reg_c45, new_val);
 
199
200	return err;
201}
202
203/* Set the power on/off for 10GBASE-R and 10GBASE-X4/X2 */
204static int mv88e6390_serdes_sgmii(struct mv88e6xxx_chip *chip, int addr,
205				  bool on)
206{
207	u16 val, new_val;
208	int reg_c45;
209	int err;
210
211	reg_c45 = MII_ADDR_C45 | MV88E6390_SERDES_DEVICE |
212		MV88E6390_SGMII_CONTROL;
213	err = mv88e6xxx_phy_read(chip, addr, reg_c45, &val);
214	if (err)
215		return err;
216
217	if (on)
218		new_val = val & ~(MV88E6390_SGMII_CONTROL_RESET |
219				  MV88E6390_SGMII_CONTROL_LOOPBACK |
220				  MV88E6390_SGMII_CONTROL_PDOWN);
221	else
222		new_val = val | MV88E6390_SGMII_CONTROL_PDOWN;
223
224	if (val != new_val)
225		err = mv88e6xxx_phy_write(chip, addr, reg_c45, new_val);
 
226
227	return err;
228}
229
230static int mv88e6390_serdes_lower(struct mv88e6xxx_chip *chip, u8 cmode,
231				  int port_donor, int lane, bool rxaui, bool on)
 
 
 
 
 
 
 
 
 
 
232{
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
233	int err;
234	u8 cmode_donor;
235
236	err = mv88e6xxx_port_get_cmode(chip, port_donor, &cmode_donor);
 
237	if (err)
238		return err;
239
240	switch (cmode_donor) {
241	case MV88E6XXX_PORT_STS_CMODE_RXAUI:
242		if (!rxaui)
243			break;
244		/* Fall through */
245	case MV88E6XXX_PORT_STS_CMODE_1000BASE_X:
 
 
 
 
 
 
246	case MV88E6XXX_PORT_STS_CMODE_SGMII:
 
247	case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
248		if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
249		    cmode == MV88E6XXX_PORT_STS_CMODE_SGMII)
250			return	mv88e6390_serdes_sgmii(chip, lane, on);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
251	}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
252	return 0;
253}
254
255static int mv88e6390_serdes_port9(struct mv88e6xxx_chip *chip, u8 cmode,
256				  bool on)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
257{
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
258	switch (cmode) {
259	case MV88E6XXX_PORT_STS_CMODE_1000BASE_X:
260	case MV88E6XXX_PORT_STS_CMODE_SGMII:
261		return mv88e6390_serdes_sgmii(chip, MV88E6390_PORT9_LANE0, on);
262	case MV88E6XXX_PORT_STS_CMODE_XAUI:
263	case MV88E6XXX_PORT_STS_CMODE_RXAUI:
264	case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
265		return mv88e6390_serdes_10g(chip, MV88E6390_PORT9_LANE0, on);
266	}
267
268	return 0;
269}
270
271static int mv88e6390_serdes_port10(struct mv88e6xxx_chip *chip, u8 cmode,
272				   bool on)
 
 
 
 
 
 
 
 
 
 
 
273{
 
 
 
 
 
 
 
 
 
 
 
 
 
 
274	switch (cmode) {
275	case MV88E6XXX_PORT_STS_CMODE_SGMII:
276		return mv88e6390_serdes_sgmii(chip, MV88E6390_PORT10_LANE0, on);
277	case MV88E6XXX_PORT_STS_CMODE_XAUI:
278	case MV88E6XXX_PORT_STS_CMODE_RXAUI:
279	case MV88E6XXX_PORT_STS_CMODE_1000BASE_X:
280	case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
281		return mv88e6390_serdes_10g(chip, MV88E6390_PORT10_LANE0, on);
 
 
 
282	}
283
284	return 0;
285}
286
287int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
288{
289	u8 cmode;
 
 
290	int err;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
291
292	err = mv88e6xxx_port_get_cmode(chip, port, &cmode);
 
 
 
 
 
 
 
 
 
 
 
293	if (err)
294		return err;
295
296	switch (port) {
297	case 2:
298		return mv88e6390_serdes_lower(chip, cmode, 9,
299					      MV88E6390_PORT9_LANE1,
300					      false, on);
301	case 3:
302		return mv88e6390_serdes_lower(chip, cmode, 9,
303					      MV88E6390_PORT9_LANE2,
304					      true, on);
305	case 4:
306		return mv88e6390_serdes_lower(chip, cmode, 9,
307					      MV88E6390_PORT9_LANE3,
308					      true, on);
309	case 5:
310		return mv88e6390_serdes_lower(chip, cmode, 10,
311					      MV88E6390_PORT10_LANE1,
312					      false, on);
313	case 6:
314		return mv88e6390_serdes_lower(chip, cmode, 10,
315					      MV88E6390_PORT10_LANE2,
316					      true, on);
317	case 7:
318		return mv88e6390_serdes_lower(chip, cmode, 10,
319					      MV88E6390_PORT10_LANE3,
320					      true, on);
321	case 9:
322		return mv88e6390_serdes_port9(chip, cmode, on);
323	case 10:
324		return mv88e6390_serdes_port10(chip, cmode, on);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
325	}
326
327	return 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
328}
v6.2
   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 bmsr, u16 lpa, u16 status,
  54					  struct phylink_link_state *state)
  55{
  56	state->link = false;
  57
  58	/* If the BMSR reports that the link had failed, report this to
  59	 * phylink.
  60	 */
  61	if (!(bmsr & BMSR_LSTATUS))
  62		return 0;
  63
  64	state->link = !!(status & MV88E6390_SGMII_PHY_STATUS_LINK);
  65	state->an_complete = !!(bmsr & BMSR_ANEGCOMPLETE);
  66
  67	if (status & MV88E6390_SGMII_PHY_STATUS_SPD_DPL_VALID) {
  68		/* The Spped and Duplex Resolved register is 1 if AN is enabled
  69		 * and complete, or if AN is disabled. So with disabled AN we
  70		 * still get here on link up.
  71		 */
  72		state->duplex = status &
  73				MV88E6390_SGMII_PHY_STATUS_DUPLEX_FULL ?
  74			                         DUPLEX_FULL : DUPLEX_HALF;
  75
  76		if (status & MV88E6390_SGMII_PHY_STATUS_TX_PAUSE)
  77			state->pause |= MLO_PAUSE_TX;
  78		if (status & MV88E6390_SGMII_PHY_STATUS_RX_PAUSE)
  79			state->pause |= MLO_PAUSE_RX;
  80
  81		switch (status & MV88E6390_SGMII_PHY_STATUS_SPEED_MASK) {
  82		case MV88E6390_SGMII_PHY_STATUS_SPEED_1000:
  83			if (state->interface == PHY_INTERFACE_MODE_2500BASEX)
  84				state->speed = SPEED_2500;
  85			else
  86				state->speed = SPEED_1000;
  87			break;
  88		case MV88E6390_SGMII_PHY_STATUS_SPEED_100:
  89			state->speed = SPEED_100;
  90			break;
  91		case MV88E6390_SGMII_PHY_STATUS_SPEED_10:
  92			state->speed = SPEED_10;
  93			break;
  94		default:
  95			dev_err(chip->dev, "invalid PHY speed\n");
  96			return -EINVAL;
  97		}
  98	} else if (state->link &&
  99		   state->interface != PHY_INTERFACE_MODE_SGMII) {
 100		/* If Speed and Duplex Resolved register is 0 and link is up, it
 101		 * means that AN was enabled, but link partner had it disabled
 102		 * and the PHY invoked the Auto-Negotiation Bypass feature and
 103		 * linked anyway.
 104		 */
 105		state->duplex = DUPLEX_FULL;
 106		if (state->interface == PHY_INTERFACE_MODE_2500BASEX)
 107			state->speed = SPEED_2500;
 108		else
 109			state->speed = SPEED_1000;
 110	} else {
 111		state->link = false;
 112	}
 113
 114	if (state->interface == PHY_INTERFACE_MODE_2500BASEX)
 115		mii_lpa_mod_linkmode_x(state->lp_advertising, lpa,
 116				       ETHTOOL_LINK_MODE_2500baseX_Full_BIT);
 117	else if (state->interface == PHY_INTERFACE_MODE_1000BASEX)
 118		mii_lpa_mod_linkmode_x(state->lp_advertising, lpa,
 119				       ETHTOOL_LINK_MODE_1000baseX_Full_BIT);
 120
 121	return 0;
 122}
 123
 124int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane,
 125			   bool up)
 126{
 127	u16 val, new_val;
 128	int err;
 129
 130	err = mv88e6352_serdes_read(chip, MII_BMCR, &val);
 131	if (err)
 132		return err;
 133
 134	if (up)
 135		new_val = val & ~BMCR_PDOWN;
 136	else
 137		new_val = val | BMCR_PDOWN;
 138
 139	if (val != new_val)
 140		err = mv88e6352_serdes_write(chip, MII_BMCR, new_val);
 141
 142	return err;
 143}
 144
 145int mv88e6352_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port,
 146				int lane, unsigned int mode,
 147				phy_interface_t interface,
 148				const unsigned long *advertise)
 149{
 150	u16 adv, bmcr, val;
 151	bool changed;
 152	int err;
 153
 154	switch (interface) {
 155	case PHY_INTERFACE_MODE_SGMII:
 156		adv = 0x0001;
 157		break;
 158
 159	case PHY_INTERFACE_MODE_1000BASEX:
 160		adv = linkmode_adv_to_mii_adv_x(advertise,
 161					ETHTOOL_LINK_MODE_1000baseX_Full_BIT);
 162		break;
 163
 164	default:
 165		return 0;
 166	}
 167
 168	err = mv88e6352_serdes_read(chip, MII_ADVERTISE, &val);
 169	if (err)
 170		return err;
 171
 172	changed = val != adv;
 173	if (changed) {
 174		err = mv88e6352_serdes_write(chip, MII_ADVERTISE, adv);
 175		if (err)
 176			return err;
 177	}
 178
 179	err = mv88e6352_serdes_read(chip, MII_BMCR, &val);
 180	if (err)
 181		return err;
 182
 183	if (phylink_autoneg_inband(mode))
 184		bmcr = val | BMCR_ANENABLE;
 185	else
 186		bmcr = val & ~BMCR_ANENABLE;
 187
 188	if (bmcr == val)
 189		return changed;
 190
 191	return mv88e6352_serdes_write(chip, MII_BMCR, bmcr);
 192}
 193
 194int mv88e6352_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port,
 195				   int lane, struct phylink_link_state *state)
 196{
 197	u16 bmsr, lpa, status;
 198	int err;
 199
 200	err = mv88e6352_serdes_read(chip, MII_BMSR, &bmsr);
 201	if (err) {
 202		dev_err(chip->dev, "can't read Serdes PHY BMSR: %d\n", err);
 203		return err;
 204	}
 205
 206	err = mv88e6352_serdes_read(chip, 0x11, &status);
 207	if (err) {
 208		dev_err(chip->dev, "can't read Serdes PHY status: %d\n", err);
 209		return err;
 210	}
 211
 212	err = mv88e6352_serdes_read(chip, MII_LPA, &lpa);
 213	if (err) {
 214		dev_err(chip->dev, "can't read Serdes PHY LPA: %d\n", err);
 215		return err;
 216	}
 217
 218	return mv88e6xxx_serdes_pcs_get_state(chip, bmsr, lpa, status, state);
 219}
 220
 221int mv88e6352_serdes_pcs_an_restart(struct mv88e6xxx_chip *chip, int port,
 222				    int lane)
 223{
 224	u16 bmcr;
 225	int err;
 226
 227	err = mv88e6352_serdes_read(chip, MII_BMCR, &bmcr);
 228	if (err)
 229		return err;
 230
 231	return mv88e6352_serdes_write(chip, MII_BMCR, bmcr | BMCR_ANRESTART);
 232}
 233
 234int mv88e6352_serdes_pcs_link_up(struct mv88e6xxx_chip *chip, int port,
 235				 int lane, int speed, int duplex)
 236{
 237	u16 val, bmcr;
 238	int err;
 239
 240	err = mv88e6352_serdes_read(chip, MII_BMCR, &val);
 241	if (err)
 242		return err;
 243
 244	bmcr = val & ~(BMCR_SPEED100 | BMCR_FULLDPLX | BMCR_SPEED1000);
 245	switch (speed) {
 246	case SPEED_1000:
 247		bmcr |= BMCR_SPEED1000;
 248		break;
 249	case SPEED_100:
 250		bmcr |= BMCR_SPEED100;
 251		break;
 252	case SPEED_10:
 253		break;
 254	}
 255
 256	if (duplex == DUPLEX_FULL)
 257		bmcr |= BMCR_FULLDPLX;
 258
 259	if (bmcr == val)
 260		return 0;
 261
 262	return mv88e6352_serdes_write(chip, MII_BMCR, bmcr);
 263}
 264
 265int mv88e6352_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
 266{
 267	u8 cmode = chip->ports[port].cmode;
 268	int lane = -ENODEV;
 269
 270	if ((cmode == MV88E6XXX_PORT_STS_CMODE_100BASEX) ||
 271	    (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX) ||
 272	    (cmode == MV88E6XXX_PORT_STS_CMODE_SGMII))
 273		lane = 0xff; /* Unused */
 274
 275	return lane;
 276}
 277
 278struct mv88e6352_serdes_hw_stat {
 279	char string[ETH_GSTRING_LEN];
 280	int sizeof_stat;
 281	int reg;
 282};
 283
 284static struct mv88e6352_serdes_hw_stat mv88e6352_serdes_hw_stats[] = {
 285	{ "serdes_fibre_rx_error", 16, 21 },
 286	{ "serdes_PRBS_error", 32, 24 },
 287};
 288
 289int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port)
 290{
 291	int err;
 
 292
 293	err = mv88e6352_g2_scratch_port_has_serdes(chip, port);
 294	if (err <= 0)
 295		return err;
 296
 297	return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
 298}
 299
 300int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip,
 301				 int port, uint8_t *data)
 302{
 303	struct mv88e6352_serdes_hw_stat *stat;
 304	int err, i;
 305
 306	err = mv88e6352_g2_scratch_port_has_serdes(chip, port);
 307	if (err <= 0)
 308		return err;
 309
 310	for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_hw_stats); i++) {
 311		stat = &mv88e6352_serdes_hw_stats[i];
 312		memcpy(data + i * ETH_GSTRING_LEN, stat->string,
 313		       ETH_GSTRING_LEN);
 314	}
 315	return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
 316}
 317
 318static uint64_t mv88e6352_serdes_get_stat(struct mv88e6xxx_chip *chip,
 319					  struct mv88e6352_serdes_hw_stat *stat)
 320{
 321	u64 val = 0;
 322	u16 reg;
 323	int err;
 324
 325	err = mv88e6352_serdes_read(chip, stat->reg, &reg);
 326	if (err) {
 327		dev_err(chip->dev, "failed to read statistic\n");
 328		return 0;
 329	}
 330
 331	val = reg;
 332
 333	if (stat->sizeof_stat == 32) {
 334		err = mv88e6352_serdes_read(chip, stat->reg + 1, &reg);
 335		if (err) {
 336			dev_err(chip->dev, "failed to read statistic\n");
 337			return 0;
 338		}
 339		val = val << 16 | reg;
 340	}
 341
 342	return val;
 343}
 344
 345int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
 346			       uint64_t *data)
 347{
 348	struct mv88e6xxx_port *mv88e6xxx_port = &chip->ports[port];
 349	struct mv88e6352_serdes_hw_stat *stat;
 350	int i, err;
 351	u64 value;
 
 352
 353	err = mv88e6352_g2_scratch_port_has_serdes(chip, port);
 354	if (err <= 0)
 355		return err;
 356
 357	BUILD_BUG_ON(ARRAY_SIZE(mv88e6352_serdes_hw_stats) >
 358		     ARRAY_SIZE(mv88e6xxx_port->serdes_stats));
 359
 360	for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_hw_stats); i++) {
 361		stat = &mv88e6352_serdes_hw_stats[i];
 362		value = mv88e6352_serdes_get_stat(chip, stat);
 363		mv88e6xxx_port->serdes_stats[i] += value;
 364		data[i] = mv88e6xxx_port->serdes_stats[i];
 365	}
 366
 367	return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
 368}
 369
 370static void mv88e6352_serdes_irq_link(struct mv88e6xxx_chip *chip, int port)
 371{
 372	u16 bmsr;
 373	int err;
 374
 375	/* If the link has dropped, we want to know about it. */
 376	err = mv88e6352_serdes_read(chip, MII_BMSR, &bmsr);
 377	if (err) {
 378		dev_err(chip->dev, "can't read Serdes BMSR: %d\n", err);
 379		return;
 380	}
 381
 382	dsa_port_phylink_mac_change(chip->ds, port, !!(bmsr & BMSR_LSTATUS));
 383}
 384
 385irqreturn_t mv88e6352_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
 386					int lane)
 387{
 388	irqreturn_t ret = IRQ_NONE;
 389	u16 status;
 390	int err;
 391
 392	err = mv88e6352_serdes_read(chip, MV88E6352_SERDES_INT_STATUS, &status);
 393	if (err)
 394		return ret;
 395
 396	if (status & MV88E6352_SERDES_INT_LINK_CHANGE) {
 397		ret = IRQ_HANDLED;
 398		mv88e6352_serdes_irq_link(chip, port);
 399	}
 400
 401	return ret;
 402}
 403
 404int mv88e6352_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, int lane,
 405				bool enable)
 406{
 407	u16 val = 0;
 408
 409	if (enable)
 410		val |= MV88E6352_SERDES_INT_LINK_CHANGE;
 411
 412	return mv88e6352_serdes_write(chip, MV88E6352_SERDES_INT_ENABLE, val);
 413}
 414
 415unsigned int mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port)
 416{
 417	return irq_find_mapping(chip->g2_irq.domain, MV88E6352_SERDES_IRQ);
 418}
 419
 420int mv88e6352_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port)
 421{
 422	int err;
 423
 424	mv88e6xxx_reg_lock(chip);
 425	err = mv88e6352_g2_scratch_port_has_serdes(chip, port);
 426	mv88e6xxx_reg_unlock(chip);
 427	if (err <= 0)
 428		return err;
 429
 430	return 32 * sizeof(u16);
 431}
 432
 433void mv88e6352_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p)
 434{
 435	u16 *p = _p;
 436	u16 reg;
 437	int err;
 438	int i;
 439
 440	err = mv88e6352_g2_scratch_port_has_serdes(chip, port);
 441	if (err <= 0)
 442		return;
 443
 444	for (i = 0 ; i < 32; i++) {
 445		err = mv88e6352_serdes_read(chip, i, &reg);
 446		if (!err)
 447			p[i] = reg;
 448	}
 449}
 450
 451int mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
 452{
 453	u8 cmode = chip->ports[port].cmode;
 454	int lane = -ENODEV;
 455
 456	switch (port) {
 457	case 5:
 458		if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 459		    cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
 460		    cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
 461			lane = MV88E6341_PORT5_LANE;
 462		break;
 463	}
 464
 465	return lane;
 466}
 467
 468int mv88e6185_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane,
 469			   bool up)
 470{
 471	/* The serdes power can't be controlled on this switch chip but we need
 472	 * to supply this function to avoid returning -EOPNOTSUPP in
 473	 * mv88e6xxx_serdes_power_up/mv88e6xxx_serdes_power_down
 474	 */
 475	return 0;
 476}
 477
 478int mv88e6185_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
 479{
 480	/* There are no configurable serdes lanes on this switch chip but we
 481	 * need to return a non-negative lane number so that callers of
 482	 * mv88e6xxx_serdes_get_lane() know this is a serdes port.
 483	 */
 484	switch (chip->ports[port].cmode) {
 485	case MV88E6185_PORT_STS_CMODE_SERDES:
 486	case MV88E6185_PORT_STS_CMODE_1000BASE_X:
 487		return 0;
 488	default:
 489		return -ENODEV;
 490	}
 491}
 492
 493int mv88e6185_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port,
 494				   int lane, struct phylink_link_state *state)
 495{
 496	int err;
 497	u16 status;
 498
 499	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &status);
 500	if (err)
 501		return err;
 502
 503	state->link = !!(status & MV88E6XXX_PORT_STS_LINK);
 504
 505	if (state->link) {
 506		state->duplex = status & MV88E6XXX_PORT_STS_DUPLEX ? DUPLEX_FULL : DUPLEX_HALF;
 507
 508		switch (status &  MV88E6XXX_PORT_STS_SPEED_MASK) {
 509		case MV88E6XXX_PORT_STS_SPEED_1000:
 510			state->speed = SPEED_1000;
 511			break;
 512		case MV88E6XXX_PORT_STS_SPEED_100:
 513			state->speed = SPEED_100;
 514			break;
 515		case MV88E6XXX_PORT_STS_SPEED_10:
 516			state->speed = SPEED_10;
 517			break;
 518		default:
 519			dev_err(chip->dev, "invalid PHY speed\n");
 520			return -EINVAL;
 521		}
 522	} else {
 523		state->duplex = DUPLEX_UNKNOWN;
 524		state->speed = SPEED_UNKNOWN;
 525	}
 526
 527	return 0;
 528}
 529
 530int mv88e6097_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, int lane,
 531				bool enable)
 532{
 533	u8 cmode = chip->ports[port].cmode;
 534
 535	/* The serdes interrupts are enabled in the G2_INT_MASK register. We
 536	 * need to return 0 to avoid returning -EOPNOTSUPP in
 537	 * mv88e6xxx_serdes_irq_enable/mv88e6xxx_serdes_irq_disable
 538	 */
 539	switch (cmode) {
 540	case MV88E6185_PORT_STS_CMODE_SERDES:
 541	case MV88E6185_PORT_STS_CMODE_1000BASE_X:
 542		return 0;
 543	}
 544
 545	return -EOPNOTSUPP;
 546}
 547
 548static void mv88e6097_serdes_irq_link(struct mv88e6xxx_chip *chip, int port)
 549{
 550	u16 status;
 551	int err;
 552
 553	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &status);
 554	if (err) {
 555		dev_err(chip->dev, "can't read port status: %d\n", err);
 556		return;
 557	}
 558
 559	dsa_port_phylink_mac_change(chip->ds, port, !!(status & MV88E6XXX_PORT_STS_LINK));
 560}
 561
 562irqreturn_t mv88e6097_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
 563					int lane)
 564{
 565	u8 cmode = chip->ports[port].cmode;
 566
 567	switch (cmode) {
 568	case MV88E6185_PORT_STS_CMODE_SERDES:
 569	case MV88E6185_PORT_STS_CMODE_1000BASE_X:
 570		mv88e6097_serdes_irq_link(chip, port);
 571		return IRQ_HANDLED;
 572	}
 573
 574	return IRQ_NONE;
 575}
 576
 577int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
 578{
 579	u8 cmode = chip->ports[port].cmode;
 580	int lane = -ENODEV;
 581
 582	switch (port) {
 583	case 9:
 584		if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 585		    cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
 586		    cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
 587			lane = MV88E6390_PORT9_LANE0;
 588		break;
 589	case 10:
 590		if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 591		    cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
 592		    cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
 593			lane = MV88E6390_PORT10_LANE0;
 594		break;
 595	}
 596
 597	return lane;
 598}
 599
 600int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
 601{
 602	u8 cmode_port = chip->ports[port].cmode;
 603	u8 cmode_port10 = chip->ports[10].cmode;
 604	u8 cmode_port9 = chip->ports[9].cmode;
 605	int lane = -ENODEV;
 606
 607	switch (port) {
 608	case 2:
 609		if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 610		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
 611		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
 612			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
 613				lane = MV88E6390_PORT9_LANE1;
 614		break;
 615	case 3:
 616		if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 617		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
 618		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
 619		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
 620			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
 621				lane = MV88E6390_PORT9_LANE2;
 622		break;
 623	case 4:
 624		if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 625		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
 626		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
 627		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
 628			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
 629				lane = MV88E6390_PORT9_LANE3;
 630		break;
 631	case 5:
 632		if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 633		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
 634		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
 635			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
 636				lane = MV88E6390_PORT10_LANE1;
 637		break;
 638	case 6:
 639		if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 640		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
 641		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
 642		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
 643			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
 644				lane = MV88E6390_PORT10_LANE2;
 645		break;
 646	case 7:
 647		if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 648		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
 649		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
 650		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
 651			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
 652				lane = MV88E6390_PORT10_LANE3;
 653		break;
 654	case 9:
 655		if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 656		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
 657		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
 658		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_XAUI ||
 659		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
 660			lane = MV88E6390_PORT9_LANE0;
 661		break;
 662	case 10:
 663		if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 664		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
 665		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
 666		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_XAUI ||
 667		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
 668			lane = MV88E6390_PORT10_LANE0;
 669		break;
 670	}
 671
 672	return lane;
 673}
 674
 675/* Only Ports 0, 9 and 10 have SERDES lanes. Return the SERDES lane address
 676 * a port is using else Returns -ENODEV.
 677 */
 678int mv88e6393x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
 679{
 680	u8 cmode = chip->ports[port].cmode;
 681	int lane = -ENODEV;
 682
 683	if (port != 0 && port != 9 && port != 10)
 684		return -EOPNOTSUPP;
 685
 686	if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 687	    cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
 688	    cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
 689	    cmode == MV88E6393X_PORT_STS_CMODE_5GBASER ||
 690	    cmode == MV88E6393X_PORT_STS_CMODE_10GBASER)
 691		lane = port;
 692
 693	return lane;
 694}
 695
 696/* Set power up/down for 10GBASE-R and 10GBASE-X4/X2 */
 697static int mv88e6390_serdes_power_10g(struct mv88e6xxx_chip *chip, int lane,
 698				      bool up)
 699{
 700	u16 val, new_val;
 
 701	int err;
 702
 703	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 704				    MV88E6390_10G_CTRL1, &val);
 705
 706	if (err)
 707		return err;
 708
 709	if (up)
 710		new_val = val & ~(MDIO_CTRL1_RESET |
 711				  MDIO_PCS_CTRL1_LOOPBACK |
 712				  MDIO_CTRL1_LPOWER);
 713	else
 714		new_val = val | MDIO_CTRL1_LPOWER;
 715
 716	if (val != new_val)
 717		err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
 718					     MV88E6390_10G_CTRL1, new_val);
 719
 720	return err;
 721}
 722
 723/* Set power up/down for SGMII and 1000Base-X */
 724static int mv88e6390_serdes_power_sgmii(struct mv88e6xxx_chip *chip, int lane,
 725					bool up)
 726{
 727	u16 val, new_val;
 
 728	int err;
 729
 730	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 731				    MV88E6390_SGMII_BMCR, &val);
 
 732	if (err)
 733		return err;
 734
 735	if (up)
 736		new_val = val & ~(BMCR_RESET | BMCR_LOOPBACK | BMCR_PDOWN);
 
 
 737	else
 738		new_val = val | BMCR_PDOWN;
 739
 740	if (val != new_val)
 741		err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
 742					     MV88E6390_SGMII_BMCR, new_val);
 743
 744	return err;
 745}
 746
 747struct mv88e6390_serdes_hw_stat {
 748	char string[ETH_GSTRING_LEN];
 749	int reg;
 750};
 751
 752static struct mv88e6390_serdes_hw_stat mv88e6390_serdes_hw_stats[] = {
 753	{ "serdes_rx_pkts", 0xf021 },
 754	{ "serdes_rx_bytes", 0xf024 },
 755	{ "serdes_rx_pkts_error", 0xf027 },
 756};
 757
 758int mv88e6390_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port)
 759{
 760	if (mv88e6xxx_serdes_get_lane(chip, port) < 0)
 761		return 0;
 762
 763	return ARRAY_SIZE(mv88e6390_serdes_hw_stats);
 764}
 765
 766int mv88e6390_serdes_get_strings(struct mv88e6xxx_chip *chip,
 767				 int port, uint8_t *data)
 768{
 769	struct mv88e6390_serdes_hw_stat *stat;
 770	int i;
 771
 772	if (mv88e6xxx_serdes_get_lane(chip, port) < 0)
 773		return 0;
 774
 775	for (i = 0; i < ARRAY_SIZE(mv88e6390_serdes_hw_stats); i++) {
 776		stat = &mv88e6390_serdes_hw_stats[i];
 777		memcpy(data + i * ETH_GSTRING_LEN, stat->string,
 778		       ETH_GSTRING_LEN);
 779	}
 780	return ARRAY_SIZE(mv88e6390_serdes_hw_stats);
 781}
 782
 783static uint64_t mv88e6390_serdes_get_stat(struct mv88e6xxx_chip *chip, int lane,
 784					  struct mv88e6390_serdes_hw_stat *stat)
 785{
 786	u16 reg[3];
 787	int err, i;
 788
 789	for (i = 0; i < 3; i++) {
 790		err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 791					    stat->reg + i, &reg[i]);
 792		if (err) {
 793			dev_err(chip->dev, "failed to read statistic\n");
 794			return 0;
 795		}
 796	}
 797
 798	return reg[0] | ((u64)reg[1] << 16) | ((u64)reg[2] << 32);
 799}
 800
 801int mv88e6390_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
 802			       uint64_t *data)
 803{
 804	struct mv88e6390_serdes_hw_stat *stat;
 805	int lane;
 806	int i;
 807
 808	lane = mv88e6xxx_serdes_get_lane(chip, port);
 809	if (lane < 0)
 810		return 0;
 811
 812	for (i = 0; i < ARRAY_SIZE(mv88e6390_serdes_hw_stats); i++) {
 813		stat = &mv88e6390_serdes_hw_stats[i];
 814		data[i] = mv88e6390_serdes_get_stat(chip, lane, stat);
 815	}
 816
 817	return ARRAY_SIZE(mv88e6390_serdes_hw_stats);
 818}
 819
 820static int mv88e6390_serdes_enable_checker(struct mv88e6xxx_chip *chip, int lane)
 821{
 822	u16 reg;
 823	int err;
 
 824
 825	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 826				    MV88E6390_PG_CONTROL, &reg);
 827	if (err)
 828		return err;
 829
 830	reg |= MV88E6390_PG_CONTROL_ENABLE_PC;
 831	return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
 832				      MV88E6390_PG_CONTROL, reg);
 833}
 834
 835int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane,
 836			   bool up)
 837{
 838	u8 cmode = chip->ports[port].cmode;
 839	int err;
 840
 841	switch (cmode) {
 842	case MV88E6XXX_PORT_STS_CMODE_SGMII:
 843	case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
 844	case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
 845		err = mv88e6390_serdes_power_sgmii(chip, lane, up);
 846		break;
 847	case MV88E6XXX_PORT_STS_CMODE_XAUI:
 848	case MV88E6XXX_PORT_STS_CMODE_RXAUI:
 849		err = mv88e6390_serdes_power_10g(chip, lane, up);
 850		break;
 851	default:
 852		err = -EINVAL;
 853		break;
 854	}
 855
 856	if (!err && up)
 857		err = mv88e6390_serdes_enable_checker(chip, lane);
 858
 859	return err;
 860}
 861
 862int mv88e6390_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port,
 863				int lane, unsigned int mode,
 864				phy_interface_t interface,
 865				const unsigned long *advertise)
 866{
 867	u16 val, bmcr, adv;
 868	bool changed;
 869	int err;
 870
 871	switch (interface) {
 872	case PHY_INTERFACE_MODE_SGMII:
 873		adv = 0x0001;
 874		break;
 875
 876	case PHY_INTERFACE_MODE_1000BASEX:
 877		adv = linkmode_adv_to_mii_adv_x(advertise,
 878					ETHTOOL_LINK_MODE_1000baseX_Full_BIT);
 879		break;
 880
 881	case PHY_INTERFACE_MODE_2500BASEX:
 882		adv = linkmode_adv_to_mii_adv_x(advertise,
 883					ETHTOOL_LINK_MODE_2500baseX_Full_BIT);
 884		break;
 885
 886	default:
 887		return 0;
 888	}
 889
 890	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 891				    MV88E6390_SGMII_ADVERTISE, &val);
 892	if (err)
 893		return err;
 894
 895	changed = val != adv;
 896	if (changed) {
 897		err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
 898					     MV88E6390_SGMII_ADVERTISE, adv);
 899		if (err)
 900			return err;
 901	}
 902
 903	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 904				    MV88E6390_SGMII_BMCR, &val);
 905	if (err)
 906		return err;
 907
 908	if (phylink_autoneg_inband(mode))
 909		bmcr = val | BMCR_ANENABLE;
 910	else
 911		bmcr = val & ~BMCR_ANENABLE;
 912
 913	/* setting ANENABLE triggers a restart of negotiation */
 914	if (bmcr == val)
 915		return changed;
 916
 917	return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
 918				      MV88E6390_SGMII_BMCR, bmcr);
 919}
 920
 921static int mv88e6390_serdes_pcs_get_state_sgmii(struct mv88e6xxx_chip *chip,
 922	int port, int lane, struct phylink_link_state *state)
 923{
 924	u16 bmsr, lpa, status;
 925	int err;
 926
 927	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 928				    MV88E6390_SGMII_BMSR, &bmsr);
 929	if (err) {
 930		dev_err(chip->dev, "can't read Serdes PHY BMSR: %d\n", err);
 931		return err;
 932	}
 933
 934	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 935				    MV88E6390_SGMII_PHY_STATUS, &status);
 936	if (err) {
 937		dev_err(chip->dev, "can't read Serdes PHY status: %d\n", err);
 938		return err;
 939	}
 940
 941	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 942				    MV88E6390_SGMII_LPA, &lpa);
 943	if (err) {
 944		dev_err(chip->dev, "can't read Serdes PHY LPA: %d\n", err);
 945		return err;
 946	}
 947
 948	return mv88e6xxx_serdes_pcs_get_state(chip, bmsr, lpa, status, state);
 949}
 950
 951static int mv88e6390_serdes_pcs_get_state_10g(struct mv88e6xxx_chip *chip,
 952	int port, int lane, struct phylink_link_state *state)
 953{
 954	u16 status;
 955	int err;
 956
 957	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 958				    MV88E6390_10G_STAT1, &status);
 959	if (err)
 960		return err;
 961
 962	state->link = !!(status & MDIO_STAT1_LSTATUS);
 963	if (state->link) {
 964		state->speed = SPEED_10000;
 965		state->duplex = DUPLEX_FULL;
 966	}
 967
 968	return 0;
 969}
 970
 971static int mv88e6393x_serdes_pcs_get_state_10g(struct mv88e6xxx_chip *chip,
 972					       int port, int lane,
 973					       struct phylink_link_state *state)
 974{
 975	u16 status;
 976	int err;
 977
 978	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 979				    MV88E6390_10G_STAT1, &status);
 980	if (err)
 981		return err;
 982
 983	state->link = !!(status & MDIO_STAT1_LSTATUS);
 984	if (state->link) {
 985		if (state->interface == PHY_INTERFACE_MODE_5GBASER)
 986			state->speed = SPEED_5000;
 987		else
 988			state->speed = SPEED_10000;
 989		state->duplex = DUPLEX_FULL;
 990	}
 991
 992	return 0;
 993}
 994
 995int mv88e6390_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port,
 996				   int lane, struct phylink_link_state *state)
 997{
 998	switch (state->interface) {
 999	case PHY_INTERFACE_MODE_SGMII:
1000	case PHY_INTERFACE_MODE_1000BASEX:
1001	case PHY_INTERFACE_MODE_2500BASEX:
1002		return mv88e6390_serdes_pcs_get_state_sgmii(chip, port, lane,
1003							    state);
1004	case PHY_INTERFACE_MODE_XAUI:
1005	case PHY_INTERFACE_MODE_RXAUI:
1006		return mv88e6390_serdes_pcs_get_state_10g(chip, port, lane,
1007							  state);
1008
1009	default:
1010		return -EOPNOTSUPP;
1011	}
1012}
1013
1014int mv88e6393x_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port,
1015				    int lane, struct phylink_link_state *state)
1016{
1017	switch (state->interface) {
1018	case PHY_INTERFACE_MODE_SGMII:
1019	case PHY_INTERFACE_MODE_1000BASEX:
1020	case PHY_INTERFACE_MODE_2500BASEX:
1021		return mv88e6390_serdes_pcs_get_state_sgmii(chip, port, lane,
1022							    state);
1023	case PHY_INTERFACE_MODE_5GBASER:
1024	case PHY_INTERFACE_MODE_10GBASER:
1025		return mv88e6393x_serdes_pcs_get_state_10g(chip, port, lane,
1026							   state);
1027
1028	default:
1029		return -EOPNOTSUPP;
1030	}
1031}
1032
1033int mv88e6390_serdes_pcs_an_restart(struct mv88e6xxx_chip *chip, int port,
1034				    int lane)
1035{
1036	u16 bmcr;
1037	int err;
1038
1039	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
1040				    MV88E6390_SGMII_BMCR, &bmcr);
1041	if (err)
1042		return err;
1043
1044	return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
1045				      MV88E6390_SGMII_BMCR,
1046				      bmcr | BMCR_ANRESTART);
1047}
1048
1049int mv88e6390_serdes_pcs_link_up(struct mv88e6xxx_chip *chip, int port,
1050				 int lane, int speed, int duplex)
1051{
1052	u16 val, bmcr;
1053	int err;
1054
1055	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
1056				    MV88E6390_SGMII_BMCR, &val);
1057	if (err)
1058		return err;
1059
1060	bmcr = val & ~(BMCR_SPEED100 | BMCR_FULLDPLX | BMCR_SPEED1000);
1061	switch (speed) {
1062	case SPEED_2500:
1063	case SPEED_1000:
1064		bmcr |= BMCR_SPEED1000;
1065		break;
1066	case SPEED_100:
1067		bmcr |= BMCR_SPEED100;
1068		break;
1069	case SPEED_10:
1070		break;
1071	}
1072
1073	if (duplex == DUPLEX_FULL)
1074		bmcr |= BMCR_FULLDPLX;
1075
1076	if (bmcr == val)
1077		return 0;
1078
1079	return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
1080				      MV88E6390_SGMII_BMCR, bmcr);
1081}
1082
1083static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip,
1084					    int port, int lane)
1085{
1086	u16 bmsr;
1087	int err;
1088
1089	/* If the link has dropped, we want to know about it. */
1090	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
1091				    MV88E6390_SGMII_BMSR, &bmsr);
1092	if (err) {
1093		dev_err(chip->dev, "can't read Serdes BMSR: %d\n", err);
1094		return;
1095	}
1096
1097	dsa_port_phylink_mac_change(chip->ds, port, !!(bmsr & BMSR_LSTATUS));
1098}
1099
1100static void mv88e6393x_serdes_irq_link_10g(struct mv88e6xxx_chip *chip,
1101					   int port, u8 lane)
1102{
1103	u16 status;
1104	int err;
1105
1106	/* If the link has dropped, we want to know about it. */
1107	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
1108				    MV88E6390_10G_STAT1, &status);
1109	if (err) {
1110		dev_err(chip->dev, "can't read Serdes STAT1: %d\n", err);
1111		return;
1112	}
1113
1114	dsa_port_phylink_mac_change(chip->ds, port, !!(status & MDIO_STAT1_LSTATUS));
1115}
1116
1117static int mv88e6390_serdes_irq_enable_sgmii(struct mv88e6xxx_chip *chip,
1118					     int lane, bool enable)
1119{
1120	u16 val = 0;
1121
1122	if (enable)
1123		val |= MV88E6390_SGMII_INT_LINK_DOWN |
1124			MV88E6390_SGMII_INT_LINK_UP;
1125
1126	return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
1127				      MV88E6390_SGMII_INT_ENABLE, val);
1128}
1129
1130int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, int lane,
1131				bool enable)
1132{
1133	u8 cmode = chip->ports[port].cmode;
1134
1135	switch (cmode) {
 
1136	case MV88E6XXX_PORT_STS_CMODE_SGMII:
1137	case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
 
 
1138	case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
1139		return mv88e6390_serdes_irq_enable_sgmii(chip, lane, enable);
1140	}
1141
1142	return 0;
1143}
1144
1145static int mv88e6390_serdes_irq_status_sgmii(struct mv88e6xxx_chip *chip,
1146					     int lane, u16 *status)
1147{
1148	int err;
1149
1150	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
1151				    MV88E6390_SGMII_INT_STATUS, status);
1152
1153	return err;
1154}
1155
1156static int mv88e6393x_serdes_irq_enable_10g(struct mv88e6xxx_chip *chip,
1157					    u8 lane, bool enable)
1158{
1159	u16 val = 0;
1160
1161	if (enable)
1162		val |= MV88E6393X_10G_INT_LINK_CHANGE;
1163
1164	return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
1165				      MV88E6393X_10G_INT_ENABLE, val);
1166}
1167
1168int mv88e6393x_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port,
1169				 int lane, bool enable)
1170{
1171	u8 cmode = chip->ports[port].cmode;
1172
1173	switch (cmode) {
1174	case MV88E6XXX_PORT_STS_CMODE_SGMII:
1175	case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
 
 
 
1176	case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
1177		return mv88e6390_serdes_irq_enable_sgmii(chip, lane, enable);
1178	case MV88E6393X_PORT_STS_CMODE_5GBASER:
1179	case MV88E6393X_PORT_STS_CMODE_10GBASER:
1180		return mv88e6393x_serdes_irq_enable_10g(chip, lane, enable);
1181	}
1182
1183	return 0;
1184}
1185
1186static int mv88e6393x_serdes_irq_status_10g(struct mv88e6xxx_chip *chip,
1187					    u8 lane, u16 *status)
1188{
1189	int err;
1190
1191	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
1192				    MV88E6393X_10G_INT_STATUS, status);
1193
1194	return err;
1195}
1196
1197irqreturn_t mv88e6393x_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
1198					 int lane)
1199{
1200	u8 cmode = chip->ports[port].cmode;
1201	irqreturn_t ret = IRQ_NONE;
1202	u16 status;
1203	int err;
1204
1205	switch (cmode) {
1206	case MV88E6XXX_PORT_STS_CMODE_SGMII:
1207	case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
1208	case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
1209		err = mv88e6390_serdes_irq_status_sgmii(chip, lane, &status);
1210		if (err)
1211			return ret;
1212		if (status & (MV88E6390_SGMII_INT_LINK_DOWN |
1213			      MV88E6390_SGMII_INT_LINK_UP)) {
1214			ret = IRQ_HANDLED;
1215			mv88e6390_serdes_irq_link_sgmii(chip, port, lane);
1216		}
1217		break;
1218	case MV88E6393X_PORT_STS_CMODE_5GBASER:
1219	case MV88E6393X_PORT_STS_CMODE_10GBASER:
1220		err = mv88e6393x_serdes_irq_status_10g(chip, lane, &status);
1221		if (err)
1222			return err;
1223		if (status & MV88E6393X_10G_INT_LINK_CHANGE) {
1224			ret = IRQ_HANDLED;
1225			mv88e6393x_serdes_irq_link_10g(chip, port, lane);
1226		}
1227		break;
1228	}
1229
1230	return ret;
1231}
1232
1233irqreturn_t mv88e6390_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
1234					int lane)
1235{
1236	u8 cmode = chip->ports[port].cmode;
1237	irqreturn_t ret = IRQ_NONE;
1238	u16 status;
1239	int err;
1240
1241	switch (cmode) {
1242	case MV88E6XXX_PORT_STS_CMODE_SGMII:
1243	case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
1244	case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
1245		err = mv88e6390_serdes_irq_status_sgmii(chip, lane, &status);
1246		if (err)
1247			return ret;
1248		if (status & (MV88E6390_SGMII_INT_LINK_DOWN |
1249			      MV88E6390_SGMII_INT_LINK_UP)) {
1250			ret = IRQ_HANDLED;
1251			mv88e6390_serdes_irq_link_sgmii(chip, port, lane);
1252		}
1253	}
1254
1255	return ret;
1256}
1257
1258unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port)
1259{
1260	return irq_find_mapping(chip->g2_irq.domain, port);
1261}
1262
1263static const u16 mv88e6390_serdes_regs[] = {
1264	/* SERDES common registers */
1265	0xf00a, 0xf00b, 0xf00c,
1266	0xf010, 0xf011, 0xf012, 0xf013,
1267	0xf016, 0xf017, 0xf018,
1268	0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f,
1269	0xf020, 0xf021, 0xf022, 0xf023, 0xf024, 0xf025, 0xf026, 0xf027,
1270	0xf028, 0xf029,
1271	0xf030, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, 0xf037,
1272	0xf038, 0xf039,
1273	/* SGMII */
1274	0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007,
1275	0x2008,
1276	0x200f,
1277	0xa000, 0xa001, 0xa002, 0xa003,
1278	/* 10Gbase-X */
1279	0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006, 0x1007,
1280	0x1008,
1281	0x100e, 0x100f,
1282	0x1018, 0x1019,
1283	0x9000, 0x9001, 0x9002, 0x9003, 0x9004,
1284	0x9006,
1285	0x9010, 0x9011, 0x9012, 0x9013, 0x9014, 0x9015, 0x9016,
1286	/* 10Gbase-R */
1287	0x1020, 0x1021, 0x1022, 0x1023, 0x1024, 0x1025, 0x1026, 0x1027,
1288	0x1028, 0x1029, 0x102a, 0x102b,
1289};
1290
1291int mv88e6390_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port)
1292{
1293	if (mv88e6xxx_serdes_get_lane(chip, port) < 0)
1294		return 0;
1295
1296	return ARRAY_SIZE(mv88e6390_serdes_regs) * sizeof(u16);
1297}
1298
1299void mv88e6390_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p)
1300{
1301	u16 *p = _p;
1302	int lane;
1303	u16 reg;
1304	int err;
1305	int i;
1306
1307	lane = mv88e6xxx_serdes_get_lane(chip, port);
1308	if (lane < 0)
1309		return;
1310
1311	for (i = 0 ; i < ARRAY_SIZE(mv88e6390_serdes_regs); i++) {
1312		err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
1313					    mv88e6390_serdes_regs[i], &reg);
1314		if (!err)
1315			p[i] = reg;
1316	}
1317}
1318
1319static const int mv88e6352_serdes_p2p_to_reg[] = {
1320	/* Index of value in microvolts corresponds to the register value */
1321	14000, 112000, 210000, 308000, 406000, 504000, 602000, 700000,
1322};
1323
1324int mv88e6352_serdes_set_tx_amplitude(struct mv88e6xxx_chip *chip, int port,
1325				      int val)
1326{
1327	bool found = false;
1328	u16 ctrl, reg;
1329	int err;
1330	int i;
1331
1332	err = mv88e6352_g2_scratch_port_has_serdes(chip, port);
1333	if (err <= 0)
1334		return err;
1335
1336	for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_p2p_to_reg); ++i) {
1337		if (mv88e6352_serdes_p2p_to_reg[i] == val) {
1338			reg = i;
1339			found = true;
1340			break;
1341		}
1342	}
1343
1344	if (!found)
1345		return -EINVAL;
1346
1347	err = mv88e6352_serdes_read(chip, MV88E6352_SERDES_SPEC_CTRL2, &ctrl);
1348	if (err)
1349		return err;
1350
1351	ctrl &= ~MV88E6352_SERDES_OUT_AMP_MASK;
1352	ctrl |= reg;
1353
1354	return mv88e6352_serdes_write(chip, MV88E6352_SERDES_SPEC_CTRL2, ctrl);
1355}
1356
1357static int mv88e6393x_serdes_power_lane(struct mv88e6xxx_chip *chip, int lane,
1358					bool on)
1359{
1360	u16 reg;
1361	int err;
1362
1363	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
1364				    MV88E6393X_SERDES_CTRL1, &reg);
1365	if (err)
1366		return err;
1367
1368	if (on)
1369		reg &= ~(MV88E6393X_SERDES_CTRL1_TX_PDOWN |
1370			 MV88E6393X_SERDES_CTRL1_RX_PDOWN);
1371	else
1372		reg |= MV88E6393X_SERDES_CTRL1_TX_PDOWN |
1373		       MV88E6393X_SERDES_CTRL1_RX_PDOWN;
1374
1375	return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
1376				      MV88E6393X_SERDES_CTRL1, reg);
1377}
1378
1379static int mv88e6393x_serdes_erratum_4_6(struct mv88e6xxx_chip *chip, int lane)
1380{
1381	u16 reg;
1382	int err;
1383
1384	/* mv88e6393x family errata 4.6:
1385	 * Cannot clear PwrDn bit on SERDES if device is configured CPU_MGD
1386	 * mode or P0_mode is configured for [x]MII.
1387	 * Workaround: Set SERDES register 4.F002 bit 5=0 and bit 15=1.
1388	 *
1389	 * It seems that after this workaround the SERDES is automatically
1390	 * powered up (the bit is cleared), so power it down.
1391	 */
1392	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
1393				    MV88E6393X_SERDES_POC, &reg);
1394	if (err)
1395		return err;
1396
1397	reg &= ~MV88E6393X_SERDES_POC_PDOWN;
1398	reg |= MV88E6393X_SERDES_POC_RESET;
1399
1400	err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
1401				     MV88E6393X_SERDES_POC, reg);
1402	if (err)
1403		return err;
1404
1405	err = mv88e6390_serdes_power_sgmii(chip, lane, false);
1406	if (err)
1407		return err;
1408
1409	return mv88e6393x_serdes_power_lane(chip, lane, false);
1410}
1411
1412int mv88e6393x_serdes_setup_errata(struct mv88e6xxx_chip *chip)
1413{
1414	int err;
1415
1416	err = mv88e6393x_serdes_erratum_4_6(chip, MV88E6393X_PORT0_LANE);
1417	if (err)
1418		return err;
1419
1420	err = mv88e6393x_serdes_erratum_4_6(chip, MV88E6393X_PORT9_LANE);
1421	if (err)
1422		return err;
1423
1424	return mv88e6393x_serdes_erratum_4_6(chip, MV88E6393X_PORT10_LANE);
1425}
1426
1427static int mv88e6393x_serdes_erratum_4_8(struct mv88e6xxx_chip *chip, int lane)
1428{
1429	u16 reg, pcs;
1430	int err;
1431
1432	/* mv88e6393x family errata 4.8:
1433	 * When a SERDES port is operating in 1000BASE-X or SGMII mode link may
1434	 * not come up after hardware reset or software reset of SERDES core.
1435	 * Workaround is to write SERDES register 4.F074.14=1 for only those
1436	 * modes and 0 in all other modes.
1437	 */
1438	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
1439				    MV88E6393X_SERDES_POC, &pcs);
1440	if (err)
1441		return err;
1442
1443	pcs &= MV88E6393X_SERDES_POC_PCS_MASK;
1444
1445	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
1446				    MV88E6393X_ERRATA_4_8_REG, &reg);
1447	if (err)
1448		return err;
1449
1450	if (pcs == MV88E6393X_SERDES_POC_PCS_1000BASEX ||
1451	    pcs == MV88E6393X_SERDES_POC_PCS_SGMII_PHY ||
1452	    pcs == MV88E6393X_SERDES_POC_PCS_SGMII_MAC)
1453		reg |= MV88E6393X_ERRATA_4_8_BIT;
1454	else
1455		reg &= ~MV88E6393X_ERRATA_4_8_BIT;
1456
1457	return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
1458				      MV88E6393X_ERRATA_4_8_REG, reg);
1459}
1460
1461static int mv88e6393x_serdes_erratum_5_2(struct mv88e6xxx_chip *chip, int lane,
1462					 u8 cmode)
1463{
1464	static const struct {
1465		u16 dev, reg, val, mask;
1466	} fixes[] = {
1467		{ MDIO_MMD_VEND1, 0x8093, 0xcb5a, 0xffff },
1468		{ MDIO_MMD_VEND1, 0x8171, 0x7088, 0xffff },
1469		{ MDIO_MMD_VEND1, 0x80c9, 0x311a, 0xffff },
1470		{ MDIO_MMD_VEND1, 0x80a2, 0x8000, 0xff7f },
1471		{ MDIO_MMD_VEND1, 0x80a9, 0x0000, 0xfff0 },
1472		{ MDIO_MMD_VEND1, 0x80a3, 0x0000, 0xf8ff },
1473		{ MDIO_MMD_PHYXS, MV88E6393X_SERDES_POC,
1474		  MV88E6393X_SERDES_POC_RESET, MV88E6393X_SERDES_POC_RESET },
1475	};
1476	int err, i;
1477	u16 reg;
1478
1479	/* mv88e6393x family errata 5.2:
1480	 * For optimal signal integrity the following sequence should be applied
1481	 * to SERDES operating in 10G mode. These registers only apply to 10G
1482	 * operation and have no effect on other speeds.
1483	 */
1484	if (cmode != MV88E6393X_PORT_STS_CMODE_10GBASER)
1485		return 0;
1486
1487	for (i = 0; i < ARRAY_SIZE(fixes); ++i) {
1488		err = mv88e6390_serdes_read(chip, lane, fixes[i].dev,
1489					    fixes[i].reg, &reg);
1490		if (err)
1491			return err;
1492
1493		reg &= ~fixes[i].mask;
1494		reg |= fixes[i].val;
1495
1496		err = mv88e6390_serdes_write(chip, lane, fixes[i].dev,
1497					     fixes[i].reg, reg);
1498		if (err)
1499			return err;
1500	}
1501
1502	return 0;
1503}
1504
1505static int mv88e6393x_serdes_fix_2500basex_an(struct mv88e6xxx_chip *chip,
1506					      int lane, u8 cmode, bool on)
1507{
1508	u16 reg;
1509	int err;
1510
1511	if (cmode != MV88E6XXX_PORT_STS_CMODE_2500BASEX)
1512		return 0;
1513
1514	/* Inband AN is broken on Amethyst in 2500base-x mode when set by
1515	 * standard mechanism (via cmode).
1516	 * We can get around this by configuring the PCS mode to 1000base-x
1517	 * and then writing value 0x58 to register 1e.8000. (This must be done
1518	 * while SerDes receiver and transmitter are disabled, which is, when
1519	 * this function is called.)
1520	 * It seem that when we do this configuration to 2500base-x mode (by
1521	 * changing PCS mode to 1000base-x and frequency to 3.125 GHz from
1522	 * 1.25 GHz) and then configure to sgmii or 1000base-x, the device
1523	 * thinks that it already has SerDes at 1.25 GHz and does not change
1524	 * the 1e.8000 register, leaving SerDes at 3.125 GHz.
1525	 * To avoid this, change PCS mode back to 2500base-x when disabling
1526	 * SerDes from 2500base-x mode.
1527	 */
1528	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
1529				    MV88E6393X_SERDES_POC, &reg);
1530	if (err)
1531		return err;
1532
1533	reg &= ~(MV88E6393X_SERDES_POC_PCS_MASK | MV88E6393X_SERDES_POC_AN);
1534	if (on)
1535		reg |= MV88E6393X_SERDES_POC_PCS_1000BASEX |
1536		       MV88E6393X_SERDES_POC_AN;
1537	else
1538		reg |= MV88E6393X_SERDES_POC_PCS_2500BASEX;
1539	reg |= MV88E6393X_SERDES_POC_RESET;
1540
1541	err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
1542				     MV88E6393X_SERDES_POC, reg);
1543	if (err)
1544		return err;
1545
1546	err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_VEND1, 0x8000, 0x58);
1547	if (err)
1548		return err;
1549
1550	return 0;
1551}
1552
1553int mv88e6393x_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane,
1554			    bool on)
1555{
1556	u8 cmode = chip->ports[port].cmode;
1557	int err;
1558
1559	if (port != 0 && port != 9 && port != 10)
1560		return -EOPNOTSUPP;
1561
1562	if (on) {
1563		err = mv88e6393x_serdes_erratum_4_8(chip, lane);
1564		if (err)
1565			return err;
1566
1567		err = mv88e6393x_serdes_erratum_5_2(chip, lane, cmode);
1568		if (err)
1569			return err;
1570
1571		err = mv88e6393x_serdes_fix_2500basex_an(chip, lane, cmode,
1572							 true);
1573		if (err)
1574			return err;
1575
1576		err = mv88e6393x_serdes_power_lane(chip, lane, true);
1577		if (err)
1578			return err;
1579	}
1580
1581	switch (cmode) {
1582	case MV88E6XXX_PORT_STS_CMODE_SGMII:
1583	case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
1584	case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
1585		err = mv88e6390_serdes_power_sgmii(chip, lane, on);
1586		break;
1587	case MV88E6393X_PORT_STS_CMODE_5GBASER:
1588	case MV88E6393X_PORT_STS_CMODE_10GBASER:
1589		err = mv88e6390_serdes_power_10g(chip, lane, on);
1590		break;
1591	default:
1592		err = -EINVAL;
1593		break;
1594	}
1595
1596	if (err)
1597		return err;
1598
1599	if (!on) {
1600		err = mv88e6393x_serdes_power_lane(chip, lane, false);
1601		if (err)
1602			return err;
1603
1604		err = mv88e6393x_serdes_fix_2500basex_an(chip, lane, cmode,
1605							 false);
1606	}
1607
1608	return err;
1609}