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