cpsw_ale.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809
  1. /*
  2. * Texas Instruments 3-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/platform_device.h>
  17. #include <linux/seq_file.h>
  18. #include <linux/slab.h>
  19. #include <linux/err.h>
  20. #include <linux/io.h>
  21. #include <linux/stat.h>
  22. #include <linux/sysfs.h>
  23. #include <linux/etherdevice.h>
  24. #include "cpsw_ale.h"
  25. #define BITMASK(bits) (BIT(bits) - 1)
  26. #define ALE_VERSION_MAJOR(rev) ((rev >> 8) & 0xff)
  27. #define ALE_VERSION_MINOR(rev) (rev & 0xff)
  28. /* ALE Registers */
  29. #define ALE_IDVER 0x00
  30. #define ALE_CONTROL 0x08
  31. #define ALE_PRESCALE 0x10
  32. #define ALE_UNKNOWNVLAN 0x18
  33. #define ALE_TABLE_CONTROL 0x20
  34. #define ALE_TABLE 0x34
  35. #define ALE_PORTCTL 0x40
  36. #define ALE_TABLE_WRITE BIT(31)
  37. #define ALE_TYPE_FREE 0
  38. #define ALE_TYPE_ADDR 1
  39. #define ALE_TYPE_VLAN 2
  40. #define ALE_TYPE_VLAN_ADDR 3
  41. #define ALE_UCAST_PERSISTANT 0
  42. #define ALE_UCAST_UNTOUCHED 1
  43. #define ALE_UCAST_OUI 2
  44. #define ALE_UCAST_TOUCHED 3
  45. static inline int cpsw_ale_get_field(u32 *ale_entry, u32 start, u32 bits)
  46. {
  47. int idx;
  48. idx = start / 32;
  49. start -= idx * 32;
  50. idx = 2 - idx; /* flip */
  51. return (ale_entry[idx] >> start) & BITMASK(bits);
  52. }
  53. static inline void cpsw_ale_set_field(u32 *ale_entry, u32 start, u32 bits,
  54. u32 value)
  55. {
  56. int idx;
  57. value &= BITMASK(bits);
  58. idx = start / 32;
  59. start -= idx * 32;
  60. idx = 2 - idx; /* flip */
  61. ale_entry[idx] &= ~(BITMASK(bits) << start);
  62. ale_entry[idx] |= (value << start);
  63. }
  64. #define DEFINE_ALE_FIELD(name, start, bits) \
  65. static inline int cpsw_ale_get_##name(u32 *ale_entry) \
  66. { \
  67. return cpsw_ale_get_field(ale_entry, start, bits); \
  68. } \
  69. static inline void cpsw_ale_set_##name(u32 *ale_entry, u32 value) \
  70. { \
  71. cpsw_ale_set_field(ale_entry, start, bits, value); \
  72. }
  73. DEFINE_ALE_FIELD(entry_type, 60, 2)
  74. DEFINE_ALE_FIELD(vlan_id, 48, 12)
  75. DEFINE_ALE_FIELD(mcast_state, 62, 2)
  76. DEFINE_ALE_FIELD(port_mask, 66, 3)
  77. DEFINE_ALE_FIELD(super, 65, 1)
  78. DEFINE_ALE_FIELD(ucast_type, 62, 2)
  79. DEFINE_ALE_FIELD(port_num, 66, 2)
  80. DEFINE_ALE_FIELD(blocked, 65, 1)
  81. DEFINE_ALE_FIELD(secure, 64, 1)
  82. DEFINE_ALE_FIELD(vlan_untag_force, 24, 3)
  83. DEFINE_ALE_FIELD(vlan_reg_mcast, 16, 3)
  84. DEFINE_ALE_FIELD(vlan_unreg_mcast, 8, 3)
  85. DEFINE_ALE_FIELD(vlan_member_list, 0, 3)
  86. DEFINE_ALE_FIELD(mcast, 40, 1)
  87. /* The MAC address field in the ALE entry cannot be macroized as above */
  88. static inline void cpsw_ale_get_addr(u32 *ale_entry, u8 *addr)
  89. {
  90. int i;
  91. for (i = 0; i < 6; i++)
  92. addr[i] = cpsw_ale_get_field(ale_entry, 40 - 8*i, 8);
  93. }
  94. static inline void cpsw_ale_set_addr(u32 *ale_entry, u8 *addr)
  95. {
  96. int i;
  97. for (i = 0; i < 6; i++)
  98. cpsw_ale_set_field(ale_entry, 40 - 8*i, 8, addr[i]);
  99. }
  100. static int cpsw_ale_read(struct cpsw_ale *ale, int idx, u32 *ale_entry)
  101. {
  102. int i;
  103. WARN_ON(idx > ale->params.ale_entries);
  104. __raw_writel(idx, ale->params.ale_regs + ALE_TABLE_CONTROL);
  105. for (i = 0; i < ALE_ENTRY_WORDS; i++)
  106. ale_entry[i] = __raw_readl(ale->params.ale_regs +
  107. ALE_TABLE + 4 * i);
  108. return idx;
  109. }
  110. static int cpsw_ale_write(struct cpsw_ale *ale, int idx, u32 *ale_entry)
  111. {
  112. int i;
  113. WARN_ON(idx > ale->params.ale_entries);
  114. for (i = 0; i < ALE_ENTRY_WORDS; i++)
  115. __raw_writel(ale_entry[i], ale->params.ale_regs +
  116. ALE_TABLE + 4 * i);
  117. __raw_writel(idx | ALE_TABLE_WRITE, ale->params.ale_regs +
  118. ALE_TABLE_CONTROL);
  119. return idx;
  120. }
  121. int cpsw_ale_match_addr(struct cpsw_ale *ale, u8 *addr, u16 vid)
  122. {
  123. u32 ale_entry[ALE_ENTRY_WORDS];
  124. int type, idx;
  125. for (idx = 0; idx < ale->params.ale_entries; idx++) {
  126. u8 entry_addr[6];
  127. cpsw_ale_read(ale, idx, ale_entry);
  128. type = cpsw_ale_get_entry_type(ale_entry);
  129. if (type != ALE_TYPE_ADDR && type != ALE_TYPE_VLAN_ADDR)
  130. continue;
  131. if (cpsw_ale_get_vlan_id(ale_entry) != vid)
  132. continue;
  133. cpsw_ale_get_addr(ale_entry, entry_addr);
  134. if (ether_addr_equal(entry_addr, addr))
  135. return idx;
  136. }
  137. return -ENOENT;
  138. }
  139. int cpsw_ale_match_vlan(struct cpsw_ale *ale, u16 vid)
  140. {
  141. u32 ale_entry[ALE_ENTRY_WORDS];
  142. int type, idx;
  143. for (idx = 0; idx < ale->params.ale_entries; idx++) {
  144. cpsw_ale_read(ale, idx, ale_entry);
  145. type = cpsw_ale_get_entry_type(ale_entry);
  146. if (type != ALE_TYPE_VLAN)
  147. continue;
  148. if (cpsw_ale_get_vlan_id(ale_entry) == vid)
  149. return idx;
  150. }
  151. return -ENOENT;
  152. }
  153. static int cpsw_ale_match_free(struct cpsw_ale *ale)
  154. {
  155. u32 ale_entry[ALE_ENTRY_WORDS];
  156. int type, idx;
  157. for (idx = 0; idx < ale->params.ale_entries; idx++) {
  158. cpsw_ale_read(ale, idx, ale_entry);
  159. type = cpsw_ale_get_entry_type(ale_entry);
  160. if (type == ALE_TYPE_FREE)
  161. return idx;
  162. }
  163. return -ENOENT;
  164. }
  165. static int cpsw_ale_find_ageable(struct cpsw_ale *ale)
  166. {
  167. u32 ale_entry[ALE_ENTRY_WORDS];
  168. int type, idx;
  169. for (idx = 0; idx < ale->params.ale_entries; idx++) {
  170. cpsw_ale_read(ale, idx, ale_entry);
  171. type = cpsw_ale_get_entry_type(ale_entry);
  172. if (type != ALE_TYPE_ADDR && type != ALE_TYPE_VLAN_ADDR)
  173. continue;
  174. if (cpsw_ale_get_mcast(ale_entry))
  175. continue;
  176. type = cpsw_ale_get_ucast_type(ale_entry);
  177. if (type != ALE_UCAST_PERSISTANT &&
  178. type != ALE_UCAST_OUI)
  179. return idx;
  180. }
  181. return -ENOENT;
  182. }
  183. static void cpsw_ale_flush_mcast(struct cpsw_ale *ale, u32 *ale_entry,
  184. int port_mask)
  185. {
  186. int mask;
  187. mask = cpsw_ale_get_port_mask(ale_entry);
  188. if ((mask & port_mask) == 0)
  189. return; /* ports dont intersect, not interested */
  190. mask &= ~port_mask;
  191. /* free if only remaining port is host port */
  192. if (mask)
  193. cpsw_ale_set_port_mask(ale_entry, mask);
  194. else
  195. cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
  196. }
  197. int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask, int vid)
  198. {
  199. u32 ale_entry[ALE_ENTRY_WORDS];
  200. int ret, idx;
  201. for (idx = 0; idx < ale->params.ale_entries; idx++) {
  202. cpsw_ale_read(ale, idx, ale_entry);
  203. ret = cpsw_ale_get_entry_type(ale_entry);
  204. if (ret != ALE_TYPE_ADDR && ret != ALE_TYPE_VLAN_ADDR)
  205. continue;
  206. /* if vid passed is -1 then remove all multicast entry from
  207. * the table irrespective of vlan id, if a valid vlan id is
  208. * passed then remove only multicast added to that vlan id.
  209. * if vlan id doesn't match then move on to next entry.
  210. */
  211. if (vid != -1 && cpsw_ale_get_vlan_id(ale_entry) != vid)
  212. continue;
  213. if (cpsw_ale_get_mcast(ale_entry)) {
  214. u8 addr[6];
  215. cpsw_ale_get_addr(ale_entry, addr);
  216. if (!is_broadcast_ether_addr(addr))
  217. cpsw_ale_flush_mcast(ale, ale_entry, port_mask);
  218. }
  219. cpsw_ale_write(ale, idx, ale_entry);
  220. }
  221. return 0;
  222. }
  223. static void cpsw_ale_flush_ucast(struct cpsw_ale *ale, u32 *ale_entry,
  224. int port_mask)
  225. {
  226. int port;
  227. port = cpsw_ale_get_port_num(ale_entry);
  228. if ((BIT(port) & port_mask) == 0)
  229. return; /* ports dont intersect, not interested */
  230. cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
  231. }
  232. int cpsw_ale_flush(struct cpsw_ale *ale, int port_mask)
  233. {
  234. u32 ale_entry[ALE_ENTRY_WORDS];
  235. int ret, idx;
  236. for (idx = 0; idx < ale->params.ale_entries; idx++) {
  237. cpsw_ale_read(ale, idx, ale_entry);
  238. ret = cpsw_ale_get_entry_type(ale_entry);
  239. if (ret != ALE_TYPE_ADDR && ret != ALE_TYPE_VLAN_ADDR)
  240. continue;
  241. if (cpsw_ale_get_mcast(ale_entry))
  242. cpsw_ale_flush_mcast(ale, ale_entry, port_mask);
  243. else
  244. cpsw_ale_flush_ucast(ale, ale_entry, port_mask);
  245. cpsw_ale_write(ale, idx, ale_entry);
  246. }
  247. return 0;
  248. }
  249. static inline void cpsw_ale_set_vlan_entry_type(u32 *ale_entry,
  250. int flags, u16 vid)
  251. {
  252. if (flags & ALE_VLAN) {
  253. cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_VLAN_ADDR);
  254. cpsw_ale_set_vlan_id(ale_entry, vid);
  255. } else {
  256. cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
  257. }
  258. }
  259. int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port,
  260. int flags, u16 vid)
  261. {
  262. u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
  263. int idx;
  264. cpsw_ale_set_vlan_entry_type(ale_entry, flags, vid);
  265. cpsw_ale_set_addr(ale_entry, addr);
  266. cpsw_ale_set_ucast_type(ale_entry, ALE_UCAST_PERSISTANT);
  267. cpsw_ale_set_secure(ale_entry, (flags & ALE_SECURE) ? 1 : 0);
  268. cpsw_ale_set_blocked(ale_entry, (flags & ALE_BLOCKED) ? 1 : 0);
  269. cpsw_ale_set_port_num(ale_entry, port);
  270. idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
  271. if (idx < 0)
  272. idx = cpsw_ale_match_free(ale);
  273. if (idx < 0)
  274. idx = cpsw_ale_find_ageable(ale);
  275. if (idx < 0)
  276. return -ENOMEM;
  277. cpsw_ale_write(ale, idx, ale_entry);
  278. return 0;
  279. }
  280. int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port,
  281. int flags, u16 vid)
  282. {
  283. u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
  284. int idx;
  285. idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
  286. if (idx < 0)
  287. return -ENOENT;
  288. cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
  289. cpsw_ale_write(ale, idx, ale_entry);
  290. return 0;
  291. }
  292. int cpsw_ale_add_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
  293. int flags, u16 vid, int mcast_state)
  294. {
  295. u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
  296. int idx, mask;
  297. idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
  298. if (idx >= 0)
  299. cpsw_ale_read(ale, idx, ale_entry);
  300. cpsw_ale_set_vlan_entry_type(ale_entry, flags, vid);
  301. cpsw_ale_set_addr(ale_entry, addr);
  302. cpsw_ale_set_super(ale_entry, (flags & ALE_BLOCKED) ? 1 : 0);
  303. cpsw_ale_set_mcast_state(ale_entry, mcast_state);
  304. mask = cpsw_ale_get_port_mask(ale_entry);
  305. port_mask |= mask;
  306. cpsw_ale_set_port_mask(ale_entry, port_mask);
  307. if (idx < 0)
  308. idx = cpsw_ale_match_free(ale);
  309. if (idx < 0)
  310. idx = cpsw_ale_find_ageable(ale);
  311. if (idx < 0)
  312. return -ENOMEM;
  313. cpsw_ale_write(ale, idx, ale_entry);
  314. return 0;
  315. }
  316. int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
  317. int flags, u16 vid)
  318. {
  319. u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
  320. int idx;
  321. idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
  322. if (idx < 0)
  323. return -EINVAL;
  324. cpsw_ale_read(ale, idx, ale_entry);
  325. if (port_mask)
  326. cpsw_ale_set_port_mask(ale_entry, port_mask);
  327. else
  328. cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
  329. cpsw_ale_write(ale, idx, ale_entry);
  330. return 0;
  331. }
  332. int cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port, int untag,
  333. int reg_mcast, int unreg_mcast)
  334. {
  335. u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
  336. int idx;
  337. idx = cpsw_ale_match_vlan(ale, vid);
  338. if (idx >= 0)
  339. cpsw_ale_read(ale, idx, ale_entry);
  340. cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_VLAN);
  341. cpsw_ale_set_vlan_id(ale_entry, vid);
  342. cpsw_ale_set_vlan_untag_force(ale_entry, untag);
  343. cpsw_ale_set_vlan_reg_mcast(ale_entry, reg_mcast);
  344. cpsw_ale_set_vlan_unreg_mcast(ale_entry, unreg_mcast);
  345. cpsw_ale_set_vlan_member_list(ale_entry, port);
  346. if (idx < 0)
  347. idx = cpsw_ale_match_free(ale);
  348. if (idx < 0)
  349. idx = cpsw_ale_find_ageable(ale);
  350. if (idx < 0)
  351. return -ENOMEM;
  352. cpsw_ale_write(ale, idx, ale_entry);
  353. return 0;
  354. }
  355. int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port_mask)
  356. {
  357. u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
  358. int idx;
  359. idx = cpsw_ale_match_vlan(ale, vid);
  360. if (idx < 0)
  361. return -ENOENT;
  362. cpsw_ale_read(ale, idx, ale_entry);
  363. if (port_mask)
  364. cpsw_ale_set_vlan_member_list(ale_entry, port_mask);
  365. else
  366. cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
  367. cpsw_ale_write(ale, idx, ale_entry);
  368. return 0;
  369. }
  370. void cpsw_ale_set_allmulti(struct cpsw_ale *ale, int allmulti)
  371. {
  372. u32 ale_entry[ALE_ENTRY_WORDS];
  373. int type, idx;
  374. int unreg_mcast = 0;
  375. /* Only bother doing the work if the setting is actually changing */
  376. if (ale->allmulti == allmulti)
  377. return;
  378. /* Remember the new setting to check against next time */
  379. ale->allmulti = allmulti;
  380. for (idx = 0; idx < ale->params.ale_entries; idx++) {
  381. cpsw_ale_read(ale, idx, ale_entry);
  382. type = cpsw_ale_get_entry_type(ale_entry);
  383. if (type != ALE_TYPE_VLAN)
  384. continue;
  385. unreg_mcast = cpsw_ale_get_vlan_unreg_mcast(ale_entry);
  386. if (allmulti)
  387. unreg_mcast |= 1;
  388. else
  389. unreg_mcast &= ~1;
  390. cpsw_ale_set_vlan_unreg_mcast(ale_entry, unreg_mcast);
  391. cpsw_ale_write(ale, idx, ale_entry);
  392. }
  393. }
  394. struct ale_control_info {
  395. const char *name;
  396. int offset, port_offset;
  397. int shift, port_shift;
  398. int bits;
  399. };
  400. static const struct ale_control_info ale_controls[ALE_NUM_CONTROLS] = {
  401. [ALE_ENABLE] = {
  402. .name = "enable",
  403. .offset = ALE_CONTROL,
  404. .port_offset = 0,
  405. .shift = 31,
  406. .port_shift = 0,
  407. .bits = 1,
  408. },
  409. [ALE_CLEAR] = {
  410. .name = "clear",
  411. .offset = ALE_CONTROL,
  412. .port_offset = 0,
  413. .shift = 30,
  414. .port_shift = 0,
  415. .bits = 1,
  416. },
  417. [ALE_AGEOUT] = {
  418. .name = "ageout",
  419. .offset = ALE_CONTROL,
  420. .port_offset = 0,
  421. .shift = 29,
  422. .port_shift = 0,
  423. .bits = 1,
  424. },
  425. [ALE_P0_UNI_FLOOD] = {
  426. .name = "port0_unicast_flood",
  427. .offset = ALE_CONTROL,
  428. .port_offset = 0,
  429. .shift = 8,
  430. .port_shift = 0,
  431. .bits = 1,
  432. },
  433. [ALE_VLAN_NOLEARN] = {
  434. .name = "vlan_nolearn",
  435. .offset = ALE_CONTROL,
  436. .port_offset = 0,
  437. .shift = 7,
  438. .port_shift = 0,
  439. .bits = 1,
  440. },
  441. [ALE_NO_PORT_VLAN] = {
  442. .name = "no_port_vlan",
  443. .offset = ALE_CONTROL,
  444. .port_offset = 0,
  445. .shift = 6,
  446. .port_shift = 0,
  447. .bits = 1,
  448. },
  449. [ALE_OUI_DENY] = {
  450. .name = "oui_deny",
  451. .offset = ALE_CONTROL,
  452. .port_offset = 0,
  453. .shift = 5,
  454. .port_shift = 0,
  455. .bits = 1,
  456. },
  457. [ALE_BYPASS] = {
  458. .name = "bypass",
  459. .offset = ALE_CONTROL,
  460. .port_offset = 0,
  461. .shift = 4,
  462. .port_shift = 0,
  463. .bits = 1,
  464. },
  465. [ALE_RATE_LIMIT_TX] = {
  466. .name = "rate_limit_tx",
  467. .offset = ALE_CONTROL,
  468. .port_offset = 0,
  469. .shift = 3,
  470. .port_shift = 0,
  471. .bits = 1,
  472. },
  473. [ALE_VLAN_AWARE] = {
  474. .name = "vlan_aware",
  475. .offset = ALE_CONTROL,
  476. .port_offset = 0,
  477. .shift = 2,
  478. .port_shift = 0,
  479. .bits = 1,
  480. },
  481. [ALE_AUTH_ENABLE] = {
  482. .name = "auth_enable",
  483. .offset = ALE_CONTROL,
  484. .port_offset = 0,
  485. .shift = 1,
  486. .port_shift = 0,
  487. .bits = 1,
  488. },
  489. [ALE_RATE_LIMIT] = {
  490. .name = "rate_limit",
  491. .offset = ALE_CONTROL,
  492. .port_offset = 0,
  493. .shift = 0,
  494. .port_shift = 0,
  495. .bits = 1,
  496. },
  497. [ALE_PORT_STATE] = {
  498. .name = "port_state",
  499. .offset = ALE_PORTCTL,
  500. .port_offset = 4,
  501. .shift = 0,
  502. .port_shift = 0,
  503. .bits = 2,
  504. },
  505. [ALE_PORT_DROP_UNTAGGED] = {
  506. .name = "drop_untagged",
  507. .offset = ALE_PORTCTL,
  508. .port_offset = 4,
  509. .shift = 2,
  510. .port_shift = 0,
  511. .bits = 1,
  512. },
  513. [ALE_PORT_DROP_UNKNOWN_VLAN] = {
  514. .name = "drop_unknown",
  515. .offset = ALE_PORTCTL,
  516. .port_offset = 4,
  517. .shift = 3,
  518. .port_shift = 0,
  519. .bits = 1,
  520. },
  521. [ALE_PORT_NOLEARN] = {
  522. .name = "nolearn",
  523. .offset = ALE_PORTCTL,
  524. .port_offset = 4,
  525. .shift = 4,
  526. .port_shift = 0,
  527. .bits = 1,
  528. },
  529. [ALE_PORT_NO_SA_UPDATE] = {
  530. .name = "no_source_update",
  531. .offset = ALE_PORTCTL,
  532. .port_offset = 4,
  533. .shift = 5,
  534. .port_shift = 0,
  535. .bits = 1,
  536. },
  537. [ALE_PORT_MCAST_LIMIT] = {
  538. .name = "mcast_limit",
  539. .offset = ALE_PORTCTL,
  540. .port_offset = 4,
  541. .shift = 16,
  542. .port_shift = 0,
  543. .bits = 8,
  544. },
  545. [ALE_PORT_BCAST_LIMIT] = {
  546. .name = "bcast_limit",
  547. .offset = ALE_PORTCTL,
  548. .port_offset = 4,
  549. .shift = 24,
  550. .port_shift = 0,
  551. .bits = 8,
  552. },
  553. [ALE_PORT_UNKNOWN_VLAN_MEMBER] = {
  554. .name = "unknown_vlan_member",
  555. .offset = ALE_UNKNOWNVLAN,
  556. .port_offset = 0,
  557. .shift = 0,
  558. .port_shift = 0,
  559. .bits = 6,
  560. },
  561. [ALE_PORT_UNKNOWN_MCAST_FLOOD] = {
  562. .name = "unknown_mcast_flood",
  563. .offset = ALE_UNKNOWNVLAN,
  564. .port_offset = 0,
  565. .shift = 8,
  566. .port_shift = 0,
  567. .bits = 6,
  568. },
  569. [ALE_PORT_UNKNOWN_REG_MCAST_FLOOD] = {
  570. .name = "unknown_reg_flood",
  571. .offset = ALE_UNKNOWNVLAN,
  572. .port_offset = 0,
  573. .shift = 16,
  574. .port_shift = 0,
  575. .bits = 6,
  576. },
  577. [ALE_PORT_UNTAGGED_EGRESS] = {
  578. .name = "untagged_egress",
  579. .offset = ALE_UNKNOWNVLAN,
  580. .port_offset = 0,
  581. .shift = 24,
  582. .port_shift = 0,
  583. .bits = 6,
  584. },
  585. };
  586. int cpsw_ale_control_set(struct cpsw_ale *ale, int port, int control,
  587. int value)
  588. {
  589. const struct ale_control_info *info;
  590. int offset, shift;
  591. u32 tmp, mask;
  592. if (control < 0 || control >= ARRAY_SIZE(ale_controls))
  593. return -EINVAL;
  594. info = &ale_controls[control];
  595. if (info->port_offset == 0 && info->port_shift == 0)
  596. port = 0; /* global, port is a dont care */
  597. if (port < 0 || port > ale->params.ale_ports)
  598. return -EINVAL;
  599. mask = BITMASK(info->bits);
  600. if (value & ~mask)
  601. return -EINVAL;
  602. offset = info->offset + (port * info->port_offset);
  603. shift = info->shift + (port * info->port_shift);
  604. tmp = __raw_readl(ale->params.ale_regs + offset);
  605. tmp = (tmp & ~(mask << shift)) | (value << shift);
  606. __raw_writel(tmp, ale->params.ale_regs + offset);
  607. return 0;
  608. }
  609. int cpsw_ale_control_get(struct cpsw_ale *ale, int port, int control)
  610. {
  611. const struct ale_control_info *info;
  612. int offset, shift;
  613. u32 tmp;
  614. if (control < 0 || control >= ARRAY_SIZE(ale_controls))
  615. return -EINVAL;
  616. info = &ale_controls[control];
  617. if (info->port_offset == 0 && info->port_shift == 0)
  618. port = 0; /* global, port is a dont care */
  619. if (port < 0 || port > ale->params.ale_ports)
  620. return -EINVAL;
  621. offset = info->offset + (port * info->port_offset);
  622. shift = info->shift + (port * info->port_shift);
  623. tmp = __raw_readl(ale->params.ale_regs + offset) >> shift;
  624. return tmp & BITMASK(info->bits);
  625. }
  626. static void cpsw_ale_timer(unsigned long arg)
  627. {
  628. struct cpsw_ale *ale = (struct cpsw_ale *)arg;
  629. cpsw_ale_control_set(ale, 0, ALE_AGEOUT, 1);
  630. if (ale->ageout) {
  631. ale->timer.expires = jiffies + ale->ageout;
  632. add_timer(&ale->timer);
  633. }
  634. }
  635. int cpsw_ale_set_ageout(struct cpsw_ale *ale, int ageout)
  636. {
  637. del_timer_sync(&ale->timer);
  638. ale->ageout = ageout * HZ;
  639. if (ale->ageout) {
  640. ale->timer.expires = jiffies + ale->ageout;
  641. add_timer(&ale->timer);
  642. }
  643. return 0;
  644. }
  645. void cpsw_ale_start(struct cpsw_ale *ale)
  646. {
  647. u32 rev;
  648. rev = __raw_readl(ale->params.ale_regs + ALE_IDVER);
  649. dev_dbg(ale->params.dev, "initialized cpsw ale revision %d.%d\n",
  650. ALE_VERSION_MAJOR(rev), ALE_VERSION_MINOR(rev));
  651. cpsw_ale_control_set(ale, 0, ALE_ENABLE, 1);
  652. cpsw_ale_control_set(ale, 0, ALE_CLEAR, 1);
  653. init_timer(&ale->timer);
  654. ale->timer.data = (unsigned long)ale;
  655. ale->timer.function = cpsw_ale_timer;
  656. if (ale->ageout) {
  657. ale->timer.expires = jiffies + ale->ageout;
  658. add_timer(&ale->timer);
  659. }
  660. }
  661. void cpsw_ale_stop(struct cpsw_ale *ale)
  662. {
  663. del_timer_sync(&ale->timer);
  664. }
  665. struct cpsw_ale *cpsw_ale_create(struct cpsw_ale_params *params)
  666. {
  667. struct cpsw_ale *ale;
  668. ale = kzalloc(sizeof(*ale), GFP_KERNEL);
  669. if (!ale)
  670. return NULL;
  671. ale->params = *params;
  672. ale->ageout = ale->params.ale_ageout * HZ;
  673. return ale;
  674. }
  675. int cpsw_ale_destroy(struct cpsw_ale *ale)
  676. {
  677. if (!ale)
  678. return -EINVAL;
  679. cpsw_ale_control_set(ale, 0, ALE_ENABLE, 0);
  680. kfree(ale);
  681. return 0;
  682. }
  683. void cpsw_ale_dump(struct cpsw_ale *ale, u32 *data)
  684. {
  685. int i;
  686. for (i = 0; i < ale->params.ale_entries; i++) {
  687. cpsw_ale_read(ale, i, data);
  688. data += ALE_ENTRY_WORDS;
  689. }
  690. }