]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/blame - drivers/net/dsa/mv88e6xxx/port.c
Merge branch 'appletalk-small-cleanup-and-bugfix'
[mirror_ubuntu-eoan-kernel.git] / drivers / net / dsa / mv88e6xxx / port.c
CommitLineData
18abed21
VD
1/*
2 * Marvell 88E6xxx Switch Port Registers support
3 *
4 * Copyright (c) 2008 Marvell Semiconductor
5 *
4333d619
VD
6 * Copyright (c) 2016-2017 Savoir-faire Linux Inc.
7 * Vivien Didelot <vivien.didelot@savoirfairelinux.com>
18abed21
VD
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 */
14
ddcbabf4 15#include <linux/bitfield.h>
f894c29c 16#include <linux/if_bridge.h>
f39908d3 17#include <linux/phy.h>
c9a2356f 18#include <linux/phylink.h>
4d5f2ba7
VD
19
20#include "chip.h"
18abed21 21#include "port.h"
364e9d77 22#include "serdes.h"
18abed21
VD
23
24int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port, int reg,
25 u16 *val)
26{
27 int addr = chip->info->port_base_addr + port;
28
29 return mv88e6xxx_read(chip, addr, reg, val);
30}
31
32int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg,
33 u16 val)
34{
35 int addr = chip->info->port_base_addr + port;
36
37 return mv88e6xxx_write(chip, addr, reg, val);
38}
e28def33 39
54186b91
AL
40/* Offset 0x00: MAC (or PCS or Physical) Status Register
41 *
42 * For most devices, this is read only. However the 6185 has the MyPause
43 * bit read/write.
44 */
45int mv88e6185_port_set_pause(struct mv88e6xxx_chip *chip, int port,
46 int pause)
47{
48 u16 reg;
49 int err;
50
51 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &reg);
52 if (err)
53 return err;
54
55 if (pause)
56 reg |= MV88E6XXX_PORT_STS_MY_PAUSE;
57 else
58 reg &= ~MV88E6XXX_PORT_STS_MY_PAUSE;
59
60 return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_STS, reg);
61}
62
08ef7f10
VD
63/* Offset 0x01: MAC (or PCS or Physical) Control Register
64 *
65 * Link, Duplex and Flow Control have one force bit, one value bit.
96a2b40c
VD
66 *
67 * For port's MAC speed, ForceSpd (or SpdValue) bits 1:0 program the value.
68 * Alternative values require the 200BASE (or AltSpeed) bit 12 set.
69 * Newer chips need a ForcedSpd bit 13 set to consider the value.
08ef7f10
VD
70 */
71
a0a0f622
VD
72static int mv88e6xxx_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,
73 phy_interface_t mode)
74{
75 u16 reg;
76 int err;
77
5ee55577 78 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_MAC_CTL, &reg);
a0a0f622
VD
79 if (err)
80 return err;
81
5ee55577
VD
82 reg &= ~(MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_RXCLK |
83 MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_TXCLK);
a0a0f622
VD
84
85 switch (mode) {
86 case PHY_INTERFACE_MODE_RGMII_RXID:
5ee55577 87 reg |= MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_RXCLK;
a0a0f622
VD
88 break;
89 case PHY_INTERFACE_MODE_RGMII_TXID:
5ee55577 90 reg |= MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_TXCLK;
a0a0f622
VD
91 break;
92 case PHY_INTERFACE_MODE_RGMII_ID:
5ee55577
VD
93 reg |= MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_RXCLK |
94 MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_TXCLK;
a0a0f622 95 break;
fedf1865 96 case PHY_INTERFACE_MODE_RGMII:
a0a0f622 97 break;
fedf1865
AL
98 default:
99 return 0;
a0a0f622
VD
100 }
101
5ee55577 102 err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_MAC_CTL, reg);
a0a0f622
VD
103 if (err)
104 return err;
105
774439e5 106 dev_dbg(chip->dev, "p%d: delay RXCLK %s, TXCLK %s\n", port,
5ee55577
VD
107 reg & MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_RXCLK ? "yes" : "no",
108 reg & MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_TXCLK ? "yes" : "no");
a0a0f622
VD
109
110 return 0;
111}
112
113int mv88e6352_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,
114 phy_interface_t mode)
115{
116 if (port < 5)
117 return -EOPNOTSUPP;
118
119 return mv88e6xxx_port_set_rgmii_delay(chip, port, mode);
120}
121
122int mv88e6390_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,
123 phy_interface_t mode)
124{
125 if (port != 0)
126 return -EOPNOTSUPP;
127
128 return mv88e6xxx_port_set_rgmii_delay(chip, port, mode);
129}
130
08ef7f10
VD
131int mv88e6xxx_port_set_link(struct mv88e6xxx_chip *chip, int port, int link)
132{
133 u16 reg;
134 int err;
135
5ee55577 136 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_MAC_CTL, &reg);
08ef7f10
VD
137 if (err)
138 return err;
139
5ee55577
VD
140 reg &= ~(MV88E6XXX_PORT_MAC_CTL_FORCE_LINK |
141 MV88E6XXX_PORT_MAC_CTL_LINK_UP);
08ef7f10
VD
142
143 switch (link) {
144 case LINK_FORCED_DOWN:
5ee55577 145 reg |= MV88E6XXX_PORT_MAC_CTL_FORCE_LINK;
08ef7f10
VD
146 break;
147 case LINK_FORCED_UP:
5ee55577
VD
148 reg |= MV88E6XXX_PORT_MAC_CTL_FORCE_LINK |
149 MV88E6XXX_PORT_MAC_CTL_LINK_UP;
08ef7f10
VD
150 break;
151 case LINK_UNFORCED:
152 /* normal link detection */
153 break;
154 default:
155 return -EINVAL;
156 }
157
5ee55577 158 err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_MAC_CTL, reg);
08ef7f10
VD
159 if (err)
160 return err;
161
774439e5 162 dev_dbg(chip->dev, "p%d: %s link %s\n", port,
5ee55577
VD
163 reg & MV88E6XXX_PORT_MAC_CTL_FORCE_LINK ? "Force" : "Unforce",
164 reg & MV88E6XXX_PORT_MAC_CTL_LINK_UP ? "up" : "down");
08ef7f10
VD
165
166 return 0;
167}
168
7f1ae07b
VD
169int mv88e6xxx_port_set_duplex(struct mv88e6xxx_chip *chip, int port, int dup)
170{
171 u16 reg;
172 int err;
173
5ee55577 174 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_MAC_CTL, &reg);
7f1ae07b
VD
175 if (err)
176 return err;
177
5ee55577
VD
178 reg &= ~(MV88E6XXX_PORT_MAC_CTL_FORCE_DUPLEX |
179 MV88E6XXX_PORT_MAC_CTL_DUPLEX_FULL);
7f1ae07b
VD
180
181 switch (dup) {
182 case DUPLEX_HALF:
5ee55577 183 reg |= MV88E6XXX_PORT_MAC_CTL_FORCE_DUPLEX;
7f1ae07b
VD
184 break;
185 case DUPLEX_FULL:
5ee55577
VD
186 reg |= MV88E6XXX_PORT_MAC_CTL_FORCE_DUPLEX |
187 MV88E6XXX_PORT_MAC_CTL_DUPLEX_FULL;
7f1ae07b
VD
188 break;
189 case DUPLEX_UNFORCED:
190 /* normal duplex detection */
191 break;
192 default:
193 return -EINVAL;
194 }
195
5ee55577 196 err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_MAC_CTL, reg);
7f1ae07b
VD
197 if (err)
198 return err;
199
774439e5 200 dev_dbg(chip->dev, "p%d: %s %s duplex\n", port,
5ee55577
VD
201 reg & MV88E6XXX_PORT_MAC_CTL_FORCE_DUPLEX ? "Force" : "Unforce",
202 reg & MV88E6XXX_PORT_MAC_CTL_DUPLEX_FULL ? "full" : "half");
7f1ae07b
VD
203
204 return 0;
205}
206
96a2b40c
VD
207static int mv88e6xxx_port_set_speed(struct mv88e6xxx_chip *chip, int port,
208 int speed, bool alt_bit, bool force_bit)
209{
210 u16 reg, ctrl;
211 int err;
212
213 switch (speed) {
214 case 10:
5ee55577 215 ctrl = MV88E6XXX_PORT_MAC_CTL_SPEED_10;
96a2b40c
VD
216 break;
217 case 100:
5ee55577 218 ctrl = MV88E6XXX_PORT_MAC_CTL_SPEED_100;
96a2b40c
VD
219 break;
220 case 200:
221 if (alt_bit)
5ee55577
VD
222 ctrl = MV88E6XXX_PORT_MAC_CTL_SPEED_100 |
223 MV88E6390_PORT_MAC_CTL_ALTSPEED;
96a2b40c 224 else
5ee55577 225 ctrl = MV88E6065_PORT_MAC_CTL_SPEED_200;
96a2b40c
VD
226 break;
227 case 1000:
5ee55577 228 ctrl = MV88E6XXX_PORT_MAC_CTL_SPEED_1000;
96a2b40c
VD
229 break;
230 case 2500:
26422340
MB
231 if (alt_bit)
232 ctrl = MV88E6390_PORT_MAC_CTL_SPEED_10000 |
233 MV88E6390_PORT_MAC_CTL_ALTSPEED;
234 else
235 ctrl = MV88E6390_PORT_MAC_CTL_SPEED_10000;
96a2b40c
VD
236 break;
237 case 10000:
238 /* all bits set, fall through... */
239 case SPEED_UNFORCED:
5ee55577 240 ctrl = MV88E6XXX_PORT_MAC_CTL_SPEED_UNFORCED;
96a2b40c
VD
241 break;
242 default:
243 return -EOPNOTSUPP;
244 }
245
5ee55577 246 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_MAC_CTL, &reg);
96a2b40c
VD
247 if (err)
248 return err;
249
5ee55577 250 reg &= ~MV88E6XXX_PORT_MAC_CTL_SPEED_MASK;
96a2b40c 251 if (alt_bit)
5ee55577 252 reg &= ~MV88E6390_PORT_MAC_CTL_ALTSPEED;
96a2b40c 253 if (force_bit) {
5ee55577 254 reg &= ~MV88E6390_PORT_MAC_CTL_FORCE_SPEED;
0b6e3d03 255 if (speed != SPEED_UNFORCED)
5ee55577 256 ctrl |= MV88E6390_PORT_MAC_CTL_FORCE_SPEED;
96a2b40c
VD
257 }
258 reg |= ctrl;
259
5ee55577 260 err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_MAC_CTL, reg);
96a2b40c
VD
261 if (err)
262 return err;
263
264 if (speed)
774439e5 265 dev_dbg(chip->dev, "p%d: Speed set to %d Mbps\n", port, speed);
96a2b40c 266 else
774439e5 267 dev_dbg(chip->dev, "p%d: Speed unforced\n", port);
96a2b40c
VD
268
269 return 0;
270}
271
272/* Support 10, 100, 200 Mbps (e.g. 88E6065 family) */
273int mv88e6065_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
274{
275 if (speed == SPEED_MAX)
276 speed = 200;
277
278 if (speed > 200)
279 return -EOPNOTSUPP;
280
281 /* Setting 200 Mbps on port 0 to 3 selects 100 Mbps */
282 return mv88e6xxx_port_set_speed(chip, port, speed, false, false);
283}
284
285/* Support 10, 100, 1000 Mbps (e.g. 88E6185 family) */
286int mv88e6185_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
287{
288 if (speed == SPEED_MAX)
289 speed = 1000;
290
291 if (speed == 200 || speed > 1000)
292 return -EOPNOTSUPP;
293
294 return mv88e6xxx_port_set_speed(chip, port, speed, false, false);
295}
296
26422340
MB
297/* Support 10, 100, 200, 1000, 2500 Mbps (e.g. 88E6341) */
298int mv88e6341_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
299{
300 if (speed == SPEED_MAX)
301 speed = port < 5 ? 1000 : 2500;
302
303 if (speed > 2500)
304 return -EOPNOTSUPP;
305
306 if (speed == 200 && port != 0)
307 return -EOPNOTSUPP;
308
309 if (speed == 2500 && port < 5)
310 return -EOPNOTSUPP;
311
312 return mv88e6xxx_port_set_speed(chip, port, speed, !port, true);
313}
314
96a2b40c
VD
315/* Support 10, 100, 200, 1000 Mbps (e.g. 88E6352 family) */
316int mv88e6352_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
317{
318 if (speed == SPEED_MAX)
319 speed = 1000;
320
321 if (speed > 1000)
322 return -EOPNOTSUPP;
323
324 if (speed == 200 && port < 5)
325 return -EOPNOTSUPP;
326
327 return mv88e6xxx_port_set_speed(chip, port, speed, true, false);
328}
329
330/* Support 10, 100, 200, 1000, 2500 Mbps (e.g. 88E6390) */
331int mv88e6390_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
332{
333 if (speed == SPEED_MAX)
334 speed = port < 9 ? 1000 : 2500;
335
336 if (speed > 2500)
337 return -EOPNOTSUPP;
338
339 if (speed == 200 && port != 0)
340 return -EOPNOTSUPP;
341
342 if (speed == 2500 && port < 9)
343 return -EOPNOTSUPP;
344
345 return mv88e6xxx_port_set_speed(chip, port, speed, true, true);
346}
347
348/* Support 10, 100, 200, 1000, 2500, 10000 Mbps (e.g. 88E6190X) */
349int mv88e6390x_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
350{
351 if (speed == SPEED_MAX)
352 speed = port < 9 ? 1000 : 10000;
353
354 if (speed == 200 && port != 0)
355 return -EOPNOTSUPP;
356
357 if (speed >= 2500 && port < 9)
358 return -EOPNOTSUPP;
359
360 return mv88e6xxx_port_set_speed(chip, port, speed, true, true);
361}
362
f39908d3
AL
363int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
364 phy_interface_t mode)
365{
734447d4 366 int lane;
f39908d3 367 u16 cmode;
734447d4 368 u16 reg;
f39908d3
AL
369 int err;
370
f39908d3
AL
371 if (port != 9 && port != 10)
372 return -EOPNOTSUPP;
373
787799a9
AL
374 /* Default to a slow mode, so freeing up SERDES interfaces for
375 * other ports which might use them for SFPs.
376 */
377 if (mode == PHY_INTERFACE_MODE_NA)
378 mode = PHY_INTERFACE_MODE_1000BASEX;
379
f39908d3
AL
380 switch (mode) {
381 case PHY_INTERFACE_MODE_1000BASEX:
5f83dc93 382 cmode = MV88E6XXX_PORT_STS_CMODE_1000BASE_X;
f39908d3
AL
383 break;
384 case PHY_INTERFACE_MODE_SGMII:
5f83dc93 385 cmode = MV88E6XXX_PORT_STS_CMODE_SGMII;
f39908d3
AL
386 break;
387 case PHY_INTERFACE_MODE_2500BASEX:
5f83dc93 388 cmode = MV88E6XXX_PORT_STS_CMODE_2500BASEX;
f39908d3
AL
389 break;
390 case PHY_INTERFACE_MODE_XGMII:
2e51a8dc 391 case PHY_INTERFACE_MODE_XAUI:
5f83dc93 392 cmode = MV88E6XXX_PORT_STS_CMODE_XAUI;
f39908d3
AL
393 break;
394 case PHY_INTERFACE_MODE_RXAUI:
5f83dc93 395 cmode = MV88E6XXX_PORT_STS_CMODE_RXAUI;
f39908d3
AL
396 break;
397 default:
398 cmode = 0;
399 }
400
ed8fe202
HK
401 /* cmode doesn't change, nothing to do for us */
402 if (cmode == chip->ports[port].cmode)
403 return 0;
404
734447d4
AL
405 lane = mv88e6390x_serdes_get_lane(chip, port);
406 if (lane < 0)
407 return lane;
408
409 if (chip->ports[port].serdes_irq) {
410 err = mv88e6390_serdes_irq_disable(chip, port, lane);
411 if (err)
412 return err;
413 }
414
d235c48b 415 err = mv88e6390x_serdes_power(chip, port, false);
364e9d77
AL
416 if (err)
417 return err;
418
f39908d3 419 if (cmode) {
5f83dc93 420 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &reg);
f39908d3
AL
421 if (err)
422 return err;
423
5f83dc93 424 reg &= ~MV88E6XXX_PORT_STS_CMODE_MASK;
f39908d3
AL
425 reg |= cmode;
426
5f83dc93 427 err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_STS, reg);
f39908d3
AL
428 if (err)
429 return err;
364e9d77 430
d235c48b 431 err = mv88e6390x_serdes_power(chip, port, true);
364e9d77
AL
432 if (err)
433 return err;
734447d4
AL
434
435 if (chip->ports[port].serdes_irq) {
436 err = mv88e6390_serdes_irq_enable(chip, port, lane);
437 if (err)
438 return err;
439 }
f39908d3
AL
440 }
441
2d2e1dd2
AL
442 chip->ports[port].cmode = cmode;
443
f39908d3
AL
444 return 0;
445}
446
fdc71eea
AL
447int mv88e6390_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
448 phy_interface_t mode)
449{
450 switch (mode) {
451 case PHY_INTERFACE_MODE_XGMII:
452 case PHY_INTERFACE_MODE_XAUI:
453 case PHY_INTERFACE_MODE_RXAUI:
454 return -EINVAL;
455 default:
456 break;
457 }
458
459 return mv88e6390x_port_set_cmode(chip, port, mode);
460}
461
2d2e1dd2 462int mv88e6185_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode)
6c422e34
RK
463{
464 int err;
465 u16 reg;
466
467 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &reg);
468 if (err)
469 return err;
470
2d2e1dd2
AL
471 *cmode = reg & MV88E6185_PORT_STS_CMODE_MASK;
472
473 return 0;
6c422e34
RK
474}
475
2d2e1dd2 476int mv88e6352_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode)
f39908d3
AL
477{
478 int err;
479 u16 reg;
480
5f83dc93 481 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &reg);
f39908d3
AL
482 if (err)
483 return err;
484
5f83dc93 485 *cmode = reg & MV88E6XXX_PORT_STS_CMODE_MASK;
f39908d3
AL
486
487 return 0;
488}
489
6c422e34 490int mv88e6352_port_link_state(struct mv88e6xxx_chip *chip, int port,
c9a2356f
RK
491 struct phylink_link_state *state)
492{
493 int err;
494 u16 reg;
495
496 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &reg);
497 if (err)
498 return err;
499
500 switch (reg & MV88E6XXX_PORT_STS_SPEED_MASK) {
501 case MV88E6XXX_PORT_STS_SPEED_10:
502 state->speed = SPEED_10;
503 break;
504 case MV88E6XXX_PORT_STS_SPEED_100:
505 state->speed = SPEED_100;
506 break;
507 case MV88E6XXX_PORT_STS_SPEED_1000:
508 state->speed = SPEED_1000;
509 break;
510 case MV88E6XXX_PORT_STS_SPEED_10000:
6c422e34 511 if ((reg & MV88E6XXX_PORT_STS_CMODE_MASK) ==
c9a2356f
RK
512 MV88E6XXX_PORT_STS_CMODE_2500BASEX)
513 state->speed = SPEED_2500;
514 else
515 state->speed = SPEED_10000;
516 break;
517 }
518
519 state->duplex = reg & MV88E6XXX_PORT_STS_DUPLEX ?
520 DUPLEX_FULL : DUPLEX_HALF;
521 state->link = !!(reg & MV88E6XXX_PORT_STS_LINK);
522 state->an_enabled = 1;
523 state->an_complete = state->link;
524
525 return 0;
526}
527
6c422e34
RK
528int mv88e6185_port_link_state(struct mv88e6xxx_chip *chip, int port,
529 struct phylink_link_state *state)
530{
531 if (state->interface == PHY_INTERFACE_MODE_1000BASEX) {
2d2e1dd2 532 u8 cmode = chip->ports[port].cmode;
6c422e34
RK
533
534 /* When a port is in "Cross-chip serdes" mode, it uses
535 * 1000Base-X full duplex mode, but there is no automatic
536 * link detection. Use the sync OK status for link (as it
537 * would do for 1000Base-X mode.)
538 */
539 if (cmode == MV88E6185_PORT_STS_CMODE_SERDES) {
540 u16 mac;
541 int err;
542
543 err = mv88e6xxx_port_read(chip, port,
544 MV88E6XXX_PORT_MAC_CTL, &mac);
545 if (err)
546 return err;
547
548 state->link = !!(mac & MV88E6185_PORT_MAC_CTL_SYNC_OK);
549 state->an_enabled = 1;
550 state->an_complete =
551 !!(mac & MV88E6185_PORT_MAC_CTL_AN_DONE);
552 state->duplex =
553 state->link ? DUPLEX_FULL : DUPLEX_UNKNOWN;
554 state->speed =
555 state->link ? SPEED_1000 : SPEED_UNKNOWN;
556
557 return 0;
558 }
559 }
560
561 return mv88e6352_port_link_state(chip, port, state);
562}
563
6c96bbfd 564/* Offset 0x02: Jamming Control
b35d322a
AL
565 *
566 * Do not limit the period of time that this port can be paused for by
567 * the remote end or the period of time that this port can pause the
568 * remote end.
569 */
0898432c
VD
570int mv88e6097_port_pause_limit(struct mv88e6xxx_chip *chip, int port, u8 in,
571 u8 out)
b35d322a 572{
6c96bbfd
VD
573 return mv88e6xxx_port_write(chip, port, MV88E6097_PORT_JAM_CTL,
574 out << 8 | in);
b35d322a
AL
575}
576
0898432c
VD
577int mv88e6390_port_pause_limit(struct mv88e6xxx_chip *chip, int port, u8 in,
578 u8 out)
3ce0e65e
AL
579{
580 int err;
581
6c96bbfd
VD
582 err = mv88e6xxx_port_write(chip, port, MV88E6390_PORT_FLOW_CTL,
583 MV88E6390_PORT_FLOW_CTL_UPDATE |
584 MV88E6390_PORT_FLOW_CTL_LIMIT_IN | in);
3ce0e65e
AL
585 if (err)
586 return err;
587
6c96bbfd
VD
588 return mv88e6xxx_port_write(chip, port, MV88E6390_PORT_FLOW_CTL,
589 MV88E6390_PORT_FLOW_CTL_UPDATE |
590 MV88E6390_PORT_FLOW_CTL_LIMIT_OUT | out);
3ce0e65e
AL
591}
592
e28def33
VD
593/* Offset 0x04: Port Control Register */
594
595static const char * const mv88e6xxx_port_state_names[] = {
a89b433b
VD
596 [MV88E6XXX_PORT_CTL0_STATE_DISABLED] = "Disabled",
597 [MV88E6XXX_PORT_CTL0_STATE_BLOCKING] = "Blocking/Listening",
598 [MV88E6XXX_PORT_CTL0_STATE_LEARNING] = "Learning",
599 [MV88E6XXX_PORT_CTL0_STATE_FORWARDING] = "Forwarding",
e28def33
VD
600};
601
602int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state)
603{
604 u16 reg;
605 int err;
606
a89b433b 607 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, &reg);
e28def33
VD
608 if (err)
609 return err;
610
a89b433b 611 reg &= ~MV88E6XXX_PORT_CTL0_STATE_MASK;
f894c29c
VD
612
613 switch (state) {
614 case BR_STATE_DISABLED:
a89b433b 615 state = MV88E6XXX_PORT_CTL0_STATE_DISABLED;
f894c29c
VD
616 break;
617 case BR_STATE_BLOCKING:
618 case BR_STATE_LISTENING:
a89b433b 619 state = MV88E6XXX_PORT_CTL0_STATE_BLOCKING;
f894c29c
VD
620 break;
621 case BR_STATE_LEARNING:
a89b433b 622 state = MV88E6XXX_PORT_CTL0_STATE_LEARNING;
f894c29c
VD
623 break;
624 case BR_STATE_FORWARDING:
a89b433b 625 state = MV88E6XXX_PORT_CTL0_STATE_FORWARDING;
f894c29c
VD
626 break;
627 default:
628 return -EINVAL;
629 }
630
e28def33
VD
631 reg |= state;
632
a89b433b 633 err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
e28def33
VD
634 if (err)
635 return err;
636
774439e5
VD
637 dev_dbg(chip->dev, "p%d: PortState set to %s\n", port,
638 mv88e6xxx_port_state_names[state]);
e28def33
VD
639
640 return 0;
641}
5a7921f4 642
56995cbc 643int mv88e6xxx_port_set_egress_mode(struct mv88e6xxx_chip *chip, int port,
31bef4e9 644 enum mv88e6xxx_egress_mode mode)
56995cbc
AL
645{
646 int err;
647 u16 reg;
648
a89b433b 649 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, &reg);
56995cbc
AL
650 if (err)
651 return err;
652
a89b433b 653 reg &= ~MV88E6XXX_PORT_CTL0_EGRESS_MODE_MASK;
31bef4e9
VD
654
655 switch (mode) {
656 case MV88E6XXX_EGRESS_MODE_UNMODIFIED:
a89b433b 657 reg |= MV88E6XXX_PORT_CTL0_EGRESS_MODE_UNMODIFIED;
31bef4e9
VD
658 break;
659 case MV88E6XXX_EGRESS_MODE_UNTAGGED:
a89b433b 660 reg |= MV88E6XXX_PORT_CTL0_EGRESS_MODE_UNTAGGED;
31bef4e9
VD
661 break;
662 case MV88E6XXX_EGRESS_MODE_TAGGED:
a89b433b 663 reg |= MV88E6XXX_PORT_CTL0_EGRESS_MODE_TAGGED;
31bef4e9
VD
664 break;
665 case MV88E6XXX_EGRESS_MODE_ETHERTYPE:
a89b433b 666 reg |= MV88E6XXX_PORT_CTL0_EGRESS_MODE_ETHER_TYPE_DSA;
31bef4e9
VD
667 break;
668 default:
669 return -EINVAL;
670 }
56995cbc 671
a89b433b 672 return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
56995cbc
AL
673}
674
675int mv88e6085_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port,
676 enum mv88e6xxx_frame_mode mode)
677{
678 int err;
679 u16 reg;
680
a89b433b 681 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, &reg);
56995cbc
AL
682 if (err)
683 return err;
684
a89b433b 685 reg &= ~MV88E6XXX_PORT_CTL0_FRAME_MODE_MASK;
56995cbc
AL
686
687 switch (mode) {
688 case MV88E6XXX_FRAME_MODE_NORMAL:
a89b433b 689 reg |= MV88E6XXX_PORT_CTL0_FRAME_MODE_NORMAL;
56995cbc
AL
690 break;
691 case MV88E6XXX_FRAME_MODE_DSA:
a89b433b 692 reg |= MV88E6XXX_PORT_CTL0_FRAME_MODE_DSA;
56995cbc
AL
693 break;
694 default:
695 return -EINVAL;
696 }
697
a89b433b 698 return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
56995cbc
AL
699}
700
701int mv88e6351_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port,
702 enum mv88e6xxx_frame_mode mode)
703{
704 int err;
705 u16 reg;
706
a89b433b 707 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, &reg);
56995cbc
AL
708 if (err)
709 return err;
710
a89b433b 711 reg &= ~MV88E6XXX_PORT_CTL0_FRAME_MODE_MASK;
56995cbc
AL
712
713 switch (mode) {
714 case MV88E6XXX_FRAME_MODE_NORMAL:
a89b433b 715 reg |= MV88E6XXX_PORT_CTL0_FRAME_MODE_NORMAL;
56995cbc
AL
716 break;
717 case MV88E6XXX_FRAME_MODE_DSA:
a89b433b 718 reg |= MV88E6XXX_PORT_CTL0_FRAME_MODE_DSA;
56995cbc
AL
719 break;
720 case MV88E6XXX_FRAME_MODE_PROVIDER:
a89b433b 721 reg |= MV88E6XXX_PORT_CTL0_FRAME_MODE_PROVIDER;
56995cbc
AL
722 break;
723 case MV88E6XXX_FRAME_MODE_ETHERTYPE:
a89b433b 724 reg |= MV88E6XXX_PORT_CTL0_FRAME_MODE_ETHER_TYPE_DSA;
56995cbc
AL
725 break;
726 default:
727 return -EINVAL;
728 }
729
a89b433b 730 return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
56995cbc
AL
731}
732
601aeed3
VD
733static int mv88e6185_port_set_forward_unknown(struct mv88e6xxx_chip *chip,
734 int port, bool unicast)
56995cbc
AL
735{
736 int err;
737 u16 reg;
738
a89b433b 739 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, &reg);
56995cbc
AL
740 if (err)
741 return err;
742
601aeed3 743 if (unicast)
a89b433b 744 reg |= MV88E6185_PORT_CTL0_FORWARD_UNKNOWN;
56995cbc 745 else
a89b433b 746 reg &= ~MV88E6185_PORT_CTL0_FORWARD_UNKNOWN;
56995cbc 747
a89b433b 748 return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
56995cbc
AL
749}
750
601aeed3
VD
751int mv88e6352_port_set_egress_floods(struct mv88e6xxx_chip *chip, int port,
752 bool unicast, bool multicast)
56995cbc
AL
753{
754 int err;
755 u16 reg;
756
a89b433b 757 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, &reg);
56995cbc
AL
758 if (err)
759 return err;
760
a89b433b 761 reg &= ~MV88E6352_PORT_CTL0_EGRESS_FLOODS_MASK;
601aeed3
VD
762
763 if (unicast && multicast)
a89b433b 764 reg |= MV88E6352_PORT_CTL0_EGRESS_FLOODS_ALL_UNKNOWN_DA;
601aeed3 765 else if (unicast)
a89b433b 766 reg |= MV88E6352_PORT_CTL0_EGRESS_FLOODS_NO_UNKNOWN_MC_DA;
601aeed3 767 else if (multicast)
a89b433b 768 reg |= MV88E6352_PORT_CTL0_EGRESS_FLOODS_NO_UNKNOWN_UC_DA;
56995cbc 769 else
a89b433b 770 reg |= MV88E6352_PORT_CTL0_EGRESS_FLOODS_NO_UNKNOWN_DA;
56995cbc 771
a89b433b 772 return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
56995cbc
AL
773}
774
b4e48c50
VD
775/* Offset 0x05: Port Control 1 */
776
ea698f4f
VD
777int mv88e6xxx_port_set_message_port(struct mv88e6xxx_chip *chip, int port,
778 bool message_port)
779{
780 u16 val;
781 int err;
782
cd985bbf 783 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL1, &val);
ea698f4f
VD
784 if (err)
785 return err;
786
787 if (message_port)
cd985bbf 788 val |= MV88E6XXX_PORT_CTL1_MESSAGE_PORT;
ea698f4f 789 else
cd985bbf 790 val &= ~MV88E6XXX_PORT_CTL1_MESSAGE_PORT;
ea698f4f 791
cd985bbf 792 return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL1, val);
ea698f4f
VD
793}
794
5a7921f4
VD
795/* Offset 0x06: Port Based VLAN Map */
796
797int mv88e6xxx_port_set_vlan_map(struct mv88e6xxx_chip *chip, int port, u16 map)
798{
4d294af2 799 const u16 mask = mv88e6xxx_port_mask(chip);
5a7921f4
VD
800 u16 reg;
801 int err;
802
7e5cc5f1 803 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_BASE_VLAN, &reg);
5a7921f4
VD
804 if (err)
805 return err;
806
807 reg &= ~mask;
808 reg |= map & mask;
809
7e5cc5f1 810 err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_BASE_VLAN, reg);
5a7921f4
VD
811 if (err)
812 return err;
813
774439e5 814 dev_dbg(chip->dev, "p%d: VLANTable set to %.3x\n", port, map);
5a7921f4
VD
815
816 return 0;
817}
b4e48c50
VD
818
819int mv88e6xxx_port_get_fid(struct mv88e6xxx_chip *chip, int port, u16 *fid)
820{
821 const u16 upper_mask = (mv88e6xxx_num_databases(chip) - 1) >> 4;
822 u16 reg;
823 int err;
824
825 /* Port's default FID lower 4 bits are located in reg 0x06, offset 12 */
7e5cc5f1 826 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_BASE_VLAN, &reg);
b4e48c50
VD
827 if (err)
828 return err;
829
830 *fid = (reg & 0xf000) >> 12;
831
832 /* Port's default FID upper bits are located in reg 0x05, offset 0 */
833 if (upper_mask) {
cd985bbf
VD
834 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL1,
835 &reg);
b4e48c50
VD
836 if (err)
837 return err;
838
839 *fid |= (reg & upper_mask) << 4;
840 }
841
842 return 0;
843}
844
845int mv88e6xxx_port_set_fid(struct mv88e6xxx_chip *chip, int port, u16 fid)
846{
847 const u16 upper_mask = (mv88e6xxx_num_databases(chip) - 1) >> 4;
848 u16 reg;
849 int err;
850
851 if (fid >= mv88e6xxx_num_databases(chip))
852 return -EINVAL;
853
854 /* Port's default FID lower 4 bits are located in reg 0x06, offset 12 */
7e5cc5f1 855 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_BASE_VLAN, &reg);
b4e48c50
VD
856 if (err)
857 return err;
858
859 reg &= 0x0fff;
860 reg |= (fid & 0x000f) << 12;
861
7e5cc5f1 862 err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_BASE_VLAN, reg);
b4e48c50
VD
863 if (err)
864 return err;
865
866 /* Port's default FID upper bits are located in reg 0x05, offset 0 */
867 if (upper_mask) {
cd985bbf
VD
868 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL1,
869 &reg);
b4e48c50
VD
870 if (err)
871 return err;
872
873 reg &= ~upper_mask;
874 reg |= (fid >> 4) & upper_mask;
875
cd985bbf
VD
876 err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL1,
877 reg);
b4e48c50
VD
878 if (err)
879 return err;
880 }
881
774439e5 882 dev_dbg(chip->dev, "p%d: FID set to %u\n", port, fid);
b4e48c50
VD
883
884 return 0;
885}
77064f37
VD
886
887/* Offset 0x07: Default Port VLAN ID & Priority */
888
889int mv88e6xxx_port_get_pvid(struct mv88e6xxx_chip *chip, int port, u16 *pvid)
890{
891 u16 reg;
892 int err;
893
b7929fb3
VD
894 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_DEFAULT_VLAN,
895 &reg);
77064f37
VD
896 if (err)
897 return err;
898
b7929fb3 899 *pvid = reg & MV88E6XXX_PORT_DEFAULT_VLAN_MASK;
77064f37
VD
900
901 return 0;
902}
903
904int mv88e6xxx_port_set_pvid(struct mv88e6xxx_chip *chip, int port, u16 pvid)
905{
906 u16 reg;
907 int err;
908
b7929fb3
VD
909 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_DEFAULT_VLAN,
910 &reg);
77064f37
VD
911 if (err)
912 return err;
913
b7929fb3
VD
914 reg &= ~MV88E6XXX_PORT_DEFAULT_VLAN_MASK;
915 reg |= pvid & MV88E6XXX_PORT_DEFAULT_VLAN_MASK;
77064f37 916
b7929fb3
VD
917 err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_DEFAULT_VLAN,
918 reg);
77064f37
VD
919 if (err)
920 return err;
921
774439e5 922 dev_dbg(chip->dev, "p%d: DefaultVID set to %u\n", port, pvid);
77064f37
VD
923
924 return 0;
925}
385a0995
VD
926
927/* Offset 0x08: Port Control 2 Register */
928
929static const char * const mv88e6xxx_port_8021q_mode_names[] = {
81c6edb2
VD
930 [MV88E6XXX_PORT_CTL2_8021Q_MODE_DISABLED] = "Disabled",
931 [MV88E6XXX_PORT_CTL2_8021Q_MODE_FALLBACK] = "Fallback",
932 [MV88E6XXX_PORT_CTL2_8021Q_MODE_CHECK] = "Check",
933 [MV88E6XXX_PORT_CTL2_8021Q_MODE_SECURE] = "Secure",
385a0995
VD
934};
935
601aeed3
VD
936static int mv88e6185_port_set_default_forward(struct mv88e6xxx_chip *chip,
937 int port, bool multicast)
a23b2961
AL
938{
939 int err;
940 u16 reg;
941
81c6edb2 942 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, &reg);
a23b2961
AL
943 if (err)
944 return err;
945
601aeed3 946 if (multicast)
81c6edb2 947 reg |= MV88E6XXX_PORT_CTL2_DEFAULT_FORWARD;
a23b2961 948 else
81c6edb2 949 reg &= ~MV88E6XXX_PORT_CTL2_DEFAULT_FORWARD;
a23b2961 950
81c6edb2 951 return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg);
a23b2961
AL
952}
953
601aeed3
VD
954int mv88e6185_port_set_egress_floods(struct mv88e6xxx_chip *chip, int port,
955 bool unicast, bool multicast)
956{
957 int err;
958
959 err = mv88e6185_port_set_forward_unknown(chip, port, unicast);
960 if (err)
961 return err;
962
963 return mv88e6185_port_set_default_forward(chip, port, multicast);
964}
965
a23b2961
AL
966int mv88e6095_port_set_upstream_port(struct mv88e6xxx_chip *chip, int port,
967 int upstream_port)
968{
969 int err;
970 u16 reg;
971
81c6edb2 972 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, &reg);
a23b2961
AL
973 if (err)
974 return err;
975
81c6edb2 976 reg &= ~MV88E6095_PORT_CTL2_CPU_PORT_MASK;
a23b2961
AL
977 reg |= upstream_port;
978
81c6edb2 979 return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg);
a23b2961
AL
980}
981
385a0995
VD
982int mv88e6xxx_port_set_8021q_mode(struct mv88e6xxx_chip *chip, int port,
983 u16 mode)
984{
985 u16 reg;
986 int err;
987
81c6edb2 988 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, &reg);
385a0995
VD
989 if (err)
990 return err;
991
81c6edb2
VD
992 reg &= ~MV88E6XXX_PORT_CTL2_8021Q_MODE_MASK;
993 reg |= mode & MV88E6XXX_PORT_CTL2_8021Q_MODE_MASK;
385a0995 994
81c6edb2 995 err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg);
385a0995
VD
996 if (err)
997 return err;
998
774439e5
VD
999 dev_dbg(chip->dev, "p%d: 802.1QMode set to %s\n", port,
1000 mv88e6xxx_port_8021q_mode_names[mode]);
385a0995
VD
1001
1002 return 0;
1003}
ef0a7318 1004
a23b2961
AL
1005int mv88e6xxx_port_set_map_da(struct mv88e6xxx_chip *chip, int port)
1006{
1007 u16 reg;
1008 int err;
1009
81c6edb2 1010 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, &reg);
a23b2961
AL
1011 if (err)
1012 return err;
1013
81c6edb2 1014 reg |= MV88E6XXX_PORT_CTL2_MAP_DA;
a23b2961 1015
81c6edb2 1016 return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg);
a23b2961
AL
1017}
1018
cd782656
VD
1019int mv88e6165_port_set_jumbo_size(struct mv88e6xxx_chip *chip, int port,
1020 size_t size)
5f436666
AL
1021{
1022 u16 reg;
1023 int err;
1024
81c6edb2 1025 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, &reg);
5f436666
AL
1026 if (err)
1027 return err;
1028
81c6edb2 1029 reg &= ~MV88E6XXX_PORT_CTL2_JUMBO_MODE_MASK;
cd782656
VD
1030
1031 if (size <= 1522)
81c6edb2 1032 reg |= MV88E6XXX_PORT_CTL2_JUMBO_MODE_1522;
cd782656 1033 else if (size <= 2048)
81c6edb2 1034 reg |= MV88E6XXX_PORT_CTL2_JUMBO_MODE_2048;
cd782656 1035 else if (size <= 10240)
81c6edb2 1036 reg |= MV88E6XXX_PORT_CTL2_JUMBO_MODE_10240;
cd782656
VD
1037 else
1038 return -ERANGE;
5f436666 1039
81c6edb2 1040 return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg);
5f436666
AL
1041}
1042
ef70b111
AL
1043/* Offset 0x09: Port Rate Control */
1044
1045int mv88e6095_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port)
1046{
2cb8cb14
VD
1047 return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_EGRESS_RATE_CTL1,
1048 0x0000);
ef70b111
AL
1049}
1050
1051int mv88e6097_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port)
1052{
2cb8cb14
VD
1053 return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_EGRESS_RATE_CTL1,
1054 0x0001);
ef70b111
AL
1055}
1056
c8c94891
VD
1057/* Offset 0x0C: Port ATU Control */
1058
1059int mv88e6xxx_port_disable_learn_limit(struct mv88e6xxx_chip *chip, int port)
1060{
b8109594 1061 return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_ATU_CTL, 0);
c8c94891
VD
1062}
1063
9dbfb4e1
VD
1064/* Offset 0x0D: (Priority) Override Register */
1065
1066int mv88e6xxx_port_disable_pri_override(struct mv88e6xxx_chip *chip, int port)
1067{
b8109594 1068 return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_PRI_OVERRIDE, 0);
9dbfb4e1
VD
1069}
1070
56995cbc
AL
1071/* Offset 0x0f: Port Ether type */
1072
1073int mv88e6351_port_set_ether_type(struct mv88e6xxx_chip *chip, int port,
1074 u16 etype)
1075{
b8109594 1076 return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_ETH_TYPE, etype);
56995cbc
AL
1077}
1078
ef0a7318
AL
1079/* Offset 0x18: Port IEEE Priority Remapping Registers [0-3]
1080 * Offset 0x19: Port IEEE Priority Remapping Registers [4-7]
1081 */
1082
1083int mv88e6095_port_tag_remap(struct mv88e6xxx_chip *chip, int port)
1084{
1085 int err;
1086
1087 /* Use a direct priority mapping for all IEEE tagged frames */
8009df9e
VD
1088 err = mv88e6xxx_port_write(chip, port,
1089 MV88E6095_PORT_IEEE_PRIO_REMAP_0123,
1090 0x3210);
ef0a7318
AL
1091 if (err)
1092 return err;
1093
8009df9e
VD
1094 return mv88e6xxx_port_write(chip, port,
1095 MV88E6095_PORT_IEEE_PRIO_REMAP_4567,
1096 0x7654);
ef0a7318
AL
1097}
1098
1099static int mv88e6xxx_port_ieeepmt_write(struct mv88e6xxx_chip *chip,
ddcbabf4 1100 int port, u16 table, u8 ptr, u16 data)
ef0a7318
AL
1101{
1102 u16 reg;
1103
ddcbabf4
VD
1104 reg = MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_UPDATE | table |
1105 (ptr << __bf_shf(MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_PTR_MASK)) |
1106 (data & MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_DATA_MASK);
ef0a7318 1107
8009df9e
VD
1108 return mv88e6xxx_port_write(chip, port,
1109 MV88E6390_PORT_IEEE_PRIO_MAP_TABLE, reg);
ef0a7318
AL
1110}
1111
1112int mv88e6390_port_tag_remap(struct mv88e6xxx_chip *chip, int port)
1113{
1114 int err, i;
8009df9e 1115 u16 table;
ef0a7318
AL
1116
1117 for (i = 0; i <= 7; i++) {
8009df9e
VD
1118 table = MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_INGRESS_PCP;
1119 err = mv88e6xxx_port_ieeepmt_write(chip, port, table, i,
1120 (i | i << 4));
ef0a7318
AL
1121 if (err)
1122 return err;
1123
8009df9e
VD
1124 table = MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_GREEN_PCP;
1125 err = mv88e6xxx_port_ieeepmt_write(chip, port, table, i, i);
ef0a7318
AL
1126 if (err)
1127 return err;
1128
8009df9e
VD
1129 table = MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_YELLOW_PCP;
1130 err = mv88e6xxx_port_ieeepmt_write(chip, port, table, i, i);
ef0a7318
AL
1131 if (err)
1132 return err;
1133
8009df9e
VD
1134 table = MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_AVB_PCP;
1135 err = mv88e6xxx_port_ieeepmt_write(chip, port, table, i, i);
ef0a7318
AL
1136 if (err)
1137 return err;
1138 }
1139
1140 return 0;
1141}