hc
2024-09-20 cf4ce59b3b70238352c7f1729f0f7223214828ad
kernel/drivers/net/dsa/mv88e6xxx/serdes.c
....@@ -1,14 +1,10 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Marvell 88E6xxx SERDES manipulation, via SMI bus
34 *
45 * Copyright (c) 2008 Marvell Semiconductor
56 *
67 * 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.
128 */
139
1410 #include <linux/interrupt.h>
....@@ -53,7 +49,54 @@
5349 return mv88e6xxx_phy_write(chip, lane, reg_c45, val);
5450 }
5551
56
-static int mv88e6352_serdes_power_set(struct mv88e6xxx_chip *chip, bool on)
52
+static 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
+
98
+int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, u8 lane,
99
+ bool up)
57100 {
58101 u16 val, new_val;
59102 int err;
....@@ -62,7 +105,7 @@
62105 if (err)
63106 return err;
64107
65
- if (on)
108
+ if (up)
66109 new_val = val & ~BMCR_PDOWN;
67110 else
68111 new_val = val | BMCR_PDOWN;
....@@ -73,29 +116,139 @@
73116 return err;
74117 }
75118
76
-static bool mv88e6352_port_has_serdes(struct mv88e6xxx_chip *chip, int port)
119
+int 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)
77123 {
78
- u8 cmode = chip->ports[port].cmode;
79
-
80
- if ((cmode == MV88E6XXX_PORT_STS_CMODE_100BASE_X) ||
81
- (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X) ||
82
- (cmode == MV88E6XXX_PORT_STS_CMODE_SGMII))
83
- return true;
84
-
85
- return false;
86
-}
87
-
88
-int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
89
-{
124
+ u16 adv, bmcr, val;
125
+ bool changed;
90126 int err;
91127
92
- if (mv88e6352_port_has_serdes(chip, port)) {
93
- err = mv88e6352_serdes_power_set(chip, on);
94
- if (err < 0)
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)
95150 return err;
96151 }
97152
98
- return 0;
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
+
168
+int 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
+
189
+int 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
+
202
+int 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
+
233
+u8 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
+
246
+static 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;
99252 }
100253
101254 struct mv88e6352_serdes_hw_stat {
....@@ -185,293 +338,575 @@
185338 return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
186339 }
187340
188
-/* Return the SERDES lane address a port is using. Only Ports 9 and 10
189
- * have SERDES lanes. Returns -ENODEV if a port does not have a lane.
190
- */
191
-static int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
341
+static void mv88e6352_serdes_irq_link(struct mv88e6xxx_chip *chip, int port)
192342 {
193
- u8 cmode = chip->ports[port].cmode;
343
+ u16 bmsr;
344
+ int err;
194345
195
- switch (port) {
196
- case 9:
197
- if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
198
- cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
199
- cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
200
- return MV88E6390_PORT9_LANE0;
201
- return -ENODEV;
202
- case 10:
203
- if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
204
- cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
205
- cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
206
- return MV88E6390_PORT10_LANE0;
207
- return -ENODEV;
208
- default:
209
- return -ENODEV;
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
+
356
+irqreturn_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
+
375
+int 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
+
386
+unsigned 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
+
391
+int 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
+
399
+void mv88e6352_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p)
400
+{
401
+ u16 *p = _p;
402
+ u16 reg;
403
+ int i;
404
+
405
+ if (!mv88e6352_port_has_serdes(chip, port))
406
+ return;
407
+
408
+ for (i = 0 ; i < 32; i++) {
409
+ mv88e6352_serdes_read(chip, i, &reg);
410
+ p[i] = reg;
210411 }
211412 }
212413
213
-/* Return the SERDES lane address a port is using. Ports 9 and 10 can
214
- * use multiple lanes. If so, return the first lane the port uses.
215
- * Returns -ENODEV if a port does not have a lane.
216
- */
217
-int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
414
+u8 mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
218415 {
219
- u8 cmode_port9, cmode_port10, cmode_port;
416
+ u8 cmode = chip->ports[port].cmode;
417
+ u8 lane = 0;
220418
221
- cmode_port9 = chip->ports[9].cmode;
222
- cmode_port10 = chip->ports[10].cmode;
223
- cmode_port = chip->ports[port].cmode;
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
+
431
+u8 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
+
454
+u8 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;
224460
225461 switch (port) {
226462 case 2:
227
- if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
463
+ if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
228464 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
229465 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
230
- if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X)
231
- return MV88E6390_PORT9_LANE1;
232
- return -ENODEV;
466
+ if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
467
+ lane = MV88E6390_PORT9_LANE1;
468
+ break;
233469 case 3:
234
- if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
470
+ if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
235471 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
236472 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
237473 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
238
- if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X)
239
- return MV88E6390_PORT9_LANE2;
240
- return -ENODEV;
474
+ if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
475
+ lane = MV88E6390_PORT9_LANE2;
476
+ break;
241477 case 4:
242
- if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
478
+ if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
243479 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
244480 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
245481 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
246
- if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X)
247
- return MV88E6390_PORT9_LANE3;
248
- return -ENODEV;
482
+ if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
483
+ lane = MV88E6390_PORT9_LANE3;
484
+ break;
249485 case 5:
250
- if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
486
+ if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
251487 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
252488 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
253
- if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X)
254
- return MV88E6390_PORT10_LANE1;
255
- return -ENODEV;
489
+ if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
490
+ lane = MV88E6390_PORT10_LANE1;
491
+ break;
256492 case 6:
257
- if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
493
+ if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
258494 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
259495 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
260496 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
261
- if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X)
262
- return MV88E6390_PORT10_LANE2;
263
- return -ENODEV;
497
+ if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
498
+ lane = MV88E6390_PORT10_LANE2;
499
+ break;
264500 case 7:
265
- if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
501
+ if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
266502 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
267503 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
268504 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
269
- if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X)
270
- return MV88E6390_PORT10_LANE3;
271
- return -ENODEV;
505
+ if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
506
+ lane = MV88E6390_PORT10_LANE3;
507
+ break;
272508 case 9:
273
- if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
509
+ if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
274510 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
275511 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
276512 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_XAUI ||
277513 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
278
- return MV88E6390_PORT9_LANE0;
279
- return -ENODEV;
514
+ lane = MV88E6390_PORT9_LANE0;
515
+ break;
280516 case 10:
281
- if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
517
+ if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
282518 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
283519 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
284520 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_XAUI ||
285521 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
286
- return MV88E6390_PORT10_LANE0;
287
- return -ENODEV;
288
- default:
289
- return -ENODEV;
522
+ lane = MV88E6390_PORT10_LANE0;
523
+ break;
290524 }
525
+
526
+ return lane;
291527 }
292528
293
-/* Set the power on/off for 10GBASE-R and 10GBASE-X4/X2 */
294
-static int mv88e6390_serdes_power_10g(struct mv88e6xxx_chip *chip, int lane,
295
- bool on)
529
+/* Set power up/down for 10GBASE-R and 10GBASE-X4/X2 */
530
+static int mv88e6390_serdes_power_10g(struct mv88e6xxx_chip *chip, u8 lane,
531
+ bool up)
296532 {
297533 u16 val, new_val;
298534 int err;
299535
300536 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
301
- MV88E6390_PCS_CONTROL_1, &val);
537
+ MV88E6390_10G_CTRL1, &val);
302538
303539 if (err)
304540 return err;
305541
306
- if (on)
307
- new_val = val & ~(MV88E6390_PCS_CONTROL_1_RESET |
308
- MV88E6390_PCS_CONTROL_1_LOOPBACK |
309
- MV88E6390_PCS_CONTROL_1_PDOWN);
542
+ if (up)
543
+ new_val = val & ~(MDIO_CTRL1_RESET |
544
+ MDIO_PCS_CTRL1_LOOPBACK |
545
+ MDIO_CTRL1_LPOWER);
310546 else
311
- new_val = val | MV88E6390_PCS_CONTROL_1_PDOWN;
547
+ new_val = val | MDIO_CTRL1_LPOWER;
312548
313549 if (val != new_val)
314550 err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
315
- MV88E6390_PCS_CONTROL_1, new_val);
551
+ MV88E6390_10G_CTRL1, new_val);
316552
317553 return err;
318554 }
319555
320
-/* Set the power on/off for SGMII and 1000Base-X */
321
-static int mv88e6390_serdes_power_sgmii(struct mv88e6xxx_chip *chip, int lane,
322
- bool on)
556
+/* Set power up/down for SGMII and 1000Base-X */
557
+static int mv88e6390_serdes_power_sgmii(struct mv88e6xxx_chip *chip, u8 lane,
558
+ bool up)
323559 {
324560 u16 val, new_val;
325561 int err;
326562
327563 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
328
- MV88E6390_SGMII_CONTROL, &val);
564
+ MV88E6390_SGMII_BMCR, &val);
329565 if (err)
330566 return err;
331567
332
- if (on)
333
- new_val = val & ~(MV88E6390_SGMII_CONTROL_RESET |
334
- MV88E6390_SGMII_CONTROL_LOOPBACK |
335
- MV88E6390_SGMII_CONTROL_PDOWN);
568
+ if (up)
569
+ new_val = val & ~(BMCR_RESET | BMCR_LOOPBACK | BMCR_PDOWN);
336570 else
337
- new_val = val | MV88E6390_SGMII_CONTROL_PDOWN;
571
+ new_val = val | BMCR_PDOWN;
338572
339573 if (val != new_val)
340574 err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
341
- MV88E6390_SGMII_CONTROL, new_val);
575
+ MV88E6390_SGMII_BMCR, new_val);
342576
343577 return err;
344578 }
345579
346
-static int mv88e6390_serdes_power_lane(struct mv88e6xxx_chip *chip, int port,
347
- int lane, bool on)
580
+struct mv88e6390_serdes_hw_stat {
581
+ char string[ETH_GSTRING_LEN];
582
+ int reg;
583
+};
584
+
585
+static 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
+
591
+int mv88e6390_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port)
592
+{
593
+ if (mv88e6xxx_serdes_get_lane(chip, port) == 0)
594
+ return 0;
595
+
596
+ return ARRAY_SIZE(mv88e6390_serdes_hw_stats);
597
+}
598
+
599
+int 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 (mv88e6xxx_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
+
616
+static uint64_t mv88e6390_serdes_get_stat(struct mv88e6xxx_chip *chip, int lane,
617
+ struct mv88e6390_serdes_hw_stat *stat)
618
+{
619
+ u16 reg[3];
620
+ int err, i;
621
+
622
+ for (i = 0; i < 3; i++) {
623
+ err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
624
+ stat->reg + i, &reg[i]);
625
+ if (err) {
626
+ dev_err(chip->dev, "failed to read statistic\n");
627
+ return 0;
628
+ }
629
+ }
630
+
631
+ return reg[0] | ((u64)reg[1] << 16) | ((u64)reg[2] << 32);
632
+}
633
+
634
+int 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 = mv88e6xxx_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
+
653
+static int mv88e6390_serdes_enable_checker(struct mv88e6xxx_chip *chip, u8 lane)
654
+{
655
+ u16 reg;
656
+ int err;
657
+
658
+ err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
659
+ MV88E6390_PG_CONTROL, &reg);
660
+ if (err)
661
+ return err;
662
+
663
+ reg |= MV88E6390_PG_CONTROL_ENABLE_PC;
664
+ return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
665
+ MV88E6390_PG_CONTROL, reg);
666
+}
667
+
668
+int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, u8 lane,
669
+ bool up)
348670 {
349671 u8 cmode = chip->ports[port].cmode;
672
+ int err = 0;
350673
351674 switch (cmode) {
352675 case MV88E6XXX_PORT_STS_CMODE_SGMII:
353
- case MV88E6XXX_PORT_STS_CMODE_1000BASE_X:
676
+ case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
354677 case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
355
- return mv88e6390_serdes_power_sgmii(chip, lane, on);
678
+ err = mv88e6390_serdes_power_sgmii(chip, lane, up);
679
+ break;
356680 case MV88E6XXX_PORT_STS_CMODE_XAUI:
357681 case MV88E6XXX_PORT_STS_CMODE_RXAUI:
358
- return mv88e6390_serdes_power_10g(chip, lane, on);
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
+
692
+int 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
+
751
+static 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
+
774
+static 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;
359789 }
360790
361791 return 0;
362792 }
363793
364
-int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
794
+int mv88e6390_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port,
795
+ u8 lane, struct phylink_link_state *state)
365796 {
366
- int lane;
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);
367807
368
- lane = mv88e6390_serdes_get_lane(chip, port);
369
- if (lane == -ENODEV)
370
- return 0;
371
-
372
- if (lane < 0)
373
- return lane;
374
-
375
- switch (port) {
376
- case 9 ... 10:
377
- return mv88e6390_serdes_power_lane(chip, port, lane, on);
808
+ default:
809
+ return -EOPNOTSUPP;
378810 }
379
-
380
- return 0;
381811 }
382812
383
-int mv88e6390x_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
813
+int mv88e6390_serdes_pcs_an_restart(struct mv88e6xxx_chip *chip, int port,
814
+ u8 lane)
384815 {
385
- int lane;
816
+ u16 bmcr;
817
+ int err;
386818
387
- lane = mv88e6390x_serdes_get_lane(chip, port);
388
- if (lane == -ENODEV)
389
- return 0;
819
+ err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
820
+ MV88E6390_SGMII_BMCR, &bmcr);
821
+ if (err)
822
+ return err;
390823
391
- if (lane < 0)
392
- return lane;
824
+ return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
825
+ MV88E6390_SGMII_BMCR,
826
+ bmcr | BMCR_ANRESTART);
827
+}
393828
394
- switch (port) {
395
- case 2 ... 4:
396
- case 5 ... 7:
397
- case 9 ... 10:
398
- return mv88e6390_serdes_power_lane(chip, port, lane, on);
829
+int 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;
399851 }
400852
401
- return 0;
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);
402861 }
403862
404863 static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip,
405
- int port, int lane)
864
+ int port, u8 lane)
406865 {
407
- struct dsa_switch *ds = chip->ds;
408
- u16 status;
409
- bool up;
866
+ u16 bmsr;
867
+ int err;
410868
411
- mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
412
- MV88E6390_SGMII_STATUS, &status);
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
+ }
413876
414
- /* Status must be read twice in order to give the current link
415
- * status. Otherwise the change in link status since the last
416
- * read of the register is returned.
417
- */
418
- mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
419
- MV88E6390_SGMII_STATUS, &status);
420
- up = status & MV88E6390_SGMII_STATUS_LINK;
421
-
422
- dsa_port_phylink_mac_change(ds, port, up);
877
+ dsa_port_phylink_mac_change(chip->ds, port, !!(bmsr & BMSR_LSTATUS));
423878 }
424879
425880 static int mv88e6390_serdes_irq_enable_sgmii(struct mv88e6xxx_chip *chip,
426
- int lane)
881
+ u8 lane, bool enable)
427882 {
883
+ u16 val = 0;
884
+
885
+ if (enable)
886
+ val |= MV88E6390_SGMII_INT_LINK_DOWN |
887
+ MV88E6390_SGMII_INT_LINK_UP;
888
+
428889 return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
429
- MV88E6390_SGMII_INT_ENABLE,
430
- MV88E6390_SGMII_INT_LINK_DOWN |
431
- MV88E6390_SGMII_INT_LINK_UP);
890
+ MV88E6390_SGMII_INT_ENABLE, val);
432891 }
433892
434
-static int mv88e6390_serdes_irq_disable_sgmii(struct mv88e6xxx_chip *chip,
435
- int lane)
436
-{
437
- return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
438
- MV88E6390_SGMII_INT_ENABLE, 0);
439
-}
440
-
441
-int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port,
442
- int lane)
893
+int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, u8 lane,
894
+ bool enable)
443895 {
444896 u8 cmode = chip->ports[port].cmode;
445
- int err = 0;
446897
447898 switch (cmode) {
448899 case MV88E6XXX_PORT_STS_CMODE_SGMII:
449
- case MV88E6XXX_PORT_STS_CMODE_1000BASE_X:
900
+ case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
450901 case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
451
- err = mv88e6390_serdes_irq_enable_sgmii(chip, lane);
902
+ return mv88e6390_serdes_irq_enable_sgmii(chip, lane, enable);
452903 }
453904
454
- return err;
455
-}
456
-
457
-int mv88e6390_serdes_irq_disable(struct mv88e6xxx_chip *chip, int port,
458
- int lane)
459
-{
460
- u8 cmode = chip->ports[port].cmode;
461
- int err = 0;
462
-
463
- switch (cmode) {
464
- case MV88E6XXX_PORT_STS_CMODE_SGMII:
465
- case MV88E6XXX_PORT_STS_CMODE_1000BASE_X:
466
- case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
467
- err = mv88e6390_serdes_irq_disable_sgmii(chip, lane);
468
- }
469
-
470
- return err;
905
+ return 0;
471906 }
472907
473908 static int mv88e6390_serdes_irq_status_sgmii(struct mv88e6xxx_chip *chip,
474
- int lane, u16 *status)
909
+ u8 lane, u16 *status)
475910 {
476911 int err;
477912
....@@ -481,117 +916,86 @@
481916 return err;
482917 }
483918
484
-static irqreturn_t mv88e6390_serdes_thread_fn(int irq, void *dev_id)
919
+irqreturn_t mv88e6390_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
920
+ u8 lane)
485921 {
486
- struct mv88e6xxx_port *port = dev_id;
487
- struct mv88e6xxx_chip *chip = port->chip;
922
+ u8 cmode = chip->ports[port].cmode;
488923 irqreturn_t ret = IRQ_NONE;
489
- u8 cmode = port->cmode;
490924 u16 status;
491
- int lane;
492925 int err;
493
-
494
- lane = mv88e6390x_serdes_get_lane(chip, port->port);
495
-
496
- mutex_lock(&chip->reg_lock);
497926
498927 switch (cmode) {
499928 case MV88E6XXX_PORT_STS_CMODE_SGMII:
500
- case MV88E6XXX_PORT_STS_CMODE_1000BASE_X:
929
+ case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
501930 case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
502931 err = mv88e6390_serdes_irq_status_sgmii(chip, lane, &status);
503932 if (err)
504
- goto out;
933
+ return ret;
505934 if (status & (MV88E6390_SGMII_INT_LINK_DOWN |
506935 MV88E6390_SGMII_INT_LINK_UP)) {
507936 ret = IRQ_HANDLED;
508
- mv88e6390_serdes_irq_link_sgmii(chip, port->port, lane);
937
+ mv88e6390_serdes_irq_link_sgmii(chip, port, lane);
509938 }
510939 }
511
-out:
512
- mutex_unlock(&chip->reg_lock);
513940
514941 return ret;
515942 }
516943
517
-int mv88e6390_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port)
944
+unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port)
518945 {
946
+ return irq_find_mapping(chip->g2_irq.domain, port);
947
+}
948
+
949
+static 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
+
977
+int 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
+
985
+void mv88e6390_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p)
986
+{
987
+ u16 *p = _p;
519988 int lane;
520
- int err;
989
+ u16 reg;
990
+ int i;
521991
522
- /* Only support ports 9 and 10 at the moment */
523
- if (port < 9)
524
- return 0;
525
-
526
- lane = mv88e6390x_serdes_get_lane(chip, port);
527
-
528
- if (lane == -ENODEV)
529
- return 0;
530
-
531
- if (lane < 0)
532
- return lane;
533
-
534
- chip->ports[port].serdes_irq = irq_find_mapping(chip->g2_irq.domain,
535
- port);
536
- if (chip->ports[port].serdes_irq < 0) {
537
- dev_err(chip->dev, "Unable to map SERDES irq: %d\n",
538
- chip->ports[port].serdes_irq);
539
- return chip->ports[port].serdes_irq;
540
- }
541
-
542
- /* Requesting the IRQ will trigger irq callbacks. So we cannot
543
- * hold the reg_lock.
544
- */
545
- mutex_unlock(&chip->reg_lock);
546
- err = request_threaded_irq(chip->ports[port].serdes_irq, NULL,
547
- mv88e6390_serdes_thread_fn,
548
- IRQF_ONESHOT, "mv88e6xxx-serdes",
549
- &chip->ports[port]);
550
- mutex_lock(&chip->reg_lock);
551
-
552
- if (err) {
553
- dev_err(chip->dev, "Unable to request SERDES interrupt: %d\n",
554
- err);
555
- return err;
556
- }
557
-
558
- return mv88e6390_serdes_irq_enable(chip, port, lane);
559
-}
560
-
561
-void mv88e6390_serdes_irq_free(struct mv88e6xxx_chip *chip, int port)
562
-{
563
- int lane = mv88e6390x_serdes_get_lane(chip, port);
564
-
565
- if (port < 9)
992
+ lane = mv88e6xxx_serdes_get_lane(chip, port);
993
+ if (lane == 0)
566994 return;
567995
568
- if (lane < 0)
569
- return;
570
-
571
- mv88e6390_serdes_irq_disable(chip, port, lane);
572
-
573
- /* Freeing the IRQ will trigger irq callbacks. So we cannot
574
- * hold the reg_lock.
575
- */
576
- mutex_unlock(&chip->reg_lock);
577
- free_irq(chip->ports[port].serdes_irq, &chip->ports[port]);
578
- mutex_lock(&chip->reg_lock);
579
-
580
- chip->ports[port].serdes_irq = 0;
581
-}
582
-
583
-int mv88e6341_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
584
-{
585
- u8 cmode = chip->ports[port].cmode;
586
-
587
- if (port != 5)
588
- return 0;
589
-
590
- if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
591
- cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
592
- cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
593
- return mv88e6390_serdes_power_sgmii(chip, MV88E6341_ADDR_SERDES,
594
- on);
595
-
596
- return 0;
996
+ for (i = 0 ; i < ARRAY_SIZE(mv88e6390_serdes_regs); i++) {
997
+ mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
998
+ mv88e6390_serdes_regs[i], &reg);
999
+ p[i] = reg;
1000
+ }
5971001 }