xref: /linux/drivers/net/dsa/mv88e6xxx/global1_vtu.c (revision f474808acb3c4b30552d9c59b181244e0300d218)
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 mv88e6250_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[5:4] are located in VTU Operation 9: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 & 0x0300) >> 4;
330 	}
331 
332 	return 0;
333 }
334 
335 int mv88e6185_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
336 			     struct mv88e6xxx_vtu_entry *entry)
337 {
338 	u16 val;
339 	int err;
340 
341 	err = mv88e6xxx_g1_vtu_getnext(chip, entry);
342 	if (err)
343 		return err;
344 
345 	if (entry->valid) {
346 		err = mv88e6185_g1_vtu_data_read(chip, entry);
347 		if (err)
348 			return err;
349 
350 		/* VTU DBNum[3:0] are located in VTU Operation 3:0
351 		 * VTU DBNum[7:4] are located in VTU Operation 11:8
352 		 */
353 		err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val);
354 		if (err)
355 			return err;
356 
357 		entry->fid = val & 0x000f;
358 		entry->fid |= (val & 0x0f00) >> 4;
359 	}
360 
361 	return 0;
362 }
363 
364 int mv88e6352_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
365 			     struct mv88e6xxx_vtu_entry *entry)
366 {
367 	int err;
368 
369 	/* Fetch VLAN MemberTag data from the VTU */
370 	err = mv88e6xxx_g1_vtu_getnext(chip, entry);
371 	if (err)
372 		return err;
373 
374 	if (entry->valid) {
375 		/* Fetch (and mask) VLAN PortState data from the STU */
376 		err = mv88e6xxx_g1_vtu_stu_get(chip, entry);
377 		if (err)
378 			return err;
379 
380 		err = mv88e6185_g1_vtu_data_read(chip, entry);
381 		if (err)
382 			return err;
383 
384 		err = mv88e6xxx_g1_vtu_fid_read(chip, entry);
385 		if (err)
386 			return err;
387 	}
388 
389 	return 0;
390 }
391 
392 int mv88e6390_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
393 			     struct mv88e6xxx_vtu_entry *entry)
394 {
395 	int err;
396 
397 	/* Fetch VLAN MemberTag data from the VTU */
398 	err = mv88e6xxx_g1_vtu_getnext(chip, entry);
399 	if (err)
400 		return err;
401 
402 	if (entry->valid) {
403 		err = mv88e6390_g1_vtu_data_read(chip, entry->member);
404 		if (err)
405 			return err;
406 
407 		/* Fetch VLAN PortState data from the STU */
408 		err = mv88e6xxx_g1_vtu_stu_get(chip, entry);
409 		if (err)
410 			return err;
411 
412 		err = mv88e6390_g1_vtu_data_read(chip, entry->state);
413 		if (err)
414 			return err;
415 
416 		err = mv88e6xxx_g1_vtu_fid_read(chip, entry);
417 		if (err)
418 			return err;
419 	}
420 
421 	return 0;
422 }
423 
424 int mv88e6250_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
425 			       struct mv88e6xxx_vtu_entry *entry)
426 {
427 	u16 op = MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE;
428 	int err;
429 
430 	err = mv88e6xxx_g1_vtu_op_wait(chip);
431 	if (err)
432 		return err;
433 
434 	err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
435 	if (err)
436 		return err;
437 
438 	if (entry->valid) {
439 		err = mv88e6185_g1_vtu_data_write(chip, entry);
440 		if (err)
441 			return err;
442 
443 		/* VTU DBNum[3:0] are located in VTU Operation 3:0
444 		 * VTU DBNum[5:4] are located in VTU Operation 9:8
445 		 */
446 		op |= entry->fid & 0x000f;
447 		op |= (entry->fid & 0x0030) << 4;
448 	}
449 
450 	return mv88e6xxx_g1_vtu_op(chip, op);
451 }
452 
453 int mv88e6185_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
454 			       struct mv88e6xxx_vtu_entry *entry)
455 {
456 	u16 op = MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE;
457 	int err;
458 
459 	err = mv88e6xxx_g1_vtu_op_wait(chip);
460 	if (err)
461 		return err;
462 
463 	err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
464 	if (err)
465 		return err;
466 
467 	if (entry->valid) {
468 		err = mv88e6185_g1_vtu_data_write(chip, entry);
469 		if (err)
470 			return err;
471 
472 		/* VTU DBNum[3:0] are located in VTU Operation 3:0
473 		 * VTU DBNum[7:4] are located in VTU Operation 11:8
474 		 */
475 		op |= entry->fid & 0x000f;
476 		op |= (entry->fid & 0x00f0) << 4;
477 	}
478 
479 	return mv88e6xxx_g1_vtu_op(chip, op);
480 }
481 
482 int mv88e6352_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
483 			       struct mv88e6xxx_vtu_entry *entry)
484 {
485 	int err;
486 
487 	err = mv88e6xxx_g1_vtu_op_wait(chip);
488 	if (err)
489 		return err;
490 
491 	err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
492 	if (err)
493 		return err;
494 
495 	if (entry->valid) {
496 		/* Write MemberTag and PortState data */
497 		err = mv88e6185_g1_vtu_data_write(chip, entry);
498 		if (err)
499 			return err;
500 
501 		err = mv88e6xxx_g1_vtu_sid_write(chip, entry);
502 		if (err)
503 			return err;
504 
505 		/* Load STU entry */
506 		err = mv88e6xxx_g1_vtu_op(chip,
507 					  MV88E6XXX_G1_VTU_OP_STU_LOAD_PURGE);
508 		if (err)
509 			return err;
510 
511 		err = mv88e6xxx_g1_vtu_fid_write(chip, entry);
512 		if (err)
513 			return err;
514 	}
515 
516 	/* Load/Purge VTU entry */
517 	return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE);
518 }
519 
520 int mv88e6390_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
521 			       struct mv88e6xxx_vtu_entry *entry)
522 {
523 	int err;
524 
525 	err = mv88e6xxx_g1_vtu_op_wait(chip);
526 	if (err)
527 		return err;
528 
529 	err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
530 	if (err)
531 		return err;
532 
533 	if (entry->valid) {
534 		/* Write PortState data */
535 		err = mv88e6390_g1_vtu_data_write(chip, entry->state);
536 		if (err)
537 			return err;
538 
539 		err = mv88e6xxx_g1_vtu_sid_write(chip, entry);
540 		if (err)
541 			return err;
542 
543 		/* Load STU entry */
544 		err = mv88e6xxx_g1_vtu_op(chip,
545 					  MV88E6XXX_G1_VTU_OP_STU_LOAD_PURGE);
546 		if (err)
547 			return err;
548 
549 		/* Write MemberTag data */
550 		err = mv88e6390_g1_vtu_data_write(chip, entry->member);
551 		if (err)
552 			return err;
553 
554 		err = mv88e6xxx_g1_vtu_fid_write(chip, entry);
555 		if (err)
556 			return err;
557 	}
558 
559 	/* Load/Purge VTU entry */
560 	return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE);
561 }
562 
563 int mv88e6xxx_g1_vtu_flush(struct mv88e6xxx_chip *chip)
564 {
565 	int err;
566 
567 	err = mv88e6xxx_g1_vtu_op_wait(chip);
568 	if (err)
569 		return err;
570 
571 	return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_FLUSH_ALL);
572 }
573 
574 static irqreturn_t mv88e6xxx_g1_vtu_prob_irq_thread_fn(int irq, void *dev_id)
575 {
576 	struct mv88e6xxx_chip *chip = dev_id;
577 	struct mv88e6xxx_vtu_entry entry;
578 	int spid;
579 	int err;
580 	u16 val;
581 
582 	mv88e6xxx_reg_lock(chip);
583 
584 	err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_GET_CLR_VIOLATION);
585 	if (err)
586 		goto out;
587 
588 	err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val);
589 	if (err)
590 		goto out;
591 
592 	err = mv88e6xxx_g1_vtu_vid_read(chip, &entry);
593 	if (err)
594 		goto out;
595 
596 	spid = val & MV88E6XXX_G1_VTU_OP_SPID_MASK;
597 
598 	if (val & MV88E6XXX_G1_VTU_OP_MEMBER_VIOLATION) {
599 		dev_err_ratelimited(chip->dev, "VTU member violation for vid %d, source port %d\n",
600 				    entry.vid, spid);
601 		chip->ports[spid].vtu_member_violation++;
602 	}
603 
604 	if (val & MV88E6XXX_G1_VTU_OP_MISS_VIOLATION) {
605 		dev_dbg_ratelimited(chip->dev, "VTU miss violation for vid %d, source port %d\n",
606 				    entry.vid, spid);
607 		chip->ports[spid].vtu_miss_violation++;
608 	}
609 
610 	mv88e6xxx_reg_unlock(chip);
611 
612 	return IRQ_HANDLED;
613 
614 out:
615 	mv88e6xxx_reg_unlock(chip);
616 
617 	dev_err(chip->dev, "VTU problem: error %d while handling interrupt\n",
618 		err);
619 
620 	return IRQ_HANDLED;
621 }
622 
623 int mv88e6xxx_g1_vtu_prob_irq_setup(struct mv88e6xxx_chip *chip)
624 {
625 	int err;
626 
627 	chip->vtu_prob_irq = irq_find_mapping(chip->g1_irq.domain,
628 					      MV88E6XXX_G1_STS_IRQ_VTU_PROB);
629 	if (chip->vtu_prob_irq < 0)
630 		return chip->vtu_prob_irq;
631 
632 	err = request_threaded_irq(chip->vtu_prob_irq, NULL,
633 				   mv88e6xxx_g1_vtu_prob_irq_thread_fn,
634 				   IRQF_ONESHOT, "mv88e6xxx-g1-vtu-prob",
635 				   chip);
636 	if (err)
637 		irq_dispose_mapping(chip->vtu_prob_irq);
638 
639 	return err;
640 }
641 
642 void mv88e6xxx_g1_vtu_prob_irq_free(struct mv88e6xxx_chip *chip)
643 {
644 	free_irq(chip->vtu_prob_irq, chip);
645 	irq_dispose_mapping(chip->vtu_prob_irq);
646 }
647