Loading...
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, ®);
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, ®);
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, ®);
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, ®[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], ®);
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}
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, ®);
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, ®);
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, ®);
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, ®[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, ®);
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], ®);
999 p[i] = reg;
1000 }
1001}