1
2
3
4
5
6
7
8
9
10#include <linux/bitfield.h>
11#include <linux/interrupt.h>
12#include <linux/irqdomain.h>
13
14#include "chip.h"
15#include "global1.h"
16
17
18
19static int mv88e6xxx_g1_vtu_fid_read(struct mv88e6xxx_chip *chip,
20 struct mv88e6xxx_vtu_entry *entry)
21{
22 u16 val;
23 int err;
24
25 err = mv88e6xxx_g1_read(chip, MV88E6352_G1_VTU_FID, &val);
26 if (err)
27 return err;
28
29 entry->fid = val & MV88E6352_G1_VTU_FID_MASK;
30
31 return 0;
32}
33
34static int mv88e6xxx_g1_vtu_fid_write(struct mv88e6xxx_chip *chip,
35 struct mv88e6xxx_vtu_entry *entry)
36{
37 u16 val = entry->fid & MV88E6352_G1_VTU_FID_MASK;
38
39 return mv88e6xxx_g1_write(chip, MV88E6352_G1_VTU_FID, val);
40}
41
42
43
44static int mv88e6xxx_g1_vtu_sid_read(struct mv88e6xxx_chip *chip,
45 struct mv88e6xxx_vtu_entry *entry)
46{
47 u16 val;
48 int err;
49
50 err = mv88e6xxx_g1_read(chip, MV88E6352_G1_VTU_SID, &val);
51 if (err)
52 return err;
53
54 entry->sid = val & MV88E6352_G1_VTU_SID_MASK;
55
56 return 0;
57}
58
59static int mv88e6xxx_g1_vtu_sid_write(struct mv88e6xxx_chip *chip,
60 struct mv88e6xxx_vtu_entry *entry)
61{
62 u16 val = entry->sid & MV88E6352_G1_VTU_SID_MASK;
63
64 return mv88e6xxx_g1_write(chip, MV88E6352_G1_VTU_SID, val);
65}
66
67
68
69static int mv88e6xxx_g1_vtu_op_wait(struct mv88e6xxx_chip *chip)
70{
71 int bit = __bf_shf(MV88E6XXX_G1_VTU_OP_BUSY);
72
73 return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_VTU_OP, bit, 0);
74}
75
76static int mv88e6xxx_g1_vtu_op(struct mv88e6xxx_chip *chip, u16 op)
77{
78 int err;
79
80 err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_OP,
81 MV88E6XXX_G1_VTU_OP_BUSY | op);
82 if (err)
83 return err;
84
85 return mv88e6xxx_g1_vtu_op_wait(chip);
86}
87
88
89
90static int mv88e6xxx_g1_vtu_vid_read(struct mv88e6xxx_chip *chip,
91 struct mv88e6xxx_vtu_entry *entry)
92{
93 u16 val;
94 int err;
95
96 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_VID, &val);
97 if (err)
98 return err;
99
100 entry->vid = val & 0xfff;
101
102 if (val & MV88E6390_G1_VTU_VID_PAGE)
103 entry->vid |= 0x1000;
104
105 entry->valid = !!(val & MV88E6XXX_G1_VTU_VID_VALID);
106
107 return 0;
108}
109
110static int mv88e6xxx_g1_vtu_vid_write(struct mv88e6xxx_chip *chip,
111 struct mv88e6xxx_vtu_entry *entry)
112{
113 u16 val = entry->vid & 0xfff;
114
115 if (entry->vid & 0x1000)
116 val |= MV88E6390_G1_VTU_VID_PAGE;
117
118 if (entry->valid)
119 val |= MV88E6XXX_G1_VTU_VID_VALID;
120
121 return mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_VID, val);
122}
123
124
125
126
127
128static int mv88e6185_g1_vtu_stu_data_read(struct mv88e6xxx_chip *chip,
129 u16 *regs)
130{
131 int i;
132
133
134 for (i = 0; i < 3; ++i) {
135 u16 *reg = ®s[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 return 0;
144}
145
146static int mv88e6185_g1_vtu_data_read(struct mv88e6xxx_chip *chip,
147 struct mv88e6xxx_vtu_entry *entry)
148{
149 u16 regs[3];
150 int err;
151 int i;
152
153 err = mv88e6185_g1_vtu_stu_data_read(chip, regs);
154 if (err)
155 return err;
156
157
158 for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
159 unsigned int member_offset = (i % 4) * 4;
160
161 entry->member[i] = (regs[i / 4] >> member_offset) & 0x3;
162 }
163
164 return 0;
165}
166
167static int mv88e6185_g1_stu_data_read(struct mv88e6xxx_chip *chip,
168 struct mv88e6xxx_vtu_entry *entry)
169{
170 u16 regs[3];
171 int err;
172 int i;
173
174 err = mv88e6185_g1_vtu_stu_data_read(chip, regs);
175 if (err)
176 return err;
177
178
179 for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
180 unsigned int state_offset = (i % 4) * 4 + 2;
181
182 entry->state[i] = (regs[i / 4] >> state_offset) & 0x3;
183 }
184
185 return 0;
186}
187
188static int mv88e6185_g1_vtu_data_write(struct mv88e6xxx_chip *chip,
189 struct mv88e6xxx_vtu_entry *entry)
190{
191 u16 regs[3] = { 0 };
192 int i;
193
194
195 for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
196 unsigned int member_offset = (i % 4) * 4;
197 unsigned int state_offset = member_offset + 2;
198
199 regs[i / 4] |= (entry->member[i] & 0x3) << member_offset;
200 regs[i / 4] |= (entry->state[i] & 0x3) << state_offset;
201 }
202
203
204 for (i = 0; i < 3; ++i) {
205 u16 reg = regs[i];
206 int err;
207
208 err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
209 if (err)
210 return err;
211 }
212
213 return 0;
214}
215
216static int mv88e6390_g1_vtu_data_read(struct mv88e6xxx_chip *chip, u8 *data)
217{
218 u16 regs[2];
219 int i;
220
221
222 for (i = 0; i < 2; ++i) {
223 u16 *reg = ®s[i];
224 int err;
225
226 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
227 if (err)
228 return err;
229 }
230
231
232 for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
233 unsigned int offset = (i % 8) * 2;
234
235 data[i] = (regs[i / 8] >> offset) & 0x3;
236 }
237
238 return 0;
239}
240
241static int mv88e6390_g1_vtu_data_write(struct mv88e6xxx_chip *chip, u8 *data)
242{
243 u16 regs[2] = { 0 };
244 int i;
245
246
247 for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
248 unsigned int offset = (i % 8) * 2;
249
250 regs[i / 8] |= (data[i] & 0x3) << offset;
251 }
252
253
254 for (i = 0; i < 2; ++i) {
255 u16 reg = regs[i];
256 int err;
257
258 err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
259 if (err)
260 return err;
261 }
262
263 return 0;
264}
265
266
267
268static int mv88e6xxx_g1_vtu_stu_getnext(struct mv88e6xxx_chip *chip,
269 struct mv88e6xxx_vtu_entry *entry)
270{
271 int err;
272
273 err = mv88e6xxx_g1_vtu_sid_write(chip, entry);
274 if (err)
275 return err;
276
277 err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_STU_GET_NEXT);
278 if (err)
279 return err;
280
281 err = mv88e6xxx_g1_vtu_sid_read(chip, entry);
282 if (err)
283 return err;
284
285 return mv88e6xxx_g1_vtu_vid_read(chip, entry);
286}
287
288static int mv88e6xxx_g1_vtu_stu_get(struct mv88e6xxx_chip *chip,
289 struct mv88e6xxx_vtu_entry *vtu)
290{
291 struct mv88e6xxx_vtu_entry stu;
292 int err;
293
294 err = mv88e6xxx_g1_vtu_sid_read(chip, vtu);
295 if (err)
296 return err;
297
298 stu.sid = vtu->sid - 1;
299
300 err = mv88e6xxx_g1_vtu_stu_getnext(chip, &stu);
301 if (err)
302 return err;
303
304 if (stu.sid != vtu->sid || !stu.valid)
305 return -EINVAL;
306
307 return 0;
308}
309
310static int mv88e6xxx_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
311 struct mv88e6xxx_vtu_entry *entry)
312{
313 int err;
314
315 err = mv88e6xxx_g1_vtu_op_wait(chip);
316 if (err)
317 return err;
318
319
320
321
322
323
324
325
326 if (!entry->valid) {
327 err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
328 if (err)
329 return err;
330 }
331
332 err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_GET_NEXT);
333 if (err)
334 return err;
335
336 return mv88e6xxx_g1_vtu_vid_read(chip, entry);
337}
338
339int mv88e6250_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
340 struct mv88e6xxx_vtu_entry *entry)
341{
342 u16 val;
343 int err;
344
345 err = mv88e6xxx_g1_vtu_getnext(chip, entry);
346 if (err)
347 return err;
348
349 if (entry->valid) {
350 err = mv88e6185_g1_vtu_data_read(chip, entry);
351 if (err)
352 return err;
353
354
355
356
357 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val);
358 if (err)
359 return err;
360
361 entry->fid = val & 0x000f;
362 entry->fid |= (val & 0x0300) >> 4;
363 }
364
365 return 0;
366}
367
368int mv88e6185_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
369 struct mv88e6xxx_vtu_entry *entry)
370{
371 u16 val;
372 int err;
373
374 err = mv88e6xxx_g1_vtu_getnext(chip, entry);
375 if (err)
376 return err;
377
378 if (entry->valid) {
379 err = mv88e6185_g1_vtu_data_read(chip, entry);
380 if (err)
381 return err;
382
383 err = mv88e6185_g1_stu_data_read(chip, entry);
384 if (err)
385 return err;
386
387
388
389
390 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val);
391 if (err)
392 return err;
393
394 entry->fid = val & 0x000f;
395 entry->fid |= (val & 0x0f00) >> 4;
396 }
397
398 return 0;
399}
400
401int mv88e6352_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
402 struct mv88e6xxx_vtu_entry *entry)
403{
404 int err;
405
406
407 err = mv88e6xxx_g1_vtu_getnext(chip, entry);
408 if (err)
409 return err;
410
411 if (entry->valid) {
412 err = mv88e6185_g1_vtu_data_read(chip, entry);
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 err = mv88e6xxx_g1_vtu_stu_get(chip, entry);
422 if (err)
423 return err;
424
425 err = mv88e6185_g1_stu_data_read(chip, entry);
426 if (err)
427 return err;
428 }
429
430 return 0;
431}
432
433int mv88e6390_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
434 struct mv88e6xxx_vtu_entry *entry)
435{
436 int err;
437
438
439 err = mv88e6xxx_g1_vtu_getnext(chip, entry);
440 if (err)
441 return err;
442
443 if (entry->valid) {
444 err = mv88e6390_g1_vtu_data_read(chip, entry->member);
445 if (err)
446 return err;
447
448
449 err = mv88e6xxx_g1_vtu_stu_get(chip, entry);
450 if (err)
451 return err;
452
453 err = mv88e6390_g1_vtu_data_read(chip, entry->state);
454 if (err)
455 return err;
456
457 err = mv88e6xxx_g1_vtu_fid_read(chip, entry);
458 if (err)
459 return err;
460 }
461
462 return 0;
463}
464
465int mv88e6250_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
466 struct mv88e6xxx_vtu_entry *entry)
467{
468 u16 op = MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE;
469 int err;
470
471 err = mv88e6xxx_g1_vtu_op_wait(chip);
472 if (err)
473 return err;
474
475 err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
476 if (err)
477 return err;
478
479 if (entry->valid) {
480 err = mv88e6185_g1_vtu_data_write(chip, entry);
481 if (err)
482 return err;
483
484
485
486
487 op |= entry->fid & 0x000f;
488 op |= (entry->fid & 0x0030) << 4;
489 }
490
491 return mv88e6xxx_g1_vtu_op(chip, op);
492}
493
494int mv88e6185_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
495 struct mv88e6xxx_vtu_entry *entry)
496{
497 u16 op = MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE;
498 int err;
499
500 err = mv88e6xxx_g1_vtu_op_wait(chip);
501 if (err)
502 return err;
503
504 err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
505 if (err)
506 return err;
507
508 if (entry->valid) {
509 err = mv88e6185_g1_vtu_data_write(chip, entry);
510 if (err)
511 return err;
512
513
514
515
516 op |= entry->fid & 0x000f;
517 op |= (entry->fid & 0x00f0) << 4;
518 }
519
520 return mv88e6xxx_g1_vtu_op(chip, op);
521}
522
523int mv88e6352_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
524 struct mv88e6xxx_vtu_entry *entry)
525{
526 int err;
527
528 err = mv88e6xxx_g1_vtu_op_wait(chip);
529 if (err)
530 return err;
531
532 err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
533 if (err)
534 return err;
535
536 if (entry->valid) {
537
538 err = mv88e6185_g1_vtu_data_write(chip, entry);
539 if (err)
540 return err;
541
542 err = mv88e6xxx_g1_vtu_sid_write(chip, entry);
543 if (err)
544 return err;
545
546
547 err = mv88e6xxx_g1_vtu_op(chip,
548 MV88E6XXX_G1_VTU_OP_STU_LOAD_PURGE);
549 if (err)
550 return err;
551
552 err = mv88e6xxx_g1_vtu_fid_write(chip, entry);
553 if (err)
554 return err;
555 }
556
557
558 return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE);
559}
560
561int mv88e6390_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
562 struct mv88e6xxx_vtu_entry *entry)
563{
564 int err;
565
566 err = mv88e6xxx_g1_vtu_op_wait(chip);
567 if (err)
568 return err;
569
570 err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
571 if (err)
572 return err;
573
574 if (entry->valid) {
575
576 err = mv88e6390_g1_vtu_data_write(chip, entry->state);
577 if (err)
578 return err;
579
580 err = mv88e6xxx_g1_vtu_sid_write(chip, entry);
581 if (err)
582 return err;
583
584
585 err = mv88e6xxx_g1_vtu_op(chip,
586 MV88E6XXX_G1_VTU_OP_STU_LOAD_PURGE);
587 if (err)
588 return err;
589
590
591 err = mv88e6390_g1_vtu_data_write(chip, entry->member);
592 if (err)
593 return err;
594
595 err = mv88e6xxx_g1_vtu_fid_write(chip, entry);
596 if (err)
597 return err;
598 }
599
600
601 return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE);
602}
603
604int mv88e6xxx_g1_vtu_flush(struct mv88e6xxx_chip *chip)
605{
606 int err;
607
608 err = mv88e6xxx_g1_vtu_op_wait(chip);
609 if (err)
610 return err;
611
612 return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_FLUSH_ALL);
613}
614
615static irqreturn_t mv88e6xxx_g1_vtu_prob_irq_thread_fn(int irq, void *dev_id)
616{
617 struct mv88e6xxx_chip *chip = dev_id;
618 struct mv88e6xxx_vtu_entry entry;
619 int spid;
620 int err;
621 u16 val;
622
623 mv88e6xxx_reg_lock(chip);
624
625 err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_GET_CLR_VIOLATION);
626 if (err)
627 goto out;
628
629 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val);
630 if (err)
631 goto out;
632
633 err = mv88e6xxx_g1_vtu_vid_read(chip, &entry);
634 if (err)
635 goto out;
636
637 spid = val & MV88E6XXX_G1_VTU_OP_SPID_MASK;
638
639 if (val & MV88E6XXX_G1_VTU_OP_MEMBER_VIOLATION) {
640 dev_err_ratelimited(chip->dev, "VTU member violation for vid %d, source port %d\n",
641 entry.vid, spid);
642 chip->ports[spid].vtu_member_violation++;
643 }
644
645 if (val & MV88E6XXX_G1_VTU_OP_MISS_VIOLATION) {
646 dev_dbg_ratelimited(chip->dev, "VTU miss violation for vid %d, source port %d\n",
647 entry.vid, spid);
648 chip->ports[spid].vtu_miss_violation++;
649 }
650
651 mv88e6xxx_reg_unlock(chip);
652
653 return IRQ_HANDLED;
654
655out:
656 mv88e6xxx_reg_unlock(chip);
657
658 dev_err(chip->dev, "VTU problem: error %d while handling interrupt\n",
659 err);
660
661 return IRQ_HANDLED;
662}
663
664int mv88e6xxx_g1_vtu_prob_irq_setup(struct mv88e6xxx_chip *chip)
665{
666 int err;
667
668 chip->vtu_prob_irq = irq_find_mapping(chip->g1_irq.domain,
669 MV88E6XXX_G1_STS_IRQ_VTU_PROB);
670 if (chip->vtu_prob_irq < 0)
671 return chip->vtu_prob_irq;
672
673 snprintf(chip->vtu_prob_irq_name, sizeof(chip->vtu_prob_irq_name),
674 "mv88e6xxx-%s-g1-vtu-prob", dev_name(chip->dev));
675
676 err = request_threaded_irq(chip->vtu_prob_irq, NULL,
677 mv88e6xxx_g1_vtu_prob_irq_thread_fn,
678 IRQF_ONESHOT, chip->vtu_prob_irq_name,
679 chip);
680 if (err)
681 irq_dispose_mapping(chip->vtu_prob_irq);
682
683 return err;
684}
685
686void mv88e6xxx_g1_vtu_prob_irq_free(struct mv88e6xxx_chip *chip)
687{
688 free_irq(chip->vtu_prob_irq, chip);
689 irq_dispose_mapping(chip->vtu_prob_irq);
690}
691