xref: /linux/drivers/net/dsa/mv88e6xxx/global1_vtu.c (revision e9a83bd2322035ed9d7dcf35753d3f984d76c6a5)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Marvell 88E6xxx VLAN [Spanning Tree] Translation Unit (VTU [STU]) support
4  *
5  * Copyright (c) 2008 Marvell Semiconductor
6  * Copyright (c) 2015 CMC Electronics, Inc.
7  * Copyright (c) 2017 Savoir-faire Linux, Inc.
8  */
9 
10 #include <linux/interrupt.h>
11 #include <linux/irqdomain.h>
12 
13 #include "chip.h"
14 #include "global1.h"
15 
16 /* Offset 0x02: VTU FID Register */
17 
18 static int mv88e6xxx_g1_vtu_fid_read(struct mv88e6xxx_chip *chip,
19 				     struct mv88e6xxx_vtu_entry *entry)
20 {
21 	u16 val;
22 	int err;
23 
24 	err = mv88e6xxx_g1_read(chip, MV88E6352_G1_VTU_FID, &val);
25 	if (err)
26 		return err;
27 
28 	entry->fid = val & MV88E6352_G1_VTU_FID_MASK;
29 
30 	return 0;
31 }
32 
33 static int mv88e6xxx_g1_vtu_fid_write(struct mv88e6xxx_chip *chip,
34 				      struct mv88e6xxx_vtu_entry *entry)
35 {
36 	u16 val = entry->fid & MV88E6352_G1_VTU_FID_MASK;
37 
38 	return mv88e6xxx_g1_write(chip, MV88E6352_G1_VTU_FID, val);
39 }
40 
41 /* Offset 0x03: VTU SID Register */
42 
43 static int mv88e6xxx_g1_vtu_sid_read(struct mv88e6xxx_chip *chip,
44 				     struct mv88e6xxx_vtu_entry *entry)
45 {
46 	u16 val;
47 	int err;
48 
49 	err = mv88e6xxx_g1_read(chip, MV88E6352_G1_VTU_SID, &val);
50 	if (err)
51 		return err;
52 
53 	entry->sid = val & MV88E6352_G1_VTU_SID_MASK;
54 
55 	return 0;
56 }
57 
58 static int mv88e6xxx_g1_vtu_sid_write(struct mv88e6xxx_chip *chip,
59 				      struct mv88e6xxx_vtu_entry *entry)
60 {
61 	u16 val = entry->sid & MV88E6352_G1_VTU_SID_MASK;
62 
63 	return mv88e6xxx_g1_write(chip, MV88E6352_G1_VTU_SID, val);
64 }
65 
66 /* Offset 0x05: VTU Operation Register */
67 
68 static int mv88e6xxx_g1_vtu_op_wait(struct mv88e6xxx_chip *chip)
69 {
70 	return mv88e6xxx_g1_wait(chip, MV88E6XXX_G1_VTU_OP,
71 				 MV88E6XXX_G1_VTU_OP_BUSY);
72 }
73 
74 static int mv88e6xxx_g1_vtu_op(struct mv88e6xxx_chip *chip, u16 op)
75 {
76 	int err;
77 
78 	err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_OP,
79 				 MV88E6XXX_G1_VTU_OP_BUSY | op);
80 	if (err)
81 		return err;
82 
83 	return mv88e6xxx_g1_vtu_op_wait(chip);
84 }
85 
86 /* Offset 0x06: VTU VID Register */
87 
88 static int mv88e6xxx_g1_vtu_vid_read(struct mv88e6xxx_chip *chip,
89 				     struct mv88e6xxx_vtu_entry *entry)
90 {
91 	u16 val;
92 	int err;
93 
94 	err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_VID, &val);
95 	if (err)
96 		return err;
97 
98 	entry->vid = val & 0xfff;
99 
100 	if (val & MV88E6390_G1_VTU_VID_PAGE)
101 		entry->vid |= 0x1000;
102 
103 	entry->valid = !!(val & MV88E6XXX_G1_VTU_VID_VALID);
104 
105 	return 0;
106 }
107 
108 static int mv88e6xxx_g1_vtu_vid_write(struct mv88e6xxx_chip *chip,
109 				      struct mv88e6xxx_vtu_entry *entry)
110 {
111 	u16 val = entry->vid & 0xfff;
112 
113 	if (entry->vid & 0x1000)
114 		val |= MV88E6390_G1_VTU_VID_PAGE;
115 
116 	if (entry->valid)
117 		val |= MV88E6XXX_G1_VTU_VID_VALID;
118 
119 	return mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_VID, val);
120 }
121 
122 /* Offset 0x07: VTU/STU Data Register 1
123  * Offset 0x08: VTU/STU Data Register 2
124  * Offset 0x09: VTU/STU Data Register 3
125  */
126 
127 static int mv88e6185_g1_vtu_data_read(struct mv88e6xxx_chip *chip,
128 				      struct mv88e6xxx_vtu_entry *entry)
129 {
130 	u16 regs[3];
131 	int i;
132 
133 	/* Read all 3 VTU/STU Data registers */
134 	for (i = 0; i < 3; ++i) {
135 		u16 *reg = &regs[i];
136 		int err;
137 
138 		err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
139 		if (err)
140 			return err;
141 	}
142 
143 	/* Extract MemberTag and PortState data */
144 	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
145 		unsigned int member_offset = (i % 4) * 4;
146 		unsigned int state_offset = member_offset + 2;
147 
148 		entry->member[i] = (regs[i / 4] >> member_offset) & 0x3;
149 		entry->state[i] = (regs[i / 4] >> state_offset) & 0x3;
150 	}
151 
152 	return 0;
153 }
154 
155 static int mv88e6185_g1_vtu_data_write(struct mv88e6xxx_chip *chip,
156 				       struct mv88e6xxx_vtu_entry *entry)
157 {
158 	u16 regs[3] = { 0 };
159 	int i;
160 
161 	/* Insert MemberTag and PortState data */
162 	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
163 		unsigned int member_offset = (i % 4) * 4;
164 		unsigned int state_offset = member_offset + 2;
165 
166 		regs[i / 4] |= (entry->member[i] & 0x3) << member_offset;
167 		regs[i / 4] |= (entry->state[i] & 0x3) << state_offset;
168 	}
169 
170 	/* Write all 3 VTU/STU Data registers */
171 	for (i = 0; i < 3; ++i) {
172 		u16 reg = regs[i];
173 		int err;
174 
175 		err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
176 		if (err)
177 			return err;
178 	}
179 
180 	return 0;
181 }
182 
183 static int mv88e6390_g1_vtu_data_read(struct mv88e6xxx_chip *chip, u8 *data)
184 {
185 	u16 regs[2];
186 	int i;
187 
188 	/* Read the 2 VTU/STU Data registers */
189 	for (i = 0; i < 2; ++i) {
190 		u16 *reg = &regs[i];
191 		int err;
192 
193 		err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
194 		if (err)
195 			return err;
196 	}
197 
198 	/* Extract data */
199 	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
200 		unsigned int offset = (i % 8) * 2;
201 
202 		data[i] = (regs[i / 8] >> offset) & 0x3;
203 	}
204 
205 	return 0;
206 }
207 
208 static int mv88e6390_g1_vtu_data_write(struct mv88e6xxx_chip *chip, u8 *data)
209 {
210 	u16 regs[2] = { 0 };
211 	int i;
212 
213 	/* Insert data */
214 	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
215 		unsigned int offset = (i % 8) * 2;
216 
217 		regs[i / 8] |= (data[i] & 0x3) << offset;
218 	}
219 
220 	/* Write the 2 VTU/STU Data registers */
221 	for (i = 0; i < 2; ++i) {
222 		u16 reg = regs[i];
223 		int err;
224 
225 		err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
226 		if (err)
227 			return err;
228 	}
229 
230 	return 0;
231 }
232 
233 /* VLAN Translation Unit Operations */
234 
235 static int mv88e6xxx_g1_vtu_stu_getnext(struct mv88e6xxx_chip *chip,
236 					struct mv88e6xxx_vtu_entry *entry)
237 {
238 	int err;
239 
240 	err = mv88e6xxx_g1_vtu_sid_write(chip, entry);
241 	if (err)
242 		return err;
243 
244 	err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_STU_GET_NEXT);
245 	if (err)
246 		return err;
247 
248 	err = mv88e6xxx_g1_vtu_sid_read(chip, entry);
249 	if (err)
250 		return err;
251 
252 	return mv88e6xxx_g1_vtu_vid_read(chip, entry);
253 }
254 
255 static int mv88e6xxx_g1_vtu_stu_get(struct mv88e6xxx_chip *chip,
256 				    struct mv88e6xxx_vtu_entry *vtu)
257 {
258 	struct mv88e6xxx_vtu_entry stu;
259 	int err;
260 
261 	err = mv88e6xxx_g1_vtu_sid_read(chip, vtu);
262 	if (err)
263 		return err;
264 
265 	stu.sid = vtu->sid - 1;
266 
267 	err = mv88e6xxx_g1_vtu_stu_getnext(chip, &stu);
268 	if (err)
269 		return err;
270 
271 	if (stu.sid != vtu->sid || !stu.valid)
272 		return -EINVAL;
273 
274 	return 0;
275 }
276 
277 static int mv88e6xxx_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
278 				    struct mv88e6xxx_vtu_entry *entry)
279 {
280 	int err;
281 
282 	err = mv88e6xxx_g1_vtu_op_wait(chip);
283 	if (err)
284 		return err;
285 
286 	/* To get the next higher active VID, the VTU GetNext operation can be
287 	 * started again without setting the VID registers since it already
288 	 * contains the last VID.
289 	 *
290 	 * To save a few hardware accesses and abstract this to the caller,
291 	 * write the VID only once, when the entry is given as invalid.
292 	 */
293 	if (!entry->valid) {
294 		err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
295 		if (err)
296 			return err;
297 	}
298 
299 	err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_GET_NEXT);
300 	if (err)
301 		return err;
302 
303 	return mv88e6xxx_g1_vtu_vid_read(chip, entry);
304 }
305 
306 int mv88e6185_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
307 			     struct mv88e6xxx_vtu_entry *entry)
308 {
309 	u16 val;
310 	int err;
311 
312 	err = mv88e6xxx_g1_vtu_getnext(chip, entry);
313 	if (err)
314 		return err;
315 
316 	if (entry->valid) {
317 		err = mv88e6185_g1_vtu_data_read(chip, entry);
318 		if (err)
319 			return err;
320 
321 		/* VTU DBNum[3:0] are located in VTU Operation 3:0
322 		 * VTU DBNum[7:4] are located in VTU Operation 11:8
323 		 */
324 		err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val);
325 		if (err)
326 			return err;
327 
328 		entry->fid = val & 0x000f;
329 		entry->fid |= (val & 0x0f00) >> 4;
330 	}
331 
332 	return 0;
333 }
334 
335 int mv88e6352_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
336 			     struct mv88e6xxx_vtu_entry *entry)
337 {
338 	int err;
339 
340 	/* Fetch VLAN MemberTag data from the VTU */
341 	err = mv88e6xxx_g1_vtu_getnext(chip, entry);
342 	if (err)
343 		return err;
344 
345 	if (entry->valid) {
346 		/* Fetch (and mask) VLAN PortState data from the STU */
347 		err = mv88e6xxx_g1_vtu_stu_get(chip, entry);
348 		if (err)
349 			return err;
350 
351 		err = mv88e6185_g1_vtu_data_read(chip, entry);
352 		if (err)
353 			return err;
354 
355 		err = mv88e6xxx_g1_vtu_fid_read(chip, entry);
356 		if (err)
357 			return err;
358 	}
359 
360 	return 0;
361 }
362 
363 int mv88e6390_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
364 			     struct mv88e6xxx_vtu_entry *entry)
365 {
366 	int err;
367 
368 	/* Fetch VLAN MemberTag data from the VTU */
369 	err = mv88e6xxx_g1_vtu_getnext(chip, entry);
370 	if (err)
371 		return err;
372 
373 	if (entry->valid) {
374 		err = mv88e6390_g1_vtu_data_read(chip, entry->member);
375 		if (err)
376 			return err;
377 
378 		/* Fetch VLAN PortState data from the STU */
379 		err = mv88e6xxx_g1_vtu_stu_get(chip, entry);
380 		if (err)
381 			return err;
382 
383 		err = mv88e6390_g1_vtu_data_read(chip, entry->state);
384 		if (err)
385 			return err;
386 
387 		err = mv88e6xxx_g1_vtu_fid_read(chip, entry);
388 		if (err)
389 			return err;
390 	}
391 
392 	return 0;
393 }
394 
395 int mv88e6185_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
396 			       struct mv88e6xxx_vtu_entry *entry)
397 {
398 	u16 op = MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE;
399 	int err;
400 
401 	err = mv88e6xxx_g1_vtu_op_wait(chip);
402 	if (err)
403 		return err;
404 
405 	err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
406 	if (err)
407 		return err;
408 
409 	if (entry->valid) {
410 		err = mv88e6185_g1_vtu_data_write(chip, entry);
411 		if (err)
412 			return err;
413 
414 		/* VTU DBNum[3:0] are located in VTU Operation 3:0
415 		 * VTU DBNum[7:4] are located in VTU Operation 11:8
416 		 */
417 		op |= entry->fid & 0x000f;
418 		op |= (entry->fid & 0x00f0) << 4;
419 	}
420 
421 	return mv88e6xxx_g1_vtu_op(chip, op);
422 }
423 
424 int mv88e6352_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
425 			       struct mv88e6xxx_vtu_entry *entry)
426 {
427 	int err;
428 
429 	err = mv88e6xxx_g1_vtu_op_wait(chip);
430 	if (err)
431 		return err;
432 
433 	err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
434 	if (err)
435 		return err;
436 
437 	if (entry->valid) {
438 		/* Write MemberTag and PortState data */
439 		err = mv88e6185_g1_vtu_data_write(chip, entry);
440 		if (err)
441 			return err;
442 
443 		err = mv88e6xxx_g1_vtu_sid_write(chip, entry);
444 		if (err)
445 			return err;
446 
447 		/* Load STU entry */
448 		err = mv88e6xxx_g1_vtu_op(chip,
449 					  MV88E6XXX_G1_VTU_OP_STU_LOAD_PURGE);
450 		if (err)
451 			return err;
452 
453 		err = mv88e6xxx_g1_vtu_fid_write(chip, entry);
454 		if (err)
455 			return err;
456 	}
457 
458 	/* Load/Purge VTU entry */
459 	return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE);
460 }
461 
462 int mv88e6390_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
463 			       struct mv88e6xxx_vtu_entry *entry)
464 {
465 	int err;
466 
467 	err = mv88e6xxx_g1_vtu_op_wait(chip);
468 	if (err)
469 		return err;
470 
471 	err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
472 	if (err)
473 		return err;
474 
475 	if (entry->valid) {
476 		/* Write PortState data */
477 		err = mv88e6390_g1_vtu_data_write(chip, entry->state);
478 		if (err)
479 			return err;
480 
481 		err = mv88e6xxx_g1_vtu_sid_write(chip, entry);
482 		if (err)
483 			return err;
484 
485 		/* Load STU entry */
486 		err = mv88e6xxx_g1_vtu_op(chip,
487 					  MV88E6XXX_G1_VTU_OP_STU_LOAD_PURGE);
488 		if (err)
489 			return err;
490 
491 		/* Write MemberTag data */
492 		err = mv88e6390_g1_vtu_data_write(chip, entry->member);
493 		if (err)
494 			return err;
495 
496 		err = mv88e6xxx_g1_vtu_fid_write(chip, entry);
497 		if (err)
498 			return err;
499 	}
500 
501 	/* Load/Purge VTU entry */
502 	return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE);
503 }
504 
505 int mv88e6xxx_g1_vtu_flush(struct mv88e6xxx_chip *chip)
506 {
507 	int err;
508 
509 	err = mv88e6xxx_g1_vtu_op_wait(chip);
510 	if (err)
511 		return err;
512 
513 	return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_FLUSH_ALL);
514 }
515 
516 static irqreturn_t mv88e6xxx_g1_vtu_prob_irq_thread_fn(int irq, void *dev_id)
517 {
518 	struct mv88e6xxx_chip *chip = dev_id;
519 	struct mv88e6xxx_vtu_entry entry;
520 	int spid;
521 	int err;
522 	u16 val;
523 
524 	mutex_lock(&chip->reg_lock);
525 
526 	err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_GET_CLR_VIOLATION);
527 	if (err)
528 		goto out;
529 
530 	err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val);
531 	if (err)
532 		goto out;
533 
534 	err = mv88e6xxx_g1_vtu_vid_read(chip, &entry);
535 	if (err)
536 		goto out;
537 
538 	spid = val & MV88E6XXX_G1_VTU_OP_SPID_MASK;
539 
540 	if (val & MV88E6XXX_G1_VTU_OP_MEMBER_VIOLATION) {
541 		dev_err_ratelimited(chip->dev, "VTU member violation for vid %d, source port %d\n",
542 				    entry.vid, spid);
543 		chip->ports[spid].vtu_member_violation++;
544 	}
545 
546 	if (val & MV88E6XXX_G1_VTU_OP_MISS_VIOLATION) {
547 		dev_dbg_ratelimited(chip->dev, "VTU miss violation for vid %d, source port %d\n",
548 				    entry.vid, spid);
549 		chip->ports[spid].vtu_miss_violation++;
550 	}
551 
552 	mutex_unlock(&chip->reg_lock);
553 
554 	return IRQ_HANDLED;
555 
556 out:
557 	mutex_unlock(&chip->reg_lock);
558 
559 	dev_err(chip->dev, "VTU problem: error %d while handling interrupt\n",
560 		err);
561 
562 	return IRQ_HANDLED;
563 }
564 
565 int mv88e6xxx_g1_vtu_prob_irq_setup(struct mv88e6xxx_chip *chip)
566 {
567 	int err;
568 
569 	chip->vtu_prob_irq = irq_find_mapping(chip->g1_irq.domain,
570 					      MV88E6XXX_G1_STS_IRQ_VTU_PROB);
571 	if (chip->vtu_prob_irq < 0)
572 		return chip->vtu_prob_irq;
573 
574 	err = request_threaded_irq(chip->vtu_prob_irq, NULL,
575 				   mv88e6xxx_g1_vtu_prob_irq_thread_fn,
576 				   IRQF_ONESHOT, "mv88e6xxx-g1-vtu-prob",
577 				   chip);
578 	if (err)
579 		irq_dispose_mapping(chip->vtu_prob_irq);
580 
581 	return err;
582 }
583 
584 void mv88e6xxx_g1_vtu_prob_irq_free(struct mv88e6xxx_chip *chip)
585 {
586 	free_irq(chip->vtu_prob_irq, chip);
587 	irq_dispose_mapping(chip->vtu_prob_irq);
588 }
589