12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2332aa5ccSVivien Didelot /*
3332aa5ccSVivien Didelot  * Marvell 88E6xxx VLAN [Spanning Tree] Translation Unit (VTU [STU]) support
4332aa5ccSVivien Didelot  *
5332aa5ccSVivien Didelot  * Copyright (c) 2008 Marvell Semiconductor
6332aa5ccSVivien Didelot  * Copyright (c) 2015 CMC Electronics, Inc.
7332aa5ccSVivien Didelot  * Copyright (c) 2017 Savoir-faire Linux, Inc.
8332aa5ccSVivien Didelot  */
9332aa5ccSVivien Didelot 
1019fb7f69SVivien Didelot #include <linux/bitfield.h>
1162eb1162SAndrew Lunn #include <linux/interrupt.h>
1262eb1162SAndrew Lunn #include <linux/irqdomain.h>
1362eb1162SAndrew Lunn 
144d5f2ba7SVivien Didelot #include "chip.h"
15332aa5ccSVivien Didelot #include "global1.h"
16*9e3d9ae5SVladimir Oltean #include "trace.h"
17332aa5ccSVivien Didelot 
188ee51f6bSVivien Didelot /* Offset 0x02: VTU FID Register */
198ee51f6bSVivien Didelot 
mv88e6xxx_g1_vtu_fid_read(struct mv88e6xxx_chip * chip,struct mv88e6xxx_vtu_entry * entry)20bf7d71c0SVivien Didelot static int mv88e6xxx_g1_vtu_fid_read(struct mv88e6xxx_chip *chip,
218ee51f6bSVivien Didelot 				     struct mv88e6xxx_vtu_entry *entry)
228ee51f6bSVivien Didelot {
238ee51f6bSVivien Didelot 	u16 val;
248ee51f6bSVivien Didelot 	int err;
258ee51f6bSVivien Didelot 
267ec60d6eSVivien Didelot 	err = mv88e6xxx_g1_read(chip, MV88E6352_G1_VTU_FID, &val);
278ee51f6bSVivien Didelot 	if (err)
288ee51f6bSVivien Didelot 		return err;
298ee51f6bSVivien Didelot 
307ec60d6eSVivien Didelot 	entry->fid = val & MV88E6352_G1_VTU_FID_MASK;
31bb03b280STobias Waldekranz 	entry->policy = !!(val & MV88E6352_G1_VTU_FID_VID_POLICY);
328ee51f6bSVivien Didelot 	return 0;
338ee51f6bSVivien Didelot }
348ee51f6bSVivien Didelot 
mv88e6xxx_g1_vtu_fid_write(struct mv88e6xxx_chip * chip,struct mv88e6xxx_vtu_entry * entry)35bf7d71c0SVivien Didelot static int mv88e6xxx_g1_vtu_fid_write(struct mv88e6xxx_chip *chip,
368ee51f6bSVivien Didelot 				      struct mv88e6xxx_vtu_entry *entry)
378ee51f6bSVivien Didelot {
387ec60d6eSVivien Didelot 	u16 val = entry->fid & MV88E6352_G1_VTU_FID_MASK;
398ee51f6bSVivien Didelot 
40bb03b280STobias Waldekranz 	if (entry->policy)
41bb03b280STobias Waldekranz 		val |= MV88E6352_G1_VTU_FID_VID_POLICY;
42bb03b280STobias Waldekranz 
437ec60d6eSVivien Didelot 	return mv88e6xxx_g1_write(chip, MV88E6352_G1_VTU_FID, val);
448ee51f6bSVivien Didelot }
458ee51f6bSVivien Didelot 
46d2ca1ea1SVivien Didelot /* Offset 0x03: VTU SID Register */
47d2ca1ea1SVivien Didelot 
mv88e6xxx_g1_vtu_sid_read(struct mv88e6xxx_chip * chip,u8 * sid)4849c98c1dSTobias Waldekranz static int mv88e6xxx_g1_vtu_sid_read(struct mv88e6xxx_chip *chip, u8 *sid)
49d2ca1ea1SVivien Didelot {
50d2ca1ea1SVivien Didelot 	u16 val;
51d2ca1ea1SVivien Didelot 	int err;
52d2ca1ea1SVivien Didelot 
537ec60d6eSVivien Didelot 	err = mv88e6xxx_g1_read(chip, MV88E6352_G1_VTU_SID, &val);
54d2ca1ea1SVivien Didelot 	if (err)
55d2ca1ea1SVivien Didelot 		return err;
56d2ca1ea1SVivien Didelot 
5749c98c1dSTobias Waldekranz 	*sid = val & MV88E6352_G1_VTU_SID_MASK;
58d2ca1ea1SVivien Didelot 
59d2ca1ea1SVivien Didelot 	return 0;
60d2ca1ea1SVivien Didelot }
61d2ca1ea1SVivien Didelot 
mv88e6xxx_g1_vtu_sid_write(struct mv88e6xxx_chip * chip,u8 sid)6249c98c1dSTobias Waldekranz static int mv88e6xxx_g1_vtu_sid_write(struct mv88e6xxx_chip *chip, u8 sid)
63d2ca1ea1SVivien Didelot {
6449c98c1dSTobias Waldekranz 	u16 val = sid & MV88E6352_G1_VTU_SID_MASK;
65d2ca1ea1SVivien Didelot 
667ec60d6eSVivien Didelot 	return mv88e6xxx_g1_write(chip, MV88E6352_G1_VTU_SID, val);
67d2ca1ea1SVivien Didelot }
68d2ca1ea1SVivien Didelot 
69332aa5ccSVivien Didelot /* Offset 0x05: VTU Operation Register */
70332aa5ccSVivien Didelot 
mv88e6xxx_g1_vtu_op_wait(struct mv88e6xxx_chip * chip)71bf7d71c0SVivien Didelot static int mv88e6xxx_g1_vtu_op_wait(struct mv88e6xxx_chip *chip)
72332aa5ccSVivien Didelot {
7319fb7f69SVivien Didelot 	int bit = __bf_shf(MV88E6XXX_G1_VTU_OP_BUSY);
7419fb7f69SVivien Didelot 
7519fb7f69SVivien Didelot 	return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_VTU_OP, bit, 0);
76332aa5ccSVivien Didelot }
77332aa5ccSVivien Didelot 
mv88e6xxx_g1_vtu_op(struct mv88e6xxx_chip * chip,u16 op)78bf7d71c0SVivien Didelot static int mv88e6xxx_g1_vtu_op(struct mv88e6xxx_chip *chip, u16 op)
79332aa5ccSVivien Didelot {
80332aa5ccSVivien Didelot 	int err;
81332aa5ccSVivien Didelot 
827ec60d6eSVivien Didelot 	err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_OP,
837ec60d6eSVivien Didelot 				 MV88E6XXX_G1_VTU_OP_BUSY | op);
84332aa5ccSVivien Didelot 	if (err)
85332aa5ccSVivien Didelot 		return err;
86332aa5ccSVivien Didelot 
87332aa5ccSVivien Didelot 	return mv88e6xxx_g1_vtu_op_wait(chip);
88332aa5ccSVivien Didelot }
89b486d7c9SVivien Didelot 
903afb4bdeSVivien Didelot /* Offset 0x06: VTU VID Register */
913afb4bdeSVivien Didelot 
mv88e6xxx_g1_vtu_vid_read(struct mv88e6xxx_chip * chip,bool * valid,u16 * vid)92bf7d71c0SVivien Didelot static int mv88e6xxx_g1_vtu_vid_read(struct mv88e6xxx_chip *chip,
9349c98c1dSTobias Waldekranz 				     bool *valid, u16 *vid)
943afb4bdeSVivien Didelot {
953afb4bdeSVivien Didelot 	u16 val;
963afb4bdeSVivien Didelot 	int err;
973afb4bdeSVivien Didelot 
987ec60d6eSVivien Didelot 	err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_VID, &val);
993afb4bdeSVivien Didelot 	if (err)
1003afb4bdeSVivien Didelot 		return err;
1013afb4bdeSVivien Didelot 
10249c98c1dSTobias Waldekranz 	if (vid) {
10349c98c1dSTobias Waldekranz 		*vid = val & 0xfff;
1041ac75864SVivien Didelot 
1057ec60d6eSVivien Didelot 		if (val & MV88E6390_G1_VTU_VID_PAGE)
10649c98c1dSTobias Waldekranz 			*vid |= 0x1000;
10749c98c1dSTobias Waldekranz 	}
1081ac75864SVivien Didelot 
10949c98c1dSTobias Waldekranz 	if (valid)
11049c98c1dSTobias Waldekranz 		*valid = !!(val & MV88E6XXX_G1_VTU_VID_VALID);
1113afb4bdeSVivien Didelot 
1123afb4bdeSVivien Didelot 	return 0;
1133afb4bdeSVivien Didelot }
1143afb4bdeSVivien Didelot 
mv88e6xxx_g1_vtu_vid_write(struct mv88e6xxx_chip * chip,bool valid,u16 vid)115bf7d71c0SVivien Didelot static int mv88e6xxx_g1_vtu_vid_write(struct mv88e6xxx_chip *chip,
11649c98c1dSTobias Waldekranz 				      bool valid, u16 vid)
1173afb4bdeSVivien Didelot {
11849c98c1dSTobias Waldekranz 	u16 val = vid & 0xfff;
1193afb4bdeSVivien Didelot 
12049c98c1dSTobias Waldekranz 	if (vid & 0x1000)
1217ec60d6eSVivien Didelot 		val |= MV88E6390_G1_VTU_VID_PAGE;
1221ac75864SVivien Didelot 
12349c98c1dSTobias Waldekranz 	if (valid)
1247ec60d6eSVivien Didelot 		val |= MV88E6XXX_G1_VTU_VID_VALID;
1253afb4bdeSVivien Didelot 
1267ec60d6eSVivien Didelot 	return mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_VID, val);
1273afb4bdeSVivien Didelot }
1283afb4bdeSVivien Didelot 
129c499a64fSVivien Didelot /* Offset 0x07: VTU/STU Data Register 1
130c499a64fSVivien Didelot  * Offset 0x08: VTU/STU Data Register 2
131c499a64fSVivien Didelot  * Offset 0x09: VTU/STU Data Register 3
132c499a64fSVivien Didelot  */
mv88e6185_g1_vtu_stu_data_read(struct mv88e6xxx_chip * chip,u16 * regs)13392307069STobias Waldekranz static int mv88e6185_g1_vtu_stu_data_read(struct mv88e6xxx_chip *chip,
13492307069STobias Waldekranz 					  u16 *regs)
135c499a64fSVivien Didelot {
136c499a64fSVivien Didelot 	int i;
137c499a64fSVivien Didelot 
138c499a64fSVivien Didelot 	/* Read all 3 VTU/STU Data registers */
139c499a64fSVivien Didelot 	for (i = 0; i < 3; ++i) {
140c499a64fSVivien Didelot 		u16 *reg = &regs[i];
141c499a64fSVivien Didelot 		int err;
142c499a64fSVivien Didelot 
1437ec60d6eSVivien Didelot 		err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
144c499a64fSVivien Didelot 		if (err)
145c499a64fSVivien Didelot 			return err;
146c499a64fSVivien Didelot 	}
147c499a64fSVivien Didelot 
14892307069STobias Waldekranz 	return 0;
14992307069STobias Waldekranz }
15092307069STobias Waldekranz 
mv88e6185_g1_vtu_data_read(struct mv88e6xxx_chip * chip,u8 * member,u8 * state)15192307069STobias Waldekranz static int mv88e6185_g1_vtu_data_read(struct mv88e6xxx_chip *chip,
15249c98c1dSTobias Waldekranz 				      u8 *member, u8 *state)
15392307069STobias Waldekranz {
15492307069STobias Waldekranz 	u16 regs[3];
15592307069STobias Waldekranz 	int err;
15692307069STobias Waldekranz 	int i;
15792307069STobias Waldekranz 
15892307069STobias Waldekranz 	err = mv88e6185_g1_vtu_stu_data_read(chip, regs);
15992307069STobias Waldekranz 	if (err)
16092307069STobias Waldekranz 		return err;
16192307069STobias Waldekranz 
16292307069STobias Waldekranz 	/* Extract MemberTag data */
163c499a64fSVivien Didelot 	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
164c499a64fSVivien Didelot 		unsigned int member_offset = (i % 4) * 4;
16549c98c1dSTobias Waldekranz 		unsigned int state_offset = member_offset + 2;
166c499a64fSVivien Didelot 
16749c98c1dSTobias Waldekranz 		if (member)
16849c98c1dSTobias Waldekranz 			member[i] = (regs[i / 4] >> member_offset) & 0x3;
16992307069STobias Waldekranz 
17049c98c1dSTobias Waldekranz 		if (state)
17149c98c1dSTobias Waldekranz 			state[i] = (regs[i / 4] >> state_offset) & 0x3;
172c499a64fSVivien Didelot 	}
173c499a64fSVivien Didelot 
174c499a64fSVivien Didelot 	return 0;
175c499a64fSVivien Didelot }
176c499a64fSVivien Didelot 
mv88e6185_g1_vtu_data_write(struct mv88e6xxx_chip * chip,u8 * member,u8 * state)177bf7d71c0SVivien Didelot static int mv88e6185_g1_vtu_data_write(struct mv88e6xxx_chip *chip,
17849c98c1dSTobias Waldekranz 				       u8 *member, u8 *state)
179c499a64fSVivien Didelot {
180c499a64fSVivien Didelot 	u16 regs[3] = { 0 };
181c499a64fSVivien Didelot 	int i;
182c499a64fSVivien Didelot 
183c499a64fSVivien Didelot 	/* Insert MemberTag and PortState data */
184c499a64fSVivien Didelot 	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
185c499a64fSVivien Didelot 		unsigned int member_offset = (i % 4) * 4;
186c499a64fSVivien Didelot 		unsigned int state_offset = member_offset + 2;
187c499a64fSVivien Didelot 
18849c98c1dSTobias Waldekranz 		if (member)
18949c98c1dSTobias Waldekranz 			regs[i / 4] |= (member[i] & 0x3) << member_offset;
19049c98c1dSTobias Waldekranz 
19149c98c1dSTobias Waldekranz 		if (state)
19249c98c1dSTobias Waldekranz 			regs[i / 4] |= (state[i] & 0x3) << state_offset;
193c499a64fSVivien Didelot 	}
194c499a64fSVivien Didelot 
195c499a64fSVivien Didelot 	/* Write all 3 VTU/STU Data registers */
196c499a64fSVivien Didelot 	for (i = 0; i < 3; ++i) {
197c499a64fSVivien Didelot 		u16 reg = regs[i];
198c499a64fSVivien Didelot 		int err;
199c499a64fSVivien Didelot 
2007ec60d6eSVivien Didelot 		err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
201c499a64fSVivien Didelot 		if (err)
202c499a64fSVivien Didelot 			return err;
203c499a64fSVivien Didelot 	}
204c499a64fSVivien Didelot 
205c499a64fSVivien Didelot 	return 0;
206c499a64fSVivien Didelot }
207c499a64fSVivien Didelot 
mv88e6390_g1_vtu_data_read(struct mv88e6xxx_chip * chip,u8 * data)208931d1822SVivien Didelot static int mv88e6390_g1_vtu_data_read(struct mv88e6xxx_chip *chip, u8 *data)
209931d1822SVivien Didelot {
210931d1822SVivien Didelot 	u16 regs[2];
211931d1822SVivien Didelot 	int i;
212931d1822SVivien Didelot 
213931d1822SVivien Didelot 	/* Read the 2 VTU/STU Data registers */
214931d1822SVivien Didelot 	for (i = 0; i < 2; ++i) {
215931d1822SVivien Didelot 		u16 *reg = &regs[i];
216931d1822SVivien Didelot 		int err;
217931d1822SVivien Didelot 
2187ec60d6eSVivien Didelot 		err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
219931d1822SVivien Didelot 		if (err)
220931d1822SVivien Didelot 			return err;
221931d1822SVivien Didelot 	}
222931d1822SVivien Didelot 
223931d1822SVivien Didelot 	/* Extract data */
224931d1822SVivien Didelot 	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
225931d1822SVivien Didelot 		unsigned int offset = (i % 8) * 2;
226931d1822SVivien Didelot 
227931d1822SVivien Didelot 		data[i] = (regs[i / 8] >> offset) & 0x3;
228931d1822SVivien Didelot 	}
229931d1822SVivien Didelot 
230931d1822SVivien Didelot 	return 0;
231931d1822SVivien Didelot }
232931d1822SVivien Didelot 
mv88e6390_g1_vtu_data_write(struct mv88e6xxx_chip * chip,u8 * data)233931d1822SVivien Didelot static int mv88e6390_g1_vtu_data_write(struct mv88e6xxx_chip *chip, u8 *data)
234931d1822SVivien Didelot {
235931d1822SVivien Didelot 	u16 regs[2] = { 0 };
236931d1822SVivien Didelot 	int i;
237931d1822SVivien Didelot 
238931d1822SVivien Didelot 	/* Insert data */
239931d1822SVivien Didelot 	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
240931d1822SVivien Didelot 		unsigned int offset = (i % 8) * 2;
241931d1822SVivien Didelot 
242931d1822SVivien Didelot 		regs[i / 8] |= (data[i] & 0x3) << offset;
243931d1822SVivien Didelot 	}
244931d1822SVivien Didelot 
245931d1822SVivien Didelot 	/* Write the 2 VTU/STU Data registers */
246931d1822SVivien Didelot 	for (i = 0; i < 2; ++i) {
247931d1822SVivien Didelot 		u16 reg = regs[i];
248931d1822SVivien Didelot 		int err;
249931d1822SVivien Didelot 
2507ec60d6eSVivien Didelot 		err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
251931d1822SVivien Didelot 		if (err)
252931d1822SVivien Didelot 			return err;
253931d1822SVivien Didelot 	}
254931d1822SVivien Didelot 
255931d1822SVivien Didelot 	return 0;
256931d1822SVivien Didelot }
257931d1822SVivien Didelot 
258b486d7c9SVivien Didelot /* VLAN Translation Unit Operations */
259b486d7c9SVivien Didelot 
mv88e6xxx_g1_vtu_getnext(struct mv88e6xxx_chip * chip,struct mv88e6xxx_vtu_entry * entry)260ca4d632aSTobias Waldekranz int mv88e6xxx_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
261f169e5eeSVivien Didelot 			     struct mv88e6xxx_vtu_entry *entry)
262f169e5eeSVivien Didelot {
263f169e5eeSVivien Didelot 	int err;
264f169e5eeSVivien Didelot 
265f169e5eeSVivien Didelot 	err = mv88e6xxx_g1_vtu_op_wait(chip);
266f169e5eeSVivien Didelot 	if (err)
267f169e5eeSVivien Didelot 		return err;
268f169e5eeSVivien Didelot 
269f169e5eeSVivien Didelot 	/* To get the next higher active VID, the VTU GetNext operation can be
270f169e5eeSVivien Didelot 	 * started again without setting the VID registers since it already
271f169e5eeSVivien Didelot 	 * contains the last VID.
272f169e5eeSVivien Didelot 	 *
273f169e5eeSVivien Didelot 	 * To save a few hardware accesses and abstract this to the caller,
274f169e5eeSVivien Didelot 	 * write the VID only once, when the entry is given as invalid.
275f169e5eeSVivien Didelot 	 */
276f169e5eeSVivien Didelot 	if (!entry->valid) {
27749c98c1dSTobias Waldekranz 		err = mv88e6xxx_g1_vtu_vid_write(chip, false, entry->vid);
278f169e5eeSVivien Didelot 		if (err)
279f169e5eeSVivien Didelot 			return err;
280f169e5eeSVivien Didelot 	}
281f169e5eeSVivien Didelot 
2827ec60d6eSVivien Didelot 	err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_GET_NEXT);
283f169e5eeSVivien Didelot 	if (err)
284f169e5eeSVivien Didelot 		return err;
285f169e5eeSVivien Didelot 
28649c98c1dSTobias Waldekranz 	return mv88e6xxx_g1_vtu_vid_read(chip, &entry->valid, &entry->vid);
287f169e5eeSVivien Didelot }
288f169e5eeSVivien Didelot 
mv88e6185_g1_vtu_getnext(struct mv88e6xxx_chip * chip,struct mv88e6xxx_vtu_entry * entry)289f1394b78SVivien Didelot int mv88e6185_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
290f1394b78SVivien Didelot 			     struct mv88e6xxx_vtu_entry *entry)
291f1394b78SVivien Didelot {
292f1394b78SVivien Didelot 	u16 val;
293f1394b78SVivien Didelot 	int err;
294f1394b78SVivien Didelot 
295f1394b78SVivien Didelot 	err = mv88e6xxx_g1_vtu_getnext(chip, entry);
296f1394b78SVivien Didelot 	if (err)
297f1394b78SVivien Didelot 		return err;
298f1394b78SVivien Didelot 
299f1394b78SVivien Didelot 	if (entry->valid) {
30049c98c1dSTobias Waldekranz 		err = mv88e6185_g1_vtu_data_read(chip, entry->member, entry->state);
30192307069STobias Waldekranz 		if (err)
30292307069STobias Waldekranz 			return err;
30392307069STobias Waldekranz 
304f1394b78SVivien Didelot 		/* VTU DBNum[3:0] are located in VTU Operation 3:0
30567c9ed1cSRasmus Villemoes 		 * VTU DBNum[7:4] ([5:4] for 6250) are located in VTU Operation 11:8 (9:8)
306f1394b78SVivien Didelot 		 */
3077ec60d6eSVivien Didelot 		err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val);
308f1394b78SVivien Didelot 		if (err)
309f1394b78SVivien Didelot 			return err;
310f1394b78SVivien Didelot 
311f1394b78SVivien Didelot 		entry->fid = val & 0x000f;
312f1394b78SVivien Didelot 		entry->fid |= (val & 0x0f00) >> 4;
31367c9ed1cSRasmus Villemoes 		entry->fid &= mv88e6xxx_num_databases(chip) - 1;
314f1394b78SVivien Didelot 	}
315f1394b78SVivien Didelot 
316f1394b78SVivien Didelot 	return 0;
317f1394b78SVivien Didelot }
318f1394b78SVivien Didelot 
mv88e6352_g1_vtu_getnext(struct mv88e6xxx_chip * chip,struct mv88e6xxx_vtu_entry * entry)319f1394b78SVivien Didelot int mv88e6352_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
320f1394b78SVivien Didelot 			     struct mv88e6xxx_vtu_entry *entry)
321f1394b78SVivien Didelot {
322f1394b78SVivien Didelot 	int err;
323f1394b78SVivien Didelot 
324f1394b78SVivien Didelot 	/* Fetch VLAN MemberTag data from the VTU */
325f1394b78SVivien Didelot 	err = mv88e6xxx_g1_vtu_getnext(chip, entry);
326f1394b78SVivien Didelot 	if (err)
327f1394b78SVivien Didelot 		return err;
328f1394b78SVivien Didelot 
329f1394b78SVivien Didelot 	if (entry->valid) {
33049c98c1dSTobias Waldekranz 		err = mv88e6185_g1_vtu_data_read(chip, entry->member, NULL);
331f1394b78SVivien Didelot 		if (err)
332f1394b78SVivien Didelot 			return err;
333f1394b78SVivien Didelot 
334f1394b78SVivien Didelot 		err = mv88e6xxx_g1_vtu_fid_read(chip, entry);
335f1394b78SVivien Didelot 		if (err)
336f1394b78SVivien Didelot 			return err;
33792307069STobias Waldekranz 
33849c98c1dSTobias Waldekranz 		err = mv88e6xxx_g1_vtu_sid_read(chip, &entry->sid);
33992307069STobias Waldekranz 		if (err)
34092307069STobias Waldekranz 			return err;
341f1394b78SVivien Didelot 	}
342f1394b78SVivien Didelot 
343f1394b78SVivien Didelot 	return 0;
344f1394b78SVivien Didelot }
345f1394b78SVivien Didelot 
mv88e6390_g1_vtu_getnext(struct mv88e6xxx_chip * chip,struct mv88e6xxx_vtu_entry * entry)346931d1822SVivien Didelot int mv88e6390_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
347931d1822SVivien Didelot 			     struct mv88e6xxx_vtu_entry *entry)
348931d1822SVivien Didelot {
349931d1822SVivien Didelot 	int err;
350931d1822SVivien Didelot 
351931d1822SVivien Didelot 	/* Fetch VLAN MemberTag data from the VTU */
352931d1822SVivien Didelot 	err = mv88e6xxx_g1_vtu_getnext(chip, entry);
353931d1822SVivien Didelot 	if (err)
354931d1822SVivien Didelot 		return err;
355931d1822SVivien Didelot 
356931d1822SVivien Didelot 	if (entry->valid) {
357931d1822SVivien Didelot 		err = mv88e6390_g1_vtu_data_read(chip, entry->member);
358931d1822SVivien Didelot 		if (err)
359931d1822SVivien Didelot 			return err;
360931d1822SVivien Didelot 
361931d1822SVivien Didelot 		err = mv88e6xxx_g1_vtu_fid_read(chip, entry);
362931d1822SVivien Didelot 		if (err)
363931d1822SVivien Didelot 			return err;
36449c98c1dSTobias Waldekranz 
36549c98c1dSTobias Waldekranz 		err = mv88e6xxx_g1_vtu_sid_read(chip, &entry->sid);
36649c98c1dSTobias Waldekranz 		if (err)
36749c98c1dSTobias Waldekranz 			return err;
368931d1822SVivien Didelot 	}
369931d1822SVivien Didelot 
370931d1822SVivien Didelot 	return 0;
371931d1822SVivien Didelot }
372931d1822SVivien Didelot 
mv88e6185_g1_vtu_loadpurge(struct mv88e6xxx_chip * chip,struct mv88e6xxx_vtu_entry * entry)3730ad5daf6SVivien Didelot int mv88e6185_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
3740ad5daf6SVivien Didelot 			       struct mv88e6xxx_vtu_entry *entry)
3750ad5daf6SVivien Didelot {
3767ec60d6eSVivien Didelot 	u16 op = MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE;
3770ad5daf6SVivien Didelot 	int err;
3780ad5daf6SVivien Didelot 
3790ad5daf6SVivien Didelot 	err = mv88e6xxx_g1_vtu_op_wait(chip);
3800ad5daf6SVivien Didelot 	if (err)
3810ad5daf6SVivien Didelot 		return err;
3820ad5daf6SVivien Didelot 
38349c98c1dSTobias Waldekranz 	err = mv88e6xxx_g1_vtu_vid_write(chip, entry->valid, entry->vid);
3840ad5daf6SVivien Didelot 	if (err)
3850ad5daf6SVivien Didelot 		return err;
3860ad5daf6SVivien Didelot 
3870ad5daf6SVivien Didelot 	if (entry->valid) {
38849c98c1dSTobias Waldekranz 		err = mv88e6185_g1_vtu_data_write(chip, entry->member, entry->state);
3890ad5daf6SVivien Didelot 		if (err)
3900ad5daf6SVivien Didelot 			return err;
3910ad5daf6SVivien Didelot 
3920ad5daf6SVivien Didelot 		/* VTU DBNum[3:0] are located in VTU Operation 3:0
3930ad5daf6SVivien Didelot 		 * VTU DBNum[7:4] are located in VTU Operation 11:8
394b28f3f3cSRasmus Villemoes 		 *
395b28f3f3cSRasmus Villemoes 		 * For the 6250/6220, the latter are really [5:4] and
396b28f3f3cSRasmus Villemoes 		 * 9:8, but in those cases bits 7:6 of entry->fid are
397b28f3f3cSRasmus Villemoes 		 * 0 since they have num_databases = 64.
3980ad5daf6SVivien Didelot 		 */
3990ad5daf6SVivien Didelot 		op |= entry->fid & 0x000f;
40048620e34SRasmus Villemoes 		op |= (entry->fid & 0x00f0) << 4;
4010ad5daf6SVivien Didelot 	}
4020ad5daf6SVivien Didelot 
4030ad5daf6SVivien Didelot 	return mv88e6xxx_g1_vtu_op(chip, op);
4040ad5daf6SVivien Didelot }
4050ad5daf6SVivien Didelot 
mv88e6352_g1_vtu_loadpurge(struct mv88e6xxx_chip * chip,struct mv88e6xxx_vtu_entry * entry)4060ad5daf6SVivien Didelot int mv88e6352_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
4070ad5daf6SVivien Didelot 			       struct mv88e6xxx_vtu_entry *entry)
4080ad5daf6SVivien Didelot {
4090ad5daf6SVivien Didelot 	int err;
4100ad5daf6SVivien Didelot 
4110ad5daf6SVivien Didelot 	err = mv88e6xxx_g1_vtu_op_wait(chip);
4120ad5daf6SVivien Didelot 	if (err)
4130ad5daf6SVivien Didelot 		return err;
4140ad5daf6SVivien Didelot 
41549c98c1dSTobias Waldekranz 	err = mv88e6xxx_g1_vtu_vid_write(chip, entry->valid, entry->vid);
4160ad5daf6SVivien Didelot 	if (err)
4170ad5daf6SVivien Didelot 		return err;
4180ad5daf6SVivien Didelot 
4190ad5daf6SVivien Didelot 	if (entry->valid) {
42049c98c1dSTobias Waldekranz 		/* Write MemberTag data */
42149c98c1dSTobias Waldekranz 		err = mv88e6185_g1_vtu_data_write(chip, entry->member, NULL);
4220ad5daf6SVivien Didelot 		if (err)
4230ad5daf6SVivien Didelot 			return err;
4240ad5daf6SVivien Didelot 
4250ad5daf6SVivien Didelot 		err = mv88e6xxx_g1_vtu_fid_write(chip, entry);
4260ad5daf6SVivien Didelot 		if (err)
4270ad5daf6SVivien Didelot 			return err;
42849c98c1dSTobias Waldekranz 
42949c98c1dSTobias Waldekranz 		err = mv88e6xxx_g1_vtu_sid_write(chip, entry->sid);
43049c98c1dSTobias Waldekranz 		if (err)
43149c98c1dSTobias Waldekranz 			return err;
4320ad5daf6SVivien Didelot 	}
4330ad5daf6SVivien Didelot 
4340ad5daf6SVivien Didelot 	/* Load/Purge VTU entry */
4357ec60d6eSVivien Didelot 	return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE);
4360ad5daf6SVivien Didelot }
4370ad5daf6SVivien Didelot 
mv88e6390_g1_vtu_loadpurge(struct mv88e6xxx_chip * chip,struct mv88e6xxx_vtu_entry * entry)438931d1822SVivien Didelot int mv88e6390_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
439931d1822SVivien Didelot 			       struct mv88e6xxx_vtu_entry *entry)
440931d1822SVivien Didelot {
441931d1822SVivien Didelot 	int err;
442931d1822SVivien Didelot 
443931d1822SVivien Didelot 	err = mv88e6xxx_g1_vtu_op_wait(chip);
444931d1822SVivien Didelot 	if (err)
445931d1822SVivien Didelot 		return err;
446931d1822SVivien Didelot 
44749c98c1dSTobias Waldekranz 	err = mv88e6xxx_g1_vtu_vid_write(chip, entry->valid, entry->vid);
448931d1822SVivien Didelot 	if (err)
449931d1822SVivien Didelot 		return err;
450931d1822SVivien Didelot 
451931d1822SVivien Didelot 	if (entry->valid) {
452931d1822SVivien Didelot 		/* Write MemberTag data */
453931d1822SVivien Didelot 		err = mv88e6390_g1_vtu_data_write(chip, entry->member);
454931d1822SVivien Didelot 		if (err)
455931d1822SVivien Didelot 			return err;
456931d1822SVivien Didelot 
457931d1822SVivien Didelot 		err = mv88e6xxx_g1_vtu_fid_write(chip, entry);
458931d1822SVivien Didelot 		if (err)
459931d1822SVivien Didelot 			return err;
46049c98c1dSTobias Waldekranz 
46149c98c1dSTobias Waldekranz 		err = mv88e6xxx_g1_vtu_sid_write(chip, entry->sid);
46249c98c1dSTobias Waldekranz 		if (err)
46349c98c1dSTobias Waldekranz 			return err;
464931d1822SVivien Didelot 	}
465931d1822SVivien Didelot 
466931d1822SVivien Didelot 	/* Load/Purge VTU entry */
4677ec60d6eSVivien Didelot 	return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE);
468931d1822SVivien Didelot }
469931d1822SVivien Didelot 
mv88e6xxx_g1_vtu_flush(struct mv88e6xxx_chip * chip)470b486d7c9SVivien Didelot int mv88e6xxx_g1_vtu_flush(struct mv88e6xxx_chip *chip)
471b486d7c9SVivien Didelot {
472b486d7c9SVivien Didelot 	int err;
473b486d7c9SVivien Didelot 
474b486d7c9SVivien Didelot 	err = mv88e6xxx_g1_vtu_op_wait(chip);
475b486d7c9SVivien Didelot 	if (err)
476b486d7c9SVivien Didelot 		return err;
477b486d7c9SVivien Didelot 
4787ec60d6eSVivien Didelot 	return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_FLUSH_ALL);
479b486d7c9SVivien Didelot }
48062eb1162SAndrew Lunn 
48149c98c1dSTobias Waldekranz /* Spanning Tree Unit Operations */
48249c98c1dSTobias Waldekranz 
mv88e6xxx_g1_stu_getnext(struct mv88e6xxx_chip * chip,struct mv88e6xxx_stu_entry * entry)48349c98c1dSTobias Waldekranz int mv88e6xxx_g1_stu_getnext(struct mv88e6xxx_chip *chip,
48449c98c1dSTobias Waldekranz 			     struct mv88e6xxx_stu_entry *entry)
48549c98c1dSTobias Waldekranz {
48649c98c1dSTobias Waldekranz 	int err;
48749c98c1dSTobias Waldekranz 
48849c98c1dSTobias Waldekranz 	err = mv88e6xxx_g1_vtu_op_wait(chip);
48949c98c1dSTobias Waldekranz 	if (err)
49049c98c1dSTobias Waldekranz 		return err;
49149c98c1dSTobias Waldekranz 
49249c98c1dSTobias Waldekranz 	/* To get the next higher active SID, the STU GetNext operation can be
49349c98c1dSTobias Waldekranz 	 * started again without setting the SID registers since it already
49449c98c1dSTobias Waldekranz 	 * contains the last SID.
49549c98c1dSTobias Waldekranz 	 *
49649c98c1dSTobias Waldekranz 	 * To save a few hardware accesses and abstract this to the caller,
49749c98c1dSTobias Waldekranz 	 * write the SID only once, when the entry is given as invalid.
49849c98c1dSTobias Waldekranz 	 */
49949c98c1dSTobias Waldekranz 	if (!entry->valid) {
50049c98c1dSTobias Waldekranz 		err = mv88e6xxx_g1_vtu_sid_write(chip, entry->sid);
50149c98c1dSTobias Waldekranz 		if (err)
50249c98c1dSTobias Waldekranz 			return err;
50349c98c1dSTobias Waldekranz 	}
50449c98c1dSTobias Waldekranz 
50549c98c1dSTobias Waldekranz 	err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_STU_GET_NEXT);
50649c98c1dSTobias Waldekranz 	if (err)
50749c98c1dSTobias Waldekranz 		return err;
50849c98c1dSTobias Waldekranz 
50949c98c1dSTobias Waldekranz 	err = mv88e6xxx_g1_vtu_vid_read(chip, &entry->valid, NULL);
51049c98c1dSTobias Waldekranz 	if (err)
51149c98c1dSTobias Waldekranz 		return err;
51249c98c1dSTobias Waldekranz 
51349c98c1dSTobias Waldekranz 	if (entry->valid) {
51449c98c1dSTobias Waldekranz 		err = mv88e6xxx_g1_vtu_sid_read(chip, &entry->sid);
51549c98c1dSTobias Waldekranz 		if (err)
51649c98c1dSTobias Waldekranz 			return err;
51749c98c1dSTobias Waldekranz 	}
51849c98c1dSTobias Waldekranz 
51949c98c1dSTobias Waldekranz 	return 0;
52049c98c1dSTobias Waldekranz }
52149c98c1dSTobias Waldekranz 
mv88e6352_g1_stu_getnext(struct mv88e6xxx_chip * chip,struct mv88e6xxx_stu_entry * entry)52249c98c1dSTobias Waldekranz int mv88e6352_g1_stu_getnext(struct mv88e6xxx_chip *chip,
52349c98c1dSTobias Waldekranz 			     struct mv88e6xxx_stu_entry *entry)
52449c98c1dSTobias Waldekranz {
52549c98c1dSTobias Waldekranz 	int err;
52649c98c1dSTobias Waldekranz 
52749c98c1dSTobias Waldekranz 	err = mv88e6xxx_g1_stu_getnext(chip, entry);
52849c98c1dSTobias Waldekranz 	if (err)
52949c98c1dSTobias Waldekranz 		return err;
53049c98c1dSTobias Waldekranz 
53149c98c1dSTobias Waldekranz 	if (!entry->valid)
53249c98c1dSTobias Waldekranz 		return 0;
53349c98c1dSTobias Waldekranz 
53449c98c1dSTobias Waldekranz 	return mv88e6185_g1_vtu_data_read(chip, NULL, entry->state);
53549c98c1dSTobias Waldekranz }
53649c98c1dSTobias Waldekranz 
mv88e6390_g1_stu_getnext(struct mv88e6xxx_chip * chip,struct mv88e6xxx_stu_entry * entry)53749c98c1dSTobias Waldekranz int mv88e6390_g1_stu_getnext(struct mv88e6xxx_chip *chip,
53849c98c1dSTobias Waldekranz 			     struct mv88e6xxx_stu_entry *entry)
53949c98c1dSTobias Waldekranz {
54049c98c1dSTobias Waldekranz 	int err;
54149c98c1dSTobias Waldekranz 
54249c98c1dSTobias Waldekranz 	err = mv88e6xxx_g1_stu_getnext(chip, entry);
54349c98c1dSTobias Waldekranz 	if (err)
54449c98c1dSTobias Waldekranz 		return err;
54549c98c1dSTobias Waldekranz 
54649c98c1dSTobias Waldekranz 	if (!entry->valid)
54749c98c1dSTobias Waldekranz 		return 0;
54849c98c1dSTobias Waldekranz 
54949c98c1dSTobias Waldekranz 	return mv88e6390_g1_vtu_data_read(chip, entry->state);
55049c98c1dSTobias Waldekranz }
55149c98c1dSTobias Waldekranz 
mv88e6352_g1_stu_loadpurge(struct mv88e6xxx_chip * chip,struct mv88e6xxx_stu_entry * entry)55249c98c1dSTobias Waldekranz int mv88e6352_g1_stu_loadpurge(struct mv88e6xxx_chip *chip,
55349c98c1dSTobias Waldekranz 			       struct mv88e6xxx_stu_entry *entry)
55449c98c1dSTobias Waldekranz {
55549c98c1dSTobias Waldekranz 	int err;
55649c98c1dSTobias Waldekranz 
55749c98c1dSTobias Waldekranz 	err = mv88e6xxx_g1_vtu_op_wait(chip);
55849c98c1dSTobias Waldekranz 	if (err)
55949c98c1dSTobias Waldekranz 		return err;
56049c98c1dSTobias Waldekranz 
56149c98c1dSTobias Waldekranz 	err = mv88e6xxx_g1_vtu_vid_write(chip, entry->valid, 0);
56249c98c1dSTobias Waldekranz 	if (err)
56349c98c1dSTobias Waldekranz 		return err;
56449c98c1dSTobias Waldekranz 
56549c98c1dSTobias Waldekranz 	err = mv88e6xxx_g1_vtu_sid_write(chip, entry->sid);
56649c98c1dSTobias Waldekranz 	if (err)
56749c98c1dSTobias Waldekranz 		return err;
56849c98c1dSTobias Waldekranz 
56949c98c1dSTobias Waldekranz 	if (entry->valid) {
57049c98c1dSTobias Waldekranz 		err = mv88e6185_g1_vtu_data_write(chip, NULL, entry->state);
57149c98c1dSTobias Waldekranz 		if (err)
57249c98c1dSTobias Waldekranz 			return err;
57349c98c1dSTobias Waldekranz 	}
57449c98c1dSTobias Waldekranz 
57549c98c1dSTobias Waldekranz 	/* Load/Purge STU entry */
57649c98c1dSTobias Waldekranz 	return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_STU_LOAD_PURGE);
57749c98c1dSTobias Waldekranz }
57849c98c1dSTobias Waldekranz 
mv88e6390_g1_stu_loadpurge(struct mv88e6xxx_chip * chip,struct mv88e6xxx_stu_entry * entry)57949c98c1dSTobias Waldekranz int mv88e6390_g1_stu_loadpurge(struct mv88e6xxx_chip *chip,
58049c98c1dSTobias Waldekranz 			       struct mv88e6xxx_stu_entry *entry)
58149c98c1dSTobias Waldekranz {
58249c98c1dSTobias Waldekranz 	int err;
58349c98c1dSTobias Waldekranz 
58449c98c1dSTobias Waldekranz 	err = mv88e6xxx_g1_vtu_op_wait(chip);
58549c98c1dSTobias Waldekranz 	if (err)
58649c98c1dSTobias Waldekranz 		return err;
58749c98c1dSTobias Waldekranz 
58849c98c1dSTobias Waldekranz 	err = mv88e6xxx_g1_vtu_vid_write(chip, entry->valid, 0);
58949c98c1dSTobias Waldekranz 	if (err)
59049c98c1dSTobias Waldekranz 		return err;
59149c98c1dSTobias Waldekranz 
59249c98c1dSTobias Waldekranz 	err = mv88e6xxx_g1_vtu_sid_write(chip, entry->sid);
59349c98c1dSTobias Waldekranz 	if (err)
59449c98c1dSTobias Waldekranz 		return err;
59549c98c1dSTobias Waldekranz 
59649c98c1dSTobias Waldekranz 	if (entry->valid) {
59749c98c1dSTobias Waldekranz 		err = mv88e6390_g1_vtu_data_write(chip, entry->state);
59849c98c1dSTobias Waldekranz 		if (err)
59949c98c1dSTobias Waldekranz 			return err;
60049c98c1dSTobias Waldekranz 	}
60149c98c1dSTobias Waldekranz 
60249c98c1dSTobias Waldekranz 	/* Load/Purge STU entry */
60349c98c1dSTobias Waldekranz 	return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_STU_LOAD_PURGE);
60449c98c1dSTobias Waldekranz }
60549c98c1dSTobias Waldekranz 
60649c98c1dSTobias Waldekranz /* VTU Violation Management */
60749c98c1dSTobias Waldekranz 
mv88e6xxx_g1_vtu_prob_irq_thread_fn(int irq,void * dev_id)60862eb1162SAndrew Lunn static irqreturn_t mv88e6xxx_g1_vtu_prob_irq_thread_fn(int irq, void *dev_id)
60962eb1162SAndrew Lunn {
61062eb1162SAndrew Lunn 	struct mv88e6xxx_chip *chip = dev_id;
61149c98c1dSTobias Waldekranz 	u16 val, vid;
61262eb1162SAndrew Lunn 	int spid;
61362eb1162SAndrew Lunn 	int err;
61462eb1162SAndrew Lunn 
615c9acece0SRasmus Villemoes 	mv88e6xxx_reg_lock(chip);
61662eb1162SAndrew Lunn 
61762eb1162SAndrew Lunn 	err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_GET_CLR_VIOLATION);
61862eb1162SAndrew Lunn 	if (err)
61962eb1162SAndrew Lunn 		goto out;
62062eb1162SAndrew Lunn 
62162eb1162SAndrew Lunn 	err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val);
62262eb1162SAndrew Lunn 	if (err)
62362eb1162SAndrew Lunn 		goto out;
62462eb1162SAndrew Lunn 
62549c98c1dSTobias Waldekranz 	err = mv88e6xxx_g1_vtu_vid_read(chip, NULL, &vid);
62662eb1162SAndrew Lunn 	if (err)
62762eb1162SAndrew Lunn 		goto out;
62862eb1162SAndrew Lunn 
62962eb1162SAndrew Lunn 	spid = val & MV88E6XXX_G1_VTU_OP_SPID_MASK;
63062eb1162SAndrew Lunn 
63162eb1162SAndrew Lunn 	if (val & MV88E6XXX_G1_VTU_OP_MEMBER_VIOLATION) {
632*9e3d9ae5SVladimir Oltean 		trace_mv88e6xxx_vtu_member_violation(chip->dev, spid, vid);
63365f60e45SAndrew Lunn 		chip->ports[spid].vtu_member_violation++;
63462eb1162SAndrew Lunn 	}
63562eb1162SAndrew Lunn 
63665f60e45SAndrew Lunn 	if (val & MV88E6XXX_G1_VTU_OP_MISS_VIOLATION) {
637*9e3d9ae5SVladimir Oltean 		trace_mv88e6xxx_vtu_miss_violation(chip->dev, spid, vid);
63865f60e45SAndrew Lunn 		chip->ports[spid].vtu_miss_violation++;
63965f60e45SAndrew Lunn 	}
6407f20d834SAndrew Lunn 
641c9acece0SRasmus Villemoes 	mv88e6xxx_reg_unlock(chip);
64262eb1162SAndrew Lunn 
64362eb1162SAndrew Lunn 	return IRQ_HANDLED;
64462eb1162SAndrew Lunn 
64562eb1162SAndrew Lunn out:
646c9acece0SRasmus Villemoes 	mv88e6xxx_reg_unlock(chip);
64762eb1162SAndrew Lunn 
64862eb1162SAndrew Lunn 	dev_err(chip->dev, "VTU problem: error %d while handling interrupt\n",
64962eb1162SAndrew Lunn 		err);
65062eb1162SAndrew Lunn 
65162eb1162SAndrew Lunn 	return IRQ_HANDLED;
65262eb1162SAndrew Lunn }
65362eb1162SAndrew Lunn 
mv88e6xxx_g1_vtu_prob_irq_setup(struct mv88e6xxx_chip * chip)65462eb1162SAndrew Lunn int mv88e6xxx_g1_vtu_prob_irq_setup(struct mv88e6xxx_chip *chip)
65562eb1162SAndrew Lunn {
65662eb1162SAndrew Lunn 	int err;
65762eb1162SAndrew Lunn 
65862eb1162SAndrew Lunn 	chip->vtu_prob_irq = irq_find_mapping(chip->g1_irq.domain,
65962eb1162SAndrew Lunn 					      MV88E6XXX_G1_STS_IRQ_VTU_PROB);
66062eb1162SAndrew Lunn 	if (chip->vtu_prob_irq < 0)
6619b662a3eSAndrew Lunn 		return chip->vtu_prob_irq;
66262eb1162SAndrew Lunn 
6638ddf0b56SAndrew Lunn 	snprintf(chip->vtu_prob_irq_name, sizeof(chip->vtu_prob_irq_name),
6648ddf0b56SAndrew Lunn 		 "mv88e6xxx-%s-g1-vtu-prob", dev_name(chip->dev));
6658ddf0b56SAndrew Lunn 
66662eb1162SAndrew Lunn 	err = request_threaded_irq(chip->vtu_prob_irq, NULL,
66762eb1162SAndrew Lunn 				   mv88e6xxx_g1_vtu_prob_irq_thread_fn,
6688ddf0b56SAndrew Lunn 				   IRQF_ONESHOT, chip->vtu_prob_irq_name,
66962eb1162SAndrew Lunn 				   chip);
67062eb1162SAndrew Lunn 	if (err)
67162eb1162SAndrew Lunn 		irq_dispose_mapping(chip->vtu_prob_irq);
67262eb1162SAndrew Lunn 
67362eb1162SAndrew Lunn 	return err;
67462eb1162SAndrew Lunn }
67562eb1162SAndrew Lunn 
mv88e6xxx_g1_vtu_prob_irq_free(struct mv88e6xxx_chip * chip)67662eb1162SAndrew Lunn void mv88e6xxx_g1_vtu_prob_irq_free(struct mv88e6xxx_chip *chip)
67762eb1162SAndrew Lunn {
67862eb1162SAndrew Lunn 	free_irq(chip->vtu_prob_irq, chip);
67962eb1162SAndrew Lunn 	irq_dispose_mapping(chip->vtu_prob_irq);
68062eb1162SAndrew Lunn }
681