fca5c29ef5f5713047944a52c65e4628f85f66a0
[linux-2.6-block.git] / drivers / net / ethernet / ti / cpsw_ale.c
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         writel_relaxed(idx, ale->params.ale_regs + ALE_TABLE_CONTROL);
154
155         for (i = 0; i < ALE_ENTRY_WORDS; i++)
156                 ale_entry[i] = readl_relaxed(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                 writel_relaxed(ale_entry[i], ale->params.ale_regs +
170                                ALE_TABLE + 4 * i);
171
172         writel_relaxed(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 = readl_relaxed(ale->params.ale_regs + offset);
737         tmp = (tmp & ~(mask << shift)) | (value << shift);
738         writel_relaxed(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 = readl_relaxed(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 = readl_relaxed(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                         readl_relaxed(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");