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