net: dsa: mv88e6xxx: Cache the port cmode
[linux-2.6-block.git] / drivers / net / dsa / mv88e6xxx / port.c
1 /*
2  * Marvell 88E6xxx Switch Port Registers support
3  *
4  * Copyright (c) 2008 Marvell Semiconductor
5  *
6  * Copyright (c) 2016-2017 Savoir-faire Linux Inc.
7  *      Vivien Didelot <vivien.didelot@savoirfairelinux.com>
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
15 #include <linux/bitfield.h>
16 #include <linux/if_bridge.h>
17 #include <linux/phy.h>
18 #include <linux/phylink.h>
19
20 #include "chip.h"
21 #include "port.h"
22
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
31 int 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 }
38
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  */
44 int 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
62 /* Offset 0x01: MAC (or PCS or Physical) Control Register
63  *
64  * Link, Duplex and Flow Control have one force bit, one value bit.
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.
69  */
70
71 static 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
77         err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_MAC_CTL, &reg);
78         if (err)
79                 return err;
80
81         reg &= ~(MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_RXCLK |
82                  MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_TXCLK);
83
84         switch (mode) {
85         case PHY_INTERFACE_MODE_RGMII_RXID:
86                 reg |= MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_RXCLK;
87                 break;
88         case PHY_INTERFACE_MODE_RGMII_TXID:
89                 reg |= MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_TXCLK;
90                 break;
91         case PHY_INTERFACE_MODE_RGMII_ID:
92                 reg |= MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_RXCLK |
93                         MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_TXCLK;
94                 break;
95         case PHY_INTERFACE_MODE_RGMII:
96                 break;
97         default:
98                 return 0;
99         }
100
101         err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_MAC_CTL, reg);
102         if (err)
103                 return err;
104
105         dev_dbg(chip->dev, "p%d: delay RXCLK %s, TXCLK %s\n", port,
106                 reg & MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_RXCLK ? "yes" : "no",
107                 reg & MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_TXCLK ? "yes" : "no");
108
109         return 0;
110 }
111
112 int 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
121 int 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
130 int mv88e6xxx_port_set_link(struct mv88e6xxx_chip *chip, int port, int link)
131 {
132         u16 reg;
133         int err;
134
135         err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_MAC_CTL, &reg);
136         if (err)
137                 return err;
138
139         reg &= ~(MV88E6XXX_PORT_MAC_CTL_FORCE_LINK |
140                  MV88E6XXX_PORT_MAC_CTL_LINK_UP);
141
142         switch (link) {
143         case LINK_FORCED_DOWN:
144                 reg |= MV88E6XXX_PORT_MAC_CTL_FORCE_LINK;
145                 break;
146         case LINK_FORCED_UP:
147                 reg |= MV88E6XXX_PORT_MAC_CTL_FORCE_LINK |
148                         MV88E6XXX_PORT_MAC_CTL_LINK_UP;
149                 break;
150         case LINK_UNFORCED:
151                 /* normal link detection */
152                 break;
153         default:
154                 return -EINVAL;
155         }
156
157         err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_MAC_CTL, reg);
158         if (err)
159                 return err;
160
161         dev_dbg(chip->dev, "p%d: %s link %s\n", port,
162                 reg & MV88E6XXX_PORT_MAC_CTL_FORCE_LINK ? "Force" : "Unforce",
163                 reg & MV88E6XXX_PORT_MAC_CTL_LINK_UP ? "up" : "down");
164
165         return 0;
166 }
167
168 int mv88e6xxx_port_set_duplex(struct mv88e6xxx_chip *chip, int port, int dup)
169 {
170         u16 reg;
171         int err;
172
173         err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_MAC_CTL, &reg);
174         if (err)
175                 return err;
176
177         reg &= ~(MV88E6XXX_PORT_MAC_CTL_FORCE_DUPLEX |
178                  MV88E6XXX_PORT_MAC_CTL_DUPLEX_FULL);
179
180         switch (dup) {
181         case DUPLEX_HALF:
182                 reg |= MV88E6XXX_PORT_MAC_CTL_FORCE_DUPLEX;
183                 break;
184         case DUPLEX_FULL:
185                 reg |= MV88E6XXX_PORT_MAC_CTL_FORCE_DUPLEX |
186                         MV88E6XXX_PORT_MAC_CTL_DUPLEX_FULL;
187                 break;
188         case DUPLEX_UNFORCED:
189                 /* normal duplex detection */
190                 break;
191         default:
192                 return -EINVAL;
193         }
194
195         err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_MAC_CTL, reg);
196         if (err)
197                 return err;
198
199         dev_dbg(chip->dev, "p%d: %s %s duplex\n", port,
200                 reg & MV88E6XXX_PORT_MAC_CTL_FORCE_DUPLEX ? "Force" : "Unforce",
201                 reg & MV88E6XXX_PORT_MAC_CTL_DUPLEX_FULL ? "full" : "half");
202
203         return 0;
204 }
205
206 static 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:
214                 ctrl = MV88E6XXX_PORT_MAC_CTL_SPEED_10;
215                 break;
216         case 100:
217                 ctrl = MV88E6XXX_PORT_MAC_CTL_SPEED_100;
218                 break;
219         case 200:
220                 if (alt_bit)
221                         ctrl = MV88E6XXX_PORT_MAC_CTL_SPEED_100 |
222                                 MV88E6390_PORT_MAC_CTL_ALTSPEED;
223                 else
224                         ctrl = MV88E6065_PORT_MAC_CTL_SPEED_200;
225                 break;
226         case 1000:
227                 ctrl = MV88E6XXX_PORT_MAC_CTL_SPEED_1000;
228                 break;
229         case 2500:
230                 ctrl = MV88E6390_PORT_MAC_CTL_SPEED_10000 |
231                         MV88E6390_PORT_MAC_CTL_ALTSPEED;
232                 break;
233         case 10000:
234                 /* all bits set, fall through... */
235         case SPEED_UNFORCED:
236                 ctrl = MV88E6XXX_PORT_MAC_CTL_SPEED_UNFORCED;
237                 break;
238         default:
239                 return -EOPNOTSUPP;
240         }
241
242         err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_MAC_CTL, &reg);
243         if (err)
244                 return err;
245
246         reg &= ~MV88E6XXX_PORT_MAC_CTL_SPEED_MASK;
247         if (alt_bit)
248                 reg &= ~MV88E6390_PORT_MAC_CTL_ALTSPEED;
249         if (force_bit) {
250                 reg &= ~MV88E6390_PORT_MAC_CTL_FORCE_SPEED;
251                 if (speed != SPEED_UNFORCED)
252                         ctrl |= MV88E6390_PORT_MAC_CTL_FORCE_SPEED;
253         }
254         reg |= ctrl;
255
256         err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_MAC_CTL, reg);
257         if (err)
258                 return err;
259
260         if (speed)
261                 dev_dbg(chip->dev, "p%d: Speed set to %d Mbps\n", port, speed);
262         else
263                 dev_dbg(chip->dev, "p%d: Speed unforced\n", port);
264
265         return 0;
266 }
267
268 /* Support 10, 100, 200 Mbps (e.g. 88E6065 family) */
269 int 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) */
282 int 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) */
294 int 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) */
309 int 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) */
327 int 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
341 int 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:
356                 cmode = MV88E6XXX_PORT_STS_CMODE_1000BASE_X;
357                 break;
358         case PHY_INTERFACE_MODE_SGMII:
359                 cmode = MV88E6XXX_PORT_STS_CMODE_SGMII;
360                 break;
361         case PHY_INTERFACE_MODE_2500BASEX:
362                 cmode = MV88E6XXX_PORT_STS_CMODE_2500BASEX;
363                 break;
364         case PHY_INTERFACE_MODE_XGMII:
365         case PHY_INTERFACE_MODE_XAUI:
366                 cmode = MV88E6XXX_PORT_STS_CMODE_XAUI;
367                 break;
368         case PHY_INTERFACE_MODE_RXAUI:
369                 cmode = MV88E6XXX_PORT_STS_CMODE_RXAUI;
370                 break;
371         default:
372                 cmode = 0;
373         }
374
375         if (cmode) {
376                 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &reg);
377                 if (err)
378                         return err;
379
380                 reg &= ~MV88E6XXX_PORT_STS_CMODE_MASK;
381                 reg |= cmode;
382
383                 err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_STS, reg);
384                 if (err)
385                         return err;
386         }
387
388         chip->ports[port].cmode = cmode;
389
390         return 0;
391 }
392
393 int mv88e6185_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode)
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
402         *cmode = reg & MV88E6185_PORT_STS_CMODE_MASK;
403
404         return 0;
405 }
406
407 int mv88e6352_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode)
408 {
409         int err;
410         u16 reg;
411
412         err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &reg);
413         if (err)
414                 return err;
415
416         *cmode = reg & MV88E6XXX_PORT_STS_CMODE_MASK;
417
418         return 0;
419 }
420
421 int mv88e6352_port_link_state(struct mv88e6xxx_chip *chip, int port,
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:
442                 if ((reg & MV88E6XXX_PORT_STS_CMODE_MASK) ==
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
459 int 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) {
463                 u8 cmode = chip->ports[port].cmode;
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
495 /* Offset 0x02: Jamming Control
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  */
501 int mv88e6097_port_pause_limit(struct mv88e6xxx_chip *chip, int port, u8 in,
502                                u8 out)
503 {
504         return mv88e6xxx_port_write(chip, port, MV88E6097_PORT_JAM_CTL,
505                                     out << 8 | in);
506 }
507
508 int mv88e6390_port_pause_limit(struct mv88e6xxx_chip *chip, int port, u8 in,
509                                u8 out)
510 {
511         int err;
512
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);
516         if (err)
517                 return err;
518
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);
522 }
523
524 /* Offset 0x04: Port Control Register */
525
526 static const char * const mv88e6xxx_port_state_names[] = {
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",
531 };
532
533 int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state)
534 {
535         u16 reg;
536         int err;
537
538         err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, &reg);
539         if (err)
540                 return err;
541
542         reg &= ~MV88E6XXX_PORT_CTL0_STATE_MASK;
543
544         switch (state) {
545         case BR_STATE_DISABLED:
546                 state = MV88E6XXX_PORT_CTL0_STATE_DISABLED;
547                 break;
548         case BR_STATE_BLOCKING:
549         case BR_STATE_LISTENING:
550                 state = MV88E6XXX_PORT_CTL0_STATE_BLOCKING;
551                 break;
552         case BR_STATE_LEARNING:
553                 state = MV88E6XXX_PORT_CTL0_STATE_LEARNING;
554                 break;
555         case BR_STATE_FORWARDING:
556                 state = MV88E6XXX_PORT_CTL0_STATE_FORWARDING;
557                 break;
558         default:
559                 return -EINVAL;
560         }
561
562         reg |= state;
563
564         err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
565         if (err)
566                 return err;
567
568         dev_dbg(chip->dev, "p%d: PortState set to %s\n", port,
569                 mv88e6xxx_port_state_names[state]);
570
571         return 0;
572 }
573
574 int mv88e6xxx_port_set_egress_mode(struct mv88e6xxx_chip *chip, int port,
575                                    enum mv88e6xxx_egress_mode mode)
576 {
577         int err;
578         u16 reg;
579
580         err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, &reg);
581         if (err)
582                 return err;
583
584         reg &= ~MV88E6XXX_PORT_CTL0_EGRESS_MODE_MASK;
585
586         switch (mode) {
587         case MV88E6XXX_EGRESS_MODE_UNMODIFIED:
588                 reg |= MV88E6XXX_PORT_CTL0_EGRESS_MODE_UNMODIFIED;
589                 break;
590         case MV88E6XXX_EGRESS_MODE_UNTAGGED:
591                 reg |= MV88E6XXX_PORT_CTL0_EGRESS_MODE_UNTAGGED;
592                 break;
593         case MV88E6XXX_EGRESS_MODE_TAGGED:
594                 reg |= MV88E6XXX_PORT_CTL0_EGRESS_MODE_TAGGED;
595                 break;
596         case MV88E6XXX_EGRESS_MODE_ETHERTYPE:
597                 reg |= MV88E6XXX_PORT_CTL0_EGRESS_MODE_ETHER_TYPE_DSA;
598                 break;
599         default:
600                 return -EINVAL;
601         }
602
603         return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
604 }
605
606 int 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
612         err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, &reg);
613         if (err)
614                 return err;
615
616         reg &= ~MV88E6XXX_PORT_CTL0_FRAME_MODE_MASK;
617
618         switch (mode) {
619         case MV88E6XXX_FRAME_MODE_NORMAL:
620                 reg |= MV88E6XXX_PORT_CTL0_FRAME_MODE_NORMAL;
621                 break;
622         case MV88E6XXX_FRAME_MODE_DSA:
623                 reg |= MV88E6XXX_PORT_CTL0_FRAME_MODE_DSA;
624                 break;
625         default:
626                 return -EINVAL;
627         }
628
629         return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
630 }
631
632 int 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
638         err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, &reg);
639         if (err)
640                 return err;
641
642         reg &= ~MV88E6XXX_PORT_CTL0_FRAME_MODE_MASK;
643
644         switch (mode) {
645         case MV88E6XXX_FRAME_MODE_NORMAL:
646                 reg |= MV88E6XXX_PORT_CTL0_FRAME_MODE_NORMAL;
647                 break;
648         case MV88E6XXX_FRAME_MODE_DSA:
649                 reg |= MV88E6XXX_PORT_CTL0_FRAME_MODE_DSA;
650                 break;
651         case MV88E6XXX_FRAME_MODE_PROVIDER:
652                 reg |= MV88E6XXX_PORT_CTL0_FRAME_MODE_PROVIDER;
653                 break;
654         case MV88E6XXX_FRAME_MODE_ETHERTYPE:
655                 reg |= MV88E6XXX_PORT_CTL0_FRAME_MODE_ETHER_TYPE_DSA;
656                 break;
657         default:
658                 return -EINVAL;
659         }
660
661         return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
662 }
663
664 static int mv88e6185_port_set_forward_unknown(struct mv88e6xxx_chip *chip,
665                                               int port, bool unicast)
666 {
667         int err;
668         u16 reg;
669
670         err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, &reg);
671         if (err)
672                 return err;
673
674         if (unicast)
675                 reg |= MV88E6185_PORT_CTL0_FORWARD_UNKNOWN;
676         else
677                 reg &= ~MV88E6185_PORT_CTL0_FORWARD_UNKNOWN;
678
679         return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
680 }
681
682 int mv88e6352_port_set_egress_floods(struct mv88e6xxx_chip *chip, int port,
683                                      bool unicast, bool multicast)
684 {
685         int err;
686         u16 reg;
687
688         err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, &reg);
689         if (err)
690                 return err;
691
692         reg &= ~MV88E6352_PORT_CTL0_EGRESS_FLOODS_MASK;
693
694         if (unicast && multicast)
695                 reg |= MV88E6352_PORT_CTL0_EGRESS_FLOODS_ALL_UNKNOWN_DA;
696         else if (unicast)
697                 reg |= MV88E6352_PORT_CTL0_EGRESS_FLOODS_NO_UNKNOWN_MC_DA;
698         else if (multicast)
699                 reg |= MV88E6352_PORT_CTL0_EGRESS_FLOODS_NO_UNKNOWN_UC_DA;
700         else
701                 reg |= MV88E6352_PORT_CTL0_EGRESS_FLOODS_NO_UNKNOWN_DA;
702
703         return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
704 }
705
706 /* Offset 0x05: Port Control 1 */
707
708 int mv88e6xxx_port_set_message_port(struct mv88e6xxx_chip *chip, int port,
709                                     bool message_port)
710 {
711         u16 val;
712         int err;
713
714         err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL1, &val);
715         if (err)
716                 return err;
717
718         if (message_port)
719                 val |= MV88E6XXX_PORT_CTL1_MESSAGE_PORT;
720         else
721                 val &= ~MV88E6XXX_PORT_CTL1_MESSAGE_PORT;
722
723         return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL1, val);
724 }
725
726 /* Offset 0x06: Port Based VLAN Map */
727
728 int mv88e6xxx_port_set_vlan_map(struct mv88e6xxx_chip *chip, int port, u16 map)
729 {
730         const u16 mask = mv88e6xxx_port_mask(chip);
731         u16 reg;
732         int err;
733
734         err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_BASE_VLAN, &reg);
735         if (err)
736                 return err;
737
738         reg &= ~mask;
739         reg |= map & mask;
740
741         err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_BASE_VLAN, reg);
742         if (err)
743                 return err;
744
745         dev_dbg(chip->dev, "p%d: VLANTable set to %.3x\n", port, map);
746
747         return 0;
748 }
749
750 int 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 */
757         err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_BASE_VLAN, &reg);
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) {
765                 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL1,
766                                           &reg);
767                 if (err)
768                         return err;
769
770                 *fid |= (reg & upper_mask) << 4;
771         }
772
773         return 0;
774 }
775
776 int 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 */
786         err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_BASE_VLAN, &reg);
787         if (err)
788                 return err;
789
790         reg &= 0x0fff;
791         reg |= (fid & 0x000f) << 12;
792
793         err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_BASE_VLAN, reg);
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) {
799                 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL1,
800                                           &reg);
801                 if (err)
802                         return err;
803
804                 reg &= ~upper_mask;
805                 reg |= (fid >> 4) & upper_mask;
806
807                 err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL1,
808                                            reg);
809                 if (err)
810                         return err;
811         }
812
813         dev_dbg(chip->dev, "p%d: FID set to %u\n", port, fid);
814
815         return 0;
816 }
817
818 /* Offset 0x07: Default Port VLAN ID & Priority */
819
820 int mv88e6xxx_port_get_pvid(struct mv88e6xxx_chip *chip, int port, u16 *pvid)
821 {
822         u16 reg;
823         int err;
824
825         err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_DEFAULT_VLAN,
826                                   &reg);
827         if (err)
828                 return err;
829
830         *pvid = reg & MV88E6XXX_PORT_DEFAULT_VLAN_MASK;
831
832         return 0;
833 }
834
835 int mv88e6xxx_port_set_pvid(struct mv88e6xxx_chip *chip, int port, u16 pvid)
836 {
837         u16 reg;
838         int err;
839
840         err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_DEFAULT_VLAN,
841                                   &reg);
842         if (err)
843                 return err;
844
845         reg &= ~MV88E6XXX_PORT_DEFAULT_VLAN_MASK;
846         reg |= pvid & MV88E6XXX_PORT_DEFAULT_VLAN_MASK;
847
848         err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_DEFAULT_VLAN,
849                                    reg);
850         if (err)
851                 return err;
852
853         dev_dbg(chip->dev, "p%d: DefaultVID set to %u\n", port, pvid);
854
855         return 0;
856 }
857
858 /* Offset 0x08: Port Control 2 Register */
859
860 static const char * const mv88e6xxx_port_8021q_mode_names[] = {
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",
865 };
866
867 static int mv88e6185_port_set_default_forward(struct mv88e6xxx_chip *chip,
868                                               int port, bool multicast)
869 {
870         int err;
871         u16 reg;
872
873         err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, &reg);
874         if (err)
875                 return err;
876
877         if (multicast)
878                 reg |= MV88E6XXX_PORT_CTL2_DEFAULT_FORWARD;
879         else
880                 reg &= ~MV88E6XXX_PORT_CTL2_DEFAULT_FORWARD;
881
882         return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg);
883 }
884
885 int 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
897 int mv88e6095_port_set_upstream_port(struct mv88e6xxx_chip *chip, int port,
898                                      int upstream_port)
899 {
900         int err;
901         u16 reg;
902
903         err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, &reg);
904         if (err)
905                 return err;
906
907         reg &= ~MV88E6095_PORT_CTL2_CPU_PORT_MASK;
908         reg |= upstream_port;
909
910         return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg);
911 }
912
913 int mv88e6xxx_port_set_8021q_mode(struct mv88e6xxx_chip *chip, int port,
914                                   u16 mode)
915 {
916         u16 reg;
917         int err;
918
919         err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, &reg);
920         if (err)
921                 return err;
922
923         reg &= ~MV88E6XXX_PORT_CTL2_8021Q_MODE_MASK;
924         reg |= mode & MV88E6XXX_PORT_CTL2_8021Q_MODE_MASK;
925
926         err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg);
927         if (err)
928                 return err;
929
930         dev_dbg(chip->dev, "p%d: 802.1QMode set to %s\n", port,
931                 mv88e6xxx_port_8021q_mode_names[mode]);
932
933         return 0;
934 }
935
936 int mv88e6xxx_port_set_map_da(struct mv88e6xxx_chip *chip, int port)
937 {
938         u16 reg;
939         int err;
940
941         err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, &reg);
942         if (err)
943                 return err;
944
945         reg |= MV88E6XXX_PORT_CTL2_MAP_DA;
946
947         return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg);
948 }
949
950 int mv88e6165_port_set_jumbo_size(struct mv88e6xxx_chip *chip, int port,
951                                   size_t size)
952 {
953         u16 reg;
954         int err;
955
956         err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, &reg);
957         if (err)
958                 return err;
959
960         reg &= ~MV88E6XXX_PORT_CTL2_JUMBO_MODE_MASK;
961
962         if (size <= 1522)
963                 reg |= MV88E6XXX_PORT_CTL2_JUMBO_MODE_1522;
964         else if (size <= 2048)
965                 reg |= MV88E6XXX_PORT_CTL2_JUMBO_MODE_2048;
966         else if (size <= 10240)
967                 reg |= MV88E6XXX_PORT_CTL2_JUMBO_MODE_10240;
968         else
969                 return -ERANGE;
970
971         return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg);
972 }
973
974 /* Offset 0x09: Port Rate Control */
975
976 int mv88e6095_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port)
977 {
978         return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_EGRESS_RATE_CTL1,
979                                     0x0000);
980 }
981
982 int mv88e6097_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port)
983 {
984         return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_EGRESS_RATE_CTL1,
985                                     0x0001);
986 }
987
988 /* Offset 0x0C: Port ATU Control */
989
990 int mv88e6xxx_port_disable_learn_limit(struct mv88e6xxx_chip *chip, int port)
991 {
992         return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_ATU_CTL, 0);
993 }
994
995 /* Offset 0x0D: (Priority) Override Register */
996
997 int mv88e6xxx_port_disable_pri_override(struct mv88e6xxx_chip *chip, int port)
998 {
999         return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_PRI_OVERRIDE, 0);
1000 }
1001
1002 /* Offset 0x0f: Port Ether type */
1003
1004 int mv88e6351_port_set_ether_type(struct mv88e6xxx_chip *chip, int port,
1005                                   u16 etype)
1006 {
1007         return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_ETH_TYPE, etype);
1008 }
1009
1010 /* Offset 0x18: Port IEEE Priority Remapping Registers [0-3]
1011  * Offset 0x19: Port IEEE Priority Remapping Registers [4-7]
1012  */
1013
1014 int 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 */
1019         err = mv88e6xxx_port_write(chip, port,
1020                                    MV88E6095_PORT_IEEE_PRIO_REMAP_0123,
1021                                    0x3210);
1022         if (err)
1023                 return err;
1024
1025         return mv88e6xxx_port_write(chip, port,
1026                                     MV88E6095_PORT_IEEE_PRIO_REMAP_4567,
1027                                     0x7654);
1028 }
1029
1030 static int mv88e6xxx_port_ieeepmt_write(struct mv88e6xxx_chip *chip,
1031                                         int port, u16 table, u8 ptr, u16 data)
1032 {
1033         u16 reg;
1034
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);
1038
1039         return mv88e6xxx_port_write(chip, port,
1040                                     MV88E6390_PORT_IEEE_PRIO_MAP_TABLE, reg);
1041 }
1042
1043 int mv88e6390_port_tag_remap(struct mv88e6xxx_chip *chip, int port)
1044 {
1045         int err, i;
1046         u16 table;
1047
1048         for (i = 0; i <= 7; i++) {
1049                 table = MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_INGRESS_PCP;
1050                 err = mv88e6xxx_port_ieeepmt_write(chip, port, table, i,
1051                                                    (i | i << 4));
1052                 if (err)
1053                         return err;
1054
1055                 table = MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_GREEN_PCP;
1056                 err = mv88e6xxx_port_ieeepmt_write(chip, port, table, i, i);
1057                 if (err)
1058                         return err;
1059
1060                 table = MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_YELLOW_PCP;
1061                 err = mv88e6xxx_port_ieeepmt_write(chip, port, table, i, i);
1062                 if (err)
1063                         return err;
1064
1065                 table = MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_AVB_PCP;
1066                 err = mv88e6xxx_port_ieeepmt_write(chip, port, table, i, i);
1067                 if (err)
1068                         return err;
1069         }
1070
1071         return 0;
1072 }