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>
22 #include <linux/stat.h>
23 #include <linux/sysfs.h>
24 #include <linux/etherdevice.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
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)
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,
83 value &= BITMASK(bits);
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) \
94 return cpsw_ale_get_field(ale_entry, start, bits); \
96 static inline void cpsw_ale_set_##name(u32 *ale_entry, u32 value) \
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, \
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)
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, u8 *addr)
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)
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 +
162 static int cpsw_ale_write(struct cpsw_ale *ale, int idx, u32 *ale_entry)
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 +
172 writel_relaxed(idx | ALE_TABLE_WRITE, ale->params.ale_regs +
178 static int cpsw_ale_match_addr(struct cpsw_ale *ale, u8 *addr, u16 vid)
180 u32 ale_entry[ALE_ENTRY_WORDS];
183 for (idx = 0; idx < ale->params.ale_entries; idx++) {
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)
190 if (cpsw_ale_get_vlan_id(ale_entry) != vid)
192 cpsw_ale_get_addr(ale_entry, entry_addr);
193 if (ether_addr_equal(entry_addr, addr))
199 static int cpsw_ale_match_vlan(struct cpsw_ale *ale, u16 vid)
201 u32 ale_entry[ALE_ENTRY_WORDS];
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)
209 if (cpsw_ale_get_vlan_id(ale_entry) == vid)
215 static int cpsw_ale_match_free(struct cpsw_ale *ale)
217 u32 ale_entry[ALE_ENTRY_WORDS];
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)
229 static int cpsw_ale_find_ageable(struct cpsw_ale *ale)
231 u32 ale_entry[ALE_ENTRY_WORDS];
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)
239 if (cpsw_ale_get_mcast(ale_entry))
241 type = cpsw_ale_get_ucast_type(ale_entry);
242 if (type != ALE_UCAST_PERSISTANT &&
243 type != ALE_UCAST_OUI)
249 static void cpsw_ale_flush_mcast(struct cpsw_ale *ale, u32 *ale_entry,
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 */
260 /* free if only remaining port is host port */
262 cpsw_ale_set_port_mask(ale_entry, mask,
263 ale->port_mask_bits);
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];
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)
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)
287 if (cpsw_ale_get_mcast(ale_entry)) {
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);
299 EXPORT_SYMBOL_GPL(cpsw_ale_flush_multicast);
301 static inline void cpsw_ale_set_vlan_entry_type(u32 *ale_entry,
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);
308 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
312 int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port,
315 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
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);
328 idx = cpsw_ale_match_free(ale);
330 idx = cpsw_ale_find_ageable(ale);
334 cpsw_ale_write(ale, idx, ale_entry);
337 EXPORT_SYMBOL_GPL(cpsw_ale_add_ucast);
339 int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port,
342 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
345 idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
349 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
350 cpsw_ale_write(ale, idx, ale_entry);
353 EXPORT_SYMBOL_GPL(cpsw_ale_del_ucast);
355 int cpsw_ale_add_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
356 int flags, u16 vid, int mcast_state)
358 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
361 idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 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);
374 cpsw_ale_set_port_mask(ale_entry, port_mask,
375 ale->port_mask_bits);
378 idx = cpsw_ale_match_free(ale);
380 idx = cpsw_ale_find_ageable(ale);
384 cpsw_ale_write(ale, idx, ale_entry);
387 EXPORT_SYMBOL_GPL(cpsw_ale_add_mcast);
389 int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
392 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
395 idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
399 cpsw_ale_read(ale, idx, ale_entry);
402 cpsw_ale_set_port_mask(ale_entry, port_mask,
403 ale->port_mask_bits);
405 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
407 cpsw_ale_write(ale, idx, ale_entry);
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)
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};
433 idx = cpsw_ale_match_vlan(ale, vid);
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);
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);
452 idx = cpsw_ale_match_free(ale);
454 idx = cpsw_ale_find_ageable(ale);
458 cpsw_ale_write(ale, idx, ale_entry);
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};
468 idx = cpsw_ale_match_vlan(ale, vid);
472 cpsw_ale_read(ale, idx, ale_entry);
475 cpsw_ale_set_vlan_member_list(ale_entry, port_mask,
476 ale->vlan_field_bits);
478 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
480 cpsw_ale_write(ale, idx, ale_entry);
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];
491 /* Only bother doing the work if the setting is actually changing */
492 if (ale->allmulti == allmulti)
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)
505 cpsw_ale_get_vlan_unreg_mcast(ale_entry,
506 ale->vlan_field_bits);
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 {
520 int offset, port_offset;
521 int shift, port_shift;
525 static struct ale_control_info ale_controls[ALE_NUM_CONTROLS] = {
528 .offset = ALE_CONTROL,
536 .offset = ALE_CONTROL,
544 .offset = ALE_CONTROL,
550 [ALE_P0_UNI_FLOOD] = {
551 .name = "port0_unicast_flood",
552 .offset = ALE_CONTROL,
558 [ALE_VLAN_NOLEARN] = {
559 .name = "vlan_nolearn",
560 .offset = ALE_CONTROL,
566 [ALE_NO_PORT_VLAN] = {
567 .name = "no_port_vlan",
568 .offset = ALE_CONTROL,
576 .offset = ALE_CONTROL,
584 .offset = ALE_CONTROL,
590 [ALE_RATE_LIMIT_TX] = {
591 .name = "rate_limit_tx",
592 .offset = ALE_CONTROL,
599 .name = "vlan_aware",
600 .offset = ALE_CONTROL,
606 [ALE_AUTH_ENABLE] = {
607 .name = "auth_enable",
608 .offset = ALE_CONTROL,
615 .name = "rate_limit",
616 .offset = ALE_CONTROL,
623 .name = "port_state",
624 .offset = ALE_PORTCTL,
630 [ALE_PORT_DROP_UNTAGGED] = {
631 .name = "drop_untagged",
632 .offset = ALE_PORTCTL,
638 [ALE_PORT_DROP_UNKNOWN_VLAN] = {
639 .name = "drop_unknown",
640 .offset = ALE_PORTCTL,
646 [ALE_PORT_NOLEARN] = {
648 .offset = ALE_PORTCTL,
654 [ALE_PORT_NO_SA_UPDATE] = {
655 .name = "no_source_update",
656 .offset = ALE_PORTCTL,
662 [ALE_PORT_MCAST_LIMIT] = {
663 .name = "mcast_limit",
664 .offset = ALE_PORTCTL,
670 [ALE_PORT_BCAST_LIMIT] = {
671 .name = "bcast_limit",
672 .offset = ALE_PORTCTL,
678 [ALE_PORT_UNKNOWN_VLAN_MEMBER] = {
679 .name = "unknown_vlan_member",
680 .offset = ALE_UNKNOWNVLAN,
686 [ALE_PORT_UNKNOWN_MCAST_FLOOD] = {
687 .name = "unknown_mcast_flood",
688 .offset = ALE_UNKNOWNVLAN,
694 [ALE_PORT_UNKNOWN_REG_MCAST_FLOOD] = {
695 .name = "unknown_reg_flood",
696 .offset = ALE_UNKNOWNVLAN,
702 [ALE_PORT_UNTAGGED_EGRESS] = {
703 .name = "untagged_egress",
704 .offset = ALE_UNKNOWNVLAN,
712 int cpsw_ale_control_set(struct cpsw_ale *ale, int port, int control,
715 const struct ale_control_info *info;
719 if (control < 0 || control >= ARRAY_SIZE(ale_controls))
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)
729 mask = BITMASK(info->bits);
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);
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;
750 if (control < 0 || control >= ARRAY_SIZE(ale_controls))
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)
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);
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);
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);
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;
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) {
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
838 ale_entries = ALE_TABLE_SIZE_DEFAULT;
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
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;
882 EXPORT_SYMBOL_GPL(cpsw_ale_create);
884 void cpsw_ale_dump(struct cpsw_ale *ale, u32 *data)
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");