e4978f6367aac351e8de67a779b72e930779c17e
[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 Vivien Didelot <vivien.didelot@savoirfairelinux.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  */
13
14 #include "mv88e6xxx.h"
15 #include "port.h"
16
17 int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port, int reg,
18                         u16 *val)
19 {
20         int addr = chip->info->port_base_addr + port;
21
22         return mv88e6xxx_read(chip, addr, reg, val);
23 }
24
25 int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg,
26                          u16 val)
27 {
28         int addr = chip->info->port_base_addr + port;
29
30         return mv88e6xxx_write(chip, addr, reg, val);
31 }
32
33 /* Offset 0x01: MAC (or PCS or Physical) Control Register
34  *
35  * Link, Duplex and Flow Control have one force bit, one value bit.
36  *
37  * For port's MAC speed, ForceSpd (or SpdValue) bits 1:0 program the value.
38  * Alternative values require the 200BASE (or AltSpeed) bit 12 set.
39  * Newer chips need a ForcedSpd bit 13 set to consider the value.
40  */
41
42 static int mv88e6xxx_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,
43                                           phy_interface_t mode)
44 {
45         u16 reg;
46         int err;
47
48         err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, &reg);
49         if (err)
50                 return err;
51
52         reg &= ~(PORT_PCS_CTRL_RGMII_DELAY_RXCLK |
53                  PORT_PCS_CTRL_RGMII_DELAY_TXCLK);
54
55         switch (mode) {
56         case PHY_INTERFACE_MODE_RGMII_RXID:
57                 reg |= PORT_PCS_CTRL_RGMII_DELAY_RXCLK;
58                 break;
59         case PHY_INTERFACE_MODE_RGMII_TXID:
60                 reg |= PORT_PCS_CTRL_RGMII_DELAY_TXCLK;
61                 break;
62         case PHY_INTERFACE_MODE_RGMII_ID:
63                 reg |= PORT_PCS_CTRL_RGMII_DELAY_RXCLK |
64                         PORT_PCS_CTRL_RGMII_DELAY_TXCLK;
65                 break;
66         case PHY_INTERFACE_MODE_RGMII:
67                 break;
68         default:
69                 return 0;
70         }
71
72         err = mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg);
73         if (err)
74                 return err;
75
76         netdev_dbg(chip->ds->ports[port].netdev, "delay RXCLK %s, TXCLK %s\n",
77                    reg & PORT_PCS_CTRL_RGMII_DELAY_RXCLK ? "yes" : "no",
78                    reg & PORT_PCS_CTRL_RGMII_DELAY_TXCLK ? "yes" : "no");
79
80         return 0;
81 }
82
83 int mv88e6352_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,
84                                    phy_interface_t mode)
85 {
86         if (port < 5)
87                 return -EOPNOTSUPP;
88
89         return mv88e6xxx_port_set_rgmii_delay(chip, port, mode);
90 }
91
92 int mv88e6390_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,
93                                    phy_interface_t mode)
94 {
95         if (port != 0)
96                 return -EOPNOTSUPP;
97
98         return mv88e6xxx_port_set_rgmii_delay(chip, port, mode);
99 }
100
101 int mv88e6xxx_port_set_link(struct mv88e6xxx_chip *chip, int port, int link)
102 {
103         u16 reg;
104         int err;
105
106         err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, &reg);
107         if (err)
108                 return err;
109
110         reg &= ~(PORT_PCS_CTRL_FORCE_LINK | PORT_PCS_CTRL_LINK_UP);
111
112         switch (link) {
113         case LINK_FORCED_DOWN:
114                 reg |= PORT_PCS_CTRL_FORCE_LINK;
115                 break;
116         case LINK_FORCED_UP:
117                 reg |= PORT_PCS_CTRL_FORCE_LINK | PORT_PCS_CTRL_LINK_UP;
118                 break;
119         case LINK_UNFORCED:
120                 /* normal link detection */
121                 break;
122         default:
123                 return -EINVAL;
124         }
125
126         err = mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg);
127         if (err)
128                 return err;
129
130         netdev_dbg(chip->ds->ports[port].netdev, "%s link %s\n",
131                    reg & PORT_PCS_CTRL_FORCE_LINK ? "Force" : "Unforce",
132                    reg & PORT_PCS_CTRL_LINK_UP ? "up" : "down");
133
134         return 0;
135 }
136
137 int mv88e6xxx_port_set_duplex(struct mv88e6xxx_chip *chip, int port, int dup)
138 {
139         u16 reg;
140         int err;
141
142         err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, &reg);
143         if (err)
144                 return err;
145
146         reg &= ~(PORT_PCS_CTRL_FORCE_DUPLEX | PORT_PCS_CTRL_DUPLEX_FULL);
147
148         switch (dup) {
149         case DUPLEX_HALF:
150                 reg |= PORT_PCS_CTRL_FORCE_DUPLEX;
151                 break;
152         case DUPLEX_FULL:
153                 reg |= PORT_PCS_CTRL_FORCE_DUPLEX | PORT_PCS_CTRL_DUPLEX_FULL;
154                 break;
155         case DUPLEX_UNFORCED:
156                 /* normal duplex detection */
157                 break;
158         default:
159                 return -EINVAL;
160         }
161
162         err = mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg);
163         if (err)
164                 return err;
165
166         netdev_dbg(chip->ds->ports[port].netdev, "%s %s duplex\n",
167                    reg & PORT_PCS_CTRL_FORCE_DUPLEX ? "Force" : "Unforce",
168                    reg & PORT_PCS_CTRL_DUPLEX_FULL ? "full" : "half");
169
170         return 0;
171 }
172
173 static int mv88e6xxx_port_set_speed(struct mv88e6xxx_chip *chip, int port,
174                                     int speed, bool alt_bit, bool force_bit)
175 {
176         u16 reg, ctrl;
177         int err;
178
179         switch (speed) {
180         case 10:
181                 ctrl = PORT_PCS_CTRL_SPEED_10;
182                 break;
183         case 100:
184                 ctrl = PORT_PCS_CTRL_SPEED_100;
185                 break;
186         case 200:
187                 if (alt_bit)
188                         ctrl = PORT_PCS_CTRL_SPEED_100 | PORT_PCS_CTRL_ALTSPEED;
189                 else
190                         ctrl = PORT_PCS_CTRL_SPEED_200;
191                 break;
192         case 1000:
193                 ctrl = PORT_PCS_CTRL_SPEED_1000;
194                 break;
195         case 2500:
196                 ctrl = PORT_PCS_CTRL_SPEED_1000 | PORT_PCS_CTRL_ALTSPEED;
197                 break;
198         case 10000:
199                 /* all bits set, fall through... */
200         case SPEED_UNFORCED:
201                 ctrl = PORT_PCS_CTRL_SPEED_UNFORCED;
202                 break;
203         default:
204                 return -EOPNOTSUPP;
205         }
206
207         err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, &reg);
208         if (err)
209                 return err;
210
211         reg &= ~PORT_PCS_CTRL_SPEED_MASK;
212         if (alt_bit)
213                 reg &= ~PORT_PCS_CTRL_ALTSPEED;
214         if (force_bit) {
215                 reg &= ~PORT_PCS_CTRL_FORCE_SPEED;
216                 if (speed)
217                         ctrl |= PORT_PCS_CTRL_FORCE_SPEED;
218         }
219         reg |= ctrl;
220
221         err = mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg);
222         if (err)
223                 return err;
224
225         if (speed)
226                 netdev_dbg(chip->ds->ports[port].netdev,
227                            "Speed set to %d Mbps\n", speed);
228         else
229                 netdev_dbg(chip->ds->ports[port].netdev, "Speed unforced\n");
230
231         return 0;
232 }
233
234 /* Support 10, 100, 200 Mbps (e.g. 88E6065 family) */
235 int mv88e6065_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
236 {
237         if (speed == SPEED_MAX)
238                 speed = 200;
239
240         if (speed > 200)
241                 return -EOPNOTSUPP;
242
243         /* Setting 200 Mbps on port 0 to 3 selects 100 Mbps */
244         return mv88e6xxx_port_set_speed(chip, port, speed, false, false);
245 }
246
247 /* Support 10, 100, 1000 Mbps (e.g. 88E6185 family) */
248 int mv88e6185_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
249 {
250         if (speed == SPEED_MAX)
251                 speed = 1000;
252
253         if (speed == 200 || speed > 1000)
254                 return -EOPNOTSUPP;
255
256         return mv88e6xxx_port_set_speed(chip, port, speed, false, false);
257 }
258
259 /* Support 10, 100, 200, 1000 Mbps (e.g. 88E6352 family) */
260 int mv88e6352_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
261 {
262         if (speed == SPEED_MAX)
263                 speed = 1000;
264
265         if (speed > 1000)
266                 return -EOPNOTSUPP;
267
268         if (speed == 200 && port < 5)
269                 return -EOPNOTSUPP;
270
271         return mv88e6xxx_port_set_speed(chip, port, speed, true, false);
272 }
273
274 /* Support 10, 100, 200, 1000, 2500 Mbps (e.g. 88E6390) */
275 int mv88e6390_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
276 {
277         if (speed == SPEED_MAX)
278                 speed = port < 9 ? 1000 : 2500;
279
280         if (speed > 2500)
281                 return -EOPNOTSUPP;
282
283         if (speed == 200 && port != 0)
284                 return -EOPNOTSUPP;
285
286         if (speed == 2500 && port < 9)
287                 return -EOPNOTSUPP;
288
289         return mv88e6xxx_port_set_speed(chip, port, speed, true, true);
290 }
291
292 /* Support 10, 100, 200, 1000, 2500, 10000 Mbps (e.g. 88E6190X) */
293 int mv88e6390x_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
294 {
295         if (speed == SPEED_MAX)
296                 speed = port < 9 ? 1000 : 10000;
297
298         if (speed == 200 && port != 0)
299                 return -EOPNOTSUPP;
300
301         if (speed >= 2500 && port < 9)
302                 return -EOPNOTSUPP;
303
304         return mv88e6xxx_port_set_speed(chip, port, speed, true, true);
305 }
306
307 /* Offset 0x04: Port Control Register */
308
309 static const char * const mv88e6xxx_port_state_names[] = {
310         [PORT_CONTROL_STATE_DISABLED] = "Disabled",
311         [PORT_CONTROL_STATE_BLOCKING] = "Blocking/Listening",
312         [PORT_CONTROL_STATE_LEARNING] = "Learning",
313         [PORT_CONTROL_STATE_FORWARDING] = "Forwarding",
314 };
315
316 int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state)
317 {
318         u16 reg;
319         int err;
320
321         err = mv88e6xxx_port_read(chip, port, PORT_CONTROL, &reg);
322         if (err)
323                 return err;
324
325         reg &= ~PORT_CONTROL_STATE_MASK;
326         reg |= state;
327
328         err = mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
329         if (err)
330                 return err;
331
332         netdev_dbg(chip->ds->ports[port].netdev, "PortState set to %s\n",
333                    mv88e6xxx_port_state_names[state]);
334
335         return 0;
336 }
337
338 /* Offset 0x05: Port Control 1 */
339
340 /* Offset 0x06: Port Based VLAN Map */
341
342 int mv88e6xxx_port_set_vlan_map(struct mv88e6xxx_chip *chip, int port, u16 map)
343 {
344         const u16 mask = GENMASK(mv88e6xxx_num_ports(chip) - 1, 0);
345         u16 reg;
346         int err;
347
348         err = mv88e6xxx_port_read(chip, port, PORT_BASE_VLAN, &reg);
349         if (err)
350                 return err;
351
352         reg &= ~mask;
353         reg |= map & mask;
354
355         err = mv88e6xxx_port_write(chip, port, PORT_BASE_VLAN, reg);
356         if (err)
357                 return err;
358
359         netdev_dbg(chip->ds->ports[port].netdev, "VLANTable set to %.3x\n",
360                    map);
361
362         return 0;
363 }
364
365 int mv88e6xxx_port_get_fid(struct mv88e6xxx_chip *chip, int port, u16 *fid)
366 {
367         const u16 upper_mask = (mv88e6xxx_num_databases(chip) - 1) >> 4;
368         u16 reg;
369         int err;
370
371         /* Port's default FID lower 4 bits are located in reg 0x06, offset 12 */
372         err = mv88e6xxx_port_read(chip, port, PORT_BASE_VLAN, &reg);
373         if (err)
374                 return err;
375
376         *fid = (reg & 0xf000) >> 12;
377
378         /* Port's default FID upper bits are located in reg 0x05, offset 0 */
379         if (upper_mask) {
380                 err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_1, &reg);
381                 if (err)
382                         return err;
383
384                 *fid |= (reg & upper_mask) << 4;
385         }
386
387         return 0;
388 }
389
390 int mv88e6xxx_port_set_fid(struct mv88e6xxx_chip *chip, int port, u16 fid)
391 {
392         const u16 upper_mask = (mv88e6xxx_num_databases(chip) - 1) >> 4;
393         u16 reg;
394         int err;
395
396         if (fid >= mv88e6xxx_num_databases(chip))
397                 return -EINVAL;
398
399         /* Port's default FID lower 4 bits are located in reg 0x06, offset 12 */
400         err = mv88e6xxx_port_read(chip, port, PORT_BASE_VLAN, &reg);
401         if (err)
402                 return err;
403
404         reg &= 0x0fff;
405         reg |= (fid & 0x000f) << 12;
406
407         err = mv88e6xxx_port_write(chip, port, PORT_BASE_VLAN, reg);
408         if (err)
409                 return err;
410
411         /* Port's default FID upper bits are located in reg 0x05, offset 0 */
412         if (upper_mask) {
413                 err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_1, &reg);
414                 if (err)
415                         return err;
416
417                 reg &= ~upper_mask;
418                 reg |= (fid >> 4) & upper_mask;
419
420                 err = mv88e6xxx_port_write(chip, port, PORT_CONTROL_1, reg);
421                 if (err)
422                         return err;
423         }
424
425         netdev_dbg(chip->ds->ports[port].netdev, "FID set to %u\n", fid);
426
427         return 0;
428 }
429
430 /* Offset 0x07: Default Port VLAN ID & Priority */
431
432 int mv88e6xxx_port_get_pvid(struct mv88e6xxx_chip *chip, int port, u16 *pvid)
433 {
434         u16 reg;
435         int err;
436
437         err = mv88e6xxx_port_read(chip, port, PORT_DEFAULT_VLAN, &reg);
438         if (err)
439                 return err;
440
441         *pvid = reg & PORT_DEFAULT_VLAN_MASK;
442
443         return 0;
444 }
445
446 int mv88e6xxx_port_set_pvid(struct mv88e6xxx_chip *chip, int port, u16 pvid)
447 {
448         u16 reg;
449         int err;
450
451         err = mv88e6xxx_port_read(chip, port, PORT_DEFAULT_VLAN, &reg);
452         if (err)
453                 return err;
454
455         reg &= ~PORT_DEFAULT_VLAN_MASK;
456         reg |= pvid & PORT_DEFAULT_VLAN_MASK;
457
458         err = mv88e6xxx_port_write(chip, port, PORT_DEFAULT_VLAN, reg);
459         if (err)
460                 return err;
461
462         netdev_dbg(chip->ds->ports[port].netdev, "DefaultVID set to %u\n",
463                    pvid);
464
465         return 0;
466 }
467
468 /* Offset 0x08: Port Control 2 Register */
469
470 static const char * const mv88e6xxx_port_8021q_mode_names[] = {
471         [PORT_CONTROL_2_8021Q_DISABLED] = "Disabled",
472         [PORT_CONTROL_2_8021Q_FALLBACK] = "Fallback",
473         [PORT_CONTROL_2_8021Q_CHECK] = "Check",
474         [PORT_CONTROL_2_8021Q_SECURE] = "Secure",
475 };
476
477 int mv88e6xxx_port_set_8021q_mode(struct mv88e6xxx_chip *chip, int port,
478                                   u16 mode)
479 {
480         u16 reg;
481         int err;
482
483         err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_2, &reg);
484         if (err)
485                 return err;
486
487         reg &= ~PORT_CONTROL_2_8021Q_MASK;
488         reg |= mode & PORT_CONTROL_2_8021Q_MASK;
489
490         err = mv88e6xxx_port_write(chip, port, PORT_CONTROL_2, reg);
491         if (err)
492                 return err;
493
494         netdev_dbg(chip->ds->ports[port].netdev, "802.1QMode set to %s\n",
495                    mv88e6xxx_port_8021q_mode_names[mode]);
496
497         return 0;
498 }