GNU Linux-libre 4.9-gnu1
[releases.git] / drivers / net / dsa / mv88e6xxx / global2.c
1 /*
2  * Marvell 88E6xxx Switch Global 2 Registers support (device address 0x1C)
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 "global2.h"
16
17 #define ADDR_GLOBAL2    0x1c
18
19 static int mv88e6xxx_g2_read(struct mv88e6xxx_chip *chip, int reg, u16 *val)
20 {
21         return mv88e6xxx_read(chip, ADDR_GLOBAL2, reg, val);
22 }
23
24 static int mv88e6xxx_g2_write(struct mv88e6xxx_chip *chip, int reg, u16 val)
25 {
26         return mv88e6xxx_write(chip, ADDR_GLOBAL2, reg, val);
27 }
28
29 static int mv88e6xxx_g2_update(struct mv88e6xxx_chip *chip, int reg, u16 update)
30 {
31         return mv88e6xxx_update(chip, ADDR_GLOBAL2, reg, update);
32 }
33
34 static int mv88e6xxx_g2_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask)
35 {
36         return mv88e6xxx_wait(chip, ADDR_GLOBAL2, reg, mask);
37 }
38
39 /* Offset 0x06: Device Mapping Table register */
40
41 static int mv88e6xxx_g2_device_mapping_write(struct mv88e6xxx_chip *chip,
42                                              int target, int port)
43 {
44         u16 val = (target << 8) | (port & 0xf);
45
46         return mv88e6xxx_g2_update(chip, GLOBAL2_DEVICE_MAPPING, val);
47 }
48
49 static int mv88e6xxx_g2_set_device_mapping(struct mv88e6xxx_chip *chip)
50 {
51         int target, port;
52         int err;
53
54         /* Initialize the routing port to the 32 possible target devices */
55         for (target = 0; target < 32; ++target) {
56                 port = 0xf;
57
58                 if (target < DSA_MAX_SWITCHES) {
59                         port = chip->ds->rtable[target];
60                         if (port == DSA_RTABLE_NONE)
61                                 port = 0xf;
62                 }
63
64                 err = mv88e6xxx_g2_device_mapping_write(chip, target, port);
65                 if (err)
66                         break;
67         }
68
69         return err;
70 }
71
72 /* Offset 0x07: Trunk Mask Table register */
73
74 static int mv88e6xxx_g2_trunk_mask_write(struct mv88e6xxx_chip *chip, int num,
75                                          bool hask, u16 mask)
76 {
77         const u16 port_mask = BIT(mv88e6xxx_num_ports(chip)) - 1;
78         u16 val = (num << 12) | (mask & port_mask);
79
80         if (hask)
81                 val |= GLOBAL2_TRUNK_MASK_HASK;
82
83         return mv88e6xxx_g2_update(chip, GLOBAL2_TRUNK_MASK, val);
84 }
85
86 /* Offset 0x08: Trunk Mapping Table register */
87
88 static int mv88e6xxx_g2_trunk_mapping_write(struct mv88e6xxx_chip *chip, int id,
89                                             u16 map)
90 {
91         const u16 port_mask = BIT(mv88e6xxx_num_ports(chip)) - 1;
92         u16 val = (id << 11) | (map & port_mask);
93
94         return mv88e6xxx_g2_update(chip, GLOBAL2_TRUNK_MAPPING, val);
95 }
96
97 static int mv88e6xxx_g2_clear_trunk(struct mv88e6xxx_chip *chip)
98 {
99         const u16 port_mask = BIT(mv88e6xxx_num_ports(chip)) - 1;
100         int i, err;
101
102         /* Clear all eight possible Trunk Mask vectors */
103         for (i = 0; i < 8; ++i) {
104                 err = mv88e6xxx_g2_trunk_mask_write(chip, i, false, port_mask);
105                 if (err)
106                         return err;
107         }
108
109         /* Clear all sixteen possible Trunk ID routing vectors */
110         for (i = 0; i < 16; ++i) {
111                 err = mv88e6xxx_g2_trunk_mapping_write(chip, i, 0);
112                 if (err)
113                         return err;
114         }
115
116         return 0;
117 }
118
119 /* Offset 0x09: Ingress Rate Command register
120  * Offset 0x0A: Ingress Rate Data register
121  */
122
123 static int mv88e6xxx_g2_clear_irl(struct mv88e6xxx_chip *chip)
124 {
125         int port, err;
126
127         /* Init all Ingress Rate Limit resources of all ports */
128         for (port = 0; port < mv88e6xxx_num_ports(chip); ++port) {
129                 /* XXX newer chips (like 88E6390) have different 2-bit ops */
130                 err = mv88e6xxx_g2_write(chip, GLOBAL2_IRL_CMD,
131                                          GLOBAL2_IRL_CMD_OP_INIT_ALL |
132                                          (port << 8));
133                 if (err)
134                         break;
135
136                 /* Wait for the operation to complete */
137                 err = mv88e6xxx_g2_wait(chip, GLOBAL2_IRL_CMD,
138                                         GLOBAL2_IRL_CMD_BUSY);
139                 if (err)
140                         break;
141         }
142
143         return err;
144 }
145
146 /* Offset 0x0D: Switch MAC/WoL/WoF register */
147
148 static int mv88e6xxx_g2_switch_mac_write(struct mv88e6xxx_chip *chip,
149                                          unsigned int pointer, u8 data)
150 {
151         u16 val = (pointer << 8) | data;
152
153         return mv88e6xxx_g2_update(chip, GLOBAL2_SWITCH_MAC, val);
154 }
155
156 int mv88e6xxx_g2_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr)
157 {
158         int i, err;
159
160         for (i = 0; i < 6; i++) {
161                 err = mv88e6xxx_g2_switch_mac_write(chip, i, addr[i]);
162                 if (err)
163                         break;
164         }
165
166         return err;
167 }
168
169 /* Offset 0x0F: Priority Override Table */
170
171 static int mv88e6xxx_g2_pot_write(struct mv88e6xxx_chip *chip, int pointer,
172                                   u8 data)
173 {
174         u16 val = (pointer << 8) | (data & 0x7);
175
176         return mv88e6xxx_g2_update(chip, GLOBAL2_PRIO_OVERRIDE, val);
177 }
178
179 static int mv88e6xxx_g2_clear_pot(struct mv88e6xxx_chip *chip)
180 {
181         int i, err;
182
183         /* Clear all sixteen possible Priority Override entries */
184         for (i = 0; i < 16; i++) {
185                 err = mv88e6xxx_g2_pot_write(chip, i, 0);
186                 if (err)
187                         break;
188         }
189
190         return err;
191 }
192
193 /* Offset 0x14: EEPROM Command
194  * Offset 0x15: EEPROM Data
195  */
196
197 static int mv88e6xxx_g2_eeprom_wait(struct mv88e6xxx_chip *chip)
198 {
199         return mv88e6xxx_g2_wait(chip, GLOBAL2_EEPROM_CMD,
200                                  GLOBAL2_EEPROM_CMD_BUSY |
201                                  GLOBAL2_EEPROM_CMD_RUNNING);
202 }
203
204 static int mv88e6xxx_g2_eeprom_cmd(struct mv88e6xxx_chip *chip, u16 cmd)
205 {
206         int err;
207
208         err = mv88e6xxx_g2_write(chip, GLOBAL2_EEPROM_CMD, cmd);
209         if (err)
210                 return err;
211
212         return mv88e6xxx_g2_eeprom_wait(chip);
213 }
214
215 static int mv88e6xxx_g2_eeprom_read16(struct mv88e6xxx_chip *chip,
216                                       u8 addr, u16 *data)
217 {
218         u16 cmd = GLOBAL2_EEPROM_CMD_OP_READ | addr;
219         int err;
220
221         err = mv88e6xxx_g2_eeprom_wait(chip);
222         if (err)
223                 return err;
224
225         err = mv88e6xxx_g2_eeprom_cmd(chip, cmd);
226         if (err)
227                 return err;
228
229         return mv88e6xxx_g2_read(chip, GLOBAL2_EEPROM_DATA, data);
230 }
231
232 static int mv88e6xxx_g2_eeprom_write16(struct mv88e6xxx_chip *chip,
233                                        u8 addr, u16 data)
234 {
235         u16 cmd = GLOBAL2_EEPROM_CMD_OP_WRITE | addr;
236         int err;
237
238         err = mv88e6xxx_g2_eeprom_wait(chip);
239         if (err)
240                 return err;
241
242         err = mv88e6xxx_g2_write(chip, GLOBAL2_EEPROM_DATA, data);
243         if (err)
244                 return err;
245
246         return mv88e6xxx_g2_eeprom_cmd(chip, cmd);
247 }
248
249 int mv88e6xxx_g2_get_eeprom16(struct mv88e6xxx_chip *chip,
250                               struct ethtool_eeprom *eeprom, u8 *data)
251 {
252         unsigned int offset = eeprom->offset;
253         unsigned int len = eeprom->len;
254         u16 val;
255         int err;
256
257         eeprom->len = 0;
258
259         if (offset & 1) {
260                 err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val);
261                 if (err)
262                         return err;
263
264                 *data++ = (val >> 8) & 0xff;
265
266                 offset++;
267                 len--;
268                 eeprom->len++;
269         }
270
271         while (len >= 2) {
272                 err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val);
273                 if (err)
274                         return err;
275
276                 *data++ = val & 0xff;
277                 *data++ = (val >> 8) & 0xff;
278
279                 offset += 2;
280                 len -= 2;
281                 eeprom->len += 2;
282         }
283
284         if (len) {
285                 err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val);
286                 if (err)
287                         return err;
288
289                 *data++ = val & 0xff;
290
291                 offset++;
292                 len--;
293                 eeprom->len++;
294         }
295
296         return 0;
297 }
298
299 int mv88e6xxx_g2_set_eeprom16(struct mv88e6xxx_chip *chip,
300                               struct ethtool_eeprom *eeprom, u8 *data)
301 {
302         unsigned int offset = eeprom->offset;
303         unsigned int len = eeprom->len;
304         u16 val;
305         int err;
306
307         /* Ensure the RO WriteEn bit is set */
308         err = mv88e6xxx_g2_read(chip, GLOBAL2_EEPROM_CMD, &val);
309         if (err)
310                 return err;
311
312         if (!(val & GLOBAL2_EEPROM_CMD_WRITE_EN))
313                 return -EROFS;
314
315         eeprom->len = 0;
316
317         if (offset & 1) {
318                 err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val);
319                 if (err)
320                         return err;
321
322                 val = (*data++ << 8) | (val & 0xff);
323
324                 err = mv88e6xxx_g2_eeprom_write16(chip, offset >> 1, val);
325                 if (err)
326                         return err;
327
328                 offset++;
329                 len--;
330                 eeprom->len++;
331         }
332
333         while (len >= 2) {
334                 val = *data++;
335                 val |= *data++ << 8;
336
337                 err = mv88e6xxx_g2_eeprom_write16(chip, offset >> 1, val);
338                 if (err)
339                         return err;
340
341                 offset += 2;
342                 len -= 2;
343                 eeprom->len += 2;
344         }
345
346         if (len) {
347                 err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val);
348                 if (err)
349                         return err;
350
351                 val = (val & 0xff00) | *data++;
352
353                 err = mv88e6xxx_g2_eeprom_write16(chip, offset >> 1, val);
354                 if (err)
355                         return err;
356
357                 offset++;
358                 len--;
359                 eeprom->len++;
360         }
361
362         return 0;
363 }
364
365 /* Offset 0x18: SMI PHY Command Register
366  * Offset 0x19: SMI PHY Data Register
367  */
368
369 static int mv88e6xxx_g2_smi_phy_wait(struct mv88e6xxx_chip *chip)
370 {
371         return mv88e6xxx_g2_wait(chip, GLOBAL2_SMI_PHY_CMD,
372                                  GLOBAL2_SMI_PHY_CMD_BUSY);
373 }
374
375 static int mv88e6xxx_g2_smi_phy_cmd(struct mv88e6xxx_chip *chip, u16 cmd)
376 {
377         int err;
378
379         err = mv88e6xxx_g2_write(chip, GLOBAL2_SMI_PHY_CMD, cmd);
380         if (err)
381                 return err;
382
383         return mv88e6xxx_g2_smi_phy_wait(chip);
384 }
385
386 int mv88e6xxx_g2_smi_phy_read(struct mv88e6xxx_chip *chip, int addr, int reg,
387                               u16 *val)
388 {
389         u16 cmd = GLOBAL2_SMI_PHY_CMD_OP_22_READ_DATA | (addr << 5) | reg;
390         int err;
391
392         err = mv88e6xxx_g2_smi_phy_wait(chip);
393         if (err)
394                 return err;
395
396         err = mv88e6xxx_g2_smi_phy_cmd(chip, cmd);
397         if (err)
398                 return err;
399
400         return mv88e6xxx_g2_read(chip, GLOBAL2_SMI_PHY_DATA, val);
401 }
402
403 int mv88e6xxx_g2_smi_phy_write(struct mv88e6xxx_chip *chip, int addr, int reg,
404                                u16 val)
405 {
406         u16 cmd = GLOBAL2_SMI_PHY_CMD_OP_22_WRITE_DATA | (addr << 5) | reg;
407         int err;
408
409         err = mv88e6xxx_g2_smi_phy_wait(chip);
410         if (err)
411                 return err;
412
413         err = mv88e6xxx_g2_write(chip, GLOBAL2_SMI_PHY_DATA, val);
414         if (err)
415                 return err;
416
417         return mv88e6xxx_g2_smi_phy_cmd(chip, cmd);
418 }
419
420 int mv88e6xxx_g2_setup(struct mv88e6xxx_chip *chip)
421 {
422         u16 reg;
423         int err;
424
425         if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_2X)) {
426                 /* Consider the frames with reserved multicast destination
427                  * addresses matching 01:80:c2:00:00:2x as MGMT.
428                  */
429                 err = mv88e6xxx_g2_write(chip, GLOBAL2_MGMT_EN_2X, 0xffff);
430                 if (err)
431                         return err;
432         }
433
434         if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_0X)) {
435                 /* Consider the frames with reserved multicast destination
436                  * addresses matching 01:80:c2:00:00:0x as MGMT.
437                  */
438                 err = mv88e6xxx_g2_write(chip, GLOBAL2_MGMT_EN_0X, 0xffff);
439                 if (err)
440                         return err;
441         }
442
443         /* Ignore removed tag data on doubly tagged packets, disable
444          * flow control messages, force flow control priority to the
445          * highest, and send all special multicast frames to the CPU
446          * port at the highest priority.
447          */
448         reg = GLOBAL2_SWITCH_MGMT_FORCE_FLOW_CTRL_PRI | (0x7 << 4);
449         if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_0X) ||
450             mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_2X))
451                 reg |= GLOBAL2_SWITCH_MGMT_RSVD2CPU | 0x7;
452         err = mv88e6xxx_g2_write(chip, GLOBAL2_SWITCH_MGMT, reg);
453         if (err)
454                 return err;
455
456         /* Program the DSA routing table. */
457         err = mv88e6xxx_g2_set_device_mapping(chip);
458         if (err)
459                 return err;
460
461         /* Clear all trunk masks and mapping. */
462         err = mv88e6xxx_g2_clear_trunk(chip);
463         if (err)
464                 return err;
465
466         if (mv88e6xxx_has(chip, MV88E6XXX_FLAGS_IRL)) {
467                 /* Disable ingress rate limiting by resetting all per port
468                  * ingress rate limit resources to their initial state.
469                  */
470                 err = mv88e6xxx_g2_clear_irl(chip);
471                         if (err)
472                                 return err;
473         }
474
475         if (mv88e6xxx_has(chip, MV88E6XXX_FLAGS_PVT)) {
476                 /* Initialize Cross-chip Port VLAN Table to reset defaults */
477                 err = mv88e6xxx_g2_write(chip, GLOBAL2_PVT_ADDR,
478                                          GLOBAL2_PVT_ADDR_OP_INIT_ONES);
479                 if (err)
480                         return err;
481         }
482
483         if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_POT)) {
484                 /* Clear the priority override table. */
485                 err = mv88e6xxx_g2_clear_pot(chip);
486                 if (err)
487                         return err;
488         }
489
490         return 0;
491 }