perf tools: Don't clone maps from parent when synthesizing forks
[linux/fpc-iii.git] / drivers / net / ethernet / ti / cpsw_ale.c
blob798c989d5d9342328544d44a389fd11b5b5d88c1
1 /*
2 * Texas Instruments N-Port Ethernet Switch Address Lookup Engine
4 * Copyright (C) 2012 Texas Instruments
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.
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.
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>
26 #include "cpsw_ale.h"
28 #define BITMASK(bits) (BIT(bits) - 1)
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
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
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)))
52 #define ALE_TABLE_WRITE BIT(31)
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
59 #define ALE_UCAST_PERSISTANT 0
60 #define ALE_UCAST_UNTOUCHED 1
61 #define ALE_UCAST_OUI 2
62 #define ALE_UCAST_TOUCHED 3
64 #define ALE_TABLE_SIZE_MULTIPLIER 1024
65 #define ALE_STATUS_SIZE_MASK 0x1f
66 #define ALE_TABLE_SIZE_DEFAULT 64
68 static inline int cpsw_ale_get_field(u32 *ale_entry, u32 start, u32 bits)
70 int idx;
72 idx = start / 32;
73 start -= idx * 32;
74 idx = 2 - idx; /* flip */
75 return (ale_entry[idx] >> start) & BITMASK(bits);
78 static inline void cpsw_ale_set_field(u32 *ale_entry, u32 start, u32 bits,
79 u32 value)
81 int idx;
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);
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); \
101 #define DEFINE_ALE_FIELD1(name, start) \
102 static inline int cpsw_ale_get_##name(u32 *ale_entry, u32 bits) \
104 return cpsw_ale_get_field(ale_entry, start, bits); \
106 static inline void cpsw_ale_set_##name(u32 *ale_entry, u32 value, \
107 u32 bits) \
109 cpsw_ale_set_field(ale_entry, start, bits, value); \
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)
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)
133 int i;
135 for (i = 0; i < 6; i++)
136 addr[i] = cpsw_ale_get_field(ale_entry, 40 - 8*i, 8);
139 static inline void cpsw_ale_set_addr(u32 *ale_entry, const u8 *addr)
141 int i;
143 for (i = 0; i < 6; i++)
144 cpsw_ale_set_field(ale_entry, 40 - 8*i, 8, addr[i]);
147 static int cpsw_ale_read(struct cpsw_ale *ale, int idx, u32 *ale_entry)
149 int i;
151 WARN_ON(idx > ale->params.ale_entries);
153 writel_relaxed(idx, ale->params.ale_regs + ALE_TABLE_CONTROL);
155 for (i = 0; i < ALE_ENTRY_WORDS; i++)
156 ale_entry[i] = readl_relaxed(ale->params.ale_regs +
157 ALE_TABLE + 4 * i);
159 return idx;
162 static int cpsw_ale_write(struct cpsw_ale *ale, int idx, u32 *ale_entry)
164 int i;
166 WARN_ON(idx > ale->params.ale_entries);
168 for (i = 0; i < ALE_ENTRY_WORDS; i++)
169 writel_relaxed(ale_entry[i], ale->params.ale_regs +
170 ALE_TABLE + 4 * i);
172 writel_relaxed(idx | ALE_TABLE_WRITE, ale->params.ale_regs +
173 ALE_TABLE_CONTROL);
175 return idx;
178 static int cpsw_ale_match_addr(struct cpsw_ale *ale, const u8 *addr, u16 vid)
180 u32 ale_entry[ALE_ENTRY_WORDS];
181 int type, idx;
183 for (idx = 0; idx < ale->params.ale_entries; idx++) {
184 u8 entry_addr[6];
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;
196 return -ENOENT;
199 static int cpsw_ale_match_vlan(struct cpsw_ale *ale, u16 vid)
201 u32 ale_entry[ALE_ENTRY_WORDS];
202 int type, idx;
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;
212 return -ENOENT;
215 static int cpsw_ale_match_free(struct cpsw_ale *ale)
217 u32 ale_entry[ALE_ENTRY_WORDS];
218 int type, idx;
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;
226 return -ENOENT;
229 static int cpsw_ale_find_ageable(struct cpsw_ale *ale)
231 u32 ale_entry[ALE_ENTRY_WORDS];
232 int type, idx;
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;
246 return -ENOENT;
249 static void cpsw_ale_flush_mcast(struct cpsw_ale *ale, u32 *ale_entry,
250 int port_mask)
252 int mask;
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;
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);
268 int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask, int vid)
270 u32 ale_entry[ALE_ENTRY_WORDS];
271 int ret, idx;
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;
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.
284 if (vid != -1 && cpsw_ale_get_vlan_id(ale_entry) != vid)
285 continue;
287 if (cpsw_ale_get_mcast(ale_entry)) {
288 u8 addr[6];
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);
295 cpsw_ale_write(ale, idx, ale_entry);
297 return 0;
299 EXPORT_SYMBOL_GPL(cpsw_ale_flush_multicast);
301 static inline void cpsw_ale_set_vlan_entry_type(u32 *ale_entry,
302 int flags, u16 vid)
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);
312 int cpsw_ale_add_ucast(struct cpsw_ale *ale, const u8 *addr, int port,
313 int flags, u16 vid)
315 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
316 int idx;
318 cpsw_ale_set_vlan_entry_type(ale_entry, flags, vid);
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);
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;
334 cpsw_ale_write(ale, idx, ale_entry);
335 return 0;
337 EXPORT_SYMBOL_GPL(cpsw_ale_add_ucast);
339 int cpsw_ale_del_ucast(struct cpsw_ale *ale, const u8 *addr, int port,
340 int flags, u16 vid)
342 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
343 int idx;
345 idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
346 if (idx < 0)
347 return -ENOENT;
349 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
350 cpsw_ale_write(ale, idx, ale_entry);
351 return 0;
353 EXPORT_SYMBOL_GPL(cpsw_ale_del_ucast);
355 int cpsw_ale_add_mcast(struct cpsw_ale *ale, const u8 *addr, int port_mask,
356 int flags, u16 vid, int mcast_state)
358 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
359 int idx, mask;
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);
365 cpsw_ale_set_vlan_entry_type(ale_entry, flags, vid);
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);
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);
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;
384 cpsw_ale_write(ale, idx, ale_entry);
385 return 0;
387 EXPORT_SYMBOL_GPL(cpsw_ale_add_mcast);
389 int cpsw_ale_del_mcast(struct cpsw_ale *ale, const u8 *addr, int port_mask,
390 int flags, u16 vid)
392 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
393 int idx;
395 idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
396 if (idx < 0)
397 return -ENOENT;
399 cpsw_ale_read(ale, idx, ale_entry);
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);
407 cpsw_ale_write(ale, idx, ale_entry);
408 return 0;
410 EXPORT_SYMBOL_GPL(cpsw_ale_del_mcast);
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)
416 int idx;
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));
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));
427 int cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port, int untag,
428 int reg_mcast, int unreg_mcast)
430 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
431 int idx;
433 idx = cpsw_ale_match_vlan(ale, vid);
434 if (idx >= 0)
435 cpsw_ale_read(ale, idx, ale_entry);
437 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_VLAN);
438 cpsw_ale_set_vlan_id(ale_entry, vid);
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);
449 cpsw_ale_set_vlan_member_list(ale_entry, port, ale->vlan_field_bits);
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;
458 cpsw_ale_write(ale, idx, ale_entry);
459 return 0;
461 EXPORT_SYMBOL_GPL(cpsw_ale_add_vlan);
463 int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port_mask)
465 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
466 int idx;
468 idx = cpsw_ale_match_vlan(ale, vid);
469 if (idx < 0)
470 return -ENOENT;
472 cpsw_ale_read(ale, idx, ale_entry);
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);
480 cpsw_ale_write(ale, idx, ale_entry);
481 return 0;
483 EXPORT_SYMBOL_GPL(cpsw_ale_del_vlan);
485 void cpsw_ale_set_allmulti(struct cpsw_ale *ale, int allmulti)
487 u32 ale_entry[ALE_ENTRY_WORDS];
488 int type, idx;
489 int unreg_mcast = 0;
491 /* Only bother doing the work if the setting is actually changing */
492 if (ale->allmulti == allmulti)
493 return;
495 /* Remember the new setting to check against next time */
496 ale->allmulti = allmulti;
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;
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);
516 EXPORT_SYMBOL_GPL(cpsw_ale_set_allmulti);
518 struct ale_control_info {
519 const char *name;
520 int offset, port_offset;
521 int shift, port_shift;
522 int bits;
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,
534 [ALE_CLEAR] = {
535 .name = "clear",
536 .offset = ALE_CONTROL,
537 .port_offset = 0,
538 .shift = 30,
539 .port_shift = 0,
540 .bits = 1,
542 [ALE_AGEOUT] = {
543 .name = "ageout",
544 .offset = ALE_CONTROL,
545 .port_offset = 0,
546 .shift = 29,
547 .port_shift = 0,
548 .bits = 1,
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,
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,
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,
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,
582 [ALE_BYPASS] = {
583 .name = "bypass",
584 .offset = ALE_CONTROL,
585 .port_offset = 0,
586 .shift = 4,
587 .port_shift = 0,
588 .bits = 1,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
712 int cpsw_ale_control_set(struct cpsw_ale *ale, int port, int control,
713 int value)
715 const struct ale_control_info *info;
716 int offset, shift;
717 u32 tmp, mask;
719 if (control < 0 || control >= ARRAY_SIZE(ale_controls))
720 return -EINVAL;
722 info = &ale_controls[control];
723 if (info->port_offset == 0 && info->port_shift == 0)
724 port = 0; /* global, port is a dont care */
726 if (port < 0 || port >= ale->params.ale_ports)
727 return -EINVAL;
729 mask = BITMASK(info->bits);
730 if (value & ~mask)
731 return -EINVAL;
733 offset = info->offset + (port * info->port_offset);
734 shift = info->shift + (port * info->port_shift);
736 tmp = readl_relaxed(ale->params.ale_regs + offset);
737 tmp = (tmp & ~(mask << shift)) | (value << shift);
738 writel_relaxed(tmp, ale->params.ale_regs + offset);
740 return 0;
742 EXPORT_SYMBOL_GPL(cpsw_ale_control_set);
744 int cpsw_ale_control_get(struct cpsw_ale *ale, int port, int control)
746 const struct ale_control_info *info;
747 int offset, shift;
748 u32 tmp;
750 if (control < 0 || control >= ARRAY_SIZE(ale_controls))
751 return -EINVAL;
753 info = &ale_controls[control];
754 if (info->port_offset == 0 && info->port_shift == 0)
755 port = 0; /* global, port is a dont care */
757 if (port < 0 || port >= ale->params.ale_ports)
758 return -EINVAL;
760 offset = info->offset + (port * info->port_offset);
761 shift = info->shift + (port * info->port_shift);
763 tmp = readl_relaxed(ale->params.ale_regs + offset) >> shift;
764 return tmp & BITMASK(info->bits);
766 EXPORT_SYMBOL_GPL(cpsw_ale_control_get);
768 static void cpsw_ale_timer(struct timer_list *t)
770 struct cpsw_ale *ale = from_timer(ale, t, timer);
772 cpsw_ale_control_set(ale, 0, ALE_AGEOUT, 1);
774 if (ale->ageout) {
775 ale->timer.expires = jiffies + ale->ageout;
776 add_timer(&ale->timer);
780 void cpsw_ale_start(struct cpsw_ale *ale)
782 cpsw_ale_control_set(ale, 0, ALE_ENABLE, 1);
783 cpsw_ale_control_set(ale, 0, ALE_CLEAR, 1);
785 timer_setup(&ale->timer, cpsw_ale_timer, 0);
786 if (ale->ageout) {
787 ale->timer.expires = jiffies + ale->ageout;
788 add_timer(&ale->timer);
791 EXPORT_SYMBOL_GPL(cpsw_ale_start);
793 void cpsw_ale_stop(struct cpsw_ale *ale)
795 del_timer_sync(&ale->timer);
796 cpsw_ale_control_set(ale, 0, ALE_ENABLE, 0);
798 EXPORT_SYMBOL_GPL(cpsw_ale_stop);
800 struct cpsw_ale *cpsw_ale_create(struct cpsw_ale_params *params)
802 struct cpsw_ale *ale;
803 u32 rev, ale_entries;
805 ale = devm_kzalloc(params->dev, sizeof(*ale), GFP_KERNEL);
806 if (!ale)
807 return NULL;
809 ale->params = *params;
810 ale->ageout = ale->params.ale_ageout * HZ;
812 rev = readl_relaxed(ale->params.ale_regs + ALE_IDVER);
813 if (!ale->params.major_ver_mask)
814 ale->params.major_ver_mask = 0xff;
815 ale->version =
816 (ALE_VERSION_MAJOR(rev, ale->params.major_ver_mask) << 8) |
817 ALE_VERSION_MINOR(rev);
818 dev_info(ale->params.dev, "initialized cpsw ale version %d.%d\n",
819 ALE_VERSION_MAJOR(rev, ale->params.major_ver_mask),
820 ALE_VERSION_MINOR(rev));
822 if (!ale->params.ale_entries) {
823 ale_entries =
824 readl_relaxed(ale->params.ale_regs + ALE_STATUS) &
825 ALE_STATUS_SIZE_MASK;
826 /* ALE available on newer NetCP switches has introduced
827 * a register, ALE_STATUS, to indicate the size of ALE
828 * table which shows the size as a multiple of 1024 entries.
829 * For these, params.ale_entries will be set to zero. So
830 * read the register and update the value of ale_entries.
831 * ALE table on NetCP lite, is much smaller and is indicated
832 * by a value of zero in ALE_STATUS. So use a default value
833 * of ALE_TABLE_SIZE_DEFAULT for this. Caller is expected
834 * to set the value of ale_entries for all other versions
835 * of ALE.
837 if (!ale_entries)
838 ale_entries = ALE_TABLE_SIZE_DEFAULT;
839 else
840 ale_entries *= ALE_TABLE_SIZE_MULTIPLIER;
841 ale->params.ale_entries = ale_entries;
843 dev_info(ale->params.dev,
844 "ALE Table size %ld\n", ale->params.ale_entries);
846 /* set default bits for existing h/w */
847 ale->port_mask_bits = ale->params.ale_ports;
848 ale->port_num_bits = order_base_2(ale->params.ale_ports);
849 ale->vlan_field_bits = ale->params.ale_ports;
851 /* Set defaults override for ALE on NetCP NU switch and for version
852 * 1R3
854 if (ale->params.nu_switch_ale) {
855 /* Separate registers for unknown vlan configuration.
856 * Also there are N bits, where N is number of ale
857 * ports and shift value should be 0
859 ale_controls[ALE_PORT_UNKNOWN_VLAN_MEMBER].bits =
860 ale->params.ale_ports;
861 ale_controls[ALE_PORT_UNKNOWN_VLAN_MEMBER].offset =
862 ALE_UNKNOWNVLAN_MEMBER;
863 ale_controls[ALE_PORT_UNKNOWN_MCAST_FLOOD].bits =
864 ale->params.ale_ports;
865 ale_controls[ALE_PORT_UNKNOWN_MCAST_FLOOD].shift = 0;
866 ale_controls[ALE_PORT_UNKNOWN_MCAST_FLOOD].offset =
867 ALE_UNKNOWNVLAN_UNREG_MCAST_FLOOD;
868 ale_controls[ALE_PORT_UNKNOWN_REG_MCAST_FLOOD].bits =
869 ale->params.ale_ports;
870 ale_controls[ALE_PORT_UNKNOWN_REG_MCAST_FLOOD].shift = 0;
871 ale_controls[ALE_PORT_UNKNOWN_REG_MCAST_FLOOD].offset =
872 ALE_UNKNOWNVLAN_REG_MCAST_FLOOD;
873 ale_controls[ALE_PORT_UNTAGGED_EGRESS].bits =
874 ale->params.ale_ports;
875 ale_controls[ALE_PORT_UNTAGGED_EGRESS].shift = 0;
876 ale_controls[ALE_PORT_UNTAGGED_EGRESS].offset =
877 ALE_UNKNOWNVLAN_FORCE_UNTAG_EGRESS;
880 return ale;
882 EXPORT_SYMBOL_GPL(cpsw_ale_create);
884 void cpsw_ale_dump(struct cpsw_ale *ale, u32 *data)
886 int i;
888 for (i = 0; i < ale->params.ale_entries; i++) {
889 cpsw_ale_read(ale, i, data);
890 data += ALE_ENTRY_WORDS;
893 EXPORT_SYMBOL_GPL(cpsw_ale_dump);
895 MODULE_LICENSE("GPL v2");
896 MODULE_DESCRIPTION("TI CPSW ALE driver");
897 MODULE_AUTHOR("Texas Instruments");