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