xref: /openbmc/linux/drivers/net/ethernet/ti/cpsw_ale.c (revision 68198dca)
1 /*
2  * Texas Instruments N-Port Ethernet Switch Address Lookup Engine
3  *
4  * Copyright (C) 2012 Texas Instruments
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation version 2.
9  *
10  * This program is distributed "as is" WITHOUT ANY WARRANTY of any
11  * kind, whether express or implied; without even the implied warranty
12  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  */
15 #include <linux/kernel.h>
16 #include <linux/module.h>
17 #include <linux/platform_device.h>
18 #include <linux/seq_file.h>
19 #include <linux/slab.h>
20 #include <linux/err.h>
21 #include <linux/io.h>
22 #include <linux/stat.h>
23 #include <linux/sysfs.h>
24 #include <linux/etherdevice.h>
25 
26 #include "cpsw_ale.h"
27 
28 #define BITMASK(bits)		(BIT(bits) - 1)
29 
30 #define ALE_VERSION_MAJOR(rev, mask) (((rev) >> 8) & (mask))
31 #define ALE_VERSION_MINOR(rev)	(rev & 0xff)
32 #define ALE_VERSION_1R3		0x0103
33 #define ALE_VERSION_1R4		0x0104
34 
35 /* ALE Registers */
36 #define ALE_IDVER		0x00
37 #define ALE_STATUS		0x04
38 #define ALE_CONTROL		0x08
39 #define ALE_PRESCALE		0x10
40 #define ALE_UNKNOWNVLAN		0x18
41 #define ALE_TABLE_CONTROL	0x20
42 #define ALE_TABLE		0x34
43 #define ALE_PORTCTL		0x40
44 
45 /* ALE NetCP NU switch specific Registers */
46 #define ALE_UNKNOWNVLAN_MEMBER			0x90
47 #define ALE_UNKNOWNVLAN_UNREG_MCAST_FLOOD	0x94
48 #define ALE_UNKNOWNVLAN_REG_MCAST_FLOOD		0x98
49 #define ALE_UNKNOWNVLAN_FORCE_UNTAG_EGRESS	0x9C
50 #define ALE_VLAN_MASK_MUX(reg)			(0xc0 + (0x4 * (reg)))
51 
52 #define ALE_TABLE_WRITE		BIT(31)
53 
54 #define ALE_TYPE_FREE			0
55 #define ALE_TYPE_ADDR			1
56 #define ALE_TYPE_VLAN			2
57 #define ALE_TYPE_VLAN_ADDR		3
58 
59 #define ALE_UCAST_PERSISTANT		0
60 #define ALE_UCAST_UNTOUCHED		1
61 #define ALE_UCAST_OUI			2
62 #define ALE_UCAST_TOUCHED		3
63 
64 #define ALE_TABLE_SIZE_MULTIPLIER	1024
65 #define ALE_STATUS_SIZE_MASK		0x1f
66 #define ALE_TABLE_SIZE_DEFAULT		64
67 
68 static inline int cpsw_ale_get_field(u32 *ale_entry, u32 start, u32 bits)
69 {
70 	int idx;
71 
72 	idx    = start / 32;
73 	start -= idx * 32;
74 	idx    = 2 - idx; /* flip */
75 	return (ale_entry[idx] >> start) & BITMASK(bits);
76 }
77 
78 static inline void cpsw_ale_set_field(u32 *ale_entry, u32 start, u32 bits,
79 				      u32 value)
80 {
81 	int idx;
82 
83 	value &= BITMASK(bits);
84 	idx    = start / 32;
85 	start -= idx * 32;
86 	idx    = 2 - idx; /* flip */
87 	ale_entry[idx] &= ~(BITMASK(bits) << start);
88 	ale_entry[idx] |=  (value << start);
89 }
90 
91 #define DEFINE_ALE_FIELD(name, start, bits)				\
92 static inline int cpsw_ale_get_##name(u32 *ale_entry)			\
93 {									\
94 	return cpsw_ale_get_field(ale_entry, start, bits);		\
95 }									\
96 static inline void cpsw_ale_set_##name(u32 *ale_entry, u32 value)	\
97 {									\
98 	cpsw_ale_set_field(ale_entry, start, bits, value);		\
99 }
100 
101 #define DEFINE_ALE_FIELD1(name, start)					\
102 static inline int cpsw_ale_get_##name(u32 *ale_entry, u32 bits)		\
103 {									\
104 	return cpsw_ale_get_field(ale_entry, start, bits);		\
105 }									\
106 static inline void cpsw_ale_set_##name(u32 *ale_entry, u32 value,	\
107 		u32 bits)						\
108 {									\
109 	cpsw_ale_set_field(ale_entry, start, bits, value);		\
110 }
111 
112 DEFINE_ALE_FIELD(entry_type,		60,	2)
113 DEFINE_ALE_FIELD(vlan_id,		48,	12)
114 DEFINE_ALE_FIELD(mcast_state,		62,	2)
115 DEFINE_ALE_FIELD1(port_mask,		66)
116 DEFINE_ALE_FIELD(super,			65,	1)
117 DEFINE_ALE_FIELD(ucast_type,		62,     2)
118 DEFINE_ALE_FIELD1(port_num,		66)
119 DEFINE_ALE_FIELD(blocked,		65,     1)
120 DEFINE_ALE_FIELD(secure,		64,     1)
121 DEFINE_ALE_FIELD1(vlan_untag_force,	24)
122 DEFINE_ALE_FIELD1(vlan_reg_mcast,	16)
123 DEFINE_ALE_FIELD1(vlan_unreg_mcast,	8)
124 DEFINE_ALE_FIELD1(vlan_member_list,	0)
125 DEFINE_ALE_FIELD(mcast,			40,	1)
126 /* ALE NetCP nu switch specific */
127 DEFINE_ALE_FIELD(vlan_unreg_mcast_idx,	20,	3)
128 DEFINE_ALE_FIELD(vlan_reg_mcast_idx,	44,	3)
129 
130 /* The MAC address field in the ALE entry cannot be macroized as above */
131 static inline void cpsw_ale_get_addr(u32 *ale_entry, u8 *addr)
132 {
133 	int i;
134 
135 	for (i = 0; i < 6; i++)
136 		addr[i] = cpsw_ale_get_field(ale_entry, 40 - 8*i, 8);
137 }
138 
139 static inline void cpsw_ale_set_addr(u32 *ale_entry, u8 *addr)
140 {
141 	int i;
142 
143 	for (i = 0; i < 6; i++)
144 		cpsw_ale_set_field(ale_entry, 40 - 8*i, 8, addr[i]);
145 }
146 
147 static int cpsw_ale_read(struct cpsw_ale *ale, int idx, u32 *ale_entry)
148 {
149 	int i;
150 
151 	WARN_ON(idx > ale->params.ale_entries);
152 
153 	__raw_writel(idx, ale->params.ale_regs + ALE_TABLE_CONTROL);
154 
155 	for (i = 0; i < ALE_ENTRY_WORDS; i++)
156 		ale_entry[i] = __raw_readl(ale->params.ale_regs +
157 					   ALE_TABLE + 4 * i);
158 
159 	return idx;
160 }
161 
162 static int cpsw_ale_write(struct cpsw_ale *ale, int idx, u32 *ale_entry)
163 {
164 	int i;
165 
166 	WARN_ON(idx > ale->params.ale_entries);
167 
168 	for (i = 0; i < ALE_ENTRY_WORDS; i++)
169 		__raw_writel(ale_entry[i], ale->params.ale_regs +
170 			     ALE_TABLE + 4 * i);
171 
172 	__raw_writel(idx | ALE_TABLE_WRITE, ale->params.ale_regs +
173 		     ALE_TABLE_CONTROL);
174 
175 	return idx;
176 }
177 
178 static int cpsw_ale_match_addr(struct cpsw_ale *ale, u8 *addr, u16 vid)
179 {
180 	u32 ale_entry[ALE_ENTRY_WORDS];
181 	int type, idx;
182 
183 	for (idx = 0; idx < ale->params.ale_entries; idx++) {
184 		u8 entry_addr[6];
185 
186 		cpsw_ale_read(ale, idx, ale_entry);
187 		type = cpsw_ale_get_entry_type(ale_entry);
188 		if (type != ALE_TYPE_ADDR && type != ALE_TYPE_VLAN_ADDR)
189 			continue;
190 		if (cpsw_ale_get_vlan_id(ale_entry) != vid)
191 			continue;
192 		cpsw_ale_get_addr(ale_entry, entry_addr);
193 		if (ether_addr_equal(entry_addr, addr))
194 			return idx;
195 	}
196 	return -ENOENT;
197 }
198 
199 static int cpsw_ale_match_vlan(struct cpsw_ale *ale, u16 vid)
200 {
201 	u32 ale_entry[ALE_ENTRY_WORDS];
202 	int type, idx;
203 
204 	for (idx = 0; idx < ale->params.ale_entries; idx++) {
205 		cpsw_ale_read(ale, idx, ale_entry);
206 		type = cpsw_ale_get_entry_type(ale_entry);
207 		if (type != ALE_TYPE_VLAN)
208 			continue;
209 		if (cpsw_ale_get_vlan_id(ale_entry) == vid)
210 			return idx;
211 	}
212 	return -ENOENT;
213 }
214 
215 static int cpsw_ale_match_free(struct cpsw_ale *ale)
216 {
217 	u32 ale_entry[ALE_ENTRY_WORDS];
218 	int type, idx;
219 
220 	for (idx = 0; idx < ale->params.ale_entries; idx++) {
221 		cpsw_ale_read(ale, idx, ale_entry);
222 		type = cpsw_ale_get_entry_type(ale_entry);
223 		if (type == ALE_TYPE_FREE)
224 			return idx;
225 	}
226 	return -ENOENT;
227 }
228 
229 static int cpsw_ale_find_ageable(struct cpsw_ale *ale)
230 {
231 	u32 ale_entry[ALE_ENTRY_WORDS];
232 	int type, idx;
233 
234 	for (idx = 0; idx < ale->params.ale_entries; idx++) {
235 		cpsw_ale_read(ale, idx, ale_entry);
236 		type = cpsw_ale_get_entry_type(ale_entry);
237 		if (type != ALE_TYPE_ADDR && type != ALE_TYPE_VLAN_ADDR)
238 			continue;
239 		if (cpsw_ale_get_mcast(ale_entry))
240 			continue;
241 		type = cpsw_ale_get_ucast_type(ale_entry);
242 		if (type != ALE_UCAST_PERSISTANT &&
243 		    type != ALE_UCAST_OUI)
244 			return idx;
245 	}
246 	return -ENOENT;
247 }
248 
249 static void cpsw_ale_flush_mcast(struct cpsw_ale *ale, u32 *ale_entry,
250 				 int port_mask)
251 {
252 	int mask;
253 
254 	mask = cpsw_ale_get_port_mask(ale_entry,
255 				      ale->port_mask_bits);
256 	if ((mask & port_mask) == 0)
257 		return; /* ports dont intersect, not interested */
258 	mask &= ~port_mask;
259 
260 	/* free if only remaining port is host port */
261 	if (mask)
262 		cpsw_ale_set_port_mask(ale_entry, mask,
263 				       ale->port_mask_bits);
264 	else
265 		cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
266 }
267 
268 int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask, int vid)
269 {
270 	u32 ale_entry[ALE_ENTRY_WORDS];
271 	int ret, idx;
272 
273 	for (idx = 0; idx < ale->params.ale_entries; idx++) {
274 		cpsw_ale_read(ale, idx, ale_entry);
275 		ret = cpsw_ale_get_entry_type(ale_entry);
276 		if (ret != ALE_TYPE_ADDR && ret != ALE_TYPE_VLAN_ADDR)
277 			continue;
278 
279 		/* if vid passed is -1 then remove all multicast entry from
280 		 * the table irrespective of vlan id, if a valid vlan id is
281 		 * passed then remove only multicast added to that vlan id.
282 		 * if vlan id doesn't match then move on to next entry.
283 		 */
284 		if (vid != -1 && cpsw_ale_get_vlan_id(ale_entry) != vid)
285 			continue;
286 
287 		if (cpsw_ale_get_mcast(ale_entry)) {
288 			u8 addr[6];
289 
290 			cpsw_ale_get_addr(ale_entry, addr);
291 			if (!is_broadcast_ether_addr(addr))
292 				cpsw_ale_flush_mcast(ale, ale_entry, port_mask);
293 		}
294 
295 		cpsw_ale_write(ale, idx, ale_entry);
296 	}
297 	return 0;
298 }
299 EXPORT_SYMBOL_GPL(cpsw_ale_flush_multicast);
300 
301 static inline void cpsw_ale_set_vlan_entry_type(u32 *ale_entry,
302 						int flags, u16 vid)
303 {
304 	if (flags & ALE_VLAN) {
305 		cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_VLAN_ADDR);
306 		cpsw_ale_set_vlan_id(ale_entry, vid);
307 	} else {
308 		cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
309 	}
310 }
311 
312 int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port,
313 		       int flags, u16 vid)
314 {
315 	u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
316 	int idx;
317 
318 	cpsw_ale_set_vlan_entry_type(ale_entry, flags, vid);
319 
320 	cpsw_ale_set_addr(ale_entry, addr);
321 	cpsw_ale_set_ucast_type(ale_entry, ALE_UCAST_PERSISTANT);
322 	cpsw_ale_set_secure(ale_entry, (flags & ALE_SECURE) ? 1 : 0);
323 	cpsw_ale_set_blocked(ale_entry, (flags & ALE_BLOCKED) ? 1 : 0);
324 	cpsw_ale_set_port_num(ale_entry, port, ale->port_num_bits);
325 
326 	idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
327 	if (idx < 0)
328 		idx = cpsw_ale_match_free(ale);
329 	if (idx < 0)
330 		idx = cpsw_ale_find_ageable(ale);
331 	if (idx < 0)
332 		return -ENOMEM;
333 
334 	cpsw_ale_write(ale, idx, ale_entry);
335 	return 0;
336 }
337 EXPORT_SYMBOL_GPL(cpsw_ale_add_ucast);
338 
339 int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port,
340 		       int flags, u16 vid)
341 {
342 	u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
343 	int idx;
344 
345 	idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
346 	if (idx < 0)
347 		return -ENOENT;
348 
349 	cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
350 	cpsw_ale_write(ale, idx, ale_entry);
351 	return 0;
352 }
353 EXPORT_SYMBOL_GPL(cpsw_ale_del_ucast);
354 
355 int cpsw_ale_add_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
356 		       int flags, u16 vid, int mcast_state)
357 {
358 	u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
359 	int idx, mask;
360 
361 	idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
362 	if (idx >= 0)
363 		cpsw_ale_read(ale, idx, ale_entry);
364 
365 	cpsw_ale_set_vlan_entry_type(ale_entry, flags, vid);
366 
367 	cpsw_ale_set_addr(ale_entry, addr);
368 	cpsw_ale_set_super(ale_entry, (flags & ALE_BLOCKED) ? 1 : 0);
369 	cpsw_ale_set_mcast_state(ale_entry, mcast_state);
370 
371 	mask = cpsw_ale_get_port_mask(ale_entry,
372 				      ale->port_mask_bits);
373 	port_mask |= mask;
374 	cpsw_ale_set_port_mask(ale_entry, port_mask,
375 			       ale->port_mask_bits);
376 
377 	if (idx < 0)
378 		idx = cpsw_ale_match_free(ale);
379 	if (idx < 0)
380 		idx = cpsw_ale_find_ageable(ale);
381 	if (idx < 0)
382 		return -ENOMEM;
383 
384 	cpsw_ale_write(ale, idx, ale_entry);
385 	return 0;
386 }
387 EXPORT_SYMBOL_GPL(cpsw_ale_add_mcast);
388 
389 int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
390 		       int flags, u16 vid)
391 {
392 	u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
393 	int idx;
394 
395 	idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
396 	if (idx < 0)
397 		return -EINVAL;
398 
399 	cpsw_ale_read(ale, idx, ale_entry);
400 
401 	if (port_mask)
402 		cpsw_ale_set_port_mask(ale_entry, port_mask,
403 				       ale->port_mask_bits);
404 	else
405 		cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
406 
407 	cpsw_ale_write(ale, idx, ale_entry);
408 	return 0;
409 }
410 EXPORT_SYMBOL_GPL(cpsw_ale_del_mcast);
411 
412 /* ALE NetCP NU switch specific vlan functions */
413 static void cpsw_ale_set_vlan_mcast(struct cpsw_ale *ale, u32 *ale_entry,
414 				    int reg_mcast, int unreg_mcast)
415 {
416 	int idx;
417 
418 	/* Set VLAN registered multicast flood mask */
419 	idx = cpsw_ale_get_vlan_reg_mcast_idx(ale_entry);
420 	writel(reg_mcast, ale->params.ale_regs + ALE_VLAN_MASK_MUX(idx));
421 
422 	/* Set VLAN unregistered multicast flood mask */
423 	idx = cpsw_ale_get_vlan_unreg_mcast_idx(ale_entry);
424 	writel(unreg_mcast, ale->params.ale_regs + ALE_VLAN_MASK_MUX(idx));
425 }
426 
427 int cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port, int untag,
428 		      int reg_mcast, int unreg_mcast)
429 {
430 	u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
431 	int idx;
432 
433 	idx = cpsw_ale_match_vlan(ale, vid);
434 	if (idx >= 0)
435 		cpsw_ale_read(ale, idx, ale_entry);
436 
437 	cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_VLAN);
438 	cpsw_ale_set_vlan_id(ale_entry, vid);
439 
440 	cpsw_ale_set_vlan_untag_force(ale_entry, untag, ale->vlan_field_bits);
441 	if (!ale->params.nu_switch_ale) {
442 		cpsw_ale_set_vlan_reg_mcast(ale_entry, reg_mcast,
443 					    ale->vlan_field_bits);
444 		cpsw_ale_set_vlan_unreg_mcast(ale_entry, unreg_mcast,
445 					      ale->vlan_field_bits);
446 	} else {
447 		cpsw_ale_set_vlan_mcast(ale, ale_entry, reg_mcast, unreg_mcast);
448 	}
449 	cpsw_ale_set_vlan_member_list(ale_entry, port, ale->vlan_field_bits);
450 
451 	if (idx < 0)
452 		idx = cpsw_ale_match_free(ale);
453 	if (idx < 0)
454 		idx = cpsw_ale_find_ageable(ale);
455 	if (idx < 0)
456 		return -ENOMEM;
457 
458 	cpsw_ale_write(ale, idx, ale_entry);
459 	return 0;
460 }
461 EXPORT_SYMBOL_GPL(cpsw_ale_add_vlan);
462 
463 int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port_mask)
464 {
465 	u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
466 	int idx;
467 
468 	idx = cpsw_ale_match_vlan(ale, vid);
469 	if (idx < 0)
470 		return -ENOENT;
471 
472 	cpsw_ale_read(ale, idx, ale_entry);
473 
474 	if (port_mask)
475 		cpsw_ale_set_vlan_member_list(ale_entry, port_mask,
476 					      ale->vlan_field_bits);
477 	else
478 		cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
479 
480 	cpsw_ale_write(ale, idx, ale_entry);
481 	return 0;
482 }
483 EXPORT_SYMBOL_GPL(cpsw_ale_del_vlan);
484 
485 void cpsw_ale_set_allmulti(struct cpsw_ale *ale, int allmulti)
486 {
487 	u32 ale_entry[ALE_ENTRY_WORDS];
488 	int type, idx;
489 	int unreg_mcast = 0;
490 
491 	/* Only bother doing the work if the setting is actually changing */
492 	if (ale->allmulti == allmulti)
493 		return;
494 
495 	/* Remember the new setting to check against next time */
496 	ale->allmulti = allmulti;
497 
498 	for (idx = 0; idx < ale->params.ale_entries; idx++) {
499 		cpsw_ale_read(ale, idx, ale_entry);
500 		type = cpsw_ale_get_entry_type(ale_entry);
501 		if (type != ALE_TYPE_VLAN)
502 			continue;
503 
504 		unreg_mcast =
505 			cpsw_ale_get_vlan_unreg_mcast(ale_entry,
506 						      ale->vlan_field_bits);
507 		if (allmulti)
508 			unreg_mcast |= 1;
509 		else
510 			unreg_mcast &= ~1;
511 		cpsw_ale_set_vlan_unreg_mcast(ale_entry, unreg_mcast,
512 					      ale->vlan_field_bits);
513 		cpsw_ale_write(ale, idx, ale_entry);
514 	}
515 }
516 EXPORT_SYMBOL_GPL(cpsw_ale_set_allmulti);
517 
518 struct ale_control_info {
519 	const char	*name;
520 	int		offset, port_offset;
521 	int		shift, port_shift;
522 	int		bits;
523 };
524 
525 static struct ale_control_info ale_controls[ALE_NUM_CONTROLS] = {
526 	[ALE_ENABLE]		= {
527 		.name		= "enable",
528 		.offset		= ALE_CONTROL,
529 		.port_offset	= 0,
530 		.shift		= 31,
531 		.port_shift	= 0,
532 		.bits		= 1,
533 	},
534 	[ALE_CLEAR]		= {
535 		.name		= "clear",
536 		.offset		= ALE_CONTROL,
537 		.port_offset	= 0,
538 		.shift		= 30,
539 		.port_shift	= 0,
540 		.bits		= 1,
541 	},
542 	[ALE_AGEOUT]		= {
543 		.name		= "ageout",
544 		.offset		= ALE_CONTROL,
545 		.port_offset	= 0,
546 		.shift		= 29,
547 		.port_shift	= 0,
548 		.bits		= 1,
549 	},
550 	[ALE_P0_UNI_FLOOD]	= {
551 		.name		= "port0_unicast_flood",
552 		.offset		= ALE_CONTROL,
553 		.port_offset	= 0,
554 		.shift		= 8,
555 		.port_shift	= 0,
556 		.bits		= 1,
557 	},
558 	[ALE_VLAN_NOLEARN]	= {
559 		.name		= "vlan_nolearn",
560 		.offset		= ALE_CONTROL,
561 		.port_offset	= 0,
562 		.shift		= 7,
563 		.port_shift	= 0,
564 		.bits		= 1,
565 	},
566 	[ALE_NO_PORT_VLAN]	= {
567 		.name		= "no_port_vlan",
568 		.offset		= ALE_CONTROL,
569 		.port_offset	= 0,
570 		.shift		= 6,
571 		.port_shift	= 0,
572 		.bits		= 1,
573 	},
574 	[ALE_OUI_DENY]		= {
575 		.name		= "oui_deny",
576 		.offset		= ALE_CONTROL,
577 		.port_offset	= 0,
578 		.shift		= 5,
579 		.port_shift	= 0,
580 		.bits		= 1,
581 	},
582 	[ALE_BYPASS]		= {
583 		.name		= "bypass",
584 		.offset		= ALE_CONTROL,
585 		.port_offset	= 0,
586 		.shift		= 4,
587 		.port_shift	= 0,
588 		.bits		= 1,
589 	},
590 	[ALE_RATE_LIMIT_TX]	= {
591 		.name		= "rate_limit_tx",
592 		.offset		= ALE_CONTROL,
593 		.port_offset	= 0,
594 		.shift		= 3,
595 		.port_shift	= 0,
596 		.bits		= 1,
597 	},
598 	[ALE_VLAN_AWARE]	= {
599 		.name		= "vlan_aware",
600 		.offset		= ALE_CONTROL,
601 		.port_offset	= 0,
602 		.shift		= 2,
603 		.port_shift	= 0,
604 		.bits		= 1,
605 	},
606 	[ALE_AUTH_ENABLE]	= {
607 		.name		= "auth_enable",
608 		.offset		= ALE_CONTROL,
609 		.port_offset	= 0,
610 		.shift		= 1,
611 		.port_shift	= 0,
612 		.bits		= 1,
613 	},
614 	[ALE_RATE_LIMIT]	= {
615 		.name		= "rate_limit",
616 		.offset		= ALE_CONTROL,
617 		.port_offset	= 0,
618 		.shift		= 0,
619 		.port_shift	= 0,
620 		.bits		= 1,
621 	},
622 	[ALE_PORT_STATE]	= {
623 		.name		= "port_state",
624 		.offset		= ALE_PORTCTL,
625 		.port_offset	= 4,
626 		.shift		= 0,
627 		.port_shift	= 0,
628 		.bits		= 2,
629 	},
630 	[ALE_PORT_DROP_UNTAGGED] = {
631 		.name		= "drop_untagged",
632 		.offset		= ALE_PORTCTL,
633 		.port_offset	= 4,
634 		.shift		= 2,
635 		.port_shift	= 0,
636 		.bits		= 1,
637 	},
638 	[ALE_PORT_DROP_UNKNOWN_VLAN] = {
639 		.name		= "drop_unknown",
640 		.offset		= ALE_PORTCTL,
641 		.port_offset	= 4,
642 		.shift		= 3,
643 		.port_shift	= 0,
644 		.bits		= 1,
645 	},
646 	[ALE_PORT_NOLEARN]	= {
647 		.name		= "nolearn",
648 		.offset		= ALE_PORTCTL,
649 		.port_offset	= 4,
650 		.shift		= 4,
651 		.port_shift	= 0,
652 		.bits		= 1,
653 	},
654 	[ALE_PORT_NO_SA_UPDATE]	= {
655 		.name		= "no_source_update",
656 		.offset		= ALE_PORTCTL,
657 		.port_offset	= 4,
658 		.shift		= 5,
659 		.port_shift	= 0,
660 		.bits		= 1,
661 	},
662 	[ALE_PORT_MCAST_LIMIT]	= {
663 		.name		= "mcast_limit",
664 		.offset		= ALE_PORTCTL,
665 		.port_offset	= 4,
666 		.shift		= 16,
667 		.port_shift	= 0,
668 		.bits		= 8,
669 	},
670 	[ALE_PORT_BCAST_LIMIT]	= {
671 		.name		= "bcast_limit",
672 		.offset		= ALE_PORTCTL,
673 		.port_offset	= 4,
674 		.shift		= 24,
675 		.port_shift	= 0,
676 		.bits		= 8,
677 	},
678 	[ALE_PORT_UNKNOWN_VLAN_MEMBER] = {
679 		.name		= "unknown_vlan_member",
680 		.offset		= ALE_UNKNOWNVLAN,
681 		.port_offset	= 0,
682 		.shift		= 0,
683 		.port_shift	= 0,
684 		.bits		= 6,
685 	},
686 	[ALE_PORT_UNKNOWN_MCAST_FLOOD] = {
687 		.name		= "unknown_mcast_flood",
688 		.offset		= ALE_UNKNOWNVLAN,
689 		.port_offset	= 0,
690 		.shift		= 8,
691 		.port_shift	= 0,
692 		.bits		= 6,
693 	},
694 	[ALE_PORT_UNKNOWN_REG_MCAST_FLOOD] = {
695 		.name		= "unknown_reg_flood",
696 		.offset		= ALE_UNKNOWNVLAN,
697 		.port_offset	= 0,
698 		.shift		= 16,
699 		.port_shift	= 0,
700 		.bits		= 6,
701 	},
702 	[ALE_PORT_UNTAGGED_EGRESS] = {
703 		.name		= "untagged_egress",
704 		.offset		= ALE_UNKNOWNVLAN,
705 		.port_offset	= 0,
706 		.shift		= 24,
707 		.port_shift	= 0,
708 		.bits		= 6,
709 	},
710 };
711 
712 int cpsw_ale_control_set(struct cpsw_ale *ale, int port, int control,
713 			 int value)
714 {
715 	const struct ale_control_info *info;
716 	int offset, shift;
717 	u32 tmp, mask;
718 
719 	if (control < 0 || control >= ARRAY_SIZE(ale_controls))
720 		return -EINVAL;
721 
722 	info = &ale_controls[control];
723 	if (info->port_offset == 0 && info->port_shift == 0)
724 		port = 0; /* global, port is a dont care */
725 
726 	if (port < 0 || port > ale->params.ale_ports)
727 		return -EINVAL;
728 
729 	mask = BITMASK(info->bits);
730 	if (value & ~mask)
731 		return -EINVAL;
732 
733 	offset = info->offset + (port * info->port_offset);
734 	shift  = info->shift  + (port * info->port_shift);
735 
736 	tmp = __raw_readl(ale->params.ale_regs + offset);
737 	tmp = (tmp & ~(mask << shift)) | (value << shift);
738 	__raw_writel(tmp, ale->params.ale_regs + offset);
739 
740 	return 0;
741 }
742 EXPORT_SYMBOL_GPL(cpsw_ale_control_set);
743 
744 int cpsw_ale_control_get(struct cpsw_ale *ale, int port, int control)
745 {
746 	const struct ale_control_info *info;
747 	int offset, shift;
748 	u32 tmp;
749 
750 	if (control < 0 || control >= ARRAY_SIZE(ale_controls))
751 		return -EINVAL;
752 
753 	info = &ale_controls[control];
754 	if (info->port_offset == 0 && info->port_shift == 0)
755 		port = 0; /* global, port is a dont care */
756 
757 	if (port < 0 || port > ale->params.ale_ports)
758 		return -EINVAL;
759 
760 	offset = info->offset + (port * info->port_offset);
761 	shift  = info->shift  + (port * info->port_shift);
762 
763 	tmp = __raw_readl(ale->params.ale_regs + offset) >> shift;
764 	return tmp & BITMASK(info->bits);
765 }
766 EXPORT_SYMBOL_GPL(cpsw_ale_control_get);
767 
768 static void cpsw_ale_timer(struct timer_list *t)
769 {
770 	struct cpsw_ale *ale = from_timer(ale, t, timer);
771 
772 	cpsw_ale_control_set(ale, 0, ALE_AGEOUT, 1);
773 
774 	if (ale->ageout) {
775 		ale->timer.expires = jiffies + ale->ageout;
776 		add_timer(&ale->timer);
777 	}
778 }
779 
780 void cpsw_ale_start(struct cpsw_ale *ale)
781 {
782 	u32 rev, ale_entries;
783 
784 	rev = __raw_readl(ale->params.ale_regs + ALE_IDVER);
785 	if (!ale->params.major_ver_mask)
786 		ale->params.major_ver_mask = 0xff;
787 	ale->version =
788 		(ALE_VERSION_MAJOR(rev, ale->params.major_ver_mask) << 8) |
789 		 ALE_VERSION_MINOR(rev);
790 	dev_info(ale->params.dev, "initialized cpsw ale version %d.%d\n",
791 		 ALE_VERSION_MAJOR(rev, ale->params.major_ver_mask),
792 		 ALE_VERSION_MINOR(rev));
793 
794 	if (!ale->params.ale_entries) {
795 		ale_entries =
796 			__raw_readl(ale->params.ale_regs + ALE_STATUS) &
797 				    ALE_STATUS_SIZE_MASK;
798 		/* ALE available on newer NetCP switches has introduced
799 		 * a register, ALE_STATUS, to indicate the size of ALE
800 		 * table which shows the size as a multiple of 1024 entries.
801 		 * For these, params.ale_entries will be set to zero. So
802 		 * read the register and update the value of ale_entries.
803 		 * ALE table on NetCP lite, is much smaller and is indicated
804 		 * by a value of zero in ALE_STATUS. So use a default value
805 		 * of ALE_TABLE_SIZE_DEFAULT for this. Caller is expected
806 		 * to set the value of ale_entries for all other versions
807 		 * of ALE.
808 		 */
809 		if (!ale_entries)
810 			ale_entries = ALE_TABLE_SIZE_DEFAULT;
811 		else
812 			ale_entries *= ALE_TABLE_SIZE_MULTIPLIER;
813 		ale->params.ale_entries = ale_entries;
814 	}
815 	dev_info(ale->params.dev,
816 		 "ALE Table size %ld\n", ale->params.ale_entries);
817 
818 	/* set default bits for existing h/w */
819 	ale->port_mask_bits = 3;
820 	ale->port_num_bits = 2;
821 	ale->vlan_field_bits = 3;
822 
823 	/* Set defaults override for ALE on NetCP NU switch and for version
824 	 * 1R3
825 	 */
826 	if (ale->params.nu_switch_ale) {
827 		/* Separate registers for unknown vlan configuration.
828 		 * Also there are N bits, where N is number of ale
829 		 * ports and shift value should be 0
830 		 */
831 		ale_controls[ALE_PORT_UNKNOWN_VLAN_MEMBER].bits =
832 					ale->params.ale_ports;
833 		ale_controls[ALE_PORT_UNKNOWN_VLAN_MEMBER].offset =
834 					ALE_UNKNOWNVLAN_MEMBER;
835 		ale_controls[ALE_PORT_UNKNOWN_MCAST_FLOOD].bits =
836 					ale->params.ale_ports;
837 		ale_controls[ALE_PORT_UNKNOWN_MCAST_FLOOD].shift = 0;
838 		ale_controls[ALE_PORT_UNKNOWN_MCAST_FLOOD].offset =
839 					ALE_UNKNOWNVLAN_UNREG_MCAST_FLOOD;
840 		ale_controls[ALE_PORT_UNKNOWN_REG_MCAST_FLOOD].bits =
841 					ale->params.ale_ports;
842 		ale_controls[ALE_PORT_UNKNOWN_REG_MCAST_FLOOD].shift = 0;
843 		ale_controls[ALE_PORT_UNKNOWN_REG_MCAST_FLOOD].offset =
844 					ALE_UNKNOWNVLAN_REG_MCAST_FLOOD;
845 		ale_controls[ALE_PORT_UNTAGGED_EGRESS].bits =
846 					ale->params.ale_ports;
847 		ale_controls[ALE_PORT_UNTAGGED_EGRESS].shift = 0;
848 		ale_controls[ALE_PORT_UNTAGGED_EGRESS].offset =
849 					ALE_UNKNOWNVLAN_FORCE_UNTAG_EGRESS;
850 		ale->port_mask_bits = ale->params.ale_ports;
851 		ale->port_num_bits = ale->params.ale_ports - 1;
852 		ale->vlan_field_bits = ale->params.ale_ports;
853 	} else if (ale->version == ALE_VERSION_1R3) {
854 		ale->port_mask_bits = ale->params.ale_ports;
855 		ale->port_num_bits = 3;
856 		ale->vlan_field_bits = ale->params.ale_ports;
857 	}
858 
859 	cpsw_ale_control_set(ale, 0, ALE_ENABLE, 1);
860 	cpsw_ale_control_set(ale, 0, ALE_CLEAR, 1);
861 
862 	timer_setup(&ale->timer, cpsw_ale_timer, 0);
863 	if (ale->ageout) {
864 		ale->timer.expires = jiffies + ale->ageout;
865 		add_timer(&ale->timer);
866 	}
867 }
868 EXPORT_SYMBOL_GPL(cpsw_ale_start);
869 
870 void cpsw_ale_stop(struct cpsw_ale *ale)
871 {
872 	del_timer_sync(&ale->timer);
873 }
874 EXPORT_SYMBOL_GPL(cpsw_ale_stop);
875 
876 struct cpsw_ale *cpsw_ale_create(struct cpsw_ale_params *params)
877 {
878 	struct cpsw_ale *ale;
879 
880 	ale = kzalloc(sizeof(*ale), GFP_KERNEL);
881 	if (!ale)
882 		return NULL;
883 
884 	ale->params = *params;
885 	ale->ageout = ale->params.ale_ageout * HZ;
886 
887 	return ale;
888 }
889 EXPORT_SYMBOL_GPL(cpsw_ale_create);
890 
891 int cpsw_ale_destroy(struct cpsw_ale *ale)
892 {
893 	if (!ale)
894 		return -EINVAL;
895 	cpsw_ale_control_set(ale, 0, ALE_ENABLE, 0);
896 	kfree(ale);
897 	return 0;
898 }
899 EXPORT_SYMBOL_GPL(cpsw_ale_destroy);
900 
901 void cpsw_ale_dump(struct cpsw_ale *ale, u32 *data)
902 {
903 	int i;
904 
905 	for (i = 0; i < ale->params.ale_entries; i++) {
906 		cpsw_ale_read(ale, i, data);
907 		data += ALE_ENTRY_WORDS;
908 	}
909 }
910 EXPORT_SYMBOL_GPL(cpsw_ale_dump);
911 
912 MODULE_LICENSE("GPL v2");
913 MODULE_DESCRIPTION("TI CPSW ALE driver");
914 MODULE_AUTHOR("Texas Instruments");
915