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.
17 /* Offset 0x02: VTU FID Register */
19 static int mv88e6xxx_g1_vtu_fid_read(struct mv88e6xxx_chip *chip,
20 struct mv88e6xxx_vtu_entry *entry)
25 err = mv88e6xxx_g1_read(chip, MV88E6352_G1_VTU_FID, &val);
29 entry->fid = val & MV88E6352_G1_VTU_FID_MASK;
34 static int mv88e6xxx_g1_vtu_fid_write(struct mv88e6xxx_chip *chip,
35 struct mv88e6xxx_vtu_entry *entry)
37 u16 val = entry->fid & MV88E6352_G1_VTU_FID_MASK;
39 return mv88e6xxx_g1_write(chip, MV88E6352_G1_VTU_FID, val);
42 /* Offset 0x03: VTU SID Register */
44 static int mv88e6xxx_g1_vtu_sid_read(struct mv88e6xxx_chip *chip,
45 struct mv88e6xxx_vtu_entry *entry)
50 err = mv88e6xxx_g1_read(chip, MV88E6352_G1_VTU_SID, &val);
54 entry->sid = val & MV88E6352_G1_VTU_SID_MASK;
59 static int mv88e6xxx_g1_vtu_sid_write(struct mv88e6xxx_chip *chip,
60 struct mv88e6xxx_vtu_entry *entry)
62 u16 val = entry->sid & MV88E6352_G1_VTU_SID_MASK;
64 return mv88e6xxx_g1_write(chip, MV88E6352_G1_VTU_SID, val);
67 /* Offset 0x05: VTU Operation Register */
69 static int mv88e6xxx_g1_vtu_op_wait(struct mv88e6xxx_chip *chip)
71 return mv88e6xxx_g1_wait(chip, MV88E6XXX_G1_VTU_OP,
72 MV88E6XXX_G1_VTU_OP_BUSY);
75 static int mv88e6xxx_g1_vtu_op(struct mv88e6xxx_chip *chip, u16 op)
79 err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_OP,
80 MV88E6XXX_G1_VTU_OP_BUSY | op);
84 return mv88e6xxx_g1_vtu_op_wait(chip);
87 /* Offset 0x06: VTU VID Register */
89 static int mv88e6xxx_g1_vtu_vid_read(struct mv88e6xxx_chip *chip,
90 struct mv88e6xxx_vtu_entry *entry)
95 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_VID, &val);
99 entry->vid = val & 0xfff;
101 if (val & MV88E6390_G1_VTU_VID_PAGE)
102 entry->vid |= 0x1000;
104 entry->valid = !!(val & MV88E6XXX_G1_VTU_VID_VALID);
109 static int mv88e6xxx_g1_vtu_vid_write(struct mv88e6xxx_chip *chip,
110 struct mv88e6xxx_vtu_entry *entry)
112 u16 val = entry->vid & 0xfff;
114 if (entry->vid & 0x1000)
115 val |= MV88E6390_G1_VTU_VID_PAGE;
118 val |= MV88E6XXX_G1_VTU_VID_VALID;
120 return mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_VID, val);
123 /* Offset 0x07: VTU/STU Data Register 1
124 * Offset 0x08: VTU/STU Data Register 2
125 * Offset 0x09: VTU/STU Data Register 3
127 static int mv88e6185_g1_vtu_stu_data_read(struct mv88e6xxx_chip *chip,
132 /* Read all 3 VTU/STU Data registers */
133 for (i = 0; i < 3; ++i) {
137 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
145 static int mv88e6185_g1_vtu_data_read(struct mv88e6xxx_chip *chip,
146 struct mv88e6xxx_vtu_entry *entry)
152 err = mv88e6185_g1_vtu_stu_data_read(chip, regs);
156 /* Extract MemberTag data */
157 for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
158 unsigned int member_offset = (i % 4) * 4;
160 entry->member[i] = (regs[i / 4] >> member_offset) & 0x3;
166 static int mv88e6185_g1_stu_data_read(struct mv88e6xxx_chip *chip,
167 struct mv88e6xxx_vtu_entry *entry)
173 err = mv88e6185_g1_vtu_stu_data_read(chip, regs);
177 /* Extract PortState data */
178 for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
179 unsigned int state_offset = (i % 4) * 4 + 2;
181 entry->state[i] = (regs[i / 4] >> state_offset) & 0x3;
187 static int mv88e6185_g1_vtu_data_write(struct mv88e6xxx_chip *chip,
188 struct mv88e6xxx_vtu_entry *entry)
193 /* Insert MemberTag and PortState data */
194 for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
195 unsigned int member_offset = (i % 4) * 4;
196 unsigned int state_offset = member_offset + 2;
198 regs[i / 4] |= (entry->member[i] & 0x3) << member_offset;
199 regs[i / 4] |= (entry->state[i] & 0x3) << state_offset;
202 /* Write all 3 VTU/STU Data registers */
203 for (i = 0; i < 3; ++i) {
207 err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
215 static int mv88e6390_g1_vtu_data_read(struct mv88e6xxx_chip *chip, u8 *data)
220 /* Read the 2 VTU/STU Data registers */
221 for (i = 0; i < 2; ++i) {
225 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
231 for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
232 unsigned int offset = (i % 8) * 2;
234 data[i] = (regs[i / 8] >> offset) & 0x3;
240 static int mv88e6390_g1_vtu_data_write(struct mv88e6xxx_chip *chip, u8 *data)
246 for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
247 unsigned int offset = (i % 8) * 2;
249 regs[i / 8] |= (data[i] & 0x3) << offset;
252 /* Write the 2 VTU/STU Data registers */
253 for (i = 0; i < 2; ++i) {
257 err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
265 /* VLAN Translation Unit Operations */
267 static int mv88e6xxx_g1_vtu_stu_getnext(struct mv88e6xxx_chip *chip,
268 struct mv88e6xxx_vtu_entry *entry)
272 err = mv88e6xxx_g1_vtu_sid_write(chip, entry);
276 err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_STU_GET_NEXT);
280 err = mv88e6xxx_g1_vtu_sid_read(chip, entry);
284 return mv88e6xxx_g1_vtu_vid_read(chip, entry);
287 static int mv88e6xxx_g1_vtu_stu_get(struct mv88e6xxx_chip *chip,
288 struct mv88e6xxx_vtu_entry *vtu)
290 struct mv88e6xxx_vtu_entry stu;
293 err = mv88e6xxx_g1_vtu_sid_read(chip, vtu);
297 stu.sid = vtu->sid - 1;
299 err = mv88e6xxx_g1_vtu_stu_getnext(chip, &stu);
303 if (stu.sid != vtu->sid || !stu.valid)
309 static int mv88e6xxx_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
310 struct mv88e6xxx_vtu_entry *entry)
314 err = mv88e6xxx_g1_vtu_op_wait(chip);
318 /* To get the next higher active VID, the VTU GetNext operation can be
319 * started again without setting the VID registers since it already
320 * contains the last VID.
322 * To save a few hardware accesses and abstract this to the caller,
323 * write the VID only once, when the entry is given as invalid.
326 err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
331 err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_GET_NEXT);
335 return mv88e6xxx_g1_vtu_vid_read(chip, entry);
338 int mv88e6185_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
339 struct mv88e6xxx_vtu_entry *entry)
344 err = mv88e6xxx_g1_vtu_getnext(chip, entry);
349 err = mv88e6185_g1_vtu_data_read(chip, entry);
353 err = mv88e6185_g1_stu_data_read(chip, entry);
357 /* VTU DBNum[3:0] are located in VTU Operation 3:0
358 * VTU DBNum[7:4] are located in VTU Operation 11:8
360 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val);
364 entry->fid = val & 0x000f;
365 entry->fid |= (val & 0x0f00) >> 4;
371 int mv88e6352_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
372 struct mv88e6xxx_vtu_entry *entry)
376 /* Fetch VLAN MemberTag data from the VTU */
377 err = mv88e6xxx_g1_vtu_getnext(chip, entry);
382 err = mv88e6185_g1_vtu_data_read(chip, entry);
386 err = mv88e6xxx_g1_vtu_fid_read(chip, entry);
390 /* Fetch VLAN PortState data from the STU */
391 err = mv88e6xxx_g1_vtu_stu_get(chip, entry);
395 err = mv88e6185_g1_stu_data_read(chip, entry);
403 int mv88e6390_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
404 struct mv88e6xxx_vtu_entry *entry)
408 /* Fetch VLAN MemberTag data from the VTU */
409 err = mv88e6xxx_g1_vtu_getnext(chip, entry);
414 err = mv88e6390_g1_vtu_data_read(chip, entry->member);
418 /* Fetch VLAN PortState data from the STU */
419 err = mv88e6xxx_g1_vtu_stu_get(chip, entry);
423 err = mv88e6390_g1_vtu_data_read(chip, entry->state);
427 err = mv88e6xxx_g1_vtu_fid_read(chip, entry);
435 int mv88e6185_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
436 struct mv88e6xxx_vtu_entry *entry)
438 u16 op = MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE;
441 err = mv88e6xxx_g1_vtu_op_wait(chip);
445 err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
450 err = mv88e6185_g1_vtu_data_write(chip, entry);
454 /* VTU DBNum[3:0] are located in VTU Operation 3:0
455 * VTU DBNum[7:4] are located in VTU Operation 11:8
457 op |= entry->fid & 0x000f;
458 op |= (entry->fid & 0x00f0) << 4;
461 return mv88e6xxx_g1_vtu_op(chip, op);
464 int mv88e6352_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
465 struct mv88e6xxx_vtu_entry *entry)
469 err = mv88e6xxx_g1_vtu_op_wait(chip);
473 err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
478 /* Write MemberTag and PortState data */
479 err = mv88e6185_g1_vtu_data_write(chip, entry);
483 err = mv88e6xxx_g1_vtu_sid_write(chip, entry);
488 err = mv88e6xxx_g1_vtu_op(chip,
489 MV88E6XXX_G1_VTU_OP_STU_LOAD_PURGE);
493 err = mv88e6xxx_g1_vtu_fid_write(chip, entry);
498 /* Load/Purge VTU entry */
499 return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE);
502 int mv88e6390_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
503 struct mv88e6xxx_vtu_entry *entry)
507 err = mv88e6xxx_g1_vtu_op_wait(chip);
511 err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
516 /* Write PortState data */
517 err = mv88e6390_g1_vtu_data_write(chip, entry->state);
521 err = mv88e6xxx_g1_vtu_sid_write(chip, entry);
526 err = mv88e6xxx_g1_vtu_op(chip,
527 MV88E6XXX_G1_VTU_OP_STU_LOAD_PURGE);
531 /* Write MemberTag data */
532 err = mv88e6390_g1_vtu_data_write(chip, entry->member);
536 err = mv88e6xxx_g1_vtu_fid_write(chip, entry);
541 /* Load/Purge VTU entry */
542 return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE);
545 int mv88e6xxx_g1_vtu_flush(struct mv88e6xxx_chip *chip)
549 err = mv88e6xxx_g1_vtu_op_wait(chip);
553 return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_FLUSH_ALL);