]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/blame - drivers/net/dsa/mv88e6xxx/port.c
net: dsa: mv88e6xxx: Implement Clause 45 access to SMI devices
[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 *
6 * Copyright (c) 2016 Vivien Didelot <vivien.didelot@savoirfairelinux.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 */
13
f39908d3 14#include <linux/phy.h>
18abed21
VD
15#include "mv88e6xxx.h"
16#include "port.h"
17
18int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port, int reg,
19 u16 *val)
20{
21 int addr = chip->info->port_base_addr + port;
22
23 return mv88e6xxx_read(chip, addr, reg, val);
24}
25
26int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg,
27 u16 val)
28{
29 int addr = chip->info->port_base_addr + port;
30
31 return mv88e6xxx_write(chip, addr, reg, val);
32}
e28def33 33
08ef7f10
VD
34/* Offset 0x01: MAC (or PCS or Physical) Control Register
35 *
36 * Link, Duplex and Flow Control have one force bit, one value bit.
96a2b40c
VD
37 *
38 * For port's MAC speed, ForceSpd (or SpdValue) bits 1:0 program the value.
39 * Alternative values require the 200BASE (or AltSpeed) bit 12 set.
40 * Newer chips need a ForcedSpd bit 13 set to consider the value.
08ef7f10
VD
41 */
42
a0a0f622
VD
43static int mv88e6xxx_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,
44 phy_interface_t mode)
45{
46 u16 reg;
47 int err;
48
49 err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, &reg);
50 if (err)
51 return err;
52
53 reg &= ~(PORT_PCS_CTRL_RGMII_DELAY_RXCLK |
54 PORT_PCS_CTRL_RGMII_DELAY_TXCLK);
55
56 switch (mode) {
57 case PHY_INTERFACE_MODE_RGMII_RXID:
58 reg |= PORT_PCS_CTRL_RGMII_DELAY_RXCLK;
59 break;
60 case PHY_INTERFACE_MODE_RGMII_TXID:
61 reg |= PORT_PCS_CTRL_RGMII_DELAY_TXCLK;
62 break;
63 case PHY_INTERFACE_MODE_RGMII_ID:
64 reg |= PORT_PCS_CTRL_RGMII_DELAY_RXCLK |
65 PORT_PCS_CTRL_RGMII_DELAY_TXCLK;
66 break;
fedf1865 67 case PHY_INTERFACE_MODE_RGMII:
a0a0f622 68 break;
fedf1865
AL
69 default:
70 return 0;
a0a0f622
VD
71 }
72
73 err = mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg);
74 if (err)
75 return err;
76
77 netdev_dbg(chip->ds->ports[port].netdev, "delay RXCLK %s, TXCLK %s\n",
78 reg & PORT_PCS_CTRL_RGMII_DELAY_RXCLK ? "yes" : "no",
79 reg & PORT_PCS_CTRL_RGMII_DELAY_TXCLK ? "yes" : "no");
80
81 return 0;
82}
83
84int mv88e6352_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,
85 phy_interface_t mode)
86{
87 if (port < 5)
88 return -EOPNOTSUPP;
89
90 return mv88e6xxx_port_set_rgmii_delay(chip, port, mode);
91}
92
93int mv88e6390_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,
94 phy_interface_t mode)
95{
96 if (port != 0)
97 return -EOPNOTSUPP;
98
99 return mv88e6xxx_port_set_rgmii_delay(chip, port, mode);
100}
101
08ef7f10
VD
102int mv88e6xxx_port_set_link(struct mv88e6xxx_chip *chip, int port, int link)
103{
104 u16 reg;
105 int err;
106
107 err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, &reg);
108 if (err)
109 return err;
110
111 reg &= ~(PORT_PCS_CTRL_FORCE_LINK | PORT_PCS_CTRL_LINK_UP);
112
113 switch (link) {
114 case LINK_FORCED_DOWN:
115 reg |= PORT_PCS_CTRL_FORCE_LINK;
116 break;
117 case LINK_FORCED_UP:
118 reg |= PORT_PCS_CTRL_FORCE_LINK | PORT_PCS_CTRL_LINK_UP;
119 break;
120 case LINK_UNFORCED:
121 /* normal link detection */
122 break;
123 default:
124 return -EINVAL;
125 }
126
127 err = mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg);
128 if (err)
129 return err;
130
131 netdev_dbg(chip->ds->ports[port].netdev, "%s link %s\n",
132 reg & PORT_PCS_CTRL_FORCE_LINK ? "Force" : "Unforce",
133 reg & PORT_PCS_CTRL_LINK_UP ? "up" : "down");
134
135 return 0;
136}
137
7f1ae07b
VD
138int mv88e6xxx_port_set_duplex(struct mv88e6xxx_chip *chip, int port, int dup)
139{
140 u16 reg;
141 int err;
142
143 err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, &reg);
144 if (err)
145 return err;
146
147 reg &= ~(PORT_PCS_CTRL_FORCE_DUPLEX | PORT_PCS_CTRL_DUPLEX_FULL);
148
149 switch (dup) {
150 case DUPLEX_HALF:
151 reg |= PORT_PCS_CTRL_FORCE_DUPLEX;
152 break;
153 case DUPLEX_FULL:
154 reg |= PORT_PCS_CTRL_FORCE_DUPLEX | PORT_PCS_CTRL_DUPLEX_FULL;
155 break;
156 case DUPLEX_UNFORCED:
157 /* normal duplex detection */
158 break;
159 default:
160 return -EINVAL;
161 }
162
163 err = mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg);
164 if (err)
165 return err;
166
167 netdev_dbg(chip->ds->ports[port].netdev, "%s %s duplex\n",
168 reg & PORT_PCS_CTRL_FORCE_DUPLEX ? "Force" : "Unforce",
169 reg & PORT_PCS_CTRL_DUPLEX_FULL ? "full" : "half");
170
171 return 0;
172}
173
96a2b40c
VD
174static int mv88e6xxx_port_set_speed(struct mv88e6xxx_chip *chip, int port,
175 int speed, bool alt_bit, bool force_bit)
176{
177 u16 reg, ctrl;
178 int err;
179
180 switch (speed) {
181 case 10:
182 ctrl = PORT_PCS_CTRL_SPEED_10;
183 break;
184 case 100:
185 ctrl = PORT_PCS_CTRL_SPEED_100;
186 break;
187 case 200:
188 if (alt_bit)
189 ctrl = PORT_PCS_CTRL_SPEED_100 | PORT_PCS_CTRL_ALTSPEED;
190 else
191 ctrl = PORT_PCS_CTRL_SPEED_200;
192 break;
193 case 1000:
194 ctrl = PORT_PCS_CTRL_SPEED_1000;
195 break;
196 case 2500:
740117a8 197 ctrl = PORT_PCS_CTRL_SPEED_10000 | PORT_PCS_CTRL_ALTSPEED;
96a2b40c
VD
198 break;
199 case 10000:
200 /* all bits set, fall through... */
201 case SPEED_UNFORCED:
202 ctrl = PORT_PCS_CTRL_SPEED_UNFORCED;
203 break;
204 default:
205 return -EOPNOTSUPP;
206 }
207
208 err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, &reg);
209 if (err)
210 return err;
211
212 reg &= ~PORT_PCS_CTRL_SPEED_MASK;
213 if (alt_bit)
214 reg &= ~PORT_PCS_CTRL_ALTSPEED;
215 if (force_bit) {
216 reg &= ~PORT_PCS_CTRL_FORCE_SPEED;
0b6e3d03 217 if (speed != SPEED_UNFORCED)
96a2b40c
VD
218 ctrl |= PORT_PCS_CTRL_FORCE_SPEED;
219 }
220 reg |= ctrl;
221
222 err = mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg);
223 if (err)
224 return err;
225
226 if (speed)
227 netdev_dbg(chip->ds->ports[port].netdev,
228 "Speed set to %d Mbps\n", speed);
229 else
230 netdev_dbg(chip->ds->ports[port].netdev, "Speed unforced\n");
231
232 return 0;
233}
234
235/* Support 10, 100, 200 Mbps (e.g. 88E6065 family) */
236int mv88e6065_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
237{
238 if (speed == SPEED_MAX)
239 speed = 200;
240
241 if (speed > 200)
242 return -EOPNOTSUPP;
243
244 /* Setting 200 Mbps on port 0 to 3 selects 100 Mbps */
245 return mv88e6xxx_port_set_speed(chip, port, speed, false, false);
246}
247
248/* Support 10, 100, 1000 Mbps (e.g. 88E6185 family) */
249int mv88e6185_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
250{
251 if (speed == SPEED_MAX)
252 speed = 1000;
253
254 if (speed == 200 || speed > 1000)
255 return -EOPNOTSUPP;
256
257 return mv88e6xxx_port_set_speed(chip, port, speed, false, false);
258}
259
260/* Support 10, 100, 200, 1000 Mbps (e.g. 88E6352 family) */
261int mv88e6352_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
262{
263 if (speed == SPEED_MAX)
264 speed = 1000;
265
266 if (speed > 1000)
267 return -EOPNOTSUPP;
268
269 if (speed == 200 && port < 5)
270 return -EOPNOTSUPP;
271
272 return mv88e6xxx_port_set_speed(chip, port, speed, true, false);
273}
274
275/* Support 10, 100, 200, 1000, 2500 Mbps (e.g. 88E6390) */
276int mv88e6390_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
277{
278 if (speed == SPEED_MAX)
279 speed = port < 9 ? 1000 : 2500;
280
281 if (speed > 2500)
282 return -EOPNOTSUPP;
283
284 if (speed == 200 && port != 0)
285 return -EOPNOTSUPP;
286
287 if (speed == 2500 && port < 9)
288 return -EOPNOTSUPP;
289
290 return mv88e6xxx_port_set_speed(chip, port, speed, true, true);
291}
292
293/* Support 10, 100, 200, 1000, 2500, 10000 Mbps (e.g. 88E6190X) */
294int mv88e6390x_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
295{
296 if (speed == SPEED_MAX)
297 speed = port < 9 ? 1000 : 10000;
298
299 if (speed == 200 && port != 0)
300 return -EOPNOTSUPP;
301
302 if (speed >= 2500 && port < 9)
303 return -EOPNOTSUPP;
304
305 return mv88e6xxx_port_set_speed(chip, port, speed, true, true);
306}
307
f39908d3
AL
308int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
309 phy_interface_t mode)
310{
311 u16 reg;
312 u16 cmode;
313 int err;
314
315 if (mode == PHY_INTERFACE_MODE_NA)
316 return 0;
317
318 if (port != 9 && port != 10)
319 return -EOPNOTSUPP;
320
321 switch (mode) {
322 case PHY_INTERFACE_MODE_1000BASEX:
323 cmode = PORT_STATUS_CMODE_1000BASE_X;
324 break;
325 case PHY_INTERFACE_MODE_SGMII:
326 cmode = PORT_STATUS_CMODE_SGMII;
327 break;
328 case PHY_INTERFACE_MODE_2500BASEX:
329 cmode = PORT_STATUS_CMODE_2500BASEX;
330 break;
331 case PHY_INTERFACE_MODE_XGMII:
332 cmode = PORT_STATUS_CMODE_XAUI;
333 break;
334 case PHY_INTERFACE_MODE_RXAUI:
335 cmode = PORT_STATUS_CMODE_RXAUI;
336 break;
337 default:
338 cmode = 0;
339 }
340
341 if (cmode) {
342 err = mv88e6xxx_port_read(chip, port, PORT_STATUS, &reg);
343 if (err)
344 return err;
345
346 reg &= ~PORT_STATUS_CMODE_MASK;
347 reg |= cmode;
348
349 err = mv88e6xxx_port_write(chip, port, PORT_STATUS, reg);
350 if (err)
351 return err;
352 }
353
354 return 0;
355}
356
357int mv88e6xxx_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode)
358{
359 int err;
360 u16 reg;
361
362 err = mv88e6xxx_port_read(chip, port, PORT_STATUS, &reg);
363 if (err)
364 return err;
365
366 *cmode = reg & PORT_STATUS_CMODE_MASK;
367
368 return 0;
369}
370
b35d322a
AL
371/* Offset 0x02: Pause Control
372 *
373 * Do not limit the period of time that this port can be paused for by
374 * the remote end or the period of time that this port can pause the
375 * remote end.
376 */
377int mv88e6097_port_pause_config(struct mv88e6xxx_chip *chip, int port)
378{
379 return mv88e6xxx_port_write(chip, port, PORT_PAUSE_CTRL, 0x0000);
380}
381
3ce0e65e
AL
382int mv88e6390_port_pause_config(struct mv88e6xxx_chip *chip, int port)
383{
384 int err;
385
386 err = mv88e6xxx_port_write(chip, port, PORT_PAUSE_CTRL,
387 PORT_FLOW_CTRL_LIMIT_IN | 0);
388 if (err)
389 return err;
390
391 return mv88e6xxx_port_write(chip, port, PORT_PAUSE_CTRL,
392 PORT_FLOW_CTRL_LIMIT_OUT | 0);
393}
394
e28def33
VD
395/* Offset 0x04: Port Control Register */
396
397static const char * const mv88e6xxx_port_state_names[] = {
398 [PORT_CONTROL_STATE_DISABLED] = "Disabled",
399 [PORT_CONTROL_STATE_BLOCKING] = "Blocking/Listening",
400 [PORT_CONTROL_STATE_LEARNING] = "Learning",
401 [PORT_CONTROL_STATE_FORWARDING] = "Forwarding",
402};
403
404int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state)
405{
406 u16 reg;
407 int err;
408
409 err = mv88e6xxx_port_read(chip, port, PORT_CONTROL, &reg);
410 if (err)
411 return err;
412
413 reg &= ~PORT_CONTROL_STATE_MASK;
414 reg |= state;
415
416 err = mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
417 if (err)
418 return err;
419
420 netdev_dbg(chip->ds->ports[port].netdev, "PortState set to %s\n",
421 mv88e6xxx_port_state_names[state]);
422
423 return 0;
424}
5a7921f4 425
56995cbc
AL
426int mv88e6xxx_port_set_egress_mode(struct mv88e6xxx_chip *chip, int port,
427 u16 mode)
428{
429 int err;
430 u16 reg;
431
432 err = mv88e6xxx_port_read(chip, port, PORT_CONTROL, &reg);
433 if (err)
434 return err;
435
436 reg &= ~PORT_CONTROL_EGRESS_MASK;
437 reg |= mode;
438
439 return mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
440}
441
442int mv88e6085_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port,
443 enum mv88e6xxx_frame_mode mode)
444{
445 int err;
446 u16 reg;
447
448 err = mv88e6xxx_port_read(chip, port, PORT_CONTROL, &reg);
449 if (err)
450 return err;
451
452 reg &= ~PORT_CONTROL_FRAME_MODE_DSA;
453
454 switch (mode) {
455 case MV88E6XXX_FRAME_MODE_NORMAL:
456 reg |= PORT_CONTROL_FRAME_MODE_NORMAL;
457 break;
458 case MV88E6XXX_FRAME_MODE_DSA:
459 reg |= PORT_CONTROL_FRAME_MODE_DSA;
460 break;
461 default:
462 return -EINVAL;
463 }
464
465 return mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
466}
467
468int mv88e6351_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port,
469 enum mv88e6xxx_frame_mode mode)
470{
471 int err;
472 u16 reg;
473
474 err = mv88e6xxx_port_read(chip, port, PORT_CONTROL, &reg);
475 if (err)
476 return err;
477
478 reg &= ~PORT_CONTROL_FRAME_MASK;
479
480 switch (mode) {
481 case MV88E6XXX_FRAME_MODE_NORMAL:
482 reg |= PORT_CONTROL_FRAME_MODE_NORMAL;
483 break;
484 case MV88E6XXX_FRAME_MODE_DSA:
485 reg |= PORT_CONTROL_FRAME_MODE_DSA;
486 break;
487 case MV88E6XXX_FRAME_MODE_PROVIDER:
488 reg |= PORT_CONTROL_FRAME_MODE_PROVIDER;
489 break;
490 case MV88E6XXX_FRAME_MODE_ETHERTYPE:
491 reg |= PORT_CONTROL_FRAME_ETHER_TYPE_DSA;
492 break;
493 default:
494 return -EINVAL;
495 }
496
497 return mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
498}
499
500int mv88e6085_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port,
501 bool on)
502{
503 int err;
504 u16 reg;
505
506 err = mv88e6xxx_port_read(chip, port, PORT_CONTROL, &reg);
507 if (err)
508 return err;
509
510 if (on)
511 reg |= PORT_CONTROL_FORWARD_UNKNOWN;
512 else
513 reg &= ~PORT_CONTROL_FORWARD_UNKNOWN;
514
515 return mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
516}
517
518int mv88e6351_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port,
519 bool on)
520{
521 int err;
522 u16 reg;
523
524 err = mv88e6xxx_port_read(chip, port, PORT_CONTROL, &reg);
525 if (err)
526 return err;
527
528 if (on)
529 reg |= PORT_CONTROL_EGRESS_ALL_UNKNOWN_DA;
530 else
531 reg &= ~PORT_CONTROL_EGRESS_ALL_UNKNOWN_DA;
532
533 return mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
534}
535
b4e48c50
VD
536/* Offset 0x05: Port Control 1 */
537
5a7921f4
VD
538/* Offset 0x06: Port Based VLAN Map */
539
540int mv88e6xxx_port_set_vlan_map(struct mv88e6xxx_chip *chip, int port, u16 map)
541{
542 const u16 mask = GENMASK(mv88e6xxx_num_ports(chip) - 1, 0);
543 u16 reg;
544 int err;
545
546 err = mv88e6xxx_port_read(chip, port, PORT_BASE_VLAN, &reg);
547 if (err)
548 return err;
549
550 reg &= ~mask;
551 reg |= map & mask;
552
553 err = mv88e6xxx_port_write(chip, port, PORT_BASE_VLAN, reg);
554 if (err)
555 return err;
556
557 netdev_dbg(chip->ds->ports[port].netdev, "VLANTable set to %.3x\n",
558 map);
559
560 return 0;
561}
b4e48c50
VD
562
563int mv88e6xxx_port_get_fid(struct mv88e6xxx_chip *chip, int port, u16 *fid)
564{
565 const u16 upper_mask = (mv88e6xxx_num_databases(chip) - 1) >> 4;
566 u16 reg;
567 int err;
568
569 /* Port's default FID lower 4 bits are located in reg 0x06, offset 12 */
570 err = mv88e6xxx_port_read(chip, port, PORT_BASE_VLAN, &reg);
571 if (err)
572 return err;
573
574 *fid = (reg & 0xf000) >> 12;
575
576 /* Port's default FID upper bits are located in reg 0x05, offset 0 */
577 if (upper_mask) {
578 err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_1, &reg);
579 if (err)
580 return err;
581
582 *fid |= (reg & upper_mask) << 4;
583 }
584
585 return 0;
586}
587
588int mv88e6xxx_port_set_fid(struct mv88e6xxx_chip *chip, int port, u16 fid)
589{
590 const u16 upper_mask = (mv88e6xxx_num_databases(chip) - 1) >> 4;
591 u16 reg;
592 int err;
593
594 if (fid >= mv88e6xxx_num_databases(chip))
595 return -EINVAL;
596
597 /* Port's default FID lower 4 bits are located in reg 0x06, offset 12 */
598 err = mv88e6xxx_port_read(chip, port, PORT_BASE_VLAN, &reg);
599 if (err)
600 return err;
601
602 reg &= 0x0fff;
603 reg |= (fid & 0x000f) << 12;
604
605 err = mv88e6xxx_port_write(chip, port, PORT_BASE_VLAN, reg);
606 if (err)
607 return err;
608
609 /* Port's default FID upper bits are located in reg 0x05, offset 0 */
610 if (upper_mask) {
611 err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_1, &reg);
612 if (err)
613 return err;
614
615 reg &= ~upper_mask;
616 reg |= (fid >> 4) & upper_mask;
617
618 err = mv88e6xxx_port_write(chip, port, PORT_CONTROL_1, reg);
619 if (err)
620 return err;
621 }
622
623 netdev_dbg(chip->ds->ports[port].netdev, "FID set to %u\n", fid);
624
625 return 0;
626}
77064f37
VD
627
628/* Offset 0x07: Default Port VLAN ID & Priority */
629
630int mv88e6xxx_port_get_pvid(struct mv88e6xxx_chip *chip, int port, u16 *pvid)
631{
632 u16 reg;
633 int err;
634
635 err = mv88e6xxx_port_read(chip, port, PORT_DEFAULT_VLAN, &reg);
636 if (err)
637 return err;
638
639 *pvid = reg & PORT_DEFAULT_VLAN_MASK;
640
641 return 0;
642}
643
644int mv88e6xxx_port_set_pvid(struct mv88e6xxx_chip *chip, int port, u16 pvid)
645{
646 u16 reg;
647 int err;
648
649 err = mv88e6xxx_port_read(chip, port, PORT_DEFAULT_VLAN, &reg);
650 if (err)
651 return err;
652
653 reg &= ~PORT_DEFAULT_VLAN_MASK;
654 reg |= pvid & PORT_DEFAULT_VLAN_MASK;
655
656 err = mv88e6xxx_port_write(chip, port, PORT_DEFAULT_VLAN, reg);
657 if (err)
658 return err;
659
660 netdev_dbg(chip->ds->ports[port].netdev, "DefaultVID set to %u\n",
661 pvid);
662
663 return 0;
664}
385a0995
VD
665
666/* Offset 0x08: Port Control 2 Register */
667
668static const char * const mv88e6xxx_port_8021q_mode_names[] = {
669 [PORT_CONTROL_2_8021Q_DISABLED] = "Disabled",
670 [PORT_CONTROL_2_8021Q_FALLBACK] = "Fallback",
671 [PORT_CONTROL_2_8021Q_CHECK] = "Check",
672 [PORT_CONTROL_2_8021Q_SECURE] = "Secure",
673};
674
675int mv88e6xxx_port_set_8021q_mode(struct mv88e6xxx_chip *chip, int port,
676 u16 mode)
677{
678 u16 reg;
679 int err;
680
681 err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_2, &reg);
682 if (err)
683 return err;
684
685 reg &= ~PORT_CONTROL_2_8021Q_MASK;
686 reg |= mode & PORT_CONTROL_2_8021Q_MASK;
687
688 err = mv88e6xxx_port_write(chip, port, PORT_CONTROL_2, reg);
689 if (err)
690 return err;
691
692 netdev_dbg(chip->ds->ports[port].netdev, "802.1QMode set to %s\n",
693 mv88e6xxx_port_8021q_mode_names[mode]);
694
695 return 0;
696}
ef0a7318 697
5f436666
AL
698int mv88e6165_port_jumbo_config(struct mv88e6xxx_chip *chip, int port)
699{
700 u16 reg;
701 int err;
702
703 err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_2, &reg);
704 if (err)
705 return err;
706
707 reg |= PORT_CONTROL_2_JUMBO_10240;
708
709 return mv88e6xxx_port_write(chip, port, PORT_CONTROL_2, reg);
710}
711
ef70b111
AL
712/* Offset 0x09: Port Rate Control */
713
714int mv88e6095_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port)
715{
716 return mv88e6xxx_port_write(chip, port, PORT_RATE_CONTROL, 0x0000);
717}
718
719int mv88e6097_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port)
720{
721 return mv88e6xxx_port_write(chip, port, PORT_RATE_CONTROL, 0x0001);
722}
723
56995cbc
AL
724/* Offset 0x0f: Port Ether type */
725
726int mv88e6351_port_set_ether_type(struct mv88e6xxx_chip *chip, int port,
727 u16 etype)
728{
729 return mv88e6xxx_port_write(chip, port, PORT_ETH_TYPE, etype);
730}
731
ef0a7318
AL
732/* Offset 0x18: Port IEEE Priority Remapping Registers [0-3]
733 * Offset 0x19: Port IEEE Priority Remapping Registers [4-7]
734 */
735
736int mv88e6095_port_tag_remap(struct mv88e6xxx_chip *chip, int port)
737{
738 int err;
739
740 /* Use a direct priority mapping for all IEEE tagged frames */
741 err = mv88e6xxx_port_write(chip, port, PORT_TAG_REGMAP_0123, 0x3210);
742 if (err)
743 return err;
744
745 return mv88e6xxx_port_write(chip, port, PORT_TAG_REGMAP_4567, 0x7654);
746}
747
748static int mv88e6xxx_port_ieeepmt_write(struct mv88e6xxx_chip *chip,
749 int port, u16 table,
750 u8 pointer, u16 data)
751{
752 u16 reg;
753
754 reg = PORT_IEEE_PRIO_MAP_TABLE_UPDATE |
755 table |
756 (pointer << PORT_IEEE_PRIO_MAP_TABLE_POINTER_SHIFT) |
757 data;
758
759 return mv88e6xxx_port_write(chip, port, PORT_IEEE_PRIO_MAP_TABLE, reg);
760}
761
762int mv88e6390_port_tag_remap(struct mv88e6xxx_chip *chip, int port)
763{
764 int err, i;
765
766 for (i = 0; i <= 7; i++) {
767 err = mv88e6xxx_port_ieeepmt_write(
768 chip, port, PORT_IEEE_PRIO_MAP_TABLE_INGRESS_PCP,
769 i, (i | i << 4));
770 if (err)
771 return err;
772
773 err = mv88e6xxx_port_ieeepmt_write(
774 chip, port, PORT_IEEE_PRIO_MAP_TABLE_EGRESS_GREEN_PCP,
775 i, i);
776 if (err)
777 return err;
778
779 err = mv88e6xxx_port_ieeepmt_write(
780 chip, port, PORT_IEEE_PRIO_MAP_TABLE_EGRESS_YELLOW_PCP,
781 i, i);
782 if (err)
783 return err;
784
785 err = mv88e6xxx_port_ieeepmt_write(
786 chip, port, PORT_IEEE_PRIO_MAP_TABLE_EGRESS_AVB_PCP,
787 i, i);
788 if (err)
789 return err;
790 }
791
792 return 0;
793}