1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Texas Instruments N-Port Ethernet Switch Address Lookup Engine
4 *
5 * Copyright (C) 2012 Texas Instruments
6 *
7 */
8 #include <linux/bitmap.h>
9 #include <linux/if_vlan.h>
10 #include <linux/kernel.h>
11 #include <linux/module.h>
12 #include <linux/platform_device.h>
13 #include <linux/seq_file.h>
14 #include <linux/slab.h>
15 #include <linux/err.h>
16 #include <linux/io.h>
17 #include <linux/stat.h>
18 #include <linux/sysfs.h>
19 #include <linux/etherdevice.h>
20
21 #include "cpsw_ale.h"
22
23 #define BITMASK(bits) (BIT(bits) - 1)
24
25 #define ALE_VERSION_MAJOR(rev, mask) (((rev) >> 8) & (mask))
26 #define ALE_VERSION_MINOR(rev) (rev & 0xff)
27 #define ALE_VERSION_1R3 0x0103
28 #define ALE_VERSION_1R4 0x0104
29
30 /* ALE Registers */
31 #define ALE_IDVER 0x00
32 #define ALE_STATUS 0x04
33 #define ALE_CONTROL 0x08
34 #define ALE_PRESCALE 0x10
35 #define ALE_AGING_TIMER 0x14
36 #define ALE_UNKNOWNVLAN 0x18
37 #define ALE_TABLE_CONTROL 0x20
38 #define ALE_TABLE 0x34
39 #define ALE_PORTCTL 0x40
40
41 /* ALE NetCP NU switch specific Registers */
42 #define ALE_UNKNOWNVLAN_MEMBER 0x90
43 #define ALE_UNKNOWNVLAN_UNREG_MCAST_FLOOD 0x94
44 #define ALE_UNKNOWNVLAN_REG_MCAST_FLOOD 0x98
45 #define ALE_UNKNOWNVLAN_FORCE_UNTAG_EGRESS 0x9C
46 #define ALE_VLAN_MASK_MUX(reg) (0xc0 + (0x4 * (reg)))
47
48 #define AM65_CPSW_ALE_THREAD_DEF_REG 0x134
49
50 /* ALE_AGING_TIMER */
51 #define ALE_AGING_TIMER_MASK GENMASK(23, 0)
52
53 /**
54 * struct ale_entry_fld - The ALE tbl entry field description
55 * @start_bit: field start bit
56 * @num_bits: field bit length
57 * @flags: field flags
58 */
59 struct ale_entry_fld {
60 u8 start_bit;
61 u8 num_bits;
62 u8 flags;
63 };
64
65 enum {
66 CPSW_ALE_F_STATUS_REG = BIT(0), /* Status register present */
67 CPSW_ALE_F_HW_AUTOAGING = BIT(1), /* HW auto aging */
68
69 CPSW_ALE_F_COUNT
70 };
71
72 /**
73 * struct cpsw_ale_dev_id - The ALE version/SoC specific configuration
74 * @dev_id: ALE version/SoC id
75 * @features: features supported by ALE
76 * @tbl_entries: number of ALE entries
77 * @major_ver_mask: mask of ALE Major Version Value in ALE_IDVER reg.
78 * @nu_switch_ale: NU Switch ALE
79 * @vlan_entry_tbl: ALE vlan entry fields description tbl
80 */
81 struct cpsw_ale_dev_id {
82 const char *dev_id;
83 u32 features;
84 u32 tbl_entries;
85 u32 major_ver_mask;
86 bool nu_switch_ale;
87 const struct ale_entry_fld *vlan_entry_tbl;
88 };
89
90 #define ALE_TABLE_WRITE BIT(31)
91
92 #define ALE_TYPE_FREE 0
93 #define ALE_TYPE_ADDR 1
94 #define ALE_TYPE_VLAN 2
95 #define ALE_TYPE_VLAN_ADDR 3
96
97 #define ALE_UCAST_PERSISTANT 0
98 #define ALE_UCAST_UNTOUCHED 1
99 #define ALE_UCAST_OUI 2
100 #define ALE_UCAST_TOUCHED 3
101
102 #define ALE_TABLE_SIZE_MULTIPLIER 1024
103 #define ALE_STATUS_SIZE_MASK 0x1f
104
cpsw_ale_get_field(u32 * ale_entry,u32 start,u32 bits)105 static inline int cpsw_ale_get_field(u32 *ale_entry, u32 start, u32 bits)
106 {
107 int idx, idx2;
108 u32 hi_val = 0;
109
110 idx = start / 32;
111 idx2 = (start + bits - 1) / 32;
112 /* Check if bits to be fetched exceed a word */
113 if (idx != idx2) {
114 idx2 = 2 - idx2; /* flip */
115 hi_val = ale_entry[idx2] << ((idx2 * 32) - start);
116 }
117 start -= idx * 32;
118 idx = 2 - idx; /* flip */
119 return (hi_val + (ale_entry[idx] >> start)) & BITMASK(bits);
120 }
121
cpsw_ale_set_field(u32 * ale_entry,u32 start,u32 bits,u32 value)122 static inline void cpsw_ale_set_field(u32 *ale_entry, u32 start, u32 bits,
123 u32 value)
124 {
125 int idx, idx2;
126
127 value &= BITMASK(bits);
128 idx = start / 32;
129 idx2 = (start + bits - 1) / 32;
130 /* Check if bits to be set exceed a word */
131 if (idx != idx2) {
132 idx2 = 2 - idx2; /* flip */
133 ale_entry[idx2] &= ~(BITMASK(bits + start - (idx2 * 32)));
134 ale_entry[idx2] |= (value >> ((idx2 * 32) - start));
135 }
136 start -= idx * 32;
137 idx = 2 - idx; /* flip */
138 ale_entry[idx] &= ~(BITMASK(bits) << start);
139 ale_entry[idx] |= (value << start);
140 }
141
142 #define DEFINE_ALE_FIELD(name, start, bits) \
143 static inline int cpsw_ale_get_##name(u32 *ale_entry) \
144 { \
145 return cpsw_ale_get_field(ale_entry, start, bits); \
146 } \
147 static inline void cpsw_ale_set_##name(u32 *ale_entry, u32 value) \
148 { \
149 cpsw_ale_set_field(ale_entry, start, bits, value); \
150 }
151
152 #define DEFINE_ALE_FIELD1(name, start) \
153 static inline int cpsw_ale_get_##name(u32 *ale_entry, u32 bits) \
154 { \
155 return cpsw_ale_get_field(ale_entry, start, bits); \
156 } \
157 static inline void cpsw_ale_set_##name(u32 *ale_entry, u32 value, \
158 u32 bits) \
159 { \
160 cpsw_ale_set_field(ale_entry, start, bits, value); \
161 }
162
163 enum {
164 ALE_ENT_VID_MEMBER_LIST = 0,
165 ALE_ENT_VID_UNREG_MCAST_MSK,
166 ALE_ENT_VID_REG_MCAST_MSK,
167 ALE_ENT_VID_FORCE_UNTAGGED_MSK,
168 ALE_ENT_VID_UNREG_MCAST_IDX,
169 ALE_ENT_VID_REG_MCAST_IDX,
170 ALE_ENT_VID_LAST,
171 };
172
173 #define ALE_FLD_ALLOWED BIT(0)
174 #define ALE_FLD_SIZE_PORT_MASK_BITS BIT(1)
175 #define ALE_FLD_SIZE_PORT_NUM_BITS BIT(2)
176
177 #define ALE_ENTRY_FLD(id, start, bits) \
178 [id] = { \
179 .start_bit = start, \
180 .num_bits = bits, \
181 .flags = ALE_FLD_ALLOWED, \
182 }
183
184 #define ALE_ENTRY_FLD_DYN_MSK_SIZE(id, start) \
185 [id] = { \
186 .start_bit = start, \
187 .num_bits = 0, \
188 .flags = ALE_FLD_ALLOWED | \
189 ALE_FLD_SIZE_PORT_MASK_BITS, \
190 }
191
192 /* dm814x, am3/am4/am5, k2hk */
193 static const struct ale_entry_fld vlan_entry_cpsw[ALE_ENT_VID_LAST] = {
194 ALE_ENTRY_FLD(ALE_ENT_VID_MEMBER_LIST, 0, 3),
195 ALE_ENTRY_FLD(ALE_ENT_VID_UNREG_MCAST_MSK, 8, 3),
196 ALE_ENTRY_FLD(ALE_ENT_VID_REG_MCAST_MSK, 16, 3),
197 ALE_ENTRY_FLD(ALE_ENT_VID_FORCE_UNTAGGED_MSK, 24, 3),
198 };
199
200 /* k2e/k2l, k3 am65/j721e cpsw2g */
201 static const struct ale_entry_fld vlan_entry_nu[ALE_ENT_VID_LAST] = {
202 ALE_ENTRY_FLD_DYN_MSK_SIZE(ALE_ENT_VID_MEMBER_LIST, 0),
203 ALE_ENTRY_FLD(ALE_ENT_VID_UNREG_MCAST_IDX, 20, 3),
204 ALE_ENTRY_FLD_DYN_MSK_SIZE(ALE_ENT_VID_FORCE_UNTAGGED_MSK, 24),
205 ALE_ENTRY_FLD(ALE_ENT_VID_REG_MCAST_IDX, 44, 3),
206 };
207
208 /* K3 j721e/j7200 cpsw9g/5g, am64x cpsw3g */
209 static const struct ale_entry_fld vlan_entry_k3_cpswxg[] = {
210 ALE_ENTRY_FLD_DYN_MSK_SIZE(ALE_ENT_VID_MEMBER_LIST, 0),
211 ALE_ENTRY_FLD_DYN_MSK_SIZE(ALE_ENT_VID_UNREG_MCAST_MSK, 12),
212 ALE_ENTRY_FLD_DYN_MSK_SIZE(ALE_ENT_VID_FORCE_UNTAGGED_MSK, 24),
213 ALE_ENTRY_FLD_DYN_MSK_SIZE(ALE_ENT_VID_REG_MCAST_MSK, 36),
214 };
215
216 DEFINE_ALE_FIELD(entry_type, 60, 2)
217 DEFINE_ALE_FIELD(vlan_id, 48, 12)
218 DEFINE_ALE_FIELD(mcast_state, 62, 2)
219 DEFINE_ALE_FIELD1(port_mask, 66)
220 DEFINE_ALE_FIELD(super, 65, 1)
221 DEFINE_ALE_FIELD(ucast_type, 62, 2)
222 DEFINE_ALE_FIELD1(port_num, 66)
223 DEFINE_ALE_FIELD(blocked, 65, 1)
224 DEFINE_ALE_FIELD(secure, 64, 1)
225 DEFINE_ALE_FIELD(mcast, 40, 1)
226
227 #define NU_VLAN_UNREG_MCAST_IDX 1
228
cpsw_ale_entry_get_fld(struct cpsw_ale * ale,u32 * ale_entry,const struct ale_entry_fld * entry_tbl,int fld_id)229 static int cpsw_ale_entry_get_fld(struct cpsw_ale *ale,
230 u32 *ale_entry,
231 const struct ale_entry_fld *entry_tbl,
232 int fld_id)
233 {
234 const struct ale_entry_fld *entry_fld;
235 u32 bits;
236
237 if (!ale || !ale_entry)
238 return -EINVAL;
239
240 entry_fld = &entry_tbl[fld_id];
241 if (!(entry_fld->flags & ALE_FLD_ALLOWED)) {
242 dev_err(ale->params.dev, "get: wrong ale fld id %d\n", fld_id);
243 return -ENOENT;
244 }
245
246 bits = entry_fld->num_bits;
247 if (entry_fld->flags & ALE_FLD_SIZE_PORT_MASK_BITS)
248 bits = ale->port_mask_bits;
249
250 return cpsw_ale_get_field(ale_entry, entry_fld->start_bit, bits);
251 }
252
cpsw_ale_entry_set_fld(struct cpsw_ale * ale,u32 * ale_entry,const struct ale_entry_fld * entry_tbl,int fld_id,u32 value)253 static void cpsw_ale_entry_set_fld(struct cpsw_ale *ale,
254 u32 *ale_entry,
255 const struct ale_entry_fld *entry_tbl,
256 int fld_id,
257 u32 value)
258 {
259 const struct ale_entry_fld *entry_fld;
260 u32 bits;
261
262 if (!ale || !ale_entry)
263 return;
264
265 entry_fld = &entry_tbl[fld_id];
266 if (!(entry_fld->flags & ALE_FLD_ALLOWED)) {
267 dev_err(ale->params.dev, "set: wrong ale fld id %d\n", fld_id);
268 return;
269 }
270
271 bits = entry_fld->num_bits;
272 if (entry_fld->flags & ALE_FLD_SIZE_PORT_MASK_BITS)
273 bits = ale->port_mask_bits;
274
275 cpsw_ale_set_field(ale_entry, entry_fld->start_bit, bits, value);
276 }
277
cpsw_ale_vlan_get_fld(struct cpsw_ale * ale,u32 * ale_entry,int fld_id)278 static int cpsw_ale_vlan_get_fld(struct cpsw_ale *ale,
279 u32 *ale_entry,
280 int fld_id)
281 {
282 return cpsw_ale_entry_get_fld(ale, ale_entry,
283 ale->vlan_entry_tbl, fld_id);
284 }
285
cpsw_ale_vlan_set_fld(struct cpsw_ale * ale,u32 * ale_entry,int fld_id,u32 value)286 static void cpsw_ale_vlan_set_fld(struct cpsw_ale *ale,
287 u32 *ale_entry,
288 int fld_id,
289 u32 value)
290 {
291 cpsw_ale_entry_set_fld(ale, ale_entry,
292 ale->vlan_entry_tbl, fld_id, value);
293 }
294
295 /* The MAC address field in the ALE entry cannot be macroized as above */
cpsw_ale_get_addr(u32 * ale_entry,u8 * addr)296 static inline void cpsw_ale_get_addr(u32 *ale_entry, u8 *addr)
297 {
298 int i;
299
300 for (i = 0; i < 6; i++)
301 addr[i] = cpsw_ale_get_field(ale_entry, 40 - 8*i, 8);
302 }
303
cpsw_ale_set_addr(u32 * ale_entry,const u8 * addr)304 static inline void cpsw_ale_set_addr(u32 *ale_entry, const u8 *addr)
305 {
306 int i;
307
308 for (i = 0; i < 6; i++)
309 cpsw_ale_set_field(ale_entry, 40 - 8*i, 8, addr[i]);
310 }
311
cpsw_ale_read(struct cpsw_ale * ale,int idx,u32 * ale_entry)312 static int cpsw_ale_read(struct cpsw_ale *ale, int idx, u32 *ale_entry)
313 {
314 int i;
315
316 WARN_ON(idx > ale->params.ale_entries);
317
318 writel_relaxed(idx, ale->params.ale_regs + ALE_TABLE_CONTROL);
319
320 for (i = 0; i < ALE_ENTRY_WORDS; i++)
321 ale_entry[i] = readl_relaxed(ale->params.ale_regs +
322 ALE_TABLE + 4 * i);
323
324 return idx;
325 }
326
cpsw_ale_write(struct cpsw_ale * ale,int idx,u32 * ale_entry)327 static int cpsw_ale_write(struct cpsw_ale *ale, int idx, u32 *ale_entry)
328 {
329 int i;
330
331 WARN_ON(idx > ale->params.ale_entries);
332
333 for (i = 0; i < ALE_ENTRY_WORDS; i++)
334 writel_relaxed(ale_entry[i], ale->params.ale_regs +
335 ALE_TABLE + 4 * i);
336
337 writel_relaxed(idx | ALE_TABLE_WRITE, ale->params.ale_regs +
338 ALE_TABLE_CONTROL);
339
340 return idx;
341 }
342
cpsw_ale_match_addr(struct cpsw_ale * ale,const u8 * addr,u16 vid)343 static int cpsw_ale_match_addr(struct cpsw_ale *ale, const u8 *addr, u16 vid)
344 {
345 u32 ale_entry[ALE_ENTRY_WORDS];
346 int type, idx;
347
348 for (idx = 0; idx < ale->params.ale_entries; idx++) {
349 u8 entry_addr[6];
350
351 cpsw_ale_read(ale, idx, ale_entry);
352 type = cpsw_ale_get_entry_type(ale_entry);
353 if (type != ALE_TYPE_ADDR && type != ALE_TYPE_VLAN_ADDR)
354 continue;
355 if (cpsw_ale_get_vlan_id(ale_entry) != vid)
356 continue;
357 cpsw_ale_get_addr(ale_entry, entry_addr);
358 if (ether_addr_equal(entry_addr, addr))
359 return idx;
360 }
361 return -ENOENT;
362 }
363
cpsw_ale_match_vlan(struct cpsw_ale * ale,u16 vid)364 static int cpsw_ale_match_vlan(struct cpsw_ale *ale, u16 vid)
365 {
366 u32 ale_entry[ALE_ENTRY_WORDS];
367 int type, idx;
368
369 for (idx = 0; idx < ale->params.ale_entries; idx++) {
370 cpsw_ale_read(ale, idx, ale_entry);
371 type = cpsw_ale_get_entry_type(ale_entry);
372 if (type != ALE_TYPE_VLAN)
373 continue;
374 if (cpsw_ale_get_vlan_id(ale_entry) == vid)
375 return idx;
376 }
377 return -ENOENT;
378 }
379
cpsw_ale_match_free(struct cpsw_ale * ale)380 static int cpsw_ale_match_free(struct cpsw_ale *ale)
381 {
382 u32 ale_entry[ALE_ENTRY_WORDS];
383 int type, idx;
384
385 for (idx = 0; idx < ale->params.ale_entries; idx++) {
386 cpsw_ale_read(ale, idx, ale_entry);
387 type = cpsw_ale_get_entry_type(ale_entry);
388 if (type == ALE_TYPE_FREE)
389 return idx;
390 }
391 return -ENOENT;
392 }
393
cpsw_ale_find_ageable(struct cpsw_ale * ale)394 static int cpsw_ale_find_ageable(struct cpsw_ale *ale)
395 {
396 u32 ale_entry[ALE_ENTRY_WORDS];
397 int type, idx;
398
399 for (idx = 0; idx < ale->params.ale_entries; idx++) {
400 cpsw_ale_read(ale, idx, ale_entry);
401 type = cpsw_ale_get_entry_type(ale_entry);
402 if (type != ALE_TYPE_ADDR && type != ALE_TYPE_VLAN_ADDR)
403 continue;
404 if (cpsw_ale_get_mcast(ale_entry))
405 continue;
406 type = cpsw_ale_get_ucast_type(ale_entry);
407 if (type != ALE_UCAST_PERSISTANT &&
408 type != ALE_UCAST_OUI)
409 return idx;
410 }
411 return -ENOENT;
412 }
413
cpsw_ale_flush_mcast(struct cpsw_ale * ale,u32 * ale_entry,int port_mask)414 static void cpsw_ale_flush_mcast(struct cpsw_ale *ale, u32 *ale_entry,
415 int port_mask)
416 {
417 int mask;
418
419 mask = cpsw_ale_get_port_mask(ale_entry,
420 ale->port_mask_bits);
421 if ((mask & port_mask) == 0)
422 return; /* ports dont intersect, not interested */
423 mask &= ~port_mask;
424
425 /* free if only remaining port is host port */
426 if (mask)
427 cpsw_ale_set_port_mask(ale_entry, mask,
428 ale->port_mask_bits);
429 else
430 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
431 }
432
cpsw_ale_flush_multicast(struct cpsw_ale * ale,int port_mask,int vid)433 int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask, int vid)
434 {
435 u32 ale_entry[ALE_ENTRY_WORDS];
436 int ret, idx;
437
438 for (idx = 0; idx < ale->params.ale_entries; idx++) {
439 cpsw_ale_read(ale, idx, ale_entry);
440 ret = cpsw_ale_get_entry_type(ale_entry);
441 if (ret != ALE_TYPE_ADDR && ret != ALE_TYPE_VLAN_ADDR)
442 continue;
443
444 /* if vid passed is -1 then remove all multicast entry from
445 * the table irrespective of vlan id, if a valid vlan id is
446 * passed then remove only multicast added to that vlan id.
447 * if vlan id doesn't match then move on to next entry.
448 */
449 if (vid != -1 && cpsw_ale_get_vlan_id(ale_entry) != vid)
450 continue;
451
452 if (cpsw_ale_get_mcast(ale_entry)) {
453 u8 addr[6];
454
455 if (cpsw_ale_get_super(ale_entry))
456 continue;
457
458 cpsw_ale_get_addr(ale_entry, addr);
459 if (!is_broadcast_ether_addr(addr))
460 cpsw_ale_flush_mcast(ale, ale_entry, port_mask);
461 }
462
463 cpsw_ale_write(ale, idx, ale_entry);
464 }
465 return 0;
466 }
467
cpsw_ale_set_vlan_entry_type(u32 * ale_entry,int flags,u16 vid)468 static inline void cpsw_ale_set_vlan_entry_type(u32 *ale_entry,
469 int flags, u16 vid)
470 {
471 if (flags & ALE_VLAN) {
472 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_VLAN_ADDR);
473 cpsw_ale_set_vlan_id(ale_entry, vid);
474 } else {
475 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
476 }
477 }
478
cpsw_ale_add_ucast(struct cpsw_ale * ale,const u8 * addr,int port,int flags,u16 vid)479 int cpsw_ale_add_ucast(struct cpsw_ale *ale, const u8 *addr, int port,
480 int flags, u16 vid)
481 {
482 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
483 int idx;
484
485 cpsw_ale_set_vlan_entry_type(ale_entry, flags, vid);
486
487 cpsw_ale_set_addr(ale_entry, addr);
488 cpsw_ale_set_ucast_type(ale_entry, ALE_UCAST_PERSISTANT);
489 cpsw_ale_set_secure(ale_entry, (flags & ALE_SECURE) ? 1 : 0);
490 cpsw_ale_set_blocked(ale_entry, (flags & ALE_BLOCKED) ? 1 : 0);
491 cpsw_ale_set_port_num(ale_entry, port, ale->port_num_bits);
492
493 idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
494 if (idx < 0)
495 idx = cpsw_ale_match_free(ale);
496 if (idx < 0)
497 idx = cpsw_ale_find_ageable(ale);
498 if (idx < 0)
499 return -ENOMEM;
500
501 cpsw_ale_write(ale, idx, ale_entry);
502 return 0;
503 }
504
cpsw_ale_del_ucast(struct cpsw_ale * ale,const u8 * addr,int port,int flags,u16 vid)505 int cpsw_ale_del_ucast(struct cpsw_ale *ale, const u8 *addr, int port,
506 int flags, u16 vid)
507 {
508 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
509 int idx;
510
511 idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
512 if (idx < 0)
513 return -ENOENT;
514
515 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
516 cpsw_ale_write(ale, idx, ale_entry);
517 return 0;
518 }
519
cpsw_ale_add_mcast(struct cpsw_ale * ale,const u8 * addr,int port_mask,int flags,u16 vid,int mcast_state)520 int cpsw_ale_add_mcast(struct cpsw_ale *ale, const u8 *addr, int port_mask,
521 int flags, u16 vid, int mcast_state)
522 {
523 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
524 int idx, mask;
525
526 idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
527 if (idx >= 0)
528 cpsw_ale_read(ale, idx, ale_entry);
529
530 cpsw_ale_set_vlan_entry_type(ale_entry, flags, vid);
531
532 cpsw_ale_set_addr(ale_entry, addr);
533 cpsw_ale_set_super(ale_entry, (flags & ALE_SUPER) ? 1 : 0);
534 cpsw_ale_set_mcast_state(ale_entry, mcast_state);
535
536 mask = cpsw_ale_get_port_mask(ale_entry,
537 ale->port_mask_bits);
538 port_mask |= mask;
539 cpsw_ale_set_port_mask(ale_entry, port_mask,
540 ale->port_mask_bits);
541
542 if (idx < 0)
543 idx = cpsw_ale_match_free(ale);
544 if (idx < 0)
545 idx = cpsw_ale_find_ageable(ale);
546 if (idx < 0)
547 return -ENOMEM;
548
549 cpsw_ale_write(ale, idx, ale_entry);
550 return 0;
551 }
552
cpsw_ale_del_mcast(struct cpsw_ale * ale,const u8 * addr,int port_mask,int flags,u16 vid)553 int cpsw_ale_del_mcast(struct cpsw_ale *ale, const u8 *addr, int port_mask,
554 int flags, u16 vid)
555 {
556 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
557 int mcast_members = 0;
558 int idx;
559
560 idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
561 if (idx < 0)
562 return -ENOENT;
563
564 cpsw_ale_read(ale, idx, ale_entry);
565
566 if (port_mask) {
567 mcast_members = cpsw_ale_get_port_mask(ale_entry,
568 ale->port_mask_bits);
569 mcast_members &= ~port_mask;
570 }
571
572 if (mcast_members)
573 cpsw_ale_set_port_mask(ale_entry, mcast_members,
574 ale->port_mask_bits);
575 else
576 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
577
578 cpsw_ale_write(ale, idx, ale_entry);
579 return 0;
580 }
581
582 /* ALE NetCP NU switch specific vlan functions */
cpsw_ale_set_vlan_mcast(struct cpsw_ale * ale,u32 * ale_entry,int reg_mcast,int unreg_mcast)583 static void cpsw_ale_set_vlan_mcast(struct cpsw_ale *ale, u32 *ale_entry,
584 int reg_mcast, int unreg_mcast)
585 {
586 int idx;
587
588 /* Set VLAN registered multicast flood mask */
589 idx = cpsw_ale_vlan_get_fld(ale, ale_entry,
590 ALE_ENT_VID_REG_MCAST_IDX);
591 writel(reg_mcast, ale->params.ale_regs + ALE_VLAN_MASK_MUX(idx));
592
593 /* Set VLAN unregistered multicast flood mask */
594 idx = cpsw_ale_vlan_get_fld(ale, ale_entry,
595 ALE_ENT_VID_UNREG_MCAST_IDX);
596 writel(unreg_mcast, ale->params.ale_regs + ALE_VLAN_MASK_MUX(idx));
597 }
598
cpsw_ale_set_vlan_untag(struct cpsw_ale * ale,u32 * ale_entry,u16 vid,int untag_mask)599 static void cpsw_ale_set_vlan_untag(struct cpsw_ale *ale, u32 *ale_entry,
600 u16 vid, int untag_mask)
601 {
602 cpsw_ale_vlan_set_fld(ale, ale_entry,
603 ALE_ENT_VID_FORCE_UNTAGGED_MSK,
604 untag_mask);
605 if (untag_mask & ALE_PORT_HOST)
606 bitmap_set(ale->p0_untag_vid_mask, vid, 1);
607 else
608 bitmap_clear(ale->p0_untag_vid_mask, vid, 1);
609 }
610
cpsw_ale_add_vlan(struct cpsw_ale * ale,u16 vid,int port_mask,int untag,int reg_mcast,int unreg_mcast)611 int cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port_mask, int untag,
612 int reg_mcast, int unreg_mcast)
613 {
614 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
615 int idx;
616
617 idx = cpsw_ale_match_vlan(ale, vid);
618 if (idx >= 0)
619 cpsw_ale_read(ale, idx, ale_entry);
620
621 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_VLAN);
622 cpsw_ale_set_vlan_id(ale_entry, vid);
623 cpsw_ale_set_vlan_untag(ale, ale_entry, vid, untag);
624
625 if (!ale->params.nu_switch_ale) {
626 cpsw_ale_vlan_set_fld(ale, ale_entry,
627 ALE_ENT_VID_REG_MCAST_MSK, reg_mcast);
628 cpsw_ale_vlan_set_fld(ale, ale_entry,
629 ALE_ENT_VID_UNREG_MCAST_MSK, unreg_mcast);
630 } else {
631 cpsw_ale_vlan_set_fld(ale, ale_entry,
632 ALE_ENT_VID_UNREG_MCAST_IDX,
633 NU_VLAN_UNREG_MCAST_IDX);
634 cpsw_ale_set_vlan_mcast(ale, ale_entry, reg_mcast, unreg_mcast);
635 }
636
637 cpsw_ale_vlan_set_fld(ale, ale_entry,
638 ALE_ENT_VID_MEMBER_LIST, port_mask);
639
640 if (idx < 0)
641 idx = cpsw_ale_match_free(ale);
642 if (idx < 0)
643 idx = cpsw_ale_find_ageable(ale);
644 if (idx < 0)
645 return -ENOMEM;
646
647 cpsw_ale_write(ale, idx, ale_entry);
648 return 0;
649 }
650
cpsw_ale_vlan_del_modify_int(struct cpsw_ale * ale,u32 * ale_entry,u16 vid,int port_mask)651 static void cpsw_ale_vlan_del_modify_int(struct cpsw_ale *ale, u32 *ale_entry,
652 u16 vid, int port_mask)
653 {
654 int reg_mcast, unreg_mcast;
655 int members, untag;
656
657 members = cpsw_ale_vlan_get_fld(ale, ale_entry,
658 ALE_ENT_VID_MEMBER_LIST);
659 members &= ~port_mask;
660 if (!members) {
661 cpsw_ale_set_vlan_untag(ale, ale_entry, vid, 0);
662 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
663 return;
664 }
665
666 untag = cpsw_ale_vlan_get_fld(ale, ale_entry,
667 ALE_ENT_VID_FORCE_UNTAGGED_MSK);
668 reg_mcast = cpsw_ale_vlan_get_fld(ale, ale_entry,
669 ALE_ENT_VID_REG_MCAST_MSK);
670 unreg_mcast = cpsw_ale_vlan_get_fld(ale, ale_entry,
671 ALE_ENT_VID_UNREG_MCAST_MSK);
672 untag &= members;
673 reg_mcast &= members;
674 unreg_mcast &= members;
675
676 cpsw_ale_set_vlan_untag(ale, ale_entry, vid, untag);
677
678 if (!ale->params.nu_switch_ale) {
679 cpsw_ale_vlan_set_fld(ale, ale_entry,
680 ALE_ENT_VID_REG_MCAST_MSK, reg_mcast);
681 cpsw_ale_vlan_set_fld(ale, ale_entry,
682 ALE_ENT_VID_UNREG_MCAST_MSK, unreg_mcast);
683 } else {
684 cpsw_ale_set_vlan_mcast(ale, ale_entry, reg_mcast,
685 unreg_mcast);
686 }
687 cpsw_ale_vlan_set_fld(ale, ale_entry,
688 ALE_ENT_VID_MEMBER_LIST, members);
689 }
690
cpsw_ale_vlan_del_modify(struct cpsw_ale * ale,u16 vid,int port_mask)691 int cpsw_ale_vlan_del_modify(struct cpsw_ale *ale, u16 vid, int port_mask)
692 {
693 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
694 int idx;
695
696 idx = cpsw_ale_match_vlan(ale, vid);
697 if (idx < 0)
698 return -ENOENT;
699
700 cpsw_ale_read(ale, idx, ale_entry);
701
702 cpsw_ale_vlan_del_modify_int(ale, ale_entry, vid, port_mask);
703 cpsw_ale_write(ale, idx, ale_entry);
704
705 return 0;
706 }
707
cpsw_ale_del_vlan(struct cpsw_ale * ale,u16 vid,int port_mask)708 int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port_mask)
709 {
710 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
711 int members, idx;
712
713 idx = cpsw_ale_match_vlan(ale, vid);
714 if (idx < 0)
715 return -ENOENT;
716
717 cpsw_ale_read(ale, idx, ale_entry);
718
719 /* if !port_mask - force remove VLAN (legacy).
720 * Check if there are other VLAN members ports
721 * if no - remove VLAN.
722 * if yes it means same VLAN was added to >1 port in multi port mode, so
723 * remove port_mask ports from VLAN ALE entry excluding Host port.
724 */
725 members = cpsw_ale_vlan_get_fld(ale, ale_entry, ALE_ENT_VID_MEMBER_LIST);
726 members &= ~port_mask;
727
728 if (!port_mask || !members) {
729 /* last port or force remove - remove VLAN */
730 cpsw_ale_set_vlan_untag(ale, ale_entry, vid, 0);
731 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
732 } else {
733 port_mask &= ~ALE_PORT_HOST;
734 cpsw_ale_vlan_del_modify_int(ale, ale_entry, vid, port_mask);
735 }
736
737 cpsw_ale_write(ale, idx, ale_entry);
738
739 return 0;
740 }
741
cpsw_ale_vlan_add_modify(struct cpsw_ale * ale,u16 vid,int port_mask,int untag_mask,int reg_mask,int unreg_mask)742 int cpsw_ale_vlan_add_modify(struct cpsw_ale *ale, u16 vid, int port_mask,
743 int untag_mask, int reg_mask, int unreg_mask)
744 {
745 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
746 int reg_mcast_members, unreg_mcast_members;
747 int vlan_members, untag_members;
748 int idx, ret = 0;
749
750 idx = cpsw_ale_match_vlan(ale, vid);
751 if (idx >= 0)
752 cpsw_ale_read(ale, idx, ale_entry);
753
754 vlan_members = cpsw_ale_vlan_get_fld(ale, ale_entry,
755 ALE_ENT_VID_MEMBER_LIST);
756 reg_mcast_members = cpsw_ale_vlan_get_fld(ale, ale_entry,
757 ALE_ENT_VID_REG_MCAST_MSK);
758 unreg_mcast_members =
759 cpsw_ale_vlan_get_fld(ale, ale_entry,
760 ALE_ENT_VID_UNREG_MCAST_MSK);
761 untag_members = cpsw_ale_vlan_get_fld(ale, ale_entry,
762 ALE_ENT_VID_FORCE_UNTAGGED_MSK);
763
764 vlan_members |= port_mask;
765 untag_members = (untag_members & ~port_mask) | untag_mask;
766 reg_mcast_members = (reg_mcast_members & ~port_mask) | reg_mask;
767 unreg_mcast_members = (unreg_mcast_members & ~port_mask) | unreg_mask;
768
769 ret = cpsw_ale_add_vlan(ale, vid, vlan_members, untag_members,
770 reg_mcast_members, unreg_mcast_members);
771 if (ret) {
772 dev_err(ale->params.dev, "Unable to add vlan\n");
773 return ret;
774 }
775 dev_dbg(ale->params.dev, "port mask 0x%x untag 0x%x\n", vlan_members,
776 untag_mask);
777
778 return ret;
779 }
780
cpsw_ale_set_unreg_mcast(struct cpsw_ale * ale,int unreg_mcast_mask,bool add)781 void cpsw_ale_set_unreg_mcast(struct cpsw_ale *ale, int unreg_mcast_mask,
782 bool add)
783 {
784 u32 ale_entry[ALE_ENTRY_WORDS];
785 int unreg_members = 0;
786 int type, idx;
787
788 for (idx = 0; idx < ale->params.ale_entries; idx++) {
789 cpsw_ale_read(ale, idx, ale_entry);
790 type = cpsw_ale_get_entry_type(ale_entry);
791 if (type != ALE_TYPE_VLAN)
792 continue;
793
794 unreg_members =
795 cpsw_ale_vlan_get_fld(ale, ale_entry,
796 ALE_ENT_VID_UNREG_MCAST_MSK);
797 if (add)
798 unreg_members |= unreg_mcast_mask;
799 else
800 unreg_members &= ~unreg_mcast_mask;
801 cpsw_ale_vlan_set_fld(ale, ale_entry,
802 ALE_ENT_VID_UNREG_MCAST_MSK,
803 unreg_members);
804 cpsw_ale_write(ale, idx, ale_entry);
805 }
806 }
807
cpsw_ale_vlan_set_unreg_mcast(struct cpsw_ale * ale,u32 * ale_entry,int allmulti)808 static void cpsw_ale_vlan_set_unreg_mcast(struct cpsw_ale *ale, u32 *ale_entry,
809 int allmulti)
810 {
811 int unreg_mcast;
812
813 unreg_mcast = cpsw_ale_vlan_get_fld(ale, ale_entry,
814 ALE_ENT_VID_UNREG_MCAST_MSK);
815 if (allmulti)
816 unreg_mcast |= ALE_PORT_HOST;
817 else
818 unreg_mcast &= ~ALE_PORT_HOST;
819
820 cpsw_ale_vlan_set_fld(ale, ale_entry,
821 ALE_ENT_VID_UNREG_MCAST_MSK, unreg_mcast);
822 }
823
824 static void
cpsw_ale_vlan_set_unreg_mcast_idx(struct cpsw_ale * ale,u32 * ale_entry,int allmulti)825 cpsw_ale_vlan_set_unreg_mcast_idx(struct cpsw_ale *ale, u32 *ale_entry,
826 int allmulti)
827 {
828 int unreg_mcast;
829 int idx;
830
831 idx = cpsw_ale_vlan_get_fld(ale, ale_entry,
832 ALE_ENT_VID_UNREG_MCAST_IDX);
833
834 unreg_mcast = readl(ale->params.ale_regs + ALE_VLAN_MASK_MUX(idx));
835
836 if (allmulti)
837 unreg_mcast |= ALE_PORT_HOST;
838 else
839 unreg_mcast &= ~ALE_PORT_HOST;
840
841 writel(unreg_mcast, ale->params.ale_regs + ALE_VLAN_MASK_MUX(idx));
842 }
843
cpsw_ale_set_allmulti(struct cpsw_ale * ale,int allmulti,int port)844 void cpsw_ale_set_allmulti(struct cpsw_ale *ale, int allmulti, int port)
845 {
846 u32 ale_entry[ALE_ENTRY_WORDS];
847 int type, idx;
848
849 for (idx = 0; idx < ale->params.ale_entries; idx++) {
850 int vlan_members;
851
852 cpsw_ale_read(ale, idx, ale_entry);
853 type = cpsw_ale_get_entry_type(ale_entry);
854 if (type != ALE_TYPE_VLAN)
855 continue;
856
857 vlan_members = cpsw_ale_vlan_get_fld(ale, ale_entry,
858 ALE_ENT_VID_MEMBER_LIST);
859
860 if (port != -1 && !(vlan_members & BIT(port)))
861 continue;
862
863 if (!ale->params.nu_switch_ale)
864 cpsw_ale_vlan_set_unreg_mcast(ale, ale_entry, allmulti);
865 else
866 cpsw_ale_vlan_set_unreg_mcast_idx(ale, ale_entry,
867 allmulti);
868
869 cpsw_ale_write(ale, idx, ale_entry);
870 }
871 }
872
873 struct ale_control_info {
874 const char *name;
875 int offset, port_offset;
876 int shift, port_shift;
877 int bits;
878 };
879
880 static struct ale_control_info ale_controls[ALE_NUM_CONTROLS] = {
881 [ALE_ENABLE] = {
882 .name = "enable",
883 .offset = ALE_CONTROL,
884 .port_offset = 0,
885 .shift = 31,
886 .port_shift = 0,
887 .bits = 1,
888 },
889 [ALE_CLEAR] = {
890 .name = "clear",
891 .offset = ALE_CONTROL,
892 .port_offset = 0,
893 .shift = 30,
894 .port_shift = 0,
895 .bits = 1,
896 },
897 [ALE_AGEOUT] = {
898 .name = "ageout",
899 .offset = ALE_CONTROL,
900 .port_offset = 0,
901 .shift = 29,
902 .port_shift = 0,
903 .bits = 1,
904 },
905 [ALE_P0_UNI_FLOOD] = {
906 .name = "port0_unicast_flood",
907 .offset = ALE_CONTROL,
908 .port_offset = 0,
909 .shift = 8,
910 .port_shift = 0,
911 .bits = 1,
912 },
913 [ALE_VLAN_NOLEARN] = {
914 .name = "vlan_nolearn",
915 .offset = ALE_CONTROL,
916 .port_offset = 0,
917 .shift = 7,
918 .port_shift = 0,
919 .bits = 1,
920 },
921 [ALE_NO_PORT_VLAN] = {
922 .name = "no_port_vlan",
923 .offset = ALE_CONTROL,
924 .port_offset = 0,
925 .shift = 6,
926 .port_shift = 0,
927 .bits = 1,
928 },
929 [ALE_OUI_DENY] = {
930 .name = "oui_deny",
931 .offset = ALE_CONTROL,
932 .port_offset = 0,
933 .shift = 5,
934 .port_shift = 0,
935 .bits = 1,
936 },
937 [ALE_BYPASS] = {
938 .name = "bypass",
939 .offset = ALE_CONTROL,
940 .port_offset = 0,
941 .shift = 4,
942 .port_shift = 0,
943 .bits = 1,
944 },
945 [ALE_RATE_LIMIT_TX] = {
946 .name = "rate_limit_tx",
947 .offset = ALE_CONTROL,
948 .port_offset = 0,
949 .shift = 3,
950 .port_shift = 0,
951 .bits = 1,
952 },
953 [ALE_VLAN_AWARE] = {
954 .name = "vlan_aware",
955 .offset = ALE_CONTROL,
956 .port_offset = 0,
957 .shift = 2,
958 .port_shift = 0,
959 .bits = 1,
960 },
961 [ALE_AUTH_ENABLE] = {
962 .name = "auth_enable",
963 .offset = ALE_CONTROL,
964 .port_offset = 0,
965 .shift = 1,
966 .port_shift = 0,
967 .bits = 1,
968 },
969 [ALE_RATE_LIMIT] = {
970 .name = "rate_limit",
971 .offset = ALE_CONTROL,
972 .port_offset = 0,
973 .shift = 0,
974 .port_shift = 0,
975 .bits = 1,
976 },
977 [ALE_PORT_STATE] = {
978 .name = "port_state",
979 .offset = ALE_PORTCTL,
980 .port_offset = 4,
981 .shift = 0,
982 .port_shift = 0,
983 .bits = 2,
984 },
985 [ALE_PORT_DROP_UNTAGGED] = {
986 .name = "drop_untagged",
987 .offset = ALE_PORTCTL,
988 .port_offset = 4,
989 .shift = 2,
990 .port_shift = 0,
991 .bits = 1,
992 },
993 [ALE_PORT_DROP_UNKNOWN_VLAN] = {
994 .name = "drop_unknown",
995 .offset = ALE_PORTCTL,
996 .port_offset = 4,
997 .shift = 3,
998 .port_shift = 0,
999 .bits = 1,
1000 },
1001 [ALE_PORT_NOLEARN] = {
1002 .name = "nolearn",
1003 .offset = ALE_PORTCTL,
1004 .port_offset = 4,
1005 .shift = 4,
1006 .port_shift = 0,
1007 .bits = 1,
1008 },
1009 [ALE_PORT_NO_SA_UPDATE] = {
1010 .name = "no_source_update",
1011 .offset = ALE_PORTCTL,
1012 .port_offset = 4,
1013 .shift = 5,
1014 .port_shift = 0,
1015 .bits = 1,
1016 },
1017 [ALE_PORT_MACONLY] = {
1018 .name = "mac_only_port_mode",
1019 .offset = ALE_PORTCTL,
1020 .port_offset = 4,
1021 .shift = 11,
1022 .port_shift = 0,
1023 .bits = 1,
1024 },
1025 [ALE_PORT_MACONLY_CAF] = {
1026 .name = "mac_only_port_caf",
1027 .offset = ALE_PORTCTL,
1028 .port_offset = 4,
1029 .shift = 13,
1030 .port_shift = 0,
1031 .bits = 1,
1032 },
1033 [ALE_PORT_MCAST_LIMIT] = {
1034 .name = "mcast_limit",
1035 .offset = ALE_PORTCTL,
1036 .port_offset = 4,
1037 .shift = 16,
1038 .port_shift = 0,
1039 .bits = 8,
1040 },
1041 [ALE_PORT_BCAST_LIMIT] = {
1042 .name = "bcast_limit",
1043 .offset = ALE_PORTCTL,
1044 .port_offset = 4,
1045 .shift = 24,
1046 .port_shift = 0,
1047 .bits = 8,
1048 },
1049 [ALE_PORT_UNKNOWN_VLAN_MEMBER] = {
1050 .name = "unknown_vlan_member",
1051 .offset = ALE_UNKNOWNVLAN,
1052 .port_offset = 0,
1053 .shift = 0,
1054 .port_shift = 0,
1055 .bits = 6,
1056 },
1057 [ALE_PORT_UNKNOWN_MCAST_FLOOD] = {
1058 .name = "unknown_mcast_flood",
1059 .offset = ALE_UNKNOWNVLAN,
1060 .port_offset = 0,
1061 .shift = 8,
1062 .port_shift = 0,
1063 .bits = 6,
1064 },
1065 [ALE_PORT_UNKNOWN_REG_MCAST_FLOOD] = {
1066 .name = "unknown_reg_flood",
1067 .offset = ALE_UNKNOWNVLAN,
1068 .port_offset = 0,
1069 .shift = 16,
1070 .port_shift = 0,
1071 .bits = 6,
1072 },
1073 [ALE_PORT_UNTAGGED_EGRESS] = {
1074 .name = "untagged_egress",
1075 .offset = ALE_UNKNOWNVLAN,
1076 .port_offset = 0,
1077 .shift = 24,
1078 .port_shift = 0,
1079 .bits = 6,
1080 },
1081 [ALE_DEFAULT_THREAD_ID] = {
1082 .name = "default_thread_id",
1083 .offset = AM65_CPSW_ALE_THREAD_DEF_REG,
1084 .port_offset = 0,
1085 .shift = 0,
1086 .port_shift = 0,
1087 .bits = 6,
1088 },
1089 [ALE_DEFAULT_THREAD_ENABLE] = {
1090 .name = "default_thread_id_enable",
1091 .offset = AM65_CPSW_ALE_THREAD_DEF_REG,
1092 .port_offset = 0,
1093 .shift = 15,
1094 .port_shift = 0,
1095 .bits = 1,
1096 },
1097 };
1098
cpsw_ale_control_set(struct cpsw_ale * ale,int port,int control,int value)1099 int cpsw_ale_control_set(struct cpsw_ale *ale, int port, int control,
1100 int value)
1101 {
1102 const struct ale_control_info *info;
1103 int offset, shift;
1104 u32 tmp, mask;
1105
1106 if (control < 0 || control >= ARRAY_SIZE(ale_controls))
1107 return -EINVAL;
1108
1109 info = &ale_controls[control];
1110 if (info->port_offset == 0 && info->port_shift == 0)
1111 port = 0; /* global, port is a dont care */
1112
1113 if (port < 0 || port >= ale->params.ale_ports)
1114 return -EINVAL;
1115
1116 mask = BITMASK(info->bits);
1117 if (value & ~mask)
1118 return -EINVAL;
1119
1120 offset = info->offset + (port * info->port_offset);
1121 shift = info->shift + (port * info->port_shift);
1122
1123 tmp = readl_relaxed(ale->params.ale_regs + offset);
1124 tmp = (tmp & ~(mask << shift)) | (value << shift);
1125 writel_relaxed(tmp, ale->params.ale_regs + offset);
1126
1127 return 0;
1128 }
1129
cpsw_ale_control_get(struct cpsw_ale * ale,int port,int control)1130 int cpsw_ale_control_get(struct cpsw_ale *ale, int port, int control)
1131 {
1132 const struct ale_control_info *info;
1133 int offset, shift;
1134 u32 tmp;
1135
1136 if (control < 0 || control >= ARRAY_SIZE(ale_controls))
1137 return -EINVAL;
1138
1139 info = &ale_controls[control];
1140 if (info->port_offset == 0 && info->port_shift == 0)
1141 port = 0; /* global, port is a dont care */
1142
1143 if (port < 0 || port >= ale->params.ale_ports)
1144 return -EINVAL;
1145
1146 offset = info->offset + (port * info->port_offset);
1147 shift = info->shift + (port * info->port_shift);
1148
1149 tmp = readl_relaxed(ale->params.ale_regs + offset) >> shift;
1150 return tmp & BITMASK(info->bits);
1151 }
1152
cpsw_ale_timer(struct timer_list * t)1153 static void cpsw_ale_timer(struct timer_list *t)
1154 {
1155 struct cpsw_ale *ale = from_timer(ale, t, timer);
1156
1157 cpsw_ale_control_set(ale, 0, ALE_AGEOUT, 1);
1158
1159 if (ale->ageout) {
1160 ale->timer.expires = jiffies + ale->ageout;
1161 add_timer(&ale->timer);
1162 }
1163 }
1164
cpsw_ale_hw_aging_timer_start(struct cpsw_ale * ale)1165 static void cpsw_ale_hw_aging_timer_start(struct cpsw_ale *ale)
1166 {
1167 u32 aging_timer;
1168
1169 aging_timer = ale->params.bus_freq / 1000000;
1170 aging_timer *= ale->params.ale_ageout;
1171
1172 if (aging_timer & ~ALE_AGING_TIMER_MASK) {
1173 aging_timer = ALE_AGING_TIMER_MASK;
1174 dev_warn(ale->params.dev,
1175 "ALE aging timer overflow, set to max\n");
1176 }
1177
1178 writel(aging_timer, ale->params.ale_regs + ALE_AGING_TIMER);
1179 }
1180
cpsw_ale_hw_aging_timer_stop(struct cpsw_ale * ale)1181 static void cpsw_ale_hw_aging_timer_stop(struct cpsw_ale *ale)
1182 {
1183 writel(0, ale->params.ale_regs + ALE_AGING_TIMER);
1184 }
1185
cpsw_ale_aging_start(struct cpsw_ale * ale)1186 static void cpsw_ale_aging_start(struct cpsw_ale *ale)
1187 {
1188 if (!ale->params.ale_ageout)
1189 return;
1190
1191 if (ale->features & CPSW_ALE_F_HW_AUTOAGING) {
1192 cpsw_ale_hw_aging_timer_start(ale);
1193 return;
1194 }
1195
1196 timer_setup(&ale->timer, cpsw_ale_timer, 0);
1197 ale->timer.expires = jiffies + ale->ageout;
1198 add_timer(&ale->timer);
1199 }
1200
cpsw_ale_aging_stop(struct cpsw_ale * ale)1201 static void cpsw_ale_aging_stop(struct cpsw_ale *ale)
1202 {
1203 if (!ale->params.ale_ageout)
1204 return;
1205
1206 if (ale->features & CPSW_ALE_F_HW_AUTOAGING) {
1207 cpsw_ale_hw_aging_timer_stop(ale);
1208 return;
1209 }
1210
1211 del_timer_sync(&ale->timer);
1212 }
1213
cpsw_ale_start(struct cpsw_ale * ale)1214 void cpsw_ale_start(struct cpsw_ale *ale)
1215 {
1216 cpsw_ale_control_set(ale, 0, ALE_ENABLE, 1);
1217 cpsw_ale_control_set(ale, 0, ALE_CLEAR, 1);
1218
1219 cpsw_ale_aging_start(ale);
1220 }
1221
cpsw_ale_stop(struct cpsw_ale * ale)1222 void cpsw_ale_stop(struct cpsw_ale *ale)
1223 {
1224 cpsw_ale_aging_stop(ale);
1225 cpsw_ale_control_set(ale, 0, ALE_CLEAR, 1);
1226 cpsw_ale_control_set(ale, 0, ALE_ENABLE, 0);
1227 }
1228
1229 static const struct cpsw_ale_dev_id cpsw_ale_id_match[] = {
1230 {
1231 /* am3/4/5, dra7. dm814x, 66ak2hk-gbe */
1232 .dev_id = "cpsw",
1233 .tbl_entries = 1024,
1234 .major_ver_mask = 0xff,
1235 .vlan_entry_tbl = vlan_entry_cpsw,
1236 },
1237 {
1238 /* 66ak2h_xgbe */
1239 .dev_id = "66ak2h-xgbe",
1240 .tbl_entries = 2048,
1241 .major_ver_mask = 0xff,
1242 .vlan_entry_tbl = vlan_entry_cpsw,
1243 },
1244 {
1245 .dev_id = "66ak2el",
1246 .features = CPSW_ALE_F_STATUS_REG,
1247 .major_ver_mask = 0x7,
1248 .nu_switch_ale = true,
1249 .vlan_entry_tbl = vlan_entry_nu,
1250 },
1251 {
1252 .dev_id = "66ak2g",
1253 .features = CPSW_ALE_F_STATUS_REG,
1254 .tbl_entries = 64,
1255 .major_ver_mask = 0x7,
1256 .nu_switch_ale = true,
1257 .vlan_entry_tbl = vlan_entry_nu,
1258 },
1259 {
1260 .dev_id = "am65x-cpsw2g",
1261 .features = CPSW_ALE_F_STATUS_REG | CPSW_ALE_F_HW_AUTOAGING,
1262 .tbl_entries = 64,
1263 .major_ver_mask = 0x7,
1264 .nu_switch_ale = true,
1265 .vlan_entry_tbl = vlan_entry_nu,
1266 },
1267 {
1268 .dev_id = "j721e-cpswxg",
1269 .features = CPSW_ALE_F_STATUS_REG | CPSW_ALE_F_HW_AUTOAGING,
1270 .major_ver_mask = 0x7,
1271 .vlan_entry_tbl = vlan_entry_k3_cpswxg,
1272 },
1273 {
1274 .dev_id = "am64-cpswxg",
1275 .features = CPSW_ALE_F_STATUS_REG | CPSW_ALE_F_HW_AUTOAGING,
1276 .major_ver_mask = 0x7,
1277 .vlan_entry_tbl = vlan_entry_k3_cpswxg,
1278 .tbl_entries = 512,
1279 },
1280 { },
1281 };
1282
1283 static const struct
cpsw_ale_match_id(const struct cpsw_ale_dev_id * id,const char * dev_id)1284 cpsw_ale_dev_id *cpsw_ale_match_id(const struct cpsw_ale_dev_id *id,
1285 const char *dev_id)
1286 {
1287 if (!dev_id)
1288 return NULL;
1289
1290 while (id->dev_id) {
1291 if (strcmp(dev_id, id->dev_id) == 0)
1292 return id;
1293 id++;
1294 }
1295 return NULL;
1296 }
1297
cpsw_ale_create(struct cpsw_ale_params * params)1298 struct cpsw_ale *cpsw_ale_create(struct cpsw_ale_params *params)
1299 {
1300 const struct cpsw_ale_dev_id *ale_dev_id;
1301 struct cpsw_ale *ale;
1302 u32 rev, ale_entries;
1303
1304 ale_dev_id = cpsw_ale_match_id(cpsw_ale_id_match, params->dev_id);
1305 if (!ale_dev_id)
1306 return ERR_PTR(-EINVAL);
1307
1308 params->ale_entries = ale_dev_id->tbl_entries;
1309 params->major_ver_mask = ale_dev_id->major_ver_mask;
1310 params->nu_switch_ale = ale_dev_id->nu_switch_ale;
1311
1312 ale = devm_kzalloc(params->dev, sizeof(*ale), GFP_KERNEL);
1313 if (!ale)
1314 return ERR_PTR(-ENOMEM);
1315
1316 ale->p0_untag_vid_mask = devm_bitmap_zalloc(params->dev, VLAN_N_VID,
1317 GFP_KERNEL);
1318 if (!ale->p0_untag_vid_mask)
1319 return ERR_PTR(-ENOMEM);
1320
1321 ale->params = *params;
1322 ale->ageout = ale->params.ale_ageout * HZ;
1323 ale->features = ale_dev_id->features;
1324 ale->vlan_entry_tbl = ale_dev_id->vlan_entry_tbl;
1325
1326 rev = readl_relaxed(ale->params.ale_regs + ALE_IDVER);
1327 ale->version =
1328 (ALE_VERSION_MAJOR(rev, ale->params.major_ver_mask) << 8) |
1329 ALE_VERSION_MINOR(rev);
1330 dev_info(ale->params.dev, "initialized cpsw ale version %d.%d\n",
1331 ALE_VERSION_MAJOR(rev, ale->params.major_ver_mask),
1332 ALE_VERSION_MINOR(rev));
1333
1334 if (ale->features & CPSW_ALE_F_STATUS_REG &&
1335 !ale->params.ale_entries) {
1336 ale_entries =
1337 readl_relaxed(ale->params.ale_regs + ALE_STATUS) &
1338 ALE_STATUS_SIZE_MASK;
1339 /* ALE available on newer NetCP switches has introduced
1340 * a register, ALE_STATUS, to indicate the size of ALE
1341 * table which shows the size as a multiple of 1024 entries.
1342 * For these, params.ale_entries will be set to zero. So
1343 * read the register and update the value of ale_entries.
1344 * return error if ale_entries is zero in ALE_STATUS.
1345 */
1346 if (!ale_entries)
1347 return ERR_PTR(-EINVAL);
1348
1349 ale_entries *= ALE_TABLE_SIZE_MULTIPLIER;
1350 ale->params.ale_entries = ale_entries;
1351 }
1352 dev_info(ale->params.dev,
1353 "ALE Table size %ld\n", ale->params.ale_entries);
1354
1355 /* set default bits for existing h/w */
1356 ale->port_mask_bits = ale->params.ale_ports;
1357 ale->port_num_bits = order_base_2(ale->params.ale_ports);
1358 ale->vlan_field_bits = ale->params.ale_ports;
1359
1360 /* Set defaults override for ALE on NetCP NU switch and for version
1361 * 1R3
1362 */
1363 if (ale->params.nu_switch_ale) {
1364 /* Separate registers for unknown vlan configuration.
1365 * Also there are N bits, where N is number of ale
1366 * ports and shift value should be 0
1367 */
1368 ale_controls[ALE_PORT_UNKNOWN_VLAN_MEMBER].bits =
1369 ale->params.ale_ports;
1370 ale_controls[ALE_PORT_UNKNOWN_VLAN_MEMBER].offset =
1371 ALE_UNKNOWNVLAN_MEMBER;
1372 ale_controls[ALE_PORT_UNKNOWN_MCAST_FLOOD].bits =
1373 ale->params.ale_ports;
1374 ale_controls[ALE_PORT_UNKNOWN_MCAST_FLOOD].shift = 0;
1375 ale_controls[ALE_PORT_UNKNOWN_MCAST_FLOOD].offset =
1376 ALE_UNKNOWNVLAN_UNREG_MCAST_FLOOD;
1377 ale_controls[ALE_PORT_UNKNOWN_REG_MCAST_FLOOD].bits =
1378 ale->params.ale_ports;
1379 ale_controls[ALE_PORT_UNKNOWN_REG_MCAST_FLOOD].shift = 0;
1380 ale_controls[ALE_PORT_UNKNOWN_REG_MCAST_FLOOD].offset =
1381 ALE_UNKNOWNVLAN_REG_MCAST_FLOOD;
1382 ale_controls[ALE_PORT_UNTAGGED_EGRESS].bits =
1383 ale->params.ale_ports;
1384 ale_controls[ALE_PORT_UNTAGGED_EGRESS].shift = 0;
1385 ale_controls[ALE_PORT_UNTAGGED_EGRESS].offset =
1386 ALE_UNKNOWNVLAN_FORCE_UNTAG_EGRESS;
1387 }
1388
1389 cpsw_ale_control_set(ale, 0, ALE_CLEAR, 1);
1390 return ale;
1391 }
1392
cpsw_ale_dump(struct cpsw_ale * ale,u32 * data)1393 void cpsw_ale_dump(struct cpsw_ale *ale, u32 *data)
1394 {
1395 int i;
1396
1397 for (i = 0; i < ale->params.ale_entries; i++) {
1398 cpsw_ale_read(ale, i, data);
1399 data += ALE_ENTRY_WORDS;
1400 }
1401 }
1402
cpsw_ale_get_num_entries(struct cpsw_ale * ale)1403 u32 cpsw_ale_get_num_entries(struct cpsw_ale *ale)
1404 {
1405 return ale ? ale->params.ale_entries : 0;
1406 }
1407