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>
20 /* Offset 0x02: VTU FID Register */
22 static int mv88e6xxx_g1_vtu_fid_read(struct mv88e6xxx_chip *chip,
23 struct mv88e6xxx_vtu_entry *entry)
28 err = mv88e6xxx_g1_read(chip, MV88E6352_G1_VTU_FID, &val);
32 entry->fid = val & MV88E6352_G1_VTU_FID_MASK;
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)
53 err = mv88e6xxx_g1_read(chip, MV88E6352_G1_VTU_SID, &val);
57 entry->sid = val & MV88E6352_G1_VTU_SID_MASK;
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)
82 err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_OP,
83 MV88E6XXX_G1_VTU_OP_BUSY | op);
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)
98 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_VID, &val);
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);
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;
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
130 static int mv88e6185_g1_vtu_stu_data_read(struct mv88e6xxx_chip *chip,
135 /* Read all 3 VTU/STU Data registers */
136 for (i = 0; i < 3; ++i) {
140 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
148 static int mv88e6185_g1_vtu_data_read(struct mv88e6xxx_chip *chip,
149 struct mv88e6xxx_vtu_entry *entry)
155 err = mv88e6185_g1_vtu_stu_data_read(chip, regs);
159 /* Extract MemberTag data */
160 for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
161 unsigned int member_offset = (i % 4) * 4;
163 entry->member[i] = (regs[i / 4] >> member_offset) & 0x3;
169 static int mv88e6185_g1_stu_data_read(struct mv88e6xxx_chip *chip,
170 struct mv88e6xxx_vtu_entry *entry)
176 err = mv88e6185_g1_vtu_stu_data_read(chip, regs);
180 /* Extract PortState data */
181 for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
182 unsigned int state_offset = (i % 4) * 4 + 2;
184 entry->state[i] = (regs[i / 4] >> state_offset) & 0x3;
190 static int mv88e6185_g1_vtu_data_write(struct mv88e6xxx_chip *chip,
191 struct mv88e6xxx_vtu_entry *entry)
196 /* Insert MemberTag and PortState data */
197 for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
198 unsigned int member_offset = (i % 4) * 4;
199 unsigned int state_offset = member_offset + 2;
201 regs[i / 4] |= (entry->member[i] & 0x3) << member_offset;
202 regs[i / 4] |= (entry->state[i] & 0x3) << state_offset;
205 /* Write all 3 VTU/STU Data registers */
206 for (i = 0; i < 3; ++i) {
210 err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
218 static int mv88e6390_g1_vtu_data_read(struct mv88e6xxx_chip *chip, u8 *data)
223 /* Read the 2 VTU/STU Data registers */
224 for (i = 0; i < 2; ++i) {
228 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
234 for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
235 unsigned int offset = (i % 8) * 2;
237 data[i] = (regs[i / 8] >> offset) & 0x3;
243 static int mv88e6390_g1_vtu_data_write(struct mv88e6xxx_chip *chip, u8 *data)
249 for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
250 unsigned int offset = (i % 8) * 2;
252 regs[i / 8] |= (data[i] & 0x3) << offset;
255 /* Write the 2 VTU/STU Data registers */
256 for (i = 0; i < 2; ++i) {
260 err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
268 /* VLAN Translation Unit Operations */
270 static int mv88e6xxx_g1_vtu_stu_getnext(struct mv88e6xxx_chip *chip,
271 struct mv88e6xxx_vtu_entry *entry)
275 err = mv88e6xxx_g1_vtu_sid_write(chip, entry);
279 err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_STU_GET_NEXT);
283 err = mv88e6xxx_g1_vtu_sid_read(chip, entry);
287 return mv88e6xxx_g1_vtu_vid_read(chip, entry);
290 static int mv88e6xxx_g1_vtu_stu_get(struct mv88e6xxx_chip *chip,
291 struct mv88e6xxx_vtu_entry *vtu)
293 struct mv88e6xxx_vtu_entry stu;
296 err = mv88e6xxx_g1_vtu_sid_read(chip, vtu);
300 stu.sid = vtu->sid - 1;
302 err = mv88e6xxx_g1_vtu_stu_getnext(chip, &stu);
306 if (stu.sid != vtu->sid || !stu.valid)
312 static int mv88e6xxx_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
313 struct mv88e6xxx_vtu_entry *entry)
317 err = mv88e6xxx_g1_vtu_op_wait(chip);
321 /* To get the next higher active VID, the VTU GetNext operation can be
322 * started again without setting the VID registers since it already
323 * contains the last VID.
325 * To save a few hardware accesses and abstract this to the caller,
326 * write the VID only once, when the entry is given as invalid.
329 err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
334 err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_GET_NEXT);
338 return mv88e6xxx_g1_vtu_vid_read(chip, entry);
341 int mv88e6185_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
342 struct mv88e6xxx_vtu_entry *entry)
347 err = mv88e6xxx_g1_vtu_getnext(chip, entry);
352 err = mv88e6185_g1_vtu_data_read(chip, entry);
356 err = mv88e6185_g1_stu_data_read(chip, entry);
360 /* VTU DBNum[3:0] are located in VTU Operation 3:0
361 * VTU DBNum[7:4] are located in VTU Operation 11:8
363 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val);
367 entry->fid = val & 0x000f;
368 entry->fid |= (val & 0x0f00) >> 4;
374 int mv88e6352_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
375 struct mv88e6xxx_vtu_entry *entry)
379 /* Fetch VLAN MemberTag data from the VTU */
380 err = mv88e6xxx_g1_vtu_getnext(chip, entry);
385 err = mv88e6185_g1_vtu_data_read(chip, entry);
389 err = mv88e6xxx_g1_vtu_fid_read(chip, entry);
393 /* Fetch VLAN PortState data from the STU */
394 err = mv88e6xxx_g1_vtu_stu_get(chip, entry);
398 err = mv88e6185_g1_stu_data_read(chip, entry);
406 int mv88e6390_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
407 struct mv88e6xxx_vtu_entry *entry)
411 /* Fetch VLAN MemberTag data from the VTU */
412 err = mv88e6xxx_g1_vtu_getnext(chip, entry);
417 err = mv88e6390_g1_vtu_data_read(chip, entry->member);
421 /* Fetch VLAN PortState data from the STU */
422 err = mv88e6xxx_g1_vtu_stu_get(chip, entry);
426 err = mv88e6390_g1_vtu_data_read(chip, entry->state);
430 err = mv88e6xxx_g1_vtu_fid_read(chip, entry);
438 int mv88e6185_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
439 struct mv88e6xxx_vtu_entry *entry)
441 u16 op = MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE;
444 err = mv88e6xxx_g1_vtu_op_wait(chip);
448 err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
453 err = mv88e6185_g1_vtu_data_write(chip, entry);
457 /* VTU DBNum[3:0] are located in VTU Operation 3:0
458 * VTU DBNum[7:4] are located in VTU Operation 11:8
460 op |= entry->fid & 0x000f;
461 op |= (entry->fid & 0x00f0) << 4;
464 return mv88e6xxx_g1_vtu_op(chip, op);
467 int mv88e6352_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
468 struct mv88e6xxx_vtu_entry *entry)
472 err = mv88e6xxx_g1_vtu_op_wait(chip);
476 err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
481 /* Write MemberTag and PortState data */
482 err = mv88e6185_g1_vtu_data_write(chip, entry);
486 err = mv88e6xxx_g1_vtu_sid_write(chip, entry);
491 err = mv88e6xxx_g1_vtu_op(chip,
492 MV88E6XXX_G1_VTU_OP_STU_LOAD_PURGE);
496 err = mv88e6xxx_g1_vtu_fid_write(chip, entry);
501 /* Load/Purge VTU entry */
502 return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE);
505 int mv88e6390_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
506 struct mv88e6xxx_vtu_entry *entry)
510 err = mv88e6xxx_g1_vtu_op_wait(chip);
514 err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
519 /* Write PortState data */
520 err = mv88e6390_g1_vtu_data_write(chip, entry->state);
524 err = mv88e6xxx_g1_vtu_sid_write(chip, entry);
529 err = mv88e6xxx_g1_vtu_op(chip,
530 MV88E6XXX_G1_VTU_OP_STU_LOAD_PURGE);
534 /* Write MemberTag data */
535 err = mv88e6390_g1_vtu_data_write(chip, entry->member);
539 err = mv88e6xxx_g1_vtu_fid_write(chip, entry);
544 /* Load/Purge VTU entry */
545 return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE);
548 int mv88e6xxx_g1_vtu_flush(struct mv88e6xxx_chip *chip)
552 err = mv88e6xxx_g1_vtu_op_wait(chip);
556 return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_FLUSH_ALL);
559 static irqreturn_t mv88e6xxx_g1_vtu_prob_irq_thread_fn(int irq, void *dev_id)
561 struct mv88e6xxx_chip *chip = dev_id;
562 struct mv88e6xxx_vtu_entry entry;
567 mutex_lock(&chip->reg_lock);
569 err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_GET_CLR_VIOLATION);
573 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val);
577 err = mv88e6xxx_g1_vtu_vid_read(chip, &entry);
581 spid = val & MV88E6XXX_G1_VTU_OP_SPID_MASK;
583 if (val & MV88E6XXX_G1_VTU_OP_MEMBER_VIOLATION) {
584 dev_err_ratelimited(chip->dev, "VTU member violation for vid %d, source port %d\n",
586 chip->ports[spid].vtu_member_violation++;
589 if (val & MV88E6XXX_G1_VTU_OP_MISS_VIOLATION) {
590 dev_dbg_ratelimited(chip->dev, "VTU miss violation for vid %d, source port %d\n",
592 chip->ports[spid].vtu_miss_violation++;
595 mutex_unlock(&chip->reg_lock);
600 mutex_unlock(&chip->reg_lock);
602 dev_err(chip->dev, "VTU problem: error %d while handling interrupt\n",
608 int mv88e6xxx_g1_vtu_prob_irq_setup(struct mv88e6xxx_chip *chip)
612 chip->vtu_prob_irq = irq_find_mapping(chip->g1_irq.domain,
613 MV88E6XXX_G1_STS_IRQ_VTU_PROB);
614 if (chip->vtu_prob_irq < 0)
615 return chip->vtu_prob_irq;
617 err = request_threaded_irq(chip->vtu_prob_irq, NULL,
618 mv88e6xxx_g1_vtu_prob_irq_thread_fn,
619 IRQF_ONESHOT, "mv88e6xxx-g1-vtu-prob",
622 irq_dispose_mapping(chip->vtu_prob_irq);
627 void mv88e6xxx_g1_vtu_prob_irq_free(struct mv88e6xxx_chip *chip)
629 free_irq(chip->vtu_prob_irq, chip);
630 irq_dispose_mapping(chip->vtu_prob_irq);