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