1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Marvell 88E6xxx Switch Port Registers support
4 *
5 * Copyright (c) 2008 Marvell Semiconductor
6 *
7 * Copyright (c) 2016-2017 Savoir-faire Linux Inc.
8 * Vivien Didelot <[email protected]>
9 */
10
11 #include <linux/bitfield.h>
12 #include <linux/if_bridge.h>
13 #include <linux/phy.h>
14 #include <linux/phylink.h>
15 #include <linux/property.h>
16 #include <linux/string_choices.h>
17
18 #include "chip.h"
19 #include "global2.h"
20 #include "port.h"
21 #include "serdes.h"
22
mv88e6xxx_port_read(struct mv88e6xxx_chip * chip,int port,int reg,u16 * val)23 int 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
mv88e6xxx_port_wait_bit(struct mv88e6xxx_chip * chip,int port,int reg,int bit,int val)31 int mv88e6xxx_port_wait_bit(struct mv88e6xxx_chip *chip, int port, int reg,
32 int bit, int val)
33 {
34 int addr = chip->info->port_base_addr + port;
35
36 return mv88e6xxx_wait_bit(chip, addr, reg, bit, val);
37 }
38
mv88e6xxx_port_write(struct mv88e6xxx_chip * chip,int port,int reg,u16 val)39 int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg,
40 u16 val)
41 {
42 int addr = chip->info->port_base_addr + port;
43
44 return mv88e6xxx_write(chip, addr, reg, val);
45 }
46
47 /* Offset 0x00: MAC (or PCS or Physical) Status Register
48 *
49 * For most devices, this is read only. However the 6185 has the MyPause
50 * bit read/write.
51 */
mv88e6185_port_set_pause(struct mv88e6xxx_chip * chip,int port,int pause)52 int mv88e6185_port_set_pause(struct mv88e6xxx_chip *chip, int port,
53 int pause)
54 {
55 u16 reg;
56 int err;
57
58 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, ®);
59 if (err)
60 return err;
61
62 if (pause)
63 reg |= MV88E6XXX_PORT_STS_MY_PAUSE;
64 else
65 reg &= ~MV88E6XXX_PORT_STS_MY_PAUSE;
66
67 return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_STS, reg);
68 }
69
70 /* Offset 0x01: MAC (or PCS or Physical) Control Register
71 *
72 * Link, Duplex and Flow Control have one force bit, one value bit.
73 *
74 * For port's MAC speed, ForceSpd (or SpdValue) bits 1:0 program the value.
75 * Alternative values require the 200BASE (or AltSpeed) bit 12 set.
76 * Newer chips need a ForcedSpd bit 13 set to consider the value.
77 */
78
mv88e6xxx_port_set_rgmii_delay(struct mv88e6xxx_chip * chip,int port,phy_interface_t mode)79 static int mv88e6xxx_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,
80 phy_interface_t mode)
81 {
82 u16 reg;
83 int err;
84
85 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_MAC_CTL, ®);
86 if (err)
87 return err;
88
89 reg &= ~(MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_RXCLK |
90 MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_TXCLK);
91
92 switch (mode) {
93 case PHY_INTERFACE_MODE_RGMII_RXID:
94 reg |= MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_RXCLK;
95 break;
96 case PHY_INTERFACE_MODE_RGMII_TXID:
97 reg |= MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_TXCLK;
98 break;
99 case PHY_INTERFACE_MODE_RGMII_ID:
100 reg |= MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_RXCLK |
101 MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_TXCLK;
102 break;
103 case PHY_INTERFACE_MODE_RGMII:
104 break;
105 default:
106 return 0;
107 }
108
109 err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_MAC_CTL, reg);
110 if (err)
111 return err;
112
113 dev_dbg(chip->dev, "p%d: delay RXCLK %s, TXCLK %s\n", port,
114 reg & MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_RXCLK ? "yes" : "no",
115 reg & MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_TXCLK ? "yes" : "no");
116
117 return 0;
118 }
119
mv88e6352_port_set_rgmii_delay(struct mv88e6xxx_chip * chip,int port,phy_interface_t mode)120 int mv88e6352_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,
121 phy_interface_t mode)
122 {
123 if (port < 5)
124 return -EOPNOTSUPP;
125
126 return mv88e6xxx_port_set_rgmii_delay(chip, port, mode);
127 }
128
mv88e6390_port_set_rgmii_delay(struct mv88e6xxx_chip * chip,int port,phy_interface_t mode)129 int mv88e6390_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,
130 phy_interface_t mode)
131 {
132 if (port != 0)
133 return -EOPNOTSUPP;
134
135 return mv88e6xxx_port_set_rgmii_delay(chip, port, mode);
136 }
137
mv88e6320_port_set_rgmii_delay(struct mv88e6xxx_chip * chip,int port,phy_interface_t mode)138 int mv88e6320_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,
139 phy_interface_t mode)
140 {
141 if (port != 2 && port != 5 && port != 6)
142 return -EOPNOTSUPP;
143
144 return mv88e6xxx_port_set_rgmii_delay(chip, port, mode);
145 }
146
mv88e6xxx_port_set_link(struct mv88e6xxx_chip * chip,int port,int link)147 int mv88e6xxx_port_set_link(struct mv88e6xxx_chip *chip, int port, int link)
148 {
149 u16 reg;
150 int err;
151
152 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_MAC_CTL, ®);
153 if (err)
154 return err;
155
156 reg &= ~(MV88E6XXX_PORT_MAC_CTL_FORCE_LINK |
157 MV88E6XXX_PORT_MAC_CTL_LINK_UP);
158
159 switch (link) {
160 case LINK_FORCED_DOWN:
161 reg |= MV88E6XXX_PORT_MAC_CTL_FORCE_LINK;
162 break;
163 case LINK_FORCED_UP:
164 reg |= MV88E6XXX_PORT_MAC_CTL_FORCE_LINK |
165 MV88E6XXX_PORT_MAC_CTL_LINK_UP;
166 break;
167 case LINK_UNFORCED:
168 /* normal link detection */
169 break;
170 default:
171 return -EINVAL;
172 }
173
174 err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_MAC_CTL, reg);
175 if (err)
176 return err;
177
178 dev_dbg(chip->dev, "p%d: %s link %s\n", port,
179 reg & MV88E6XXX_PORT_MAC_CTL_FORCE_LINK ? "Force" : "Unforce",
180 str_up_down(reg & MV88E6XXX_PORT_MAC_CTL_LINK_UP));
181
182 return 0;
183 }
184
mv88e6xxx_port_sync_link(struct mv88e6xxx_chip * chip,int port,unsigned int mode,bool isup)185 int mv88e6xxx_port_sync_link(struct mv88e6xxx_chip *chip, int port, unsigned int mode, bool isup)
186 {
187 const struct mv88e6xxx_ops *ops = chip->info->ops;
188 int err = 0;
189 int link;
190
191 if (isup)
192 link = LINK_FORCED_UP;
193 else
194 link = LINK_FORCED_DOWN;
195
196 if (ops->port_set_link)
197 err = ops->port_set_link(chip, port, link);
198
199 return err;
200 }
201
mv88e6185_port_sync_link(struct mv88e6xxx_chip * chip,int port,unsigned int mode,bool isup)202 int mv88e6185_port_sync_link(struct mv88e6xxx_chip *chip, int port, unsigned int mode, bool isup)
203 {
204 const struct mv88e6xxx_ops *ops = chip->info->ops;
205 int err = 0;
206 int link;
207
208 if (mode == MLO_AN_INBAND)
209 link = LINK_UNFORCED;
210 else if (isup)
211 link = LINK_FORCED_UP;
212 else
213 link = LINK_FORCED_DOWN;
214
215 if (ops->port_set_link)
216 err = ops->port_set_link(chip, port, link);
217
218 return err;
219 }
220
mv88e6xxx_port_set_speed_duplex(struct mv88e6xxx_chip * chip,int port,int speed,bool alt_bit,bool force_bit,int duplex)221 static int mv88e6xxx_port_set_speed_duplex(struct mv88e6xxx_chip *chip,
222 int port, int speed, bool alt_bit,
223 bool force_bit, int duplex)
224 {
225 u16 reg, ctrl;
226 int err;
227
228 switch (speed) {
229 case 10:
230 ctrl = MV88E6XXX_PORT_MAC_CTL_SPEED_10;
231 break;
232 case 100:
233 ctrl = MV88E6XXX_PORT_MAC_CTL_SPEED_100;
234 break;
235 case 200:
236 if (alt_bit)
237 ctrl = MV88E6XXX_PORT_MAC_CTL_SPEED_100 |
238 MV88E6390_PORT_MAC_CTL_ALTSPEED;
239 else
240 ctrl = MV88E6065_PORT_MAC_CTL_SPEED_200;
241 break;
242 case 1000:
243 ctrl = MV88E6XXX_PORT_MAC_CTL_SPEED_1000;
244 break;
245 case 2500:
246 if (alt_bit)
247 ctrl = MV88E6390_PORT_MAC_CTL_SPEED_10000 |
248 MV88E6390_PORT_MAC_CTL_ALTSPEED;
249 else
250 ctrl = MV88E6390_PORT_MAC_CTL_SPEED_10000;
251 break;
252 case 10000:
253 /* all bits set, fall through... */
254 case SPEED_UNFORCED:
255 ctrl = MV88E6XXX_PORT_MAC_CTL_SPEED_UNFORCED;
256 break;
257 default:
258 return -EOPNOTSUPP;
259 }
260
261 switch (duplex) {
262 case DUPLEX_HALF:
263 ctrl |= MV88E6XXX_PORT_MAC_CTL_FORCE_DUPLEX;
264 break;
265 case DUPLEX_FULL:
266 ctrl |= MV88E6XXX_PORT_MAC_CTL_FORCE_DUPLEX |
267 MV88E6XXX_PORT_MAC_CTL_DUPLEX_FULL;
268 break;
269 case DUPLEX_UNFORCED:
270 /* normal duplex detection */
271 break;
272 default:
273 return -EOPNOTSUPP;
274 }
275
276 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_MAC_CTL, ®);
277 if (err)
278 return err;
279
280 reg &= ~(MV88E6XXX_PORT_MAC_CTL_SPEED_MASK |
281 MV88E6XXX_PORT_MAC_CTL_FORCE_DUPLEX |
282 MV88E6XXX_PORT_MAC_CTL_DUPLEX_FULL);
283
284 if (alt_bit)
285 reg &= ~MV88E6390_PORT_MAC_CTL_ALTSPEED;
286 if (force_bit) {
287 reg &= ~MV88E6390_PORT_MAC_CTL_FORCE_SPEED;
288 if (speed != SPEED_UNFORCED)
289 ctrl |= MV88E6390_PORT_MAC_CTL_FORCE_SPEED;
290 }
291 reg |= ctrl;
292
293 err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_MAC_CTL, reg);
294 if (err)
295 return err;
296
297 if (speed != SPEED_UNFORCED)
298 dev_dbg(chip->dev, "p%d: Speed set to %d Mbps\n", port, speed);
299 else
300 dev_dbg(chip->dev, "p%d: Speed unforced\n", port);
301 dev_dbg(chip->dev, "p%d: %s %s duplex\n", port,
302 reg & MV88E6XXX_PORT_MAC_CTL_FORCE_DUPLEX ? "Force" : "Unforce",
303 reg & MV88E6XXX_PORT_MAC_CTL_DUPLEX_FULL ? "full" : "half");
304
305 return 0;
306 }
307
308 /* Support 10, 100, 1000 Mbps (e.g. 88E6185 family) */
mv88e6185_port_set_speed_duplex(struct mv88e6xxx_chip * chip,int port,int speed,int duplex)309 int mv88e6185_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
310 int speed, int duplex)
311 {
312 if (speed == 200 || speed > 1000)
313 return -EOPNOTSUPP;
314
315 return mv88e6xxx_port_set_speed_duplex(chip, port, speed, false, false,
316 duplex);
317 }
318
319 /* Support 10, 100 Mbps (e.g. 88E6250 family) */
mv88e6250_port_set_speed_duplex(struct mv88e6xxx_chip * chip,int port,int speed,int duplex)320 int mv88e6250_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
321 int speed, int duplex)
322 {
323 if (speed > 100)
324 return -EOPNOTSUPP;
325
326 return mv88e6xxx_port_set_speed_duplex(chip, port, speed, false, false,
327 duplex);
328 }
329
330 /* Support 10, 100, 200, 1000, 2500 Mbps (e.g. 88E6341) */
mv88e6341_port_set_speed_duplex(struct mv88e6xxx_chip * chip,int port,int speed,int duplex)331 int mv88e6341_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
332 int speed, int duplex)
333 {
334 if (speed > 2500)
335 return -EOPNOTSUPP;
336
337 if (speed == 200 && port != 0)
338 return -EOPNOTSUPP;
339
340 if (speed == 2500 && port < 5)
341 return -EOPNOTSUPP;
342
343 return mv88e6xxx_port_set_speed_duplex(chip, port, speed, !port, true,
344 duplex);
345 }
346
mv88e6341_port_max_speed_mode(struct mv88e6xxx_chip * chip,int port)347 phy_interface_t mv88e6341_port_max_speed_mode(struct mv88e6xxx_chip *chip,
348 int port)
349 {
350 if (port == 5)
351 return PHY_INTERFACE_MODE_2500BASEX;
352
353 return PHY_INTERFACE_MODE_NA;
354 }
355
356 /* Support 10, 100, 200, 1000 Mbps (e.g. 88E6352 family) */
mv88e6352_port_set_speed_duplex(struct mv88e6xxx_chip * chip,int port,int speed,int duplex)357 int mv88e6352_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
358 int speed, int duplex)
359 {
360 if (speed > 1000)
361 return -EOPNOTSUPP;
362
363 if (speed == 200 && port < 5)
364 return -EOPNOTSUPP;
365
366 return mv88e6xxx_port_set_speed_duplex(chip, port, speed, true, false,
367 duplex);
368 }
369
370 /* Support 10, 100, 200, 1000, 2500 Mbps (e.g. 88E6390) */
mv88e6390_port_set_speed_duplex(struct mv88e6xxx_chip * chip,int port,int speed,int duplex)371 int mv88e6390_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
372 int speed, int duplex)
373 {
374 if (speed > 2500)
375 return -EOPNOTSUPP;
376
377 if (speed == 200 && port != 0)
378 return -EOPNOTSUPP;
379
380 if (speed == 2500 && port < 9)
381 return -EOPNOTSUPP;
382
383 return mv88e6xxx_port_set_speed_duplex(chip, port, speed, true, true,
384 duplex);
385 }
386
mv88e6390_port_max_speed_mode(struct mv88e6xxx_chip * chip,int port)387 phy_interface_t mv88e6390_port_max_speed_mode(struct mv88e6xxx_chip *chip,
388 int port)
389 {
390 if (port == 9 || port == 10)
391 return PHY_INTERFACE_MODE_2500BASEX;
392
393 return PHY_INTERFACE_MODE_NA;
394 }
395
396 /* Support 10, 100, 200, 1000, 2500, 10000 Mbps (e.g. 88E6190X) */
mv88e6390x_port_set_speed_duplex(struct mv88e6xxx_chip * chip,int port,int speed,int duplex)397 int mv88e6390x_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
398 int speed, int duplex)
399 {
400 if (speed == 200 && port != 0)
401 return -EOPNOTSUPP;
402
403 if (speed >= 2500 && port < 9)
404 return -EOPNOTSUPP;
405
406 return mv88e6xxx_port_set_speed_duplex(chip, port, speed, true, true,
407 duplex);
408 }
409
mv88e6390x_port_max_speed_mode(struct mv88e6xxx_chip * chip,int port)410 phy_interface_t mv88e6390x_port_max_speed_mode(struct mv88e6xxx_chip *chip,
411 int port)
412 {
413 if (port == 9 || port == 10)
414 return PHY_INTERFACE_MODE_XAUI;
415
416 return PHY_INTERFACE_MODE_NA;
417 }
418
419 /* Support 10, 100, 200, 1000, 2500, 5000, 10000 Mbps (e.g. 88E6393X)
420 * Function mv88e6xxx_port_set_speed_duplex() can't be used as the register
421 * values for speeds 2500 & 5000 conflict.
422 */
mv88e6393x_port_set_speed_duplex(struct mv88e6xxx_chip * chip,int port,int speed,int duplex)423 int mv88e6393x_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
424 int speed, int duplex)
425 {
426 u16 reg, ctrl;
427 int err;
428
429 if (chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6361 &&
430 speed > 2500)
431 return -EOPNOTSUPP;
432
433 if (speed == 200 && port != 0)
434 return -EOPNOTSUPP;
435
436 if (speed >= 2500 && port > 0 && port < 9)
437 return -EOPNOTSUPP;
438
439 switch (speed) {
440 case 10:
441 ctrl = MV88E6XXX_PORT_MAC_CTL_SPEED_10;
442 break;
443 case 100:
444 ctrl = MV88E6XXX_PORT_MAC_CTL_SPEED_100;
445 break;
446 case 200:
447 ctrl = MV88E6XXX_PORT_MAC_CTL_SPEED_100 |
448 MV88E6390_PORT_MAC_CTL_ALTSPEED;
449 break;
450 case 1000:
451 ctrl = MV88E6XXX_PORT_MAC_CTL_SPEED_1000;
452 break;
453 case 2500:
454 ctrl = MV88E6XXX_PORT_MAC_CTL_SPEED_1000 |
455 MV88E6390_PORT_MAC_CTL_ALTSPEED;
456 break;
457 case 5000:
458 ctrl = MV88E6390_PORT_MAC_CTL_SPEED_10000 |
459 MV88E6390_PORT_MAC_CTL_ALTSPEED;
460 break;
461 case 10000:
462 case SPEED_UNFORCED:
463 ctrl = MV88E6XXX_PORT_MAC_CTL_SPEED_UNFORCED;
464 break;
465 default:
466 return -EOPNOTSUPP;
467 }
468
469 switch (duplex) {
470 case DUPLEX_HALF:
471 ctrl |= MV88E6XXX_PORT_MAC_CTL_FORCE_DUPLEX;
472 break;
473 case DUPLEX_FULL:
474 ctrl |= MV88E6XXX_PORT_MAC_CTL_FORCE_DUPLEX |
475 MV88E6XXX_PORT_MAC_CTL_DUPLEX_FULL;
476 break;
477 case DUPLEX_UNFORCED:
478 /* normal duplex detection */
479 break;
480 default:
481 return -EOPNOTSUPP;
482 }
483
484 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_MAC_CTL, ®);
485 if (err)
486 return err;
487
488 reg &= ~(MV88E6XXX_PORT_MAC_CTL_SPEED_MASK |
489 MV88E6390_PORT_MAC_CTL_ALTSPEED |
490 MV88E6390_PORT_MAC_CTL_FORCE_SPEED);
491
492 if (speed != SPEED_UNFORCED)
493 reg |= MV88E6390_PORT_MAC_CTL_FORCE_SPEED;
494
495 reg |= ctrl;
496
497 err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_MAC_CTL, reg);
498 if (err)
499 return err;
500
501 if (speed != SPEED_UNFORCED)
502 dev_dbg(chip->dev, "p%d: Speed set to %d Mbps\n", port, speed);
503 else
504 dev_dbg(chip->dev, "p%d: Speed unforced\n", port);
505 dev_dbg(chip->dev, "p%d: %s %s duplex\n", port,
506 reg & MV88E6XXX_PORT_MAC_CTL_FORCE_DUPLEX ? "Force" : "Unforce",
507 reg & MV88E6XXX_PORT_MAC_CTL_DUPLEX_FULL ? "full" : "half");
508
509 return 0;
510 }
511
mv88e6393x_port_max_speed_mode(struct mv88e6xxx_chip * chip,int port)512 phy_interface_t mv88e6393x_port_max_speed_mode(struct mv88e6xxx_chip *chip,
513 int port)
514 {
515
516 if (port != 0 && port != 9 && port != 10)
517 return PHY_INTERFACE_MODE_NA;
518
519 if (chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6361)
520 return PHY_INTERFACE_MODE_2500BASEX;
521
522 return PHY_INTERFACE_MODE_10GBASER;
523 }
524
mv88e6xxx_port_set_cmode(struct mv88e6xxx_chip * chip,int port,phy_interface_t mode,bool force)525 static int mv88e6xxx_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
526 phy_interface_t mode, bool force)
527 {
528 u16 cmode;
529 u16 reg;
530 int err;
531
532 /* Default to a slow mode, so freeing up SERDES interfaces for
533 * other ports which might use them for SFPs.
534 */
535 if (mode == PHY_INTERFACE_MODE_NA)
536 mode = PHY_INTERFACE_MODE_1000BASEX;
537
538 switch (mode) {
539 case PHY_INTERFACE_MODE_RMII:
540 cmode = MV88E6XXX_PORT_STS_CMODE_RMII;
541 break;
542 case PHY_INTERFACE_MODE_RGMII:
543 case PHY_INTERFACE_MODE_RGMII_ID:
544 case PHY_INTERFACE_MODE_RGMII_RXID:
545 case PHY_INTERFACE_MODE_RGMII_TXID:
546 cmode = MV88E6XXX_PORT_STS_CMODE_RGMII;
547 break;
548 case PHY_INTERFACE_MODE_1000BASEX:
549 cmode = MV88E6XXX_PORT_STS_CMODE_1000BASEX;
550 break;
551 case PHY_INTERFACE_MODE_SGMII:
552 cmode = MV88E6XXX_PORT_STS_CMODE_SGMII;
553 break;
554 case PHY_INTERFACE_MODE_2500BASEX:
555 cmode = MV88E6XXX_PORT_STS_CMODE_2500BASEX;
556 break;
557 case PHY_INTERFACE_MODE_5GBASER:
558 cmode = MV88E6393X_PORT_STS_CMODE_5GBASER;
559 break;
560 case PHY_INTERFACE_MODE_XGMII:
561 case PHY_INTERFACE_MODE_XAUI:
562 cmode = MV88E6XXX_PORT_STS_CMODE_XAUI;
563 break;
564 case PHY_INTERFACE_MODE_RXAUI:
565 cmode = MV88E6XXX_PORT_STS_CMODE_RXAUI;
566 break;
567 case PHY_INTERFACE_MODE_10GBASER:
568 cmode = MV88E6393X_PORT_STS_CMODE_10GBASER;
569 break;
570 case PHY_INTERFACE_MODE_USXGMII:
571 cmode = MV88E6393X_PORT_STS_CMODE_USXGMII;
572 break;
573 default:
574 cmode = 0;
575 }
576
577 /* cmode doesn't change, nothing to do for us unless forced */
578 if (cmode == chip->ports[port].cmode && !force)
579 return 0;
580
581 chip->ports[port].cmode = 0;
582
583 if (cmode) {
584 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, ®);
585 if (err)
586 return err;
587
588 reg &= ~MV88E6XXX_PORT_STS_CMODE_MASK;
589 reg |= cmode;
590
591 err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_STS, reg);
592 if (err)
593 return err;
594
595 chip->ports[port].cmode = cmode;
596 }
597
598 return 0;
599 }
600
mv88e6390x_port_set_cmode(struct mv88e6xxx_chip * chip,int port,phy_interface_t mode)601 int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
602 phy_interface_t mode)
603 {
604 if (port != 9 && port != 10)
605 return -EOPNOTSUPP;
606
607 return mv88e6xxx_port_set_cmode(chip, port, mode, false);
608 }
609
mv88e6390_port_set_cmode(struct mv88e6xxx_chip * chip,int port,phy_interface_t mode)610 int mv88e6390_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
611 phy_interface_t mode)
612 {
613 if (port != 9 && port != 10)
614 return -EOPNOTSUPP;
615
616 switch (mode) {
617 case PHY_INTERFACE_MODE_NA:
618 return 0;
619 case PHY_INTERFACE_MODE_XGMII:
620 case PHY_INTERFACE_MODE_XAUI:
621 case PHY_INTERFACE_MODE_RXAUI:
622 return -EINVAL;
623 default:
624 break;
625 }
626
627 return mv88e6xxx_port_set_cmode(chip, port, mode, false);
628 }
629
mv88e6393x_port_set_cmode(struct mv88e6xxx_chip * chip,int port,phy_interface_t mode)630 int mv88e6393x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
631 phy_interface_t mode)
632 {
633 int err;
634 u16 reg;
635
636 if (port != 0 && port != 9 && port != 10)
637 return -EOPNOTSUPP;
638
639 if (port == 9 || port == 10) {
640 switch (mode) {
641 case PHY_INTERFACE_MODE_RMII:
642 case PHY_INTERFACE_MODE_RGMII:
643 case PHY_INTERFACE_MODE_RGMII_ID:
644 case PHY_INTERFACE_MODE_RGMII_RXID:
645 case PHY_INTERFACE_MODE_RGMII_TXID:
646 return -EINVAL;
647 default:
648 break;
649 }
650 }
651
652 /* mv88e6393x errata 4.5: EEE should be disabled on SERDES ports */
653 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_MAC_CTL, ®);
654 if (err)
655 return err;
656
657 reg &= ~MV88E6XXX_PORT_MAC_CTL_EEE;
658 reg |= MV88E6XXX_PORT_MAC_CTL_FORCE_EEE;
659 err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_MAC_CTL, reg);
660 if (err)
661 return err;
662
663 return mv88e6xxx_port_set_cmode(chip, port, mode, false);
664 }
665
mv88e6341_port_set_cmode_writable(struct mv88e6xxx_chip * chip,int port)666 static int mv88e6341_port_set_cmode_writable(struct mv88e6xxx_chip *chip,
667 int port)
668 {
669 int err, addr;
670 u16 reg, bits;
671
672 if (port != 5)
673 return -EOPNOTSUPP;
674
675 addr = chip->info->port_base_addr + port;
676
677 err = mv88e6xxx_port_hidden_read(chip, 0x7, addr, 0, ®);
678 if (err)
679 return err;
680
681 bits = MV88E6341_PORT_RESERVED_1A_FORCE_CMODE |
682 MV88E6341_PORT_RESERVED_1A_SGMII_AN;
683
684 if ((reg & bits) == bits)
685 return 0;
686
687 reg |= bits;
688 return mv88e6xxx_port_hidden_write(chip, 0x7, addr, 0, reg);
689 }
690
mv88e6341_port_set_cmode(struct mv88e6xxx_chip * chip,int port,phy_interface_t mode)691 int mv88e6341_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
692 phy_interface_t mode)
693 {
694 int err;
695
696 if (port != 5)
697 return -EOPNOTSUPP;
698
699 switch (mode) {
700 case PHY_INTERFACE_MODE_NA:
701 return 0;
702 case PHY_INTERFACE_MODE_XGMII:
703 case PHY_INTERFACE_MODE_XAUI:
704 case PHY_INTERFACE_MODE_RXAUI:
705 return -EINVAL;
706 default:
707 break;
708 }
709
710 err = mv88e6341_port_set_cmode_writable(chip, port);
711 if (err)
712 return err;
713
714 return mv88e6xxx_port_set_cmode(chip, port, mode, true);
715 }
716
mv88e6185_port_get_cmode(struct mv88e6xxx_chip * chip,int port,u8 * cmode)717 int mv88e6185_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode)
718 {
719 int err;
720 u16 reg;
721
722 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, ®);
723 if (err)
724 return err;
725
726 *cmode = reg & MV88E6185_PORT_STS_CMODE_MASK;
727
728 return 0;
729 }
730
mv88e6352_port_get_cmode(struct mv88e6xxx_chip * chip,int port,u8 * cmode)731 int mv88e6352_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode)
732 {
733 int err;
734 u16 reg;
735
736 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, ®);
737 if (err)
738 return err;
739
740 *cmode = reg & MV88E6XXX_PORT_STS_CMODE_MASK;
741
742 return 0;
743 }
744
745 /* Offset 0x02: Jamming Control
746 *
747 * Do not limit the period of time that this port can be paused for by
748 * the remote end or the period of time that this port can pause the
749 * remote end.
750 */
mv88e6097_port_pause_limit(struct mv88e6xxx_chip * chip,int port,u8 in,u8 out)751 int mv88e6097_port_pause_limit(struct mv88e6xxx_chip *chip, int port, u8 in,
752 u8 out)
753 {
754 return mv88e6xxx_port_write(chip, port, MV88E6097_PORT_JAM_CTL,
755 out << 8 | in);
756 }
757
mv88e6390_port_pause_limit(struct mv88e6xxx_chip * chip,int port,u8 in,u8 out)758 int mv88e6390_port_pause_limit(struct mv88e6xxx_chip *chip, int port, u8 in,
759 u8 out)
760 {
761 int err;
762
763 err = mv88e6xxx_port_write(chip, port, MV88E6390_PORT_FLOW_CTL,
764 MV88E6390_PORT_FLOW_CTL_UPDATE |
765 MV88E6390_PORT_FLOW_CTL_LIMIT_IN | in);
766 if (err)
767 return err;
768
769 return mv88e6xxx_port_write(chip, port, MV88E6390_PORT_FLOW_CTL,
770 MV88E6390_PORT_FLOW_CTL_UPDATE |
771 MV88E6390_PORT_FLOW_CTL_LIMIT_OUT | out);
772 }
773
774 /* Offset 0x04: Port Control Register */
775
776 static const char * const mv88e6xxx_port_state_names[] = {
777 [MV88E6XXX_PORT_CTL0_STATE_DISABLED] = "Disabled",
778 [MV88E6XXX_PORT_CTL0_STATE_BLOCKING] = "Blocking/Listening",
779 [MV88E6XXX_PORT_CTL0_STATE_LEARNING] = "Learning",
780 [MV88E6XXX_PORT_CTL0_STATE_FORWARDING] = "Forwarding",
781 };
782
mv88e6xxx_port_set_state(struct mv88e6xxx_chip * chip,int port,u8 state)783 int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state)
784 {
785 u16 reg;
786 int err;
787
788 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, ®);
789 if (err)
790 return err;
791
792 reg &= ~MV88E6XXX_PORT_CTL0_STATE_MASK;
793
794 switch (state) {
795 case BR_STATE_DISABLED:
796 state = MV88E6XXX_PORT_CTL0_STATE_DISABLED;
797 break;
798 case BR_STATE_BLOCKING:
799 case BR_STATE_LISTENING:
800 state = MV88E6XXX_PORT_CTL0_STATE_BLOCKING;
801 break;
802 case BR_STATE_LEARNING:
803 state = MV88E6XXX_PORT_CTL0_STATE_LEARNING;
804 break;
805 case BR_STATE_FORWARDING:
806 state = MV88E6XXX_PORT_CTL0_STATE_FORWARDING;
807 break;
808 default:
809 return -EINVAL;
810 }
811
812 reg |= state;
813
814 err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
815 if (err)
816 return err;
817
818 dev_dbg(chip->dev, "p%d: PortState set to %s\n", port,
819 mv88e6xxx_port_state_names[state]);
820
821 return 0;
822 }
823
mv88e6xxx_port_set_egress_mode(struct mv88e6xxx_chip * chip,int port,enum mv88e6xxx_egress_mode mode)824 int mv88e6xxx_port_set_egress_mode(struct mv88e6xxx_chip *chip, int port,
825 enum mv88e6xxx_egress_mode mode)
826 {
827 int err;
828 u16 reg;
829
830 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, ®);
831 if (err)
832 return err;
833
834 reg &= ~MV88E6XXX_PORT_CTL0_EGRESS_MODE_MASK;
835
836 switch (mode) {
837 case MV88E6XXX_EGRESS_MODE_UNMODIFIED:
838 reg |= MV88E6XXX_PORT_CTL0_EGRESS_MODE_UNMODIFIED;
839 break;
840 case MV88E6XXX_EGRESS_MODE_UNTAGGED:
841 reg |= MV88E6XXX_PORT_CTL0_EGRESS_MODE_UNTAGGED;
842 break;
843 case MV88E6XXX_EGRESS_MODE_TAGGED:
844 reg |= MV88E6XXX_PORT_CTL0_EGRESS_MODE_TAGGED;
845 break;
846 case MV88E6XXX_EGRESS_MODE_ETHERTYPE:
847 reg |= MV88E6XXX_PORT_CTL0_EGRESS_MODE_ETHER_TYPE_DSA;
848 break;
849 default:
850 return -EINVAL;
851 }
852
853 return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
854 }
855
mv88e6085_port_set_frame_mode(struct mv88e6xxx_chip * chip,int port,enum mv88e6xxx_frame_mode mode)856 int mv88e6085_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port,
857 enum mv88e6xxx_frame_mode mode)
858 {
859 int err;
860 u16 reg;
861
862 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, ®);
863 if (err)
864 return err;
865
866 reg &= ~MV88E6XXX_PORT_CTL0_FRAME_MODE_MASK;
867
868 switch (mode) {
869 case MV88E6XXX_FRAME_MODE_NORMAL:
870 reg |= MV88E6XXX_PORT_CTL0_FRAME_MODE_NORMAL;
871 break;
872 case MV88E6XXX_FRAME_MODE_DSA:
873 reg |= MV88E6XXX_PORT_CTL0_FRAME_MODE_DSA;
874 break;
875 default:
876 return -EINVAL;
877 }
878
879 return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
880 }
881
mv88e6351_port_set_frame_mode(struct mv88e6xxx_chip * chip,int port,enum mv88e6xxx_frame_mode mode)882 int mv88e6351_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port,
883 enum mv88e6xxx_frame_mode mode)
884 {
885 int err;
886 u16 reg;
887
888 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, ®);
889 if (err)
890 return err;
891
892 reg &= ~MV88E6XXX_PORT_CTL0_FRAME_MODE_MASK;
893
894 switch (mode) {
895 case MV88E6XXX_FRAME_MODE_NORMAL:
896 reg |= MV88E6XXX_PORT_CTL0_FRAME_MODE_NORMAL;
897 break;
898 case MV88E6XXX_FRAME_MODE_DSA:
899 reg |= MV88E6XXX_PORT_CTL0_FRAME_MODE_DSA;
900 break;
901 case MV88E6XXX_FRAME_MODE_PROVIDER:
902 reg |= MV88E6XXX_PORT_CTL0_FRAME_MODE_PROVIDER;
903 break;
904 case MV88E6XXX_FRAME_MODE_ETHERTYPE:
905 reg |= MV88E6XXX_PORT_CTL0_FRAME_MODE_ETHER_TYPE_DSA;
906 break;
907 default:
908 return -EINVAL;
909 }
910
911 return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
912 }
913
mv88e6185_port_set_forward_unknown(struct mv88e6xxx_chip * chip,int port,bool unicast)914 int mv88e6185_port_set_forward_unknown(struct mv88e6xxx_chip *chip,
915 int port, bool unicast)
916 {
917 int err;
918 u16 reg;
919
920 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, ®);
921 if (err)
922 return err;
923
924 if (unicast)
925 reg |= MV88E6185_PORT_CTL0_FORWARD_UNKNOWN;
926 else
927 reg &= ~MV88E6185_PORT_CTL0_FORWARD_UNKNOWN;
928
929 return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
930 }
931
mv88e6352_port_set_ucast_flood(struct mv88e6xxx_chip * chip,int port,bool unicast)932 int mv88e6352_port_set_ucast_flood(struct mv88e6xxx_chip *chip, int port,
933 bool unicast)
934 {
935 int err;
936 u16 reg;
937
938 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, ®);
939 if (err)
940 return err;
941
942 if (unicast)
943 reg |= MV88E6352_PORT_CTL0_EGRESS_FLOODS_UC;
944 else
945 reg &= ~MV88E6352_PORT_CTL0_EGRESS_FLOODS_UC;
946
947 return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
948 }
949
mv88e6352_port_set_mcast_flood(struct mv88e6xxx_chip * chip,int port,bool multicast)950 int mv88e6352_port_set_mcast_flood(struct mv88e6xxx_chip *chip, int port,
951 bool multicast)
952 {
953 int err;
954 u16 reg;
955
956 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, ®);
957 if (err)
958 return err;
959
960 if (multicast)
961 reg |= MV88E6352_PORT_CTL0_EGRESS_FLOODS_MC;
962 else
963 reg &= ~MV88E6352_PORT_CTL0_EGRESS_FLOODS_MC;
964
965 return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
966 }
967
968 /* Offset 0x05: Port Control 1 */
969
mv88e6xxx_port_set_message_port(struct mv88e6xxx_chip * chip,int port,bool message_port)970 int mv88e6xxx_port_set_message_port(struct mv88e6xxx_chip *chip, int port,
971 bool message_port)
972 {
973 u16 val;
974 int err;
975
976 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL1, &val);
977 if (err)
978 return err;
979
980 if (message_port)
981 val |= MV88E6XXX_PORT_CTL1_MESSAGE_PORT;
982 else
983 val &= ~MV88E6XXX_PORT_CTL1_MESSAGE_PORT;
984
985 return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL1, val);
986 }
987
mv88e6xxx_port_set_trunk(struct mv88e6xxx_chip * chip,int port,bool trunk,u8 id)988 int mv88e6xxx_port_set_trunk(struct mv88e6xxx_chip *chip, int port,
989 bool trunk, u8 id)
990 {
991 u16 val;
992 int err;
993
994 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL1, &val);
995 if (err)
996 return err;
997
998 val &= ~MV88E6XXX_PORT_CTL1_TRUNK_ID_MASK;
999
1000 if (trunk)
1001 val |= MV88E6XXX_PORT_CTL1_TRUNK_PORT |
1002 (id << MV88E6XXX_PORT_CTL1_TRUNK_ID_SHIFT);
1003 else
1004 val &= ~MV88E6XXX_PORT_CTL1_TRUNK_PORT;
1005
1006 return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL1, val);
1007 }
1008
1009 /* Offset 0x06: Port Based VLAN Map */
1010
mv88e6xxx_port_set_vlan_map(struct mv88e6xxx_chip * chip,int port,u16 map)1011 int mv88e6xxx_port_set_vlan_map(struct mv88e6xxx_chip *chip, int port, u16 map)
1012 {
1013 const u16 mask = mv88e6xxx_port_mask(chip);
1014 u16 reg;
1015 int err;
1016
1017 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_BASE_VLAN, ®);
1018 if (err)
1019 return err;
1020
1021 reg &= ~mask;
1022 reg |= map & mask;
1023
1024 err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_BASE_VLAN, reg);
1025 if (err)
1026 return err;
1027
1028 dev_dbg(chip->dev, "p%d: VLANTable set to %.3x\n", port, map);
1029
1030 return 0;
1031 }
1032
mv88e6xxx_port_get_fid(struct mv88e6xxx_chip * chip,int port,u16 * fid)1033 int mv88e6xxx_port_get_fid(struct mv88e6xxx_chip *chip, int port, u16 *fid)
1034 {
1035 const u16 upper_mask = (mv88e6xxx_num_databases(chip) - 1) >> 4;
1036 u16 reg;
1037 int err;
1038
1039 /* Port's default FID lower 4 bits are located in reg 0x06, offset 12 */
1040 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_BASE_VLAN, ®);
1041 if (err)
1042 return err;
1043
1044 *fid = (reg & 0xf000) >> 12;
1045
1046 /* Port's default FID upper bits are located in reg 0x05, offset 0 */
1047 if (upper_mask) {
1048 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL1,
1049 ®);
1050 if (err)
1051 return err;
1052
1053 *fid |= (reg & upper_mask) << 4;
1054 }
1055
1056 return 0;
1057 }
1058
mv88e6xxx_port_set_fid(struct mv88e6xxx_chip * chip,int port,u16 fid)1059 int mv88e6xxx_port_set_fid(struct mv88e6xxx_chip *chip, int port, u16 fid)
1060 {
1061 const u16 upper_mask = (mv88e6xxx_num_databases(chip) - 1) >> 4;
1062 u16 reg;
1063 int err;
1064
1065 if (fid >= mv88e6xxx_num_databases(chip))
1066 return -EINVAL;
1067
1068 /* Port's default FID lower 4 bits are located in reg 0x06, offset 12 */
1069 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_BASE_VLAN, ®);
1070 if (err)
1071 return err;
1072
1073 reg &= 0x0fff;
1074 reg |= (fid & 0x000f) << 12;
1075
1076 err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_BASE_VLAN, reg);
1077 if (err)
1078 return err;
1079
1080 /* Port's default FID upper bits are located in reg 0x05, offset 0 */
1081 if (upper_mask) {
1082 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL1,
1083 ®);
1084 if (err)
1085 return err;
1086
1087 reg &= ~upper_mask;
1088 reg |= (fid >> 4) & upper_mask;
1089
1090 err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL1,
1091 reg);
1092 if (err)
1093 return err;
1094 }
1095
1096 dev_dbg(chip->dev, "p%d: FID set to %u\n", port, fid);
1097
1098 return 0;
1099 }
1100
1101 /* Offset 0x07: Default Port VLAN ID & Priority */
1102
mv88e6xxx_port_get_pvid(struct mv88e6xxx_chip * chip,int port,u16 * pvid)1103 int mv88e6xxx_port_get_pvid(struct mv88e6xxx_chip *chip, int port, u16 *pvid)
1104 {
1105 u16 reg;
1106 int err;
1107
1108 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_DEFAULT_VLAN,
1109 ®);
1110 if (err)
1111 return err;
1112
1113 *pvid = reg & MV88E6XXX_PORT_DEFAULT_VLAN_MASK;
1114
1115 return 0;
1116 }
1117
mv88e6xxx_port_set_pvid(struct mv88e6xxx_chip * chip,int port,u16 pvid)1118 int mv88e6xxx_port_set_pvid(struct mv88e6xxx_chip *chip, int port, u16 pvid)
1119 {
1120 u16 reg;
1121 int err;
1122
1123 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_DEFAULT_VLAN,
1124 ®);
1125 if (err)
1126 return err;
1127
1128 reg &= ~MV88E6XXX_PORT_DEFAULT_VLAN_MASK;
1129 reg |= pvid & MV88E6XXX_PORT_DEFAULT_VLAN_MASK;
1130
1131 err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_DEFAULT_VLAN,
1132 reg);
1133 if (err)
1134 return err;
1135
1136 dev_dbg(chip->dev, "p%d: DefaultVID set to %u\n", port, pvid);
1137
1138 return 0;
1139 }
1140
1141 /* Offset 0x08: Port Control 2 Register */
1142
1143 static const char * const mv88e6xxx_port_8021q_mode_names[] = {
1144 [MV88E6XXX_PORT_CTL2_8021Q_MODE_DISABLED] = "Disabled",
1145 [MV88E6XXX_PORT_CTL2_8021Q_MODE_FALLBACK] = "Fallback",
1146 [MV88E6XXX_PORT_CTL2_8021Q_MODE_CHECK] = "Check",
1147 [MV88E6XXX_PORT_CTL2_8021Q_MODE_SECURE] = "Secure",
1148 };
1149
mv88e6185_port_set_default_forward(struct mv88e6xxx_chip * chip,int port,bool multicast)1150 int mv88e6185_port_set_default_forward(struct mv88e6xxx_chip *chip,
1151 int port, bool multicast)
1152 {
1153 int err;
1154 u16 reg;
1155
1156 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, ®);
1157 if (err)
1158 return err;
1159
1160 if (multicast)
1161 reg |= MV88E6XXX_PORT_CTL2_DEFAULT_FORWARD;
1162 else
1163 reg &= ~MV88E6XXX_PORT_CTL2_DEFAULT_FORWARD;
1164
1165 return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg);
1166 }
1167
mv88e6095_port_set_upstream_port(struct mv88e6xxx_chip * chip,int port,int upstream_port)1168 int mv88e6095_port_set_upstream_port(struct mv88e6xxx_chip *chip, int port,
1169 int upstream_port)
1170 {
1171 int err;
1172 u16 reg;
1173
1174 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, ®);
1175 if (err)
1176 return err;
1177
1178 reg &= ~MV88E6095_PORT_CTL2_CPU_PORT_MASK;
1179 reg |= upstream_port;
1180
1181 return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg);
1182 }
1183
mv88e6xxx_port_set_mirror(struct mv88e6xxx_chip * chip,int port,enum mv88e6xxx_egress_direction direction,bool mirror)1184 int mv88e6xxx_port_set_mirror(struct mv88e6xxx_chip *chip, int port,
1185 enum mv88e6xxx_egress_direction direction,
1186 bool mirror)
1187 {
1188 bool *mirror_port;
1189 u16 reg;
1190 u16 bit;
1191 int err;
1192
1193 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, ®);
1194 if (err)
1195 return err;
1196
1197 switch (direction) {
1198 case MV88E6XXX_EGRESS_DIR_INGRESS:
1199 bit = MV88E6XXX_PORT_CTL2_INGRESS_MONITOR;
1200 mirror_port = &chip->ports[port].mirror_ingress;
1201 break;
1202 case MV88E6XXX_EGRESS_DIR_EGRESS:
1203 bit = MV88E6XXX_PORT_CTL2_EGRESS_MONITOR;
1204 mirror_port = &chip->ports[port].mirror_egress;
1205 break;
1206 default:
1207 return -EINVAL;
1208 }
1209
1210 reg &= ~bit;
1211 if (mirror)
1212 reg |= bit;
1213
1214 err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg);
1215 if (!err)
1216 *mirror_port = mirror;
1217
1218 return err;
1219 }
1220
mv88e6xxx_port_set_lock(struct mv88e6xxx_chip * chip,int port,bool locked)1221 int mv88e6xxx_port_set_lock(struct mv88e6xxx_chip *chip, int port,
1222 bool locked)
1223 {
1224 u16 reg;
1225 int err;
1226
1227 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, ®);
1228 if (err)
1229 return err;
1230
1231 reg &= ~MV88E6XXX_PORT_CTL0_SA_FILT_MASK;
1232 if (locked)
1233 reg |= MV88E6XXX_PORT_CTL0_SA_FILT_DROP_ON_LOCK;
1234
1235 err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
1236 if (err)
1237 return err;
1238
1239 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_ASSOC_VECTOR, ®);
1240 if (err)
1241 return err;
1242
1243 reg &= ~MV88E6XXX_PORT_ASSOC_VECTOR_LOCKED_PORT;
1244 if (locked)
1245 reg |= MV88E6XXX_PORT_ASSOC_VECTOR_LOCKED_PORT;
1246
1247 return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_ASSOC_VECTOR, reg);
1248 }
1249
mv88e6xxx_port_set_8021q_mode(struct mv88e6xxx_chip * chip,int port,u16 mode)1250 int mv88e6xxx_port_set_8021q_mode(struct mv88e6xxx_chip *chip, int port,
1251 u16 mode)
1252 {
1253 u16 reg;
1254 int err;
1255
1256 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, ®);
1257 if (err)
1258 return err;
1259
1260 reg &= ~MV88E6XXX_PORT_CTL2_8021Q_MODE_MASK;
1261 reg |= mode & MV88E6XXX_PORT_CTL2_8021Q_MODE_MASK;
1262
1263 err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg);
1264 if (err)
1265 return err;
1266
1267 dev_dbg(chip->dev, "p%d: 802.1QMode set to %s\n", port,
1268 mv88e6xxx_port_8021q_mode_names[mode]);
1269
1270 return 0;
1271 }
1272
mv88e6xxx_port_drop_untagged(struct mv88e6xxx_chip * chip,int port,bool drop_untagged)1273 int mv88e6xxx_port_drop_untagged(struct mv88e6xxx_chip *chip, int port,
1274 bool drop_untagged)
1275 {
1276 u16 old, new;
1277 int err;
1278
1279 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, &old);
1280 if (err)
1281 return err;
1282
1283 if (drop_untagged)
1284 new = old | MV88E6XXX_PORT_CTL2_DISCARD_UNTAGGED;
1285 else
1286 new = old & ~MV88E6XXX_PORT_CTL2_DISCARD_UNTAGGED;
1287
1288 if (new == old)
1289 return 0;
1290
1291 return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, new);
1292 }
1293
mv88e6xxx_port_set_map_da(struct mv88e6xxx_chip * chip,int port,bool map)1294 int mv88e6xxx_port_set_map_da(struct mv88e6xxx_chip *chip, int port, bool map)
1295 {
1296 u16 reg;
1297 int err;
1298
1299 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, ®);
1300 if (err)
1301 return err;
1302
1303 if (map)
1304 reg |= MV88E6XXX_PORT_CTL2_MAP_DA;
1305 else
1306 reg &= ~MV88E6XXX_PORT_CTL2_MAP_DA;
1307
1308 return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg);
1309 }
1310
mv88e6165_port_set_jumbo_size(struct mv88e6xxx_chip * chip,int port,size_t size)1311 int mv88e6165_port_set_jumbo_size(struct mv88e6xxx_chip *chip, int port,
1312 size_t size)
1313 {
1314 u16 reg;
1315 int err;
1316
1317 size += VLAN_ETH_HLEN + ETH_FCS_LEN;
1318
1319 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, ®);
1320 if (err)
1321 return err;
1322
1323 reg &= ~MV88E6XXX_PORT_CTL2_JUMBO_MODE_MASK;
1324
1325 if (size <= 1522)
1326 reg |= MV88E6XXX_PORT_CTL2_JUMBO_MODE_1522;
1327 else if (size <= 2048)
1328 reg |= MV88E6XXX_PORT_CTL2_JUMBO_MODE_2048;
1329 else if (size <= 10240)
1330 reg |= MV88E6XXX_PORT_CTL2_JUMBO_MODE_10240;
1331 else
1332 return -ERANGE;
1333
1334 return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg);
1335 }
1336
1337 /* Offset 0x09: Port Rate Control */
1338
mv88e6095_port_egress_rate_limiting(struct mv88e6xxx_chip * chip,int port)1339 int mv88e6095_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port)
1340 {
1341 return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_EGRESS_RATE_CTL1,
1342 0x0000);
1343 }
1344
mv88e6097_port_egress_rate_limiting(struct mv88e6xxx_chip * chip,int port)1345 int mv88e6097_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port)
1346 {
1347 return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_EGRESS_RATE_CTL1,
1348 0x0001);
1349 }
1350
1351 /* Offset 0x0B: Port Association Vector */
1352
mv88e6xxx_port_set_assoc_vector(struct mv88e6xxx_chip * chip,int port,u16 pav)1353 int mv88e6xxx_port_set_assoc_vector(struct mv88e6xxx_chip *chip, int port,
1354 u16 pav)
1355 {
1356 u16 reg, mask;
1357 int err;
1358
1359 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_ASSOC_VECTOR,
1360 ®);
1361 if (err)
1362 return err;
1363
1364 mask = mv88e6xxx_port_mask(chip);
1365 reg &= ~mask;
1366 reg |= pav & mask;
1367
1368 return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_ASSOC_VECTOR,
1369 reg);
1370 }
1371
1372 /* Offset 0x0C: Port ATU Control */
1373
mv88e6xxx_port_disable_learn_limit(struct mv88e6xxx_chip * chip,int port)1374 int mv88e6xxx_port_disable_learn_limit(struct mv88e6xxx_chip *chip, int port)
1375 {
1376 return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_ATU_CTL, 0);
1377 }
1378
1379 /* Offset 0x0D: (Priority) Override Register */
1380
mv88e6xxx_port_disable_pri_override(struct mv88e6xxx_chip * chip,int port)1381 int mv88e6xxx_port_disable_pri_override(struct mv88e6xxx_chip *chip, int port)
1382 {
1383 return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_PRI_OVERRIDE, 0);
1384 }
1385
1386 /* Offset 0x0E: Policy & MGMT Control Register for FAMILY 6191X 6193X 6393X */
1387
mv88e6393x_port_policy_read(struct mv88e6xxx_chip * chip,int port,u16 pointer,u8 * data)1388 static int mv88e6393x_port_policy_read(struct mv88e6xxx_chip *chip, int port,
1389 u16 pointer, u8 *data)
1390 {
1391 u16 reg;
1392 int err;
1393
1394 err = mv88e6xxx_port_write(chip, port, MV88E6393X_PORT_POLICY_MGMT_CTL,
1395 pointer);
1396 if (err)
1397 return err;
1398
1399 err = mv88e6xxx_port_read(chip, port, MV88E6393X_PORT_POLICY_MGMT_CTL,
1400 ®);
1401 if (err)
1402 return err;
1403
1404 *data = reg;
1405
1406 return 0;
1407 }
1408
mv88e6393x_port_policy_write(struct mv88e6xxx_chip * chip,int port,u16 pointer,u8 data)1409 static int mv88e6393x_port_policy_write(struct mv88e6xxx_chip *chip, int port,
1410 u16 pointer, u8 data)
1411 {
1412 u16 reg;
1413
1414 reg = MV88E6393X_PORT_POLICY_MGMT_CTL_UPDATE | pointer | data;
1415
1416 return mv88e6xxx_port_write(chip, port, MV88E6393X_PORT_POLICY_MGMT_CTL,
1417 reg);
1418 }
1419
mv88e6393x_port_policy_write_all(struct mv88e6xxx_chip * chip,u16 pointer,u8 data)1420 static int mv88e6393x_port_policy_write_all(struct mv88e6xxx_chip *chip,
1421 u16 pointer, u8 data)
1422 {
1423 int err, port;
1424
1425 for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
1426 if (dsa_is_unused_port(chip->ds, port))
1427 continue;
1428
1429 err = mv88e6393x_port_policy_write(chip, port, pointer, data);
1430 if (err)
1431 return err;
1432 }
1433
1434 return 0;
1435 }
1436
mv88e6393x_set_egress_port(struct mv88e6xxx_chip * chip,enum mv88e6xxx_egress_direction direction,int port)1437 int mv88e6393x_set_egress_port(struct mv88e6xxx_chip *chip,
1438 enum mv88e6xxx_egress_direction direction,
1439 int port)
1440 {
1441 u16 ptr;
1442 int err;
1443
1444 switch (direction) {
1445 case MV88E6XXX_EGRESS_DIR_INGRESS:
1446 ptr = MV88E6393X_PORT_POLICY_MGMT_CTL_PTR_INGRESS_DEST;
1447 err = mv88e6393x_port_policy_write_all(chip, ptr, port);
1448 if (err)
1449 return err;
1450 break;
1451 case MV88E6XXX_EGRESS_DIR_EGRESS:
1452 ptr = MV88E6393X_G2_EGRESS_MONITOR_DEST;
1453 err = mv88e6xxx_g2_write(chip, ptr, port);
1454 if (err)
1455 return err;
1456 break;
1457 }
1458
1459 return 0;
1460 }
1461
mv88e6393x_port_set_upstream_port(struct mv88e6xxx_chip * chip,int port,int upstream_port)1462 int mv88e6393x_port_set_upstream_port(struct mv88e6xxx_chip *chip, int port,
1463 int upstream_port)
1464 {
1465 u16 ptr = MV88E6393X_PORT_POLICY_MGMT_CTL_PTR_CPU_DEST;
1466 u8 data = MV88E6393X_PORT_POLICY_MGMT_CTL_CPU_DEST_MGMTPRI |
1467 upstream_port;
1468
1469 return mv88e6393x_port_policy_write(chip, port, ptr, data);
1470 }
1471
mv88e6393x_port_mgmt_rsvd2cpu(struct mv88e6xxx_chip * chip)1472 int mv88e6393x_port_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip)
1473 {
1474 u16 ptr;
1475 int err;
1476
1477 /* Consider the frames with reserved multicast destination
1478 * addresses matching 01:80:c2:00:00:00 and
1479 * 01:80:c2:00:00:02 as MGMT.
1480 */
1481 ptr = MV88E6393X_PORT_POLICY_MGMT_CTL_PTR_01C280000000XLO;
1482 err = mv88e6393x_port_policy_write_all(chip, ptr, 0xff);
1483 if (err)
1484 return err;
1485
1486 ptr = MV88E6393X_PORT_POLICY_MGMT_CTL_PTR_01C280000000XHI;
1487 err = mv88e6393x_port_policy_write_all(chip, ptr, 0xff);
1488 if (err)
1489 return err;
1490
1491 ptr = MV88E6393X_PORT_POLICY_MGMT_CTL_PTR_01C280000002XLO;
1492 err = mv88e6393x_port_policy_write_all(chip, ptr, 0xff);
1493 if (err)
1494 return err;
1495
1496 ptr = MV88E6393X_PORT_POLICY_MGMT_CTL_PTR_01C280000002XHI;
1497 err = mv88e6393x_port_policy_write_all(chip, ptr, 0xff);
1498 if (err)
1499 return err;
1500
1501 return 0;
1502 }
1503
1504 /* Offset 0x10 & 0x11: EPC */
1505
mv88e6393x_port_epc_wait_ready(struct mv88e6xxx_chip * chip,int port)1506 static int mv88e6393x_port_epc_wait_ready(struct mv88e6xxx_chip *chip, int port)
1507 {
1508 int bit = __bf_shf(MV88E6393X_PORT_EPC_CMD_BUSY);
1509
1510 return mv88e6xxx_port_wait_bit(chip, port, MV88E6393X_PORT_EPC_CMD, bit, 0);
1511 }
1512
1513 /* Port Ether type for 6393X family */
1514
mv88e6393x_port_set_ether_type(struct mv88e6xxx_chip * chip,int port,u16 etype)1515 int mv88e6393x_port_set_ether_type(struct mv88e6xxx_chip *chip, int port,
1516 u16 etype)
1517 {
1518 u16 val;
1519 int err;
1520
1521 err = mv88e6393x_port_epc_wait_ready(chip, port);
1522 if (err)
1523 return err;
1524
1525 err = mv88e6xxx_port_write(chip, port, MV88E6393X_PORT_EPC_DATA, etype);
1526 if (err)
1527 return err;
1528
1529 val = MV88E6393X_PORT_EPC_CMD_BUSY |
1530 MV88E6393X_PORT_EPC_CMD_WRITE |
1531 MV88E6393X_PORT_EPC_INDEX_PORT_ETYPE;
1532
1533 return mv88e6xxx_port_write(chip, port, MV88E6393X_PORT_EPC_CMD, val);
1534 }
1535
1536 /* Offset 0x0f: Port Ether type */
1537
mv88e6351_port_set_ether_type(struct mv88e6xxx_chip * chip,int port,u16 etype)1538 int mv88e6351_port_set_ether_type(struct mv88e6xxx_chip *chip, int port,
1539 u16 etype)
1540 {
1541 return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_ETH_TYPE, etype);
1542 }
1543
1544 /* Offset 0x18: Port IEEE Priority Remapping Registers [0-3]
1545 * Offset 0x19: Port IEEE Priority Remapping Registers [4-7]
1546 */
1547
mv88e6095_port_tag_remap(struct mv88e6xxx_chip * chip,int port)1548 int mv88e6095_port_tag_remap(struct mv88e6xxx_chip *chip, int port)
1549 {
1550 int err;
1551
1552 /* Use a direct priority mapping for all IEEE tagged frames */
1553 err = mv88e6xxx_port_write(chip, port,
1554 MV88E6095_PORT_IEEE_PRIO_REMAP_0123,
1555 0x3210);
1556 if (err)
1557 return err;
1558
1559 return mv88e6xxx_port_write(chip, port,
1560 MV88E6095_PORT_IEEE_PRIO_REMAP_4567,
1561 0x7654);
1562 }
1563
mv88e6xxx_port_ieeepmt_write(struct mv88e6xxx_chip * chip,int port,u16 table,u8 ptr,u16 data)1564 static int mv88e6xxx_port_ieeepmt_write(struct mv88e6xxx_chip *chip,
1565 int port, u16 table, u8 ptr, u16 data)
1566 {
1567 u16 reg;
1568
1569 reg = MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_UPDATE | table |
1570 (ptr << __bf_shf(MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_PTR_MASK)) |
1571 (data & MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_DATA_MASK);
1572
1573 return mv88e6xxx_port_write(chip, port,
1574 MV88E6390_PORT_IEEE_PRIO_MAP_TABLE, reg);
1575 }
1576
mv88e6390_port_tag_remap(struct mv88e6xxx_chip * chip,int port)1577 int mv88e6390_port_tag_remap(struct mv88e6xxx_chip *chip, int port)
1578 {
1579 int err, i;
1580 u16 table;
1581
1582 for (i = 0; i <= 7; i++) {
1583 table = MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_INGRESS_PCP;
1584 err = mv88e6xxx_port_ieeepmt_write(chip, port, table, i,
1585 (i | i << 4));
1586 if (err)
1587 return err;
1588
1589 table = MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_GREEN_PCP;
1590 err = mv88e6xxx_port_ieeepmt_write(chip, port, table, i, i);
1591 if (err)
1592 return err;
1593
1594 table = MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_YELLOW_PCP;
1595 err = mv88e6xxx_port_ieeepmt_write(chip, port, table, i, i);
1596 if (err)
1597 return err;
1598
1599 table = MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_AVB_PCP;
1600 err = mv88e6xxx_port_ieeepmt_write(chip, port, table, i, i);
1601 if (err)
1602 return err;
1603 }
1604
1605 return 0;
1606 }
1607
1608 /* Offset 0x0E: Policy Control Register */
1609
1610 static int
mv88e6xxx_port_policy_mapping_get_pos(enum mv88e6xxx_policy_mapping mapping,enum mv88e6xxx_policy_action action,u16 * mask,u16 * val,int * shift)1611 mv88e6xxx_port_policy_mapping_get_pos(enum mv88e6xxx_policy_mapping mapping,
1612 enum mv88e6xxx_policy_action action,
1613 u16 *mask, u16 *val, int *shift)
1614 {
1615 switch (mapping) {
1616 case MV88E6XXX_POLICY_MAPPING_DA:
1617 *shift = __bf_shf(MV88E6XXX_PORT_POLICY_CTL_DA_MASK);
1618 *mask = MV88E6XXX_PORT_POLICY_CTL_DA_MASK;
1619 break;
1620 case MV88E6XXX_POLICY_MAPPING_SA:
1621 *shift = __bf_shf(MV88E6XXX_PORT_POLICY_CTL_SA_MASK);
1622 *mask = MV88E6XXX_PORT_POLICY_CTL_SA_MASK;
1623 break;
1624 case MV88E6XXX_POLICY_MAPPING_VTU:
1625 *shift = __bf_shf(MV88E6XXX_PORT_POLICY_CTL_VTU_MASK);
1626 *mask = MV88E6XXX_PORT_POLICY_CTL_VTU_MASK;
1627 break;
1628 case MV88E6XXX_POLICY_MAPPING_ETYPE:
1629 *shift = __bf_shf(MV88E6XXX_PORT_POLICY_CTL_ETYPE_MASK);
1630 *mask = MV88E6XXX_PORT_POLICY_CTL_ETYPE_MASK;
1631 break;
1632 case MV88E6XXX_POLICY_MAPPING_PPPOE:
1633 *shift = __bf_shf(MV88E6XXX_PORT_POLICY_CTL_PPPOE_MASK);
1634 *mask = MV88E6XXX_PORT_POLICY_CTL_PPPOE_MASK;
1635 break;
1636 case MV88E6XXX_POLICY_MAPPING_VBAS:
1637 *shift = __bf_shf(MV88E6XXX_PORT_POLICY_CTL_VBAS_MASK);
1638 *mask = MV88E6XXX_PORT_POLICY_CTL_VBAS_MASK;
1639 break;
1640 case MV88E6XXX_POLICY_MAPPING_OPT82:
1641 *shift = __bf_shf(MV88E6XXX_PORT_POLICY_CTL_OPT82_MASK);
1642 *mask = MV88E6XXX_PORT_POLICY_CTL_OPT82_MASK;
1643 break;
1644 case MV88E6XXX_POLICY_MAPPING_UDP:
1645 *shift = __bf_shf(MV88E6XXX_PORT_POLICY_CTL_UDP_MASK);
1646 *mask = MV88E6XXX_PORT_POLICY_CTL_UDP_MASK;
1647 break;
1648 default:
1649 return -EOPNOTSUPP;
1650 }
1651
1652 switch (action) {
1653 case MV88E6XXX_POLICY_ACTION_NORMAL:
1654 *val = MV88E6XXX_PORT_POLICY_CTL_NORMAL;
1655 break;
1656 case MV88E6XXX_POLICY_ACTION_MIRROR:
1657 *val = MV88E6XXX_PORT_POLICY_CTL_MIRROR;
1658 break;
1659 case MV88E6XXX_POLICY_ACTION_TRAP:
1660 *val = MV88E6XXX_PORT_POLICY_CTL_TRAP;
1661 break;
1662 case MV88E6XXX_POLICY_ACTION_DISCARD:
1663 *val = MV88E6XXX_PORT_POLICY_CTL_DISCARD;
1664 break;
1665 default:
1666 return -EOPNOTSUPP;
1667 }
1668
1669 return 0;
1670 }
1671
mv88e6352_port_set_policy(struct mv88e6xxx_chip * chip,int port,enum mv88e6xxx_policy_mapping mapping,enum mv88e6xxx_policy_action action)1672 int mv88e6352_port_set_policy(struct mv88e6xxx_chip *chip, int port,
1673 enum mv88e6xxx_policy_mapping mapping,
1674 enum mv88e6xxx_policy_action action)
1675 {
1676 u16 reg, mask, val;
1677 int shift;
1678 int err;
1679
1680 err = mv88e6xxx_port_policy_mapping_get_pos(mapping, action, &mask,
1681 &val, &shift);
1682 if (err)
1683 return err;
1684
1685 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_POLICY_CTL, ®);
1686 if (err)
1687 return err;
1688
1689 reg &= ~mask;
1690 reg |= (val << shift) & mask;
1691
1692 return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_POLICY_CTL, reg);
1693 }
1694
mv88e6393x_port_set_policy(struct mv88e6xxx_chip * chip,int port,enum mv88e6xxx_policy_mapping mapping,enum mv88e6xxx_policy_action action)1695 int mv88e6393x_port_set_policy(struct mv88e6xxx_chip *chip, int port,
1696 enum mv88e6xxx_policy_mapping mapping,
1697 enum mv88e6xxx_policy_action action)
1698 {
1699 u16 mask, val;
1700 int shift;
1701 int err;
1702 u16 ptr;
1703 u8 reg;
1704
1705 err = mv88e6xxx_port_policy_mapping_get_pos(mapping, action, &mask,
1706 &val, &shift);
1707 if (err)
1708 return err;
1709
1710 /* The 16-bit Port Policy CTL register from older chips is on 6393x
1711 * changed to Port Policy MGMT CTL, which can access more data, but
1712 * indirectly. The original 16-bit value is divided into two 8-bit
1713 * registers.
1714 */
1715 ptr = shift / 8;
1716 shift %= 8;
1717 mask >>= ptr * 8;
1718 ptr <<= 8;
1719
1720 err = mv88e6393x_port_policy_read(chip, port, ptr, ®);
1721 if (err)
1722 return err;
1723
1724 reg &= ~mask;
1725 reg |= (val << shift) & mask;
1726
1727 return mv88e6393x_port_policy_write(chip, port, ptr, reg);
1728 }
1729