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 }
492