blob: 9bb0f2134cba76bc3f9daff0d4cafcfe6d49a4d3 [file] [log] [blame]
Vivien Didelot18abed22016-11-04 03:23:26 +01001/*
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
Andrew Lunnf39908d2017-02-04 20:02:50 +010014#include <linux/phy.h>
Vivien Didelot18abed22016-11-04 03:23:26 +010015#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}
Vivien Didelote28def332016-11-04 03:23:27 +010033
Vivien Didelot08ef7f12016-11-04 03:23:32 +010034/* Offset 0x01: MAC (or PCS or Physical) Control Register
35 *
36 * Link, Duplex and Flow Control have one force bit, one value bit.
Vivien Didelot96a2b402016-11-04 03:23:35 +010037 *
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.
Vivien Didelot08ef7f12016-11-04 03:23:32 +010041 */
42
Vivien Didelota0a0f622016-11-04 03:23:34 +010043static 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;
Andrew Lunnfedf1862016-11-10 15:44:00 +010067 case PHY_INTERFACE_MODE_RGMII:
Vivien Didelota0a0f622016-11-04 03:23:34 +010068 break;
Andrew Lunnfedf1862016-11-10 15:44:00 +010069 default:
70 return 0;
Vivien Didelota0a0f622016-11-04 03:23:34 +010071 }
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
Vivien Didelot08ef7f12016-11-04 03:23:32 +0100102int 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
Vivien Didelot7f1ae072016-11-04 03:23:33 +0100138int 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
Vivien Didelot96a2b402016-11-04 03:23:35 +0100174static 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:
Andrew Lunn740117a2017-02-02 00:46:16 +0100197 ctrl = PORT_PCS_CTRL_SPEED_10000 | PORT_PCS_CTRL_ALTSPEED;
Vivien Didelot96a2b402016-11-04 03:23:35 +0100198 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;
Andrew Lunn0b6e3d02016-11-16 04:26:48 +0100217 if (speed != SPEED_UNFORCED)
Vivien Didelot96a2b402016-11-04 03:23:35 +0100218 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
Andrew Lunnf39908d2017-02-04 20:02:50 +0100308int 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
Andrew Lunnb35d322a2016-12-03 04:45:19 +0100371/* 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
Andrew Lunn3ce0e652016-12-03 04:45:20 +0100382int 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
Vivien Didelote28def332016-11-04 03:23:27 +0100395/* 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}
Vivien Didelot5a7921f2016-11-04 03:23:28 +0100425
Andrew Lunn56995cb2016-12-03 04:35:19 +0100426int 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
Vivien Didelotb4e48c52016-11-04 03:23:29 +0100536/* Offset 0x05: Port Control 1 */
537
Vivien Didelot5a7921f2016-11-04 03:23:28 +0100538/* Offset 0x06: Port Based VLAN Map */
539
540int mv88e6xxx_port_set_vlan_map(struct mv88e6xxx_chip *chip, int port, u16 map)
541{
Vivien Didelot4d294af2017-03-11 16:12:47 -0500542 const u16 mask = mv88e6xxx_port_mask(chip);
Vivien Didelot5a7921f2016-11-04 03:23:28 +0100543 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}
Vivien Didelotb4e48c52016-11-04 03:23:29 +0100562
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}
Vivien Didelot77064f32016-11-04 03:23:30 +0100627
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}
Vivien Didelot385a0992016-11-04 03:23:31 +0100665
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
Andrew Lunna23b2962017-02-04 20:15:28 +0100675int mv88e6095_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port,
676 bool on)
677{
678 int err;
679 u16 reg;
680
681 err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_2, &reg);
682 if (err)
683 return err;
684
685 if (on)
686 reg |= PORT_CONTROL_2_FORWARD_UNKNOWN;
687 else
688 reg &= ~PORT_CONTROL_2_FORWARD_UNKNOWN;
689
690 return mv88e6xxx_port_write(chip, port, PORT_CONTROL_2, reg);
691}
692
693int mv88e6095_port_set_upstream_port(struct mv88e6xxx_chip *chip, int port,
694 int upstream_port)
695{
696 int err;
697 u16 reg;
698
699 err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_2, &reg);
700 if (err)
701 return err;
702
703 reg &= ~PORT_CONTROL_2_UPSTREAM_MASK;
704 reg |= upstream_port;
705
706 return mv88e6xxx_port_write(chip, port, PORT_CONTROL_2, reg);
707}
708
Vivien Didelot385a0992016-11-04 03:23:31 +0100709int mv88e6xxx_port_set_8021q_mode(struct mv88e6xxx_chip *chip, int port,
710 u16 mode)
711{
712 u16 reg;
713 int err;
714
715 err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_2, &reg);
716 if (err)
717 return err;
718
719 reg &= ~PORT_CONTROL_2_8021Q_MASK;
720 reg |= mode & PORT_CONTROL_2_8021Q_MASK;
721
722 err = mv88e6xxx_port_write(chip, port, PORT_CONTROL_2, reg);
723 if (err)
724 return err;
725
726 netdev_dbg(chip->ds->ports[port].netdev, "802.1QMode set to %s\n",
727 mv88e6xxx_port_8021q_mode_names[mode]);
728
729 return 0;
730}
Andrew Lunnef0a7312016-12-03 04:35:16 +0100731
Andrew Lunna23b2962017-02-04 20:15:28 +0100732int mv88e6xxx_port_set_map_da(struct mv88e6xxx_chip *chip, int port)
733{
734 u16 reg;
735 int err;
736
737 err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_2, &reg);
738 if (err)
739 return err;
740
741 reg |= PORT_CONTROL_2_MAP_DA;
742
743 return mv88e6xxx_port_write(chip, port, PORT_CONTROL_2, reg);
744}
745
Andrew Lunn5f436662016-12-03 04:45:17 +0100746int mv88e6165_port_jumbo_config(struct mv88e6xxx_chip *chip, int port)
747{
748 u16 reg;
749 int err;
750
751 err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_2, &reg);
752 if (err)
753 return err;
754
755 reg |= PORT_CONTROL_2_JUMBO_10240;
756
757 return mv88e6xxx_port_write(chip, port, PORT_CONTROL_2, reg);
758}
759
Andrew Lunnef70b112016-12-03 04:45:18 +0100760/* Offset 0x09: Port Rate Control */
761
762int mv88e6095_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port)
763{
764 return mv88e6xxx_port_write(chip, port, PORT_RATE_CONTROL, 0x0000);
765}
766
767int mv88e6097_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port)
768{
769 return mv88e6xxx_port_write(chip, port, PORT_RATE_CONTROL, 0x0001);
770}
771
Andrew Lunn56995cb2016-12-03 04:35:19 +0100772/* Offset 0x0f: Port Ether type */
773
774int mv88e6351_port_set_ether_type(struct mv88e6xxx_chip *chip, int port,
775 u16 etype)
776{
777 return mv88e6xxx_port_write(chip, port, PORT_ETH_TYPE, etype);
778}
779
Andrew Lunnef0a7312016-12-03 04:35:16 +0100780/* Offset 0x18: Port IEEE Priority Remapping Registers [0-3]
781 * Offset 0x19: Port IEEE Priority Remapping Registers [4-7]
782 */
783
784int mv88e6095_port_tag_remap(struct mv88e6xxx_chip *chip, int port)
785{
786 int err;
787
788 /* Use a direct priority mapping for all IEEE tagged frames */
789 err = mv88e6xxx_port_write(chip, port, PORT_TAG_REGMAP_0123, 0x3210);
790 if (err)
791 return err;
792
793 return mv88e6xxx_port_write(chip, port, PORT_TAG_REGMAP_4567, 0x7654);
794}
795
796static int mv88e6xxx_port_ieeepmt_write(struct mv88e6xxx_chip *chip,
797 int port, u16 table,
798 u8 pointer, u16 data)
799{
800 u16 reg;
801
802 reg = PORT_IEEE_PRIO_MAP_TABLE_UPDATE |
803 table |
804 (pointer << PORT_IEEE_PRIO_MAP_TABLE_POINTER_SHIFT) |
805 data;
806
807 return mv88e6xxx_port_write(chip, port, PORT_IEEE_PRIO_MAP_TABLE, reg);
808}
809
810int mv88e6390_port_tag_remap(struct mv88e6xxx_chip *chip, int port)
811{
812 int err, i;
813
814 for (i = 0; i <= 7; i++) {
815 err = mv88e6xxx_port_ieeepmt_write(
816 chip, port, PORT_IEEE_PRIO_MAP_TABLE_INGRESS_PCP,
817 i, (i | i << 4));
818 if (err)
819 return err;
820
821 err = mv88e6xxx_port_ieeepmt_write(
822 chip, port, PORT_IEEE_PRIO_MAP_TABLE_EGRESS_GREEN_PCP,
823 i, i);
824 if (err)
825 return err;
826
827 err = mv88e6xxx_port_ieeepmt_write(
828 chip, port, PORT_IEEE_PRIO_MAP_TABLE_EGRESS_YELLOW_PCP,
829 i, i);
830 if (err)
831 return err;
832
833 err = mv88e6xxx_port_ieeepmt_write(
834 chip, port, PORT_IEEE_PRIO_MAP_TABLE_EGRESS_AVB_PCP,
835 i, i);
836 if (err)
837 return err;
838 }
839
840 return 0;
841}