xref: /linux/drivers/net/dsa/mv88e6xxx/tcam.c (revision 0fc8f6200d2313278fbf4539bbab74677c685531)
1*639f1dcfSCedric Jehasse // SPDX-License-Identifier: GPL-2.0-or-later
2*639f1dcfSCedric Jehasse /*
3*639f1dcfSCedric Jehasse  * Marvell 88E6xxx Switch TCAM support
4*639f1dcfSCedric Jehasse  *
5*639f1dcfSCedric Jehasse  * Copyright (c) 2026 Luminex Network Intelligence
6*639f1dcfSCedric Jehasse  */
7*639f1dcfSCedric Jehasse 
8*639f1dcfSCedric Jehasse #include "linux/list.h"
9*639f1dcfSCedric Jehasse 
10*639f1dcfSCedric Jehasse #include "chip.h"
11*639f1dcfSCedric Jehasse #include "tcam.h"
12*639f1dcfSCedric Jehasse 
13*639f1dcfSCedric Jehasse /* TCAM operatation register */
14*639f1dcfSCedric Jehasse #define MV88E6XXX_TCAM_OP			0x00
15*639f1dcfSCedric Jehasse #define MV88E6XXX_TCAM_OP_BUSY			0x8000
16*639f1dcfSCedric Jehasse #define MV88E6XXX_TCAM_OP_OP_MASK		0x7000
17*639f1dcfSCedric Jehasse #define MV88E6XXX_TCAM_OP_OP_FLUSH_ALL		0x1000
18*639f1dcfSCedric Jehasse #define MV88E6XXX_TCAM_OP_OP_FLUSH		0x2000
19*639f1dcfSCedric Jehasse #define MV88E6XXX_TCAM_OP_OP_LOAD		0x3000
20*639f1dcfSCedric Jehasse #define MV88E6XXX_TCAM_OP_OP_GET_NEXT		0x4000
21*639f1dcfSCedric Jehasse #define MV88E6XXX_TCAM_OP_OP_READ		0x5000
22*639f1dcfSCedric Jehasse 
23*639f1dcfSCedric Jehasse /* TCAM extension register */
24*639f1dcfSCedric Jehasse #define MV88E6XXX_TCAM_EXTENSION		0x01
25*639f1dcfSCedric Jehasse 
26*639f1dcfSCedric Jehasse /* TCAM keys register 1 */
27*639f1dcfSCedric Jehasse #define MV88E6XXX_TCAM_KEYS1			0x02
28*639f1dcfSCedric Jehasse #define MV88E6XXX_TCAM_KEYS1_FT_MASK		0xC000
29*639f1dcfSCedric Jehasse #define MV88E6XXX_TCAM_KEYS1_SPV_MASK		0x0007
30*639f1dcfSCedric Jehasse #define MV88E6XXX_TCAM_KEYS1_SPV_MASK_MASK	0x0700
31*639f1dcfSCedric Jehasse 
32*639f1dcfSCedric Jehasse /* TCAM keys register 2 */
33*639f1dcfSCedric Jehasse #define MV88E6XXX_TCAM_KEYS2			0x03
34*639f1dcfSCedric Jehasse #define MV88E6XXX_TCAM_KEYS2_SPV_MASK		0x00ff
35*639f1dcfSCedric Jehasse #define MV88E6XXX_TCAM_KEYS2_SPV_MASK_MASK	0xff00
36*639f1dcfSCedric Jehasse 
37*639f1dcfSCedric Jehasse #define MV88E6XXX_TCAM_ING_ACT3			0x04
38*639f1dcfSCedric Jehasse #define MV88E6XXX_TCAM_ING_ACT3_SF		0x0800
39*639f1dcfSCedric Jehasse #define MV88E6XXX_TCAM_ING_ACT3_DPV_MASK	0x07ff
40*639f1dcfSCedric Jehasse 
41*639f1dcfSCedric Jehasse #define MV88E6XXX_TCAM_ING_ACT5			0x06
42*639f1dcfSCedric Jehasse #define MV88E6XXX_TCAM_ING_ACT5_DPV_MODE_MASK	0xc000
43*639f1dcfSCedric Jehasse 
44*639f1dcfSCedric Jehasse static int mv88e6xxx_tcam_write(struct mv88e6xxx_chip *chip, int reg, u16 val)
45*639f1dcfSCedric Jehasse {
46*639f1dcfSCedric Jehasse 	return mv88e6xxx_write(chip, chip->info->tcam_addr, reg, val);
47*639f1dcfSCedric Jehasse }
48*639f1dcfSCedric Jehasse 
49*639f1dcfSCedric Jehasse static int mv88e6xxx_tcam_wait(struct mv88e6xxx_chip *chip)
50*639f1dcfSCedric Jehasse {
51*639f1dcfSCedric Jehasse 	int bit = __bf_shf(MV88E6XXX_TCAM_OP_BUSY);
52*639f1dcfSCedric Jehasse 
53*639f1dcfSCedric Jehasse 	return mv88e6xxx_wait_bit(chip, chip->info->tcam_addr,
54*639f1dcfSCedric Jehasse 				  MV88E6XXX_TCAM_OP, bit, 0);
55*639f1dcfSCedric Jehasse }
56*639f1dcfSCedric Jehasse 
57*639f1dcfSCedric Jehasse static int mv88e6xxx_tcam_read_page(struct mv88e6xxx_chip *chip, u8 page,
58*639f1dcfSCedric Jehasse 				    u8 entry)
59*639f1dcfSCedric Jehasse 
60*639f1dcfSCedric Jehasse {
61*639f1dcfSCedric Jehasse 	u16 val = MV88E6XXX_TCAM_OP_BUSY | MV88E6XXX_TCAM_OP_OP_READ |
62*639f1dcfSCedric Jehasse 		  (page & 0x3) << 10 | entry;
63*639f1dcfSCedric Jehasse 	int err;
64*639f1dcfSCedric Jehasse 
65*639f1dcfSCedric Jehasse 	err = mv88e6xxx_tcam_write(chip, MV88E6XXX_TCAM_OP, val);
66*639f1dcfSCedric Jehasse 	if (err)
67*639f1dcfSCedric Jehasse 		return err;
68*639f1dcfSCedric Jehasse 
69*639f1dcfSCedric Jehasse 	return mv88e6xxx_tcam_wait(chip);
70*639f1dcfSCedric Jehasse }
71*639f1dcfSCedric Jehasse 
72*639f1dcfSCedric Jehasse static int mv88e6xxx_tcam_load_page(struct mv88e6xxx_chip *chip, u8 page,
73*639f1dcfSCedric Jehasse 				    u8 entry)
74*639f1dcfSCedric Jehasse {
75*639f1dcfSCedric Jehasse 	u16 val = MV88E6XXX_TCAM_OP_BUSY | MV88E6XXX_TCAM_OP_OP_LOAD |
76*639f1dcfSCedric Jehasse 		  (page & 0x3) << 10 | entry;
77*639f1dcfSCedric Jehasse 	int err;
78*639f1dcfSCedric Jehasse 
79*639f1dcfSCedric Jehasse 	err = mv88e6xxx_tcam_write(chip, MV88E6XXX_TCAM_OP, val);
80*639f1dcfSCedric Jehasse 	if (err)
81*639f1dcfSCedric Jehasse 		return err;
82*639f1dcfSCedric Jehasse 
83*639f1dcfSCedric Jehasse 	return mv88e6xxx_tcam_wait(chip);
84*639f1dcfSCedric Jehasse }
85*639f1dcfSCedric Jehasse 
86*639f1dcfSCedric Jehasse static int mv88e6xxx_tcam_flush_entry(struct mv88e6xxx_chip *chip, u8 entry)
87*639f1dcfSCedric Jehasse {
88*639f1dcfSCedric Jehasse 	u16 val = MV88E6XXX_TCAM_OP_BUSY | MV88E6XXX_TCAM_OP_OP_FLUSH | entry;
89*639f1dcfSCedric Jehasse 	int err;
90*639f1dcfSCedric Jehasse 
91*639f1dcfSCedric Jehasse 	err = mv88e6xxx_tcam_write(chip, MV88E6XXX_TCAM_OP, val);
92*639f1dcfSCedric Jehasse 	if (err)
93*639f1dcfSCedric Jehasse 		return err;
94*639f1dcfSCedric Jehasse 
95*639f1dcfSCedric Jehasse 	return mv88e6xxx_tcam_wait(chip);
96*639f1dcfSCedric Jehasse }
97*639f1dcfSCedric Jehasse 
98*639f1dcfSCedric Jehasse static int mv88e6xxx_tcam_flush_all(struct mv88e6xxx_chip *chip)
99*639f1dcfSCedric Jehasse {
100*639f1dcfSCedric Jehasse 	u16 val = MV88E6XXX_TCAM_OP_BUSY | MV88E6XXX_TCAM_OP_OP_FLUSH_ALL;
101*639f1dcfSCedric Jehasse 	int err;
102*639f1dcfSCedric Jehasse 
103*639f1dcfSCedric Jehasse 	err = mv88e6xxx_tcam_write(chip, MV88E6XXX_TCAM_OP, val);
104*639f1dcfSCedric Jehasse 	if (err)
105*639f1dcfSCedric Jehasse 		return err;
106*639f1dcfSCedric Jehasse 
107*639f1dcfSCedric Jehasse 	return mv88e6xxx_tcam_wait(chip);
108*639f1dcfSCedric Jehasse }
109*639f1dcfSCedric Jehasse 
110*639f1dcfSCedric Jehasse struct mv88e6xxx_tcam_entry *
111*639f1dcfSCedric Jehasse mv88e6xxx_tcam_entry_find(struct mv88e6xxx_chip *chip, unsigned long cookie)
112*639f1dcfSCedric Jehasse {
113*639f1dcfSCedric Jehasse 	struct mv88e6xxx_tcam_entry *entry;
114*639f1dcfSCedric Jehasse 
115*639f1dcfSCedric Jehasse 	list_for_each_entry(entry, &chip->tcam.entries, list)
116*639f1dcfSCedric Jehasse 		if (entry->cookie == cookie)
117*639f1dcfSCedric Jehasse 			return entry;
118*639f1dcfSCedric Jehasse 
119*639f1dcfSCedric Jehasse 	return NULL;
120*639f1dcfSCedric Jehasse }
121*639f1dcfSCedric Jehasse 
122*639f1dcfSCedric Jehasse /* insert tcam entry in ordered list and move existing entries if necessary */
123*639f1dcfSCedric Jehasse static int mv88e6xxx_tcam_insert_entry(struct mv88e6xxx_chip *chip,
124*639f1dcfSCedric Jehasse 				       struct mv88e6xxx_tcam_entry *entry)
125*639f1dcfSCedric Jehasse {
126*639f1dcfSCedric Jehasse 	struct mv88e6xxx_tcam_entry *elem;
127*639f1dcfSCedric Jehasse 	struct list_head *hpos;
128*639f1dcfSCedric Jehasse 	int err;
129*639f1dcfSCedric Jehasse 
130*639f1dcfSCedric Jehasse 	list_for_each_prev(hpos, &chip->tcam.entries) {
131*639f1dcfSCedric Jehasse 		u8 move_idx;
132*639f1dcfSCedric Jehasse 
133*639f1dcfSCedric Jehasse 		elem = list_entry(hpos, struct mv88e6xxx_tcam_entry, list);
134*639f1dcfSCedric Jehasse 		if (entry->prio >= elem->prio)
135*639f1dcfSCedric Jehasse 			break;
136*639f1dcfSCedric Jehasse 
137*639f1dcfSCedric Jehasse 		move_idx = elem->hw_idx + 1;
138*639f1dcfSCedric Jehasse 
139*639f1dcfSCedric Jehasse 		err = mv88e6xxx_tcam_flush_entry(chip, move_idx);
140*639f1dcfSCedric Jehasse 		if (err)
141*639f1dcfSCedric Jehasse 			return err;
142*639f1dcfSCedric Jehasse 
143*639f1dcfSCedric Jehasse 		err = chip->info->ops->tcam_ops->entry_add(chip, elem,
144*639f1dcfSCedric Jehasse 							   move_idx);
145*639f1dcfSCedric Jehasse 		if (err)
146*639f1dcfSCedric Jehasse 			return err;
147*639f1dcfSCedric Jehasse 
148*639f1dcfSCedric Jehasse 		elem->hw_idx = move_idx;
149*639f1dcfSCedric Jehasse 	}
150*639f1dcfSCedric Jehasse 
151*639f1dcfSCedric Jehasse 	if (list_is_head(hpos, &chip->tcam.entries)) {
152*639f1dcfSCedric Jehasse 		entry->hw_idx = 0;
153*639f1dcfSCedric Jehasse 	} else {
154*639f1dcfSCedric Jehasse 		elem = list_entry(hpos, struct mv88e6xxx_tcam_entry, list);
155*639f1dcfSCedric Jehasse 		entry->hw_idx = elem->hw_idx + 1;
156*639f1dcfSCedric Jehasse 	}
157*639f1dcfSCedric Jehasse 	list_add(&entry->list, hpos);
158*639f1dcfSCedric Jehasse 	return 0;
159*639f1dcfSCedric Jehasse }
160*639f1dcfSCedric Jehasse 
161*639f1dcfSCedric Jehasse int mv88e6xxx_tcam_entry_add(struct mv88e6xxx_chip *chip,
162*639f1dcfSCedric Jehasse 			     struct mv88e6xxx_tcam_entry *entry)
163*639f1dcfSCedric Jehasse {
164*639f1dcfSCedric Jehasse 	int err;
165*639f1dcfSCedric Jehasse 	struct mv88e6xxx_tcam_entry *last;
166*639f1dcfSCedric Jehasse 
167*639f1dcfSCedric Jehasse 	last = list_last_entry_or_null(&chip->tcam.entries,
168*639f1dcfSCedric Jehasse 				       struct mv88e6xxx_tcam_entry, list);
169*639f1dcfSCedric Jehasse 	if (last && last->hw_idx == chip->info->num_tcam_entries - 1)
170*639f1dcfSCedric Jehasse 		return -ENOSPC;
171*639f1dcfSCedric Jehasse 
172*639f1dcfSCedric Jehasse 	err = mv88e6xxx_tcam_insert_entry(chip, entry);
173*639f1dcfSCedric Jehasse 	if (err)
174*639f1dcfSCedric Jehasse 		return err;
175*639f1dcfSCedric Jehasse 
176*639f1dcfSCedric Jehasse 	err = mv88e6xxx_tcam_flush_entry(chip, entry->hw_idx);
177*639f1dcfSCedric Jehasse 	if (err)
178*639f1dcfSCedric Jehasse 		goto unlink_out;
179*639f1dcfSCedric Jehasse 
180*639f1dcfSCedric Jehasse 	err = chip->info->ops->tcam_ops->entry_add(chip, entry, entry->hw_idx);
181*639f1dcfSCedric Jehasse 	if (err)
182*639f1dcfSCedric Jehasse 		goto unlink_out;
183*639f1dcfSCedric Jehasse 
184*639f1dcfSCedric Jehasse 	return 0;
185*639f1dcfSCedric Jehasse 
186*639f1dcfSCedric Jehasse unlink_out:
187*639f1dcfSCedric Jehasse 	list_del(&entry->list);
188*639f1dcfSCedric Jehasse 	return err;
189*639f1dcfSCedric Jehasse }
190*639f1dcfSCedric Jehasse 
191*639f1dcfSCedric Jehasse int mv88e6xxx_tcam_entry_del(struct mv88e6xxx_chip *chip,
192*639f1dcfSCedric Jehasse 			     struct mv88e6xxx_tcam_entry *entry)
193*639f1dcfSCedric Jehasse {
194*639f1dcfSCedric Jehasse 	struct mv88e6xxx_tcam_entry *elem = entry;
195*639f1dcfSCedric Jehasse 	u8 move_idx = entry->hw_idx;
196*639f1dcfSCedric Jehasse 	int err;
197*639f1dcfSCedric Jehasse 
198*639f1dcfSCedric Jehasse 	err = mv88e6xxx_tcam_flush_entry(chip, entry->hw_idx);
199*639f1dcfSCedric Jehasse 	if (err)
200*639f1dcfSCedric Jehasse 		return err;
201*639f1dcfSCedric Jehasse 
202*639f1dcfSCedric Jehasse 	/* move entries that come after the deleted entry forward */
203*639f1dcfSCedric Jehasse 	list_for_each_entry_continue(elem, &chip->tcam.entries, list) {
204*639f1dcfSCedric Jehasse 		u8 tmp_idx = elem->hw_idx;
205*639f1dcfSCedric Jehasse 
206*639f1dcfSCedric Jehasse 		err = mv88e6xxx_tcam_flush_entry(chip, move_idx);
207*639f1dcfSCedric Jehasse 		if (err)
208*639f1dcfSCedric Jehasse 			break;
209*639f1dcfSCedric Jehasse 
210*639f1dcfSCedric Jehasse 		err = chip->info->ops->tcam_ops->entry_add(chip, elem,
211*639f1dcfSCedric Jehasse 							   move_idx);
212*639f1dcfSCedric Jehasse 		if (err)
213*639f1dcfSCedric Jehasse 			break;
214*639f1dcfSCedric Jehasse 
215*639f1dcfSCedric Jehasse 		elem->hw_idx =  move_idx;
216*639f1dcfSCedric Jehasse 		move_idx = tmp_idx;
217*639f1dcfSCedric Jehasse 
218*639f1dcfSCedric Jehasse 		/* flush the last entry after moving entries */
219*639f1dcfSCedric Jehasse 		if (list_is_last(&elem->list, &chip->tcam.entries))
220*639f1dcfSCedric Jehasse 			err = mv88e6xxx_tcam_flush_entry(chip, tmp_idx);
221*639f1dcfSCedric Jehasse 	}
222*639f1dcfSCedric Jehasse 
223*639f1dcfSCedric Jehasse 	list_del(&entry->list);
224*639f1dcfSCedric Jehasse 	kfree(entry);
225*639f1dcfSCedric Jehasse 	return err;
226*639f1dcfSCedric Jehasse }
227*639f1dcfSCedric Jehasse 
228*639f1dcfSCedric Jehasse static int mv88e6390_tcam_entry_add(struct mv88e6xxx_chip *chip,
229*639f1dcfSCedric Jehasse 				    struct mv88e6xxx_tcam_entry *entry, u8 idx)
230*639f1dcfSCedric Jehasse {
231*639f1dcfSCedric Jehasse 	int err = 0;
232*639f1dcfSCedric Jehasse 	int i;
233*639f1dcfSCedric Jehasse 	u16 val, spv_mask, spv;
234*639f1dcfSCedric Jehasse 
235*639f1dcfSCedric Jehasse 	err = mv88e6xxx_tcam_read_page(chip, 2, idx);
236*639f1dcfSCedric Jehasse 	if (err)
237*639f1dcfSCedric Jehasse 		return err;
238*639f1dcfSCedric Jehasse 	if (entry->action.dpv_mode != 0) {
239*639f1dcfSCedric Jehasse 		val = MV88E6XXX_TCAM_ING_ACT3_SF |
240*639f1dcfSCedric Jehasse 		      (entry->action.dpv & MV88E6XXX_TCAM_ING_ACT3_DPV_MASK);
241*639f1dcfSCedric Jehasse 
242*639f1dcfSCedric Jehasse 		err = mv88e6xxx_tcam_write(chip, MV88E6XXX_TCAM_ING_ACT3, val);
243*639f1dcfSCedric Jehasse 		if (err)
244*639f1dcfSCedric Jehasse 			return err;
245*639f1dcfSCedric Jehasse 
246*639f1dcfSCedric Jehasse 		val = entry->action.dpv_mode << 14;
247*639f1dcfSCedric Jehasse 		err = mv88e6xxx_tcam_write(chip, MV88E6XXX_TCAM_ING_ACT5, val);
248*639f1dcfSCedric Jehasse 		if (err)
249*639f1dcfSCedric Jehasse 			return err;
250*639f1dcfSCedric Jehasse 	}
251*639f1dcfSCedric Jehasse 	err = mv88e6xxx_tcam_load_page(chip, 2, idx);
252*639f1dcfSCedric Jehasse 	if (err)
253*639f1dcfSCedric Jehasse 		return err;
254*639f1dcfSCedric Jehasse 
255*639f1dcfSCedric Jehasse 	err = mv88e6xxx_tcam_read_page(chip, 1, idx);
256*639f1dcfSCedric Jehasse 	if (err)
257*639f1dcfSCedric Jehasse 		return err;
258*639f1dcfSCedric Jehasse 
259*639f1dcfSCedric Jehasse 	for (i = PAGE0_MATCH_SIZE;
260*639f1dcfSCedric Jehasse 	     i < PAGE0_MATCH_SIZE + PAGE1_MATCH_SIZE; i++) {
261*639f1dcfSCedric Jehasse 		if (entry->key.frame_mask[i]) {
262*639f1dcfSCedric Jehasse 			val = entry->key.frame_mask[i] << 8 |
263*639f1dcfSCedric Jehasse 			      entry->key.frame_data[i];
264*639f1dcfSCedric Jehasse 
265*639f1dcfSCedric Jehasse 			err = mv88e6xxx_tcam_write(chip,
266*639f1dcfSCedric Jehasse 						   i - PAGE0_MATCH_SIZE + 2,
267*639f1dcfSCedric Jehasse 						   val);
268*639f1dcfSCedric Jehasse 			if (err)
269*639f1dcfSCedric Jehasse 				return err;
270*639f1dcfSCedric Jehasse 		}
271*639f1dcfSCedric Jehasse 	}
272*639f1dcfSCedric Jehasse 	err = mv88e6xxx_tcam_load_page(chip, 1, idx);
273*639f1dcfSCedric Jehasse 	if (err)
274*639f1dcfSCedric Jehasse 		return err;
275*639f1dcfSCedric Jehasse 
276*639f1dcfSCedric Jehasse 	err = mv88e6xxx_tcam_read_page(chip, 0, idx);
277*639f1dcfSCedric Jehasse 	if (err)
278*639f1dcfSCedric Jehasse 		return err;
279*639f1dcfSCedric Jehasse 
280*639f1dcfSCedric Jehasse 	for (i = 0; i < PAGE0_MATCH_SIZE; i++) {
281*639f1dcfSCedric Jehasse 		if (entry->key.frame_mask[i]) {
282*639f1dcfSCedric Jehasse 			val = entry->key.frame_mask[i] << 8 |
283*639f1dcfSCedric Jehasse 			      entry->key.frame_data[i];
284*639f1dcfSCedric Jehasse 
285*639f1dcfSCedric Jehasse 			err = mv88e6xxx_tcam_write(chip, i + 6, val);
286*639f1dcfSCedric Jehasse 			if (err)
287*639f1dcfSCedric Jehasse 				return err;
288*639f1dcfSCedric Jehasse 		}
289*639f1dcfSCedric Jehasse 	}
290*639f1dcfSCedric Jehasse 
291*639f1dcfSCedric Jehasse 	spv_mask = entry->key.spv_mask & mv88e6xxx_port_mask(chip);
292*639f1dcfSCedric Jehasse 	spv = entry->key.spv & mv88e6xxx_port_mask(chip);
293*639f1dcfSCedric Jehasse 	/* frame type mask bits must be set for a valid entry */
294*639f1dcfSCedric Jehasse 	val = MV88E6XXX_TCAM_KEYS1_FT_MASK |
295*639f1dcfSCedric Jehasse 	      (spv_mask & MV88E6XXX_TCAM_KEYS1_SPV_MASK_MASK) |
296*639f1dcfSCedric Jehasse 	      ((spv >> 8) & MV88E6XXX_TCAM_KEYS1_SPV_MASK);
297*639f1dcfSCedric Jehasse 	err = mv88e6xxx_tcam_write(chip, MV88E6XXX_TCAM_KEYS1, val);
298*639f1dcfSCedric Jehasse 	if (err)
299*639f1dcfSCedric Jehasse 		return err;
300*639f1dcfSCedric Jehasse 
301*639f1dcfSCedric Jehasse 	val = ((spv_mask << 8) & MV88E6XXX_TCAM_KEYS2_SPV_MASK_MASK) |
302*639f1dcfSCedric Jehasse 	      (spv & MV88E6XXX_TCAM_KEYS2_SPV_MASK);
303*639f1dcfSCedric Jehasse 	err = mv88e6xxx_tcam_write(chip, MV88E6XXX_TCAM_KEYS2, val);
304*639f1dcfSCedric Jehasse 	if (err)
305*639f1dcfSCedric Jehasse 		return err;
306*639f1dcfSCedric Jehasse 
307*639f1dcfSCedric Jehasse 	err = mv88e6xxx_tcam_load_page(chip, 0, idx);
308*639f1dcfSCedric Jehasse 	if (err)
309*639f1dcfSCedric Jehasse 		return err;
310*639f1dcfSCedric Jehasse 
311*639f1dcfSCedric Jehasse 	entry->hw_idx = idx;
312*639f1dcfSCedric Jehasse 	return 0;
313*639f1dcfSCedric Jehasse }
314*639f1dcfSCedric Jehasse 
315*639f1dcfSCedric Jehasse static int mv88e6393_tcam_entry_add(struct mv88e6xxx_chip *chip,
316*639f1dcfSCedric Jehasse 				    struct mv88e6xxx_tcam_entry *entry, u8 idx)
317*639f1dcfSCedric Jehasse {
318*639f1dcfSCedric Jehasse 	int err;
319*639f1dcfSCedric Jehasse 
320*639f1dcfSCedric Jehasse 	/* select block 0 port 0, then adding an entry is the same as 6390 as
321*639f1dcfSCedric Jehasse 	 * other blocks aren't used at the moment
322*639f1dcfSCedric Jehasse 	 */
323*639f1dcfSCedric Jehasse 	err = mv88e6xxx_tcam_write(chip, MV88E6XXX_TCAM_EXTENSION, 0x00);
324*639f1dcfSCedric Jehasse 	if (err)
325*639f1dcfSCedric Jehasse 		return err;
326*639f1dcfSCedric Jehasse 
327*639f1dcfSCedric Jehasse 	return mv88e6390_tcam_entry_add(chip, entry, idx);
328*639f1dcfSCedric Jehasse }
329*639f1dcfSCedric Jehasse 
330*639f1dcfSCedric Jehasse const struct mv88e6xxx_tcam_ops mv88e6390_tcam_ops = {
331*639f1dcfSCedric Jehasse 	.entry_add = mv88e6390_tcam_entry_add,
332*639f1dcfSCedric Jehasse 	.flush_tcam = mv88e6xxx_tcam_flush_all,
333*639f1dcfSCedric Jehasse };
334*639f1dcfSCedric Jehasse 
335*639f1dcfSCedric Jehasse const struct mv88e6xxx_tcam_ops mv88e6393_tcam_ops = {
336*639f1dcfSCedric Jehasse 	.entry_add = mv88e6393_tcam_entry_add,
337*639f1dcfSCedric Jehasse 	.flush_tcam = mv88e6xxx_tcam_flush_all,
338*639f1dcfSCedric Jehasse };
339