Linux 4.19.133
[linux/fpc-iii.git] / drivers / net / dsa / mv88e6xxx / global1_vtu.c
blob7a6667e0b9f9ce6466c9fa70da78b7ae41db887d
1 /*
2 * Marvell 88E6xxx VLAN [Spanning Tree] Translation Unit (VTU [STU]) support
4 * Copyright (c) 2008 Marvell Semiconductor
5 * Copyright (c) 2015 CMC Electronics, Inc.
6 * Copyright (c) 2017 Savoir-faire Linux, Inc.
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.
14 #include <linux/interrupt.h>
15 #include <linux/irqdomain.h>
17 #include "chip.h"
18 #include "global1.h"
20 /* Offset 0x02: VTU FID Register */
22 static int mv88e6xxx_g1_vtu_fid_read(struct mv88e6xxx_chip *chip,
23 struct mv88e6xxx_vtu_entry *entry)
25 u16 val;
26 int err;
28 err = mv88e6xxx_g1_read(chip, MV88E6352_G1_VTU_FID, &val);
29 if (err)
30 return err;
32 entry->fid = val & MV88E6352_G1_VTU_FID_MASK;
34 return 0;
37 static int mv88e6xxx_g1_vtu_fid_write(struct mv88e6xxx_chip *chip,
38 struct mv88e6xxx_vtu_entry *entry)
40 u16 val = entry->fid & MV88E6352_G1_VTU_FID_MASK;
42 return mv88e6xxx_g1_write(chip, MV88E6352_G1_VTU_FID, val);
45 /* Offset 0x03: VTU SID Register */
47 static int mv88e6xxx_g1_vtu_sid_read(struct mv88e6xxx_chip *chip,
48 struct mv88e6xxx_vtu_entry *entry)
50 u16 val;
51 int err;
53 err = mv88e6xxx_g1_read(chip, MV88E6352_G1_VTU_SID, &val);
54 if (err)
55 return err;
57 entry->sid = val & MV88E6352_G1_VTU_SID_MASK;
59 return 0;
62 static int mv88e6xxx_g1_vtu_sid_write(struct mv88e6xxx_chip *chip,
63 struct mv88e6xxx_vtu_entry *entry)
65 u16 val = entry->sid & MV88E6352_G1_VTU_SID_MASK;
67 return mv88e6xxx_g1_write(chip, MV88E6352_G1_VTU_SID, val);
70 /* Offset 0x05: VTU Operation Register */
72 static int mv88e6xxx_g1_vtu_op_wait(struct mv88e6xxx_chip *chip)
74 return mv88e6xxx_g1_wait(chip, MV88E6XXX_G1_VTU_OP,
75 MV88E6XXX_G1_VTU_OP_BUSY);
78 static int mv88e6xxx_g1_vtu_op(struct mv88e6xxx_chip *chip, u16 op)
80 int err;
82 err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_OP,
83 MV88E6XXX_G1_VTU_OP_BUSY | op);
84 if (err)
85 return err;
87 return mv88e6xxx_g1_vtu_op_wait(chip);
90 /* Offset 0x06: VTU VID Register */
92 static int mv88e6xxx_g1_vtu_vid_read(struct mv88e6xxx_chip *chip,
93 struct mv88e6xxx_vtu_entry *entry)
95 u16 val;
96 int err;
98 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_VID, &val);
99 if (err)
100 return err;
102 entry->vid = val & 0xfff;
104 if (val & MV88E6390_G1_VTU_VID_PAGE)
105 entry->vid |= 0x1000;
107 entry->valid = !!(val & MV88E6XXX_G1_VTU_VID_VALID);
109 return 0;
112 static int mv88e6xxx_g1_vtu_vid_write(struct mv88e6xxx_chip *chip,
113 struct mv88e6xxx_vtu_entry *entry)
115 u16 val = entry->vid & 0xfff;
117 if (entry->vid & 0x1000)
118 val |= MV88E6390_G1_VTU_VID_PAGE;
120 if (entry->valid)
121 val |= MV88E6XXX_G1_VTU_VID_VALID;
123 return mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_VID, val);
126 /* Offset 0x07: VTU/STU Data Register 1
127 * Offset 0x08: VTU/STU Data Register 2
128 * Offset 0x09: VTU/STU Data Register 3
131 static int mv88e6185_g1_vtu_data_read(struct mv88e6xxx_chip *chip,
132 struct mv88e6xxx_vtu_entry *entry)
134 u16 regs[3];
135 int i;
137 /* Read all 3 VTU/STU Data registers */
138 for (i = 0; i < 3; ++i) {
139 u16 *reg = &regs[i];
140 int err;
142 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
143 if (err)
144 return err;
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;
152 entry->member[i] = (regs[i / 4] >> member_offset) & 0x3;
153 entry->state[i] = (regs[i / 4] >> state_offset) & 0x3;
156 return 0;
159 static int mv88e6185_g1_vtu_data_write(struct mv88e6xxx_chip *chip,
160 struct mv88e6xxx_vtu_entry *entry)
162 u16 regs[3] = { 0 };
163 int i;
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;
170 regs[i / 4] |= (entry->member[i] & 0x3) << member_offset;
171 regs[i / 4] |= (entry->state[i] & 0x3) << state_offset;
174 /* Write all 3 VTU/STU Data registers */
175 for (i = 0; i < 3; ++i) {
176 u16 reg = regs[i];
177 int err;
179 err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
180 if (err)
181 return err;
184 return 0;
187 static int mv88e6390_g1_vtu_data_read(struct mv88e6xxx_chip *chip, u8 *data)
189 u16 regs[2];
190 int i;
192 /* Read the 2 VTU/STU Data registers */
193 for (i = 0; i < 2; ++i) {
194 u16 *reg = &regs[i];
195 int err;
197 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
198 if (err)
199 return err;
202 /* Extract data */
203 for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
204 unsigned int offset = (i % 8) * 2;
206 data[i] = (regs[i / 8] >> offset) & 0x3;
209 return 0;
212 static int mv88e6390_g1_vtu_data_write(struct mv88e6xxx_chip *chip, u8 *data)
214 u16 regs[2] = { 0 };
215 int i;
217 /* Insert data */
218 for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
219 unsigned int offset = (i % 8) * 2;
221 regs[i / 8] |= (data[i] & 0x3) << offset;
224 /* Write the 2 VTU/STU Data registers */
225 for (i = 0; i < 2; ++i) {
226 u16 reg = regs[i];
227 int err;
229 err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
230 if (err)
231 return err;
234 return 0;
237 /* VLAN Translation Unit Operations */
239 static int mv88e6xxx_g1_vtu_stu_getnext(struct mv88e6xxx_chip *chip,
240 struct mv88e6xxx_vtu_entry *entry)
242 int err;
244 err = mv88e6xxx_g1_vtu_sid_write(chip, entry);
245 if (err)
246 return err;
248 err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_STU_GET_NEXT);
249 if (err)
250 return err;
252 err = mv88e6xxx_g1_vtu_sid_read(chip, entry);
253 if (err)
254 return err;
256 return mv88e6xxx_g1_vtu_vid_read(chip, entry);
259 static int mv88e6xxx_g1_vtu_stu_get(struct mv88e6xxx_chip *chip,
260 struct mv88e6xxx_vtu_entry *vtu)
262 struct mv88e6xxx_vtu_entry stu;
263 int err;
265 err = mv88e6xxx_g1_vtu_sid_read(chip, vtu);
266 if (err)
267 return err;
269 stu.sid = vtu->sid - 1;
271 err = mv88e6xxx_g1_vtu_stu_getnext(chip, &stu);
272 if (err)
273 return err;
275 if (stu.sid != vtu->sid || !stu.valid)
276 return -EINVAL;
278 return 0;
281 static int mv88e6xxx_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
282 struct mv88e6xxx_vtu_entry *entry)
284 int err;
286 err = mv88e6xxx_g1_vtu_op_wait(chip);
287 if (err)
288 return err;
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.
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.
297 if (!entry->valid) {
298 err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
299 if (err)
300 return err;
303 err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_GET_NEXT);
304 if (err)
305 return err;
307 return mv88e6xxx_g1_vtu_vid_read(chip, entry);
310 int mv88e6185_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
311 struct mv88e6xxx_vtu_entry *entry)
313 u16 val;
314 int err;
316 err = mv88e6xxx_g1_vtu_getnext(chip, entry);
317 if (err)
318 return err;
320 if (entry->valid) {
321 err = mv88e6185_g1_vtu_data_read(chip, entry);
322 if (err)
323 return err;
325 /* VTU DBNum[3:0] are located in VTU Operation 3:0
326 * VTU DBNum[7:4] are located in VTU Operation 11:8
328 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val);
329 if (err)
330 return err;
332 entry->fid = val & 0x000f;
333 entry->fid |= (val & 0x0f00) >> 4;
336 return 0;
339 int mv88e6352_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
340 struct mv88e6xxx_vtu_entry *entry)
342 int err;
344 /* Fetch VLAN MemberTag data from the VTU */
345 err = mv88e6xxx_g1_vtu_getnext(chip, entry);
346 if (err)
347 return err;
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;
355 err = mv88e6185_g1_vtu_data_read(chip, entry);
356 if (err)
357 return err;
359 err = mv88e6xxx_g1_vtu_fid_read(chip, entry);
360 if (err)
361 return err;
364 return 0;
367 int mv88e6390_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
368 struct mv88e6xxx_vtu_entry *entry)
370 int err;
372 /* Fetch VLAN MemberTag data from the VTU */
373 err = mv88e6xxx_g1_vtu_getnext(chip, entry);
374 if (err)
375 return err;
377 if (entry->valid) {
378 err = mv88e6390_g1_vtu_data_read(chip, entry->member);
379 if (err)
380 return err;
382 /* Fetch VLAN PortState data from the STU */
383 err = mv88e6xxx_g1_vtu_stu_get(chip, entry);
384 if (err)
385 return err;
387 err = mv88e6390_g1_vtu_data_read(chip, entry->state);
388 if (err)
389 return err;
391 err = mv88e6xxx_g1_vtu_fid_read(chip, entry);
392 if (err)
393 return err;
396 return 0;
399 int mv88e6185_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
400 struct mv88e6xxx_vtu_entry *entry)
402 u16 op = MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE;
403 int err;
405 err = mv88e6xxx_g1_vtu_op_wait(chip);
406 if (err)
407 return err;
409 err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
410 if (err)
411 return err;
413 if (entry->valid) {
414 err = mv88e6185_g1_vtu_data_write(chip, entry);
415 if (err)
416 return err;
418 /* VTU DBNum[3:0] are located in VTU Operation 3:0
419 * VTU DBNum[7:4] are located in VTU Operation 11:8
421 op |= entry->fid & 0x000f;
422 op |= (entry->fid & 0x00f0) << 4;
425 return mv88e6xxx_g1_vtu_op(chip, op);
428 int mv88e6352_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
429 struct mv88e6xxx_vtu_entry *entry)
431 int err;
433 err = mv88e6xxx_g1_vtu_op_wait(chip);
434 if (err)
435 return err;
437 err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
438 if (err)
439 return err;
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;
447 err = mv88e6xxx_g1_vtu_sid_write(chip, entry);
448 if (err)
449 return err;
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;
457 err = mv88e6xxx_g1_vtu_fid_write(chip, entry);
458 if (err)
459 return err;
462 /* Load/Purge VTU entry */
463 return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE);
466 int mv88e6390_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
467 struct mv88e6xxx_vtu_entry *entry)
469 int err;
471 err = mv88e6xxx_g1_vtu_op_wait(chip);
472 if (err)
473 return err;
475 err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
476 if (err)
477 return err;
479 if (entry->valid) {
480 /* Write PortState data */
481 err = mv88e6390_g1_vtu_data_write(chip, entry->state);
482 if (err)
483 return err;
485 err = mv88e6xxx_g1_vtu_sid_write(chip, entry);
486 if (err)
487 return err;
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;
495 /* Write MemberTag data */
496 err = mv88e6390_g1_vtu_data_write(chip, entry->member);
497 if (err)
498 return err;
500 err = mv88e6xxx_g1_vtu_fid_write(chip, entry);
501 if (err)
502 return err;
505 /* Load/Purge VTU entry */
506 return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE);
509 int mv88e6xxx_g1_vtu_flush(struct mv88e6xxx_chip *chip)
511 int err;
513 err = mv88e6xxx_g1_vtu_op_wait(chip);
514 if (err)
515 return err;
517 return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_FLUSH_ALL);
520 static irqreturn_t mv88e6xxx_g1_vtu_prob_irq_thread_fn(int irq, void *dev_id)
522 struct mv88e6xxx_chip *chip = dev_id;
523 struct mv88e6xxx_vtu_entry entry;
524 int spid;
525 int err;
526 u16 val;
528 mutex_lock(&chip->reg_lock);
530 err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_GET_CLR_VIOLATION);
531 if (err)
532 goto out;
534 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val);
535 if (err)
536 goto out;
538 err = mv88e6xxx_g1_vtu_vid_read(chip, &entry);
539 if (err)
540 goto out;
542 spid = val & MV88E6XXX_G1_VTU_OP_SPID_MASK;
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++;
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++;
556 mutex_unlock(&chip->reg_lock);
558 return IRQ_HANDLED;
560 out:
561 mutex_unlock(&chip->reg_lock);
563 dev_err(chip->dev, "VTU problem: error %d while handling interrupt\n",
564 err);
566 return IRQ_HANDLED;
569 int mv88e6xxx_g1_vtu_prob_irq_setup(struct mv88e6xxx_chip *chip)
571 int err;
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;
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);
585 return err;
588 void mv88e6xxx_g1_vtu_prob_irq_free(struct mv88e6xxx_chip *chip)
590 free_irq(chip->vtu_prob_irq, chip);
591 irq_dispose_mapping(chip->vtu_prob_irq);