qca8k-common.c 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2009 Felix Fietkau <nbd@nbd.name>
  4. * Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org>
  5. * Copyright (c) 2015, 2019, The Linux Foundation. All rights reserved.
  6. * Copyright (c) 2016 John Crispin <john@phrozen.org>
  7. */
  8. #include <linux/netdevice.h>
  9. #include <net/dsa.h>
  10. #include <linux/if_bridge.h>
  11. #include "qca8k.h"
  12. #define MIB_DESC(_s, _o, _n) \
  13. { \
  14. .size = (_s), \
  15. .offset = (_o), \
  16. .name = (_n), \
  17. }
  18. const struct qca8k_mib_desc ar8327_mib[] = {
  19. MIB_DESC(1, 0x00, "RxBroad"),
  20. MIB_DESC(1, 0x04, "RxPause"),
  21. MIB_DESC(1, 0x08, "RxMulti"),
  22. MIB_DESC(1, 0x0c, "RxFcsErr"),
  23. MIB_DESC(1, 0x10, "RxAlignErr"),
  24. MIB_DESC(1, 0x14, "RxRunt"),
  25. MIB_DESC(1, 0x18, "RxFragment"),
  26. MIB_DESC(1, 0x1c, "Rx64Byte"),
  27. MIB_DESC(1, 0x20, "Rx128Byte"),
  28. MIB_DESC(1, 0x24, "Rx256Byte"),
  29. MIB_DESC(1, 0x28, "Rx512Byte"),
  30. MIB_DESC(1, 0x2c, "Rx1024Byte"),
  31. MIB_DESC(1, 0x30, "Rx1518Byte"),
  32. MIB_DESC(1, 0x34, "RxMaxByte"),
  33. MIB_DESC(1, 0x38, "RxTooLong"),
  34. MIB_DESC(2, 0x3c, "RxGoodByte"),
  35. MIB_DESC(2, 0x44, "RxBadByte"),
  36. MIB_DESC(1, 0x4c, "RxOverFlow"),
  37. MIB_DESC(1, 0x50, "Filtered"),
  38. MIB_DESC(1, 0x54, "TxBroad"),
  39. MIB_DESC(1, 0x58, "TxPause"),
  40. MIB_DESC(1, 0x5c, "TxMulti"),
  41. MIB_DESC(1, 0x60, "TxUnderRun"),
  42. MIB_DESC(1, 0x64, "Tx64Byte"),
  43. MIB_DESC(1, 0x68, "Tx128Byte"),
  44. MIB_DESC(1, 0x6c, "Tx256Byte"),
  45. MIB_DESC(1, 0x70, "Tx512Byte"),
  46. MIB_DESC(1, 0x74, "Tx1024Byte"),
  47. MIB_DESC(1, 0x78, "Tx1518Byte"),
  48. MIB_DESC(1, 0x7c, "TxMaxByte"),
  49. MIB_DESC(1, 0x80, "TxOverSize"),
  50. MIB_DESC(2, 0x84, "TxByte"),
  51. MIB_DESC(1, 0x8c, "TxCollision"),
  52. MIB_DESC(1, 0x90, "TxAbortCol"),
  53. MIB_DESC(1, 0x94, "TxMultiCol"),
  54. MIB_DESC(1, 0x98, "TxSingleCol"),
  55. MIB_DESC(1, 0x9c, "TxExcDefer"),
  56. MIB_DESC(1, 0xa0, "TxDefer"),
  57. MIB_DESC(1, 0xa4, "TxLateCol"),
  58. MIB_DESC(1, 0xa8, "RXUnicast"),
  59. MIB_DESC(1, 0xac, "TXUnicast"),
  60. };
  61. int qca8k_read(struct qca8k_priv *priv, u32 reg, u32 *val)
  62. {
  63. return regmap_read(priv->regmap, reg, val);
  64. }
  65. int qca8k_write(struct qca8k_priv *priv, u32 reg, u32 val)
  66. {
  67. return regmap_write(priv->regmap, reg, val);
  68. }
  69. int qca8k_rmw(struct qca8k_priv *priv, u32 reg, u32 mask, u32 write_val)
  70. {
  71. return regmap_update_bits(priv->regmap, reg, mask, write_val);
  72. }
  73. static const struct regmap_range qca8k_readable_ranges[] = {
  74. regmap_reg_range(0x0000, 0x00e4), /* Global control */
  75. regmap_reg_range(0x0100, 0x0168), /* EEE control */
  76. regmap_reg_range(0x0200, 0x0270), /* Parser control */
  77. regmap_reg_range(0x0400, 0x0454), /* ACL */
  78. regmap_reg_range(0x0600, 0x0718), /* Lookup */
  79. regmap_reg_range(0x0800, 0x0b70), /* QM */
  80. regmap_reg_range(0x0c00, 0x0c80), /* PKT */
  81. regmap_reg_range(0x0e00, 0x0e98), /* L3 */
  82. regmap_reg_range(0x1000, 0x10ac), /* MIB - Port0 */
  83. regmap_reg_range(0x1100, 0x11ac), /* MIB - Port1 */
  84. regmap_reg_range(0x1200, 0x12ac), /* MIB - Port2 */
  85. regmap_reg_range(0x1300, 0x13ac), /* MIB - Port3 */
  86. regmap_reg_range(0x1400, 0x14ac), /* MIB - Port4 */
  87. regmap_reg_range(0x1500, 0x15ac), /* MIB - Port5 */
  88. regmap_reg_range(0x1600, 0x16ac), /* MIB - Port6 */
  89. };
  90. const struct regmap_access_table qca8k_readable_table = {
  91. .yes_ranges = qca8k_readable_ranges,
  92. .n_yes_ranges = ARRAY_SIZE(qca8k_readable_ranges),
  93. };
  94. static int qca8k_busy_wait(struct qca8k_priv *priv, u32 reg, u32 mask)
  95. {
  96. u32 val;
  97. return regmap_read_poll_timeout(priv->regmap, reg, val, !(val & mask), 0,
  98. QCA8K_BUSY_WAIT_TIMEOUT * USEC_PER_MSEC);
  99. }
  100. static int qca8k_fdb_read(struct qca8k_priv *priv, struct qca8k_fdb *fdb)
  101. {
  102. u32 reg[QCA8K_ATU_TABLE_SIZE];
  103. int ret;
  104. /* load the ARL table into an array */
  105. ret = regmap_bulk_read(priv->regmap, QCA8K_REG_ATU_DATA0, reg,
  106. QCA8K_ATU_TABLE_SIZE);
  107. if (ret)
  108. return ret;
  109. /* vid - 83:72 */
  110. fdb->vid = FIELD_GET(QCA8K_ATU_VID_MASK, reg[2]);
  111. /* aging - 67:64 */
  112. fdb->aging = FIELD_GET(QCA8K_ATU_STATUS_MASK, reg[2]);
  113. /* portmask - 54:48 */
  114. fdb->port_mask = FIELD_GET(QCA8K_ATU_PORT_MASK, reg[1]);
  115. /* mac - 47:0 */
  116. fdb->mac[0] = FIELD_GET(QCA8K_ATU_ADDR0_MASK, reg[1]);
  117. fdb->mac[1] = FIELD_GET(QCA8K_ATU_ADDR1_MASK, reg[1]);
  118. fdb->mac[2] = FIELD_GET(QCA8K_ATU_ADDR2_MASK, reg[0]);
  119. fdb->mac[3] = FIELD_GET(QCA8K_ATU_ADDR3_MASK, reg[0]);
  120. fdb->mac[4] = FIELD_GET(QCA8K_ATU_ADDR4_MASK, reg[0]);
  121. fdb->mac[5] = FIELD_GET(QCA8K_ATU_ADDR5_MASK, reg[0]);
  122. return 0;
  123. }
  124. static void qca8k_fdb_write(struct qca8k_priv *priv, u16 vid, u8 port_mask,
  125. const u8 *mac, u8 aging)
  126. {
  127. u32 reg[QCA8K_ATU_TABLE_SIZE] = { 0 };
  128. /* vid - 83:72 */
  129. reg[2] = FIELD_PREP(QCA8K_ATU_VID_MASK, vid);
  130. /* aging - 67:64 */
  131. reg[2] |= FIELD_PREP(QCA8K_ATU_STATUS_MASK, aging);
  132. /* portmask - 54:48 */
  133. reg[1] = FIELD_PREP(QCA8K_ATU_PORT_MASK, port_mask);
  134. /* mac - 47:0 */
  135. reg[1] |= FIELD_PREP(QCA8K_ATU_ADDR0_MASK, mac[0]);
  136. reg[1] |= FIELD_PREP(QCA8K_ATU_ADDR1_MASK, mac[1]);
  137. reg[0] |= FIELD_PREP(QCA8K_ATU_ADDR2_MASK, mac[2]);
  138. reg[0] |= FIELD_PREP(QCA8K_ATU_ADDR3_MASK, mac[3]);
  139. reg[0] |= FIELD_PREP(QCA8K_ATU_ADDR4_MASK, mac[4]);
  140. reg[0] |= FIELD_PREP(QCA8K_ATU_ADDR5_MASK, mac[5]);
  141. /* load the array into the ARL table */
  142. regmap_bulk_write(priv->regmap, QCA8K_REG_ATU_DATA0, reg,
  143. QCA8K_ATU_TABLE_SIZE);
  144. }
  145. static int qca8k_fdb_access(struct qca8k_priv *priv, enum qca8k_fdb_cmd cmd,
  146. int port)
  147. {
  148. u32 reg;
  149. int ret;
  150. /* Set the command and FDB index */
  151. reg = QCA8K_ATU_FUNC_BUSY;
  152. reg |= cmd;
  153. if (port >= 0) {
  154. reg |= QCA8K_ATU_FUNC_PORT_EN;
  155. reg |= FIELD_PREP(QCA8K_ATU_FUNC_PORT_MASK, port);
  156. }
  157. /* Write the function register triggering the table access */
  158. ret = qca8k_write(priv, QCA8K_REG_ATU_FUNC, reg);
  159. if (ret)
  160. return ret;
  161. /* wait for completion */
  162. ret = qca8k_busy_wait(priv, QCA8K_REG_ATU_FUNC, QCA8K_ATU_FUNC_BUSY);
  163. if (ret)
  164. return ret;
  165. /* Check for table full violation when adding an entry */
  166. if (cmd == QCA8K_FDB_LOAD) {
  167. ret = qca8k_read(priv, QCA8K_REG_ATU_FUNC, &reg);
  168. if (ret < 0)
  169. return ret;
  170. if (reg & QCA8K_ATU_FUNC_FULL)
  171. return -1;
  172. }
  173. return 0;
  174. }
  175. static int qca8k_fdb_next(struct qca8k_priv *priv, struct qca8k_fdb *fdb,
  176. int port)
  177. {
  178. int ret;
  179. qca8k_fdb_write(priv, fdb->vid, fdb->port_mask, fdb->mac, fdb->aging);
  180. ret = qca8k_fdb_access(priv, QCA8K_FDB_NEXT, port);
  181. if (ret < 0)
  182. return ret;
  183. return qca8k_fdb_read(priv, fdb);
  184. }
  185. static int qca8k_fdb_add(struct qca8k_priv *priv, const u8 *mac,
  186. u16 port_mask, u16 vid, u8 aging)
  187. {
  188. int ret;
  189. mutex_lock(&priv->reg_mutex);
  190. qca8k_fdb_write(priv, vid, port_mask, mac, aging);
  191. ret = qca8k_fdb_access(priv, QCA8K_FDB_LOAD, -1);
  192. mutex_unlock(&priv->reg_mutex);
  193. return ret;
  194. }
  195. static int qca8k_fdb_del(struct qca8k_priv *priv, const u8 *mac,
  196. u16 port_mask, u16 vid)
  197. {
  198. int ret;
  199. mutex_lock(&priv->reg_mutex);
  200. qca8k_fdb_write(priv, vid, port_mask, mac, 0);
  201. ret = qca8k_fdb_access(priv, QCA8K_FDB_PURGE, -1);
  202. mutex_unlock(&priv->reg_mutex);
  203. return ret;
  204. }
  205. void qca8k_fdb_flush(struct qca8k_priv *priv)
  206. {
  207. mutex_lock(&priv->reg_mutex);
  208. qca8k_fdb_access(priv, QCA8K_FDB_FLUSH, -1);
  209. mutex_unlock(&priv->reg_mutex);
  210. }
  211. static int qca8k_fdb_search_and_insert(struct qca8k_priv *priv, u8 port_mask,
  212. const u8 *mac, u16 vid, u8 aging)
  213. {
  214. struct qca8k_fdb fdb = { 0 };
  215. int ret;
  216. mutex_lock(&priv->reg_mutex);
  217. qca8k_fdb_write(priv, vid, 0, mac, 0);
  218. ret = qca8k_fdb_access(priv, QCA8K_FDB_SEARCH, -1);
  219. if (ret < 0)
  220. goto exit;
  221. ret = qca8k_fdb_read(priv, &fdb);
  222. if (ret < 0)
  223. goto exit;
  224. /* Rule exist. Delete first */
  225. if (fdb.aging) {
  226. ret = qca8k_fdb_access(priv, QCA8K_FDB_PURGE, -1);
  227. if (ret)
  228. goto exit;
  229. } else {
  230. fdb.aging = aging;
  231. }
  232. /* Add port to fdb portmask */
  233. fdb.port_mask |= port_mask;
  234. qca8k_fdb_write(priv, vid, fdb.port_mask, mac, fdb.aging);
  235. ret = qca8k_fdb_access(priv, QCA8K_FDB_LOAD, -1);
  236. exit:
  237. mutex_unlock(&priv->reg_mutex);
  238. return ret;
  239. }
  240. static int qca8k_fdb_search_and_del(struct qca8k_priv *priv, u8 port_mask,
  241. const u8 *mac, u16 vid)
  242. {
  243. struct qca8k_fdb fdb = { 0 };
  244. int ret;
  245. mutex_lock(&priv->reg_mutex);
  246. qca8k_fdb_write(priv, vid, 0, mac, 0);
  247. ret = qca8k_fdb_access(priv, QCA8K_FDB_SEARCH, -1);
  248. if (ret < 0)
  249. goto exit;
  250. ret = qca8k_fdb_read(priv, &fdb);
  251. if (ret < 0)
  252. goto exit;
  253. /* Rule doesn't exist. Why delete? */
  254. if (!fdb.aging) {
  255. ret = -EINVAL;
  256. goto exit;
  257. }
  258. ret = qca8k_fdb_access(priv, QCA8K_FDB_PURGE, -1);
  259. if (ret)
  260. goto exit;
  261. /* Only port in the rule is this port. Don't re insert */
  262. if (fdb.port_mask == port_mask)
  263. goto exit;
  264. /* Remove port from port mask */
  265. fdb.port_mask &= ~port_mask;
  266. qca8k_fdb_write(priv, vid, fdb.port_mask, mac, fdb.aging);
  267. ret = qca8k_fdb_access(priv, QCA8K_FDB_LOAD, -1);
  268. exit:
  269. mutex_unlock(&priv->reg_mutex);
  270. return ret;
  271. }
  272. static int qca8k_vlan_access(struct qca8k_priv *priv,
  273. enum qca8k_vlan_cmd cmd, u16 vid)
  274. {
  275. u32 reg;
  276. int ret;
  277. /* Set the command and VLAN index */
  278. reg = QCA8K_VTU_FUNC1_BUSY;
  279. reg |= cmd;
  280. reg |= FIELD_PREP(QCA8K_VTU_FUNC1_VID_MASK, vid);
  281. /* Write the function register triggering the table access */
  282. ret = qca8k_write(priv, QCA8K_REG_VTU_FUNC1, reg);
  283. if (ret)
  284. return ret;
  285. /* wait for completion */
  286. ret = qca8k_busy_wait(priv, QCA8K_REG_VTU_FUNC1, QCA8K_VTU_FUNC1_BUSY);
  287. if (ret)
  288. return ret;
  289. /* Check for table full violation when adding an entry */
  290. if (cmd == QCA8K_VLAN_LOAD) {
  291. ret = qca8k_read(priv, QCA8K_REG_VTU_FUNC1, &reg);
  292. if (ret < 0)
  293. return ret;
  294. if (reg & QCA8K_VTU_FUNC1_FULL)
  295. return -ENOMEM;
  296. }
  297. return 0;
  298. }
  299. static int qca8k_vlan_add(struct qca8k_priv *priv, u8 port, u16 vid,
  300. bool untagged)
  301. {
  302. u32 reg;
  303. int ret;
  304. /* We do the right thing with VLAN 0 and treat it as untagged while
  305. * preserving the tag on egress.
  306. */
  307. if (vid == 0)
  308. return 0;
  309. mutex_lock(&priv->reg_mutex);
  310. ret = qca8k_vlan_access(priv, QCA8K_VLAN_READ, vid);
  311. if (ret < 0)
  312. goto out;
  313. ret = qca8k_read(priv, QCA8K_REG_VTU_FUNC0, &reg);
  314. if (ret < 0)
  315. goto out;
  316. reg |= QCA8K_VTU_FUNC0_VALID | QCA8K_VTU_FUNC0_IVL_EN;
  317. reg &= ~QCA8K_VTU_FUNC0_EG_MODE_PORT_MASK(port);
  318. if (untagged)
  319. reg |= QCA8K_VTU_FUNC0_EG_MODE_PORT_UNTAG(port);
  320. else
  321. reg |= QCA8K_VTU_FUNC0_EG_MODE_PORT_TAG(port);
  322. ret = qca8k_write(priv, QCA8K_REG_VTU_FUNC0, reg);
  323. if (ret)
  324. goto out;
  325. ret = qca8k_vlan_access(priv, QCA8K_VLAN_LOAD, vid);
  326. out:
  327. mutex_unlock(&priv->reg_mutex);
  328. return ret;
  329. }
  330. static int qca8k_vlan_del(struct qca8k_priv *priv, u8 port, u16 vid)
  331. {
  332. u32 reg, mask;
  333. int ret, i;
  334. bool del;
  335. mutex_lock(&priv->reg_mutex);
  336. ret = qca8k_vlan_access(priv, QCA8K_VLAN_READ, vid);
  337. if (ret < 0)
  338. goto out;
  339. ret = qca8k_read(priv, QCA8K_REG_VTU_FUNC0, &reg);
  340. if (ret < 0)
  341. goto out;
  342. reg &= ~QCA8K_VTU_FUNC0_EG_MODE_PORT_MASK(port);
  343. reg |= QCA8K_VTU_FUNC0_EG_MODE_PORT_NOT(port);
  344. /* Check if we're the last member to be removed */
  345. del = true;
  346. for (i = 0; i < QCA8K_NUM_PORTS; i++) {
  347. mask = QCA8K_VTU_FUNC0_EG_MODE_PORT_NOT(i);
  348. if ((reg & mask) != mask) {
  349. del = false;
  350. break;
  351. }
  352. }
  353. if (del) {
  354. ret = qca8k_vlan_access(priv, QCA8K_VLAN_PURGE, vid);
  355. } else {
  356. ret = qca8k_write(priv, QCA8K_REG_VTU_FUNC0, reg);
  357. if (ret)
  358. goto out;
  359. ret = qca8k_vlan_access(priv, QCA8K_VLAN_LOAD, vid);
  360. }
  361. out:
  362. mutex_unlock(&priv->reg_mutex);
  363. return ret;
  364. }
  365. int qca8k_mib_init(struct qca8k_priv *priv)
  366. {
  367. int ret;
  368. mutex_lock(&priv->reg_mutex);
  369. ret = regmap_update_bits(priv->regmap, QCA8K_REG_MIB,
  370. QCA8K_MIB_FUNC | QCA8K_MIB_BUSY,
  371. FIELD_PREP(QCA8K_MIB_FUNC, QCA8K_MIB_FLUSH) |
  372. QCA8K_MIB_BUSY);
  373. if (ret)
  374. goto exit;
  375. ret = qca8k_busy_wait(priv, QCA8K_REG_MIB, QCA8K_MIB_BUSY);
  376. if (ret)
  377. goto exit;
  378. ret = regmap_set_bits(priv->regmap, QCA8K_REG_MIB, QCA8K_MIB_CPU_KEEP);
  379. if (ret)
  380. goto exit;
  381. ret = qca8k_write(priv, QCA8K_REG_MODULE_EN, QCA8K_MODULE_EN_MIB);
  382. exit:
  383. mutex_unlock(&priv->reg_mutex);
  384. return ret;
  385. }
  386. void qca8k_port_set_status(struct qca8k_priv *priv, int port, int enable)
  387. {
  388. u32 mask = QCA8K_PORT_STATUS_TXMAC | QCA8K_PORT_STATUS_RXMAC;
  389. /* Port 0 and 6 have no internal PHY */
  390. if (port > 0 && port < 6)
  391. mask |= QCA8K_PORT_STATUS_LINK_AUTO;
  392. if (enable)
  393. regmap_set_bits(priv->regmap, QCA8K_REG_PORT_STATUS(port), mask);
  394. else
  395. regmap_clear_bits(priv->regmap, QCA8K_REG_PORT_STATUS(port), mask);
  396. }
  397. void qca8k_get_strings(struct dsa_switch *ds, int port, u32 stringset,
  398. uint8_t *data)
  399. {
  400. struct qca8k_priv *priv = ds->priv;
  401. int i;
  402. if (stringset != ETH_SS_STATS)
  403. return;
  404. for (i = 0; i < priv->info->mib_count; i++)
  405. ethtool_puts(&data, ar8327_mib[i].name);
  406. }
  407. void qca8k_get_ethtool_stats(struct dsa_switch *ds, int port,
  408. uint64_t *data)
  409. {
  410. struct qca8k_priv *priv = ds->priv;
  411. const struct qca8k_mib_desc *mib;
  412. u32 reg, i, val;
  413. u32 hi = 0;
  414. int ret;
  415. if (priv->mgmt_conduit && priv->info->ops->autocast_mib &&
  416. priv->info->ops->autocast_mib(ds, port, data) > 0)
  417. return;
  418. for (i = 0; i < priv->info->mib_count; i++) {
  419. mib = &ar8327_mib[i];
  420. reg = QCA8K_PORT_MIB_COUNTER(port) + mib->offset;
  421. ret = qca8k_read(priv, reg, &val);
  422. if (ret < 0)
  423. continue;
  424. if (mib->size == 2) {
  425. ret = qca8k_read(priv, reg + 4, &hi);
  426. if (ret < 0)
  427. continue;
  428. }
  429. data[i] = val;
  430. if (mib->size == 2)
  431. data[i] |= (u64)hi << 32;
  432. }
  433. }
  434. int qca8k_get_sset_count(struct dsa_switch *ds, int port, int sset)
  435. {
  436. struct qca8k_priv *priv = ds->priv;
  437. if (sset != ETH_SS_STATS)
  438. return 0;
  439. return priv->info->mib_count;
  440. }
  441. int qca8k_set_mac_eee(struct dsa_switch *ds, int port,
  442. struct ethtool_keee *eee)
  443. {
  444. u32 lpi_en = QCA8K_REG_EEE_CTRL_LPI_EN(port);
  445. struct qca8k_priv *priv = ds->priv;
  446. u32 reg;
  447. int ret;
  448. mutex_lock(&priv->reg_mutex);
  449. ret = qca8k_read(priv, QCA8K_REG_EEE_CTRL, &reg);
  450. if (ret < 0)
  451. goto exit;
  452. if (eee->eee_enabled)
  453. reg |= lpi_en;
  454. else
  455. reg &= ~lpi_en;
  456. ret = qca8k_write(priv, QCA8K_REG_EEE_CTRL, reg);
  457. exit:
  458. mutex_unlock(&priv->reg_mutex);
  459. return ret;
  460. }
  461. int qca8k_get_mac_eee(struct dsa_switch *ds, int port,
  462. struct ethtool_keee *e)
  463. {
  464. /* Nothing to do on the port's MAC */
  465. return 0;
  466. }
  467. static int qca8k_port_configure_learning(struct dsa_switch *ds, int port,
  468. bool learning)
  469. {
  470. struct qca8k_priv *priv = ds->priv;
  471. if (learning)
  472. return regmap_set_bits(priv->regmap,
  473. QCA8K_PORT_LOOKUP_CTRL(port),
  474. QCA8K_PORT_LOOKUP_LEARN);
  475. else
  476. return regmap_clear_bits(priv->regmap,
  477. QCA8K_PORT_LOOKUP_CTRL(port),
  478. QCA8K_PORT_LOOKUP_LEARN);
  479. }
  480. void qca8k_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
  481. {
  482. struct dsa_port *dp = dsa_to_port(ds, port);
  483. struct qca8k_priv *priv = ds->priv;
  484. bool learning = false;
  485. u32 stp_state;
  486. switch (state) {
  487. case BR_STATE_DISABLED:
  488. stp_state = QCA8K_PORT_LOOKUP_STATE_DISABLED;
  489. break;
  490. case BR_STATE_BLOCKING:
  491. stp_state = QCA8K_PORT_LOOKUP_STATE_BLOCKING;
  492. break;
  493. case BR_STATE_LISTENING:
  494. stp_state = QCA8K_PORT_LOOKUP_STATE_LISTENING;
  495. break;
  496. case BR_STATE_LEARNING:
  497. stp_state = QCA8K_PORT_LOOKUP_STATE_LEARNING;
  498. learning = dp->learning;
  499. break;
  500. case BR_STATE_FORWARDING:
  501. learning = dp->learning;
  502. fallthrough;
  503. default:
  504. stp_state = QCA8K_PORT_LOOKUP_STATE_FORWARD;
  505. break;
  506. }
  507. qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
  508. QCA8K_PORT_LOOKUP_STATE_MASK, stp_state);
  509. qca8k_port_configure_learning(ds, port, learning);
  510. }
  511. static int qca8k_update_port_member(struct qca8k_priv *priv, int port,
  512. const struct net_device *bridge_dev,
  513. bool join)
  514. {
  515. bool isolated = !!(priv->port_isolated_map & BIT(port)), other_isolated;
  516. struct dsa_port *dp = dsa_to_port(priv->ds, port), *other_dp;
  517. u32 port_mask = BIT(dp->cpu_dp->index);
  518. int i, ret;
  519. for (i = 0; i < QCA8K_NUM_PORTS; i++) {
  520. if (i == port)
  521. continue;
  522. if (dsa_is_cpu_port(priv->ds, i))
  523. continue;
  524. other_dp = dsa_to_port(priv->ds, i);
  525. if (!dsa_port_offloads_bridge_dev(other_dp, bridge_dev))
  526. continue;
  527. other_isolated = !!(priv->port_isolated_map & BIT(i));
  528. /* Add/remove this port to/from the portvlan mask of the other
  529. * ports in the bridge
  530. */
  531. if (join && !(isolated && other_isolated)) {
  532. port_mask |= BIT(i);
  533. ret = regmap_set_bits(priv->regmap,
  534. QCA8K_PORT_LOOKUP_CTRL(i),
  535. BIT(port));
  536. } else {
  537. ret = regmap_clear_bits(priv->regmap,
  538. QCA8K_PORT_LOOKUP_CTRL(i),
  539. BIT(port));
  540. }
  541. if (ret)
  542. return ret;
  543. }
  544. /* Add/remove all other ports to/from this port's portvlan mask */
  545. ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
  546. QCA8K_PORT_LOOKUP_MEMBER, port_mask);
  547. return ret;
  548. }
  549. int qca8k_port_pre_bridge_flags(struct dsa_switch *ds, int port,
  550. struct switchdev_brport_flags flags,
  551. struct netlink_ext_ack *extack)
  552. {
  553. if (flags.mask & ~(BR_LEARNING | BR_ISOLATED))
  554. return -EINVAL;
  555. return 0;
  556. }
  557. int qca8k_port_bridge_flags(struct dsa_switch *ds, int port,
  558. struct switchdev_brport_flags flags,
  559. struct netlink_ext_ack *extack)
  560. {
  561. struct qca8k_priv *priv = ds->priv;
  562. int ret;
  563. if (flags.mask & BR_LEARNING) {
  564. ret = qca8k_port_configure_learning(ds, port,
  565. flags.val & BR_LEARNING);
  566. if (ret)
  567. return ret;
  568. }
  569. if (flags.mask & BR_ISOLATED) {
  570. struct dsa_port *dp = dsa_to_port(ds, port);
  571. struct net_device *bridge_dev = dsa_port_bridge_dev_get(dp);
  572. if (flags.val & BR_ISOLATED)
  573. priv->port_isolated_map |= BIT(port);
  574. else
  575. priv->port_isolated_map &= ~BIT(port);
  576. ret = qca8k_update_port_member(priv, port, bridge_dev, true);
  577. if (ret)
  578. return ret;
  579. }
  580. return 0;
  581. }
  582. int qca8k_port_bridge_join(struct dsa_switch *ds, int port,
  583. struct dsa_bridge bridge,
  584. bool *tx_fwd_offload,
  585. struct netlink_ext_ack *extack)
  586. {
  587. struct qca8k_priv *priv = ds->priv;
  588. return qca8k_update_port_member(priv, port, bridge.dev, true);
  589. }
  590. void qca8k_port_bridge_leave(struct dsa_switch *ds, int port,
  591. struct dsa_bridge bridge)
  592. {
  593. struct qca8k_priv *priv = ds->priv;
  594. int err;
  595. err = qca8k_update_port_member(priv, port, bridge.dev, false);
  596. if (err)
  597. dev_err(priv->dev,
  598. "Failed to update switch config for bridge leave: %d\n",
  599. err);
  600. }
  601. void qca8k_port_fast_age(struct dsa_switch *ds, int port)
  602. {
  603. struct qca8k_priv *priv = ds->priv;
  604. mutex_lock(&priv->reg_mutex);
  605. qca8k_fdb_access(priv, QCA8K_FDB_FLUSH_PORT, port);
  606. mutex_unlock(&priv->reg_mutex);
  607. }
  608. int qca8k_set_ageing_time(struct dsa_switch *ds, unsigned int msecs)
  609. {
  610. struct qca8k_priv *priv = ds->priv;
  611. unsigned int secs = msecs / 1000;
  612. u32 val;
  613. /* AGE_TIME reg is set in 7s step */
  614. val = secs / 7;
  615. /* Handle case with 0 as val to NOT disable
  616. * learning
  617. */
  618. if (!val)
  619. val = 1;
  620. return regmap_update_bits(priv->regmap, QCA8K_REG_ATU_CTRL,
  621. QCA8K_ATU_AGE_TIME_MASK,
  622. QCA8K_ATU_AGE_TIME(val));
  623. }
  624. int qca8k_port_enable(struct dsa_switch *ds, int port,
  625. struct phy_device *phy)
  626. {
  627. struct qca8k_priv *priv = ds->priv;
  628. qca8k_port_set_status(priv, port, 1);
  629. priv->port_enabled_map |= BIT(port);
  630. if (dsa_is_user_port(ds, port))
  631. phy_support_asym_pause(phy);
  632. return 0;
  633. }
  634. void qca8k_port_disable(struct dsa_switch *ds, int port)
  635. {
  636. struct qca8k_priv *priv = ds->priv;
  637. qca8k_port_set_status(priv, port, 0);
  638. priv->port_enabled_map &= ~BIT(port);
  639. }
  640. int qca8k_port_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
  641. {
  642. struct qca8k_priv *priv = ds->priv;
  643. int ret;
  644. /* We have only have a general MTU setting.
  645. * DSA always set the CPU port's MTU to the largest MTU of the user
  646. * ports.
  647. * Setting MTU just for the CPU port is sufficient to correctly set a
  648. * value for every port.
  649. */
  650. if (!dsa_is_cpu_port(ds, port))
  651. return 0;
  652. /* To change the MAX_FRAME_SIZE the cpu ports must be off or
  653. * the switch panics.
  654. * Turn off both cpu ports before applying the new value to prevent
  655. * this.
  656. */
  657. if (priv->port_enabled_map & BIT(0))
  658. qca8k_port_set_status(priv, 0, 0);
  659. if (priv->port_enabled_map & BIT(6))
  660. qca8k_port_set_status(priv, 6, 0);
  661. /* Include L2 header / FCS length */
  662. ret = qca8k_write(priv, QCA8K_MAX_FRAME_SIZE, new_mtu +
  663. ETH_HLEN + ETH_FCS_LEN);
  664. if (priv->port_enabled_map & BIT(0))
  665. qca8k_port_set_status(priv, 0, 1);
  666. if (priv->port_enabled_map & BIT(6))
  667. qca8k_port_set_status(priv, 6, 1);
  668. return ret;
  669. }
  670. int qca8k_port_max_mtu(struct dsa_switch *ds, int port)
  671. {
  672. return QCA8K_MAX_MTU;
  673. }
  674. int qca8k_port_fdb_insert(struct qca8k_priv *priv, const u8 *addr,
  675. u16 port_mask, u16 vid)
  676. {
  677. /* Set the vid to the port vlan id if no vid is set */
  678. if (!vid)
  679. vid = QCA8K_PORT_VID_DEF;
  680. return qca8k_fdb_add(priv, addr, port_mask, vid,
  681. QCA8K_ATU_STATUS_STATIC);
  682. }
  683. int qca8k_port_fdb_add(struct dsa_switch *ds, int port,
  684. const unsigned char *addr, u16 vid,
  685. struct dsa_db db)
  686. {
  687. struct qca8k_priv *priv = ds->priv;
  688. u16 port_mask = BIT(port);
  689. return qca8k_port_fdb_insert(priv, addr, port_mask, vid);
  690. }
  691. int qca8k_port_fdb_del(struct dsa_switch *ds, int port,
  692. const unsigned char *addr, u16 vid,
  693. struct dsa_db db)
  694. {
  695. struct qca8k_priv *priv = ds->priv;
  696. u16 port_mask = BIT(port);
  697. if (!vid)
  698. vid = QCA8K_PORT_VID_DEF;
  699. return qca8k_fdb_del(priv, addr, port_mask, vid);
  700. }
  701. int qca8k_port_fdb_dump(struct dsa_switch *ds, int port,
  702. dsa_fdb_dump_cb_t *cb, void *data)
  703. {
  704. struct qca8k_priv *priv = ds->priv;
  705. struct qca8k_fdb _fdb = { 0 };
  706. int cnt = QCA8K_NUM_FDB_RECORDS;
  707. bool is_static;
  708. int ret = 0;
  709. mutex_lock(&priv->reg_mutex);
  710. while (cnt-- && !qca8k_fdb_next(priv, &_fdb, port)) {
  711. if (!_fdb.aging)
  712. break;
  713. is_static = (_fdb.aging == QCA8K_ATU_STATUS_STATIC);
  714. ret = cb(_fdb.mac, _fdb.vid, is_static, data);
  715. if (ret)
  716. break;
  717. }
  718. mutex_unlock(&priv->reg_mutex);
  719. return 0;
  720. }
  721. int qca8k_port_mdb_add(struct dsa_switch *ds, int port,
  722. const struct switchdev_obj_port_mdb *mdb,
  723. struct dsa_db db)
  724. {
  725. struct qca8k_priv *priv = ds->priv;
  726. const u8 *addr = mdb->addr;
  727. u16 vid = mdb->vid;
  728. if (!vid)
  729. vid = QCA8K_PORT_VID_DEF;
  730. return qca8k_fdb_search_and_insert(priv, BIT(port), addr, vid,
  731. QCA8K_ATU_STATUS_STATIC);
  732. }
  733. int qca8k_port_mdb_del(struct dsa_switch *ds, int port,
  734. const struct switchdev_obj_port_mdb *mdb,
  735. struct dsa_db db)
  736. {
  737. struct qca8k_priv *priv = ds->priv;
  738. const u8 *addr = mdb->addr;
  739. u16 vid = mdb->vid;
  740. if (!vid)
  741. vid = QCA8K_PORT_VID_DEF;
  742. return qca8k_fdb_search_and_del(priv, BIT(port), addr, vid);
  743. }
  744. int qca8k_port_mirror_add(struct dsa_switch *ds, int port,
  745. struct dsa_mall_mirror_tc_entry *mirror,
  746. bool ingress, struct netlink_ext_ack *extack)
  747. {
  748. struct qca8k_priv *priv = ds->priv;
  749. int monitor_port, ret;
  750. u32 reg, val;
  751. /* Check for existent entry */
  752. if ((ingress ? priv->mirror_rx : priv->mirror_tx) & BIT(port))
  753. return -EEXIST;
  754. ret = regmap_read(priv->regmap, QCA8K_REG_GLOBAL_FW_CTRL0, &val);
  755. if (ret)
  756. return ret;
  757. /* QCA83xx can have only one port set to mirror mode.
  758. * Check that the correct port is requested and return error otherwise.
  759. * When no mirror port is set, the values is set to 0xF
  760. */
  761. monitor_port = FIELD_GET(QCA8K_GLOBAL_FW_CTRL0_MIRROR_PORT_NUM, val);
  762. if (monitor_port != 0xF && monitor_port != mirror->to_local_port)
  763. return -EEXIST;
  764. /* Set the monitor port */
  765. val = FIELD_PREP(QCA8K_GLOBAL_FW_CTRL0_MIRROR_PORT_NUM,
  766. mirror->to_local_port);
  767. ret = regmap_update_bits(priv->regmap, QCA8K_REG_GLOBAL_FW_CTRL0,
  768. QCA8K_GLOBAL_FW_CTRL0_MIRROR_PORT_NUM, val);
  769. if (ret)
  770. return ret;
  771. if (ingress) {
  772. reg = QCA8K_PORT_LOOKUP_CTRL(port);
  773. val = QCA8K_PORT_LOOKUP_ING_MIRROR_EN;
  774. } else {
  775. reg = QCA8K_REG_PORT_HOL_CTRL1(port);
  776. val = QCA8K_PORT_HOL_CTRL1_EG_MIRROR_EN;
  777. }
  778. ret = regmap_update_bits(priv->regmap, reg, val, val);
  779. if (ret)
  780. return ret;
  781. /* Track mirror port for tx and rx to decide when the
  782. * mirror port has to be disabled.
  783. */
  784. if (ingress)
  785. priv->mirror_rx |= BIT(port);
  786. else
  787. priv->mirror_tx |= BIT(port);
  788. return 0;
  789. }
  790. void qca8k_port_mirror_del(struct dsa_switch *ds, int port,
  791. struct dsa_mall_mirror_tc_entry *mirror)
  792. {
  793. struct qca8k_priv *priv = ds->priv;
  794. u32 reg, val;
  795. int ret;
  796. if (mirror->ingress) {
  797. reg = QCA8K_PORT_LOOKUP_CTRL(port);
  798. val = QCA8K_PORT_LOOKUP_ING_MIRROR_EN;
  799. } else {
  800. reg = QCA8K_REG_PORT_HOL_CTRL1(port);
  801. val = QCA8K_PORT_HOL_CTRL1_EG_MIRROR_EN;
  802. }
  803. ret = regmap_clear_bits(priv->regmap, reg, val);
  804. if (ret)
  805. goto err;
  806. if (mirror->ingress)
  807. priv->mirror_rx &= ~BIT(port);
  808. else
  809. priv->mirror_tx &= ~BIT(port);
  810. /* No port set to send packet to mirror port. Disable mirror port */
  811. if (!priv->mirror_rx && !priv->mirror_tx) {
  812. val = FIELD_PREP(QCA8K_GLOBAL_FW_CTRL0_MIRROR_PORT_NUM, 0xF);
  813. ret = regmap_update_bits(priv->regmap, QCA8K_REG_GLOBAL_FW_CTRL0,
  814. QCA8K_GLOBAL_FW_CTRL0_MIRROR_PORT_NUM, val);
  815. if (ret)
  816. goto err;
  817. }
  818. err:
  819. dev_err(priv->dev, "Failed to del mirror port from %d", port);
  820. }
  821. int qca8k_port_vlan_filtering(struct dsa_switch *ds, int port,
  822. bool vlan_filtering,
  823. struct netlink_ext_ack *extack)
  824. {
  825. struct qca8k_priv *priv = ds->priv;
  826. int ret;
  827. if (vlan_filtering) {
  828. ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
  829. QCA8K_PORT_LOOKUP_VLAN_MODE_MASK,
  830. QCA8K_PORT_LOOKUP_VLAN_MODE_SECURE);
  831. } else {
  832. ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
  833. QCA8K_PORT_LOOKUP_VLAN_MODE_MASK,
  834. QCA8K_PORT_LOOKUP_VLAN_MODE_NONE);
  835. }
  836. return ret;
  837. }
  838. int qca8k_port_vlan_add(struct dsa_switch *ds, int port,
  839. const struct switchdev_obj_port_vlan *vlan,
  840. struct netlink_ext_ack *extack)
  841. {
  842. bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
  843. bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
  844. struct qca8k_priv *priv = ds->priv;
  845. int ret;
  846. ret = qca8k_vlan_add(priv, port, vlan->vid, untagged);
  847. if (ret) {
  848. dev_err(priv->dev, "Failed to add VLAN to port %d (%d)", port, ret);
  849. return ret;
  850. }
  851. if (pvid) {
  852. ret = qca8k_rmw(priv, QCA8K_EGRESS_VLAN(port),
  853. QCA8K_EGREES_VLAN_PORT_MASK(port),
  854. QCA8K_EGREES_VLAN_PORT(port, vlan->vid));
  855. if (ret)
  856. return ret;
  857. ret = qca8k_write(priv, QCA8K_REG_PORT_VLAN_CTRL0(port),
  858. QCA8K_PORT_VLAN_CVID(vlan->vid) |
  859. QCA8K_PORT_VLAN_SVID(vlan->vid));
  860. }
  861. return ret;
  862. }
  863. int qca8k_port_vlan_del(struct dsa_switch *ds, int port,
  864. const struct switchdev_obj_port_vlan *vlan)
  865. {
  866. struct qca8k_priv *priv = ds->priv;
  867. int ret;
  868. ret = qca8k_vlan_del(priv, port, vlan->vid);
  869. if (ret)
  870. dev_err(priv->dev, "Failed to delete VLAN from port %d (%d)", port, ret);
  871. return ret;
  872. }
  873. static bool qca8k_lag_can_offload(struct dsa_switch *ds,
  874. struct dsa_lag lag,
  875. struct netdev_lag_upper_info *info,
  876. struct netlink_ext_ack *extack)
  877. {
  878. struct dsa_port *dp;
  879. int members = 0;
  880. if (!lag.id)
  881. return false;
  882. dsa_lag_foreach_port(dp, ds->dst, &lag)
  883. /* Includes the port joining the LAG */
  884. members++;
  885. if (members > QCA8K_NUM_PORTS_FOR_LAG) {
  886. NL_SET_ERR_MSG_MOD(extack,
  887. "Cannot offload more than 4 LAG ports");
  888. return false;
  889. }
  890. if (info->tx_type != NETDEV_LAG_TX_TYPE_HASH) {
  891. NL_SET_ERR_MSG_MOD(extack,
  892. "Can only offload LAG using hash TX type");
  893. return false;
  894. }
  895. if (info->hash_type != NETDEV_LAG_HASH_L2 &&
  896. info->hash_type != NETDEV_LAG_HASH_L23) {
  897. NL_SET_ERR_MSG_MOD(extack,
  898. "Can only offload L2 or L2+L3 TX hash");
  899. return false;
  900. }
  901. return true;
  902. }
  903. static int qca8k_lag_setup_hash(struct dsa_switch *ds,
  904. struct dsa_lag lag,
  905. struct netdev_lag_upper_info *info)
  906. {
  907. struct net_device *lag_dev = lag.dev;
  908. struct qca8k_priv *priv = ds->priv;
  909. bool unique_lag = true;
  910. unsigned int i;
  911. u32 hash = 0;
  912. switch (info->hash_type) {
  913. case NETDEV_LAG_HASH_L23:
  914. hash |= QCA8K_TRUNK_HASH_SIP_EN;
  915. hash |= QCA8K_TRUNK_HASH_DIP_EN;
  916. fallthrough;
  917. case NETDEV_LAG_HASH_L2:
  918. hash |= QCA8K_TRUNK_HASH_SA_EN;
  919. hash |= QCA8K_TRUNK_HASH_DA_EN;
  920. break;
  921. default: /* We should NEVER reach this */
  922. return -EOPNOTSUPP;
  923. }
  924. /* Check if we are the unique configured LAG */
  925. dsa_lags_foreach_id(i, ds->dst)
  926. if (i != lag.id && dsa_lag_by_id(ds->dst, i)) {
  927. unique_lag = false;
  928. break;
  929. }
  930. /* Hash Mode is global. Make sure the same Hash Mode
  931. * is set to all the 4 possible lag.
  932. * If we are the unique LAG we can set whatever hash
  933. * mode we want.
  934. * To change hash mode it's needed to remove all LAG
  935. * and change the mode with the latest.
  936. */
  937. if (unique_lag) {
  938. priv->lag_hash_mode = hash;
  939. } else if (priv->lag_hash_mode != hash) {
  940. netdev_err(lag_dev, "Error: Mismatched Hash Mode across different lag is not supported\n");
  941. return -EOPNOTSUPP;
  942. }
  943. return regmap_update_bits(priv->regmap, QCA8K_TRUNK_HASH_EN_CTRL,
  944. QCA8K_TRUNK_HASH_MASK, hash);
  945. }
  946. static int qca8k_lag_refresh_portmap(struct dsa_switch *ds, int port,
  947. struct dsa_lag lag, bool delete)
  948. {
  949. struct qca8k_priv *priv = ds->priv;
  950. int ret, id, i;
  951. u32 val;
  952. /* DSA LAG IDs are one-based, hardware is zero-based */
  953. id = lag.id - 1;
  954. /* Read current port member */
  955. ret = regmap_read(priv->regmap, QCA8K_REG_GOL_TRUNK_CTRL0, &val);
  956. if (ret)
  957. return ret;
  958. /* Shift val to the correct trunk */
  959. val >>= QCA8K_REG_GOL_TRUNK_SHIFT(id);
  960. val &= QCA8K_REG_GOL_TRUNK_MEMBER_MASK;
  961. if (delete)
  962. val &= ~BIT(port);
  963. else
  964. val |= BIT(port);
  965. /* Update port member. With empty portmap disable trunk */
  966. ret = regmap_update_bits(priv->regmap, QCA8K_REG_GOL_TRUNK_CTRL0,
  967. QCA8K_REG_GOL_TRUNK_MEMBER(id) |
  968. QCA8K_REG_GOL_TRUNK_EN(id),
  969. !val << QCA8K_REG_GOL_TRUNK_SHIFT(id) |
  970. val << QCA8K_REG_GOL_TRUNK_SHIFT(id));
  971. /* Search empty member if adding or port on deleting */
  972. for (i = 0; i < QCA8K_NUM_PORTS_FOR_LAG; i++) {
  973. ret = regmap_read(priv->regmap, QCA8K_REG_GOL_TRUNK_CTRL(id), &val);
  974. if (ret)
  975. return ret;
  976. val >>= QCA8K_REG_GOL_TRUNK_ID_MEM_ID_SHIFT(id, i);
  977. val &= QCA8K_REG_GOL_TRUNK_ID_MEM_ID_MASK;
  978. if (delete) {
  979. /* If port flagged to be disabled assume this member is
  980. * empty
  981. */
  982. if (val != QCA8K_REG_GOL_TRUNK_ID_MEM_ID_EN_MASK)
  983. continue;
  984. val &= QCA8K_REG_GOL_TRUNK_ID_MEM_ID_PORT_MASK;
  985. if (val != port)
  986. continue;
  987. } else {
  988. /* If port flagged to be enabled assume this member is
  989. * already set
  990. */
  991. if (val == QCA8K_REG_GOL_TRUNK_ID_MEM_ID_EN_MASK)
  992. continue;
  993. }
  994. /* We have found the member to add/remove */
  995. break;
  996. }
  997. /* Set port in the correct port mask or disable port if in delete mode */
  998. return regmap_update_bits(priv->regmap, QCA8K_REG_GOL_TRUNK_CTRL(id),
  999. QCA8K_REG_GOL_TRUNK_ID_MEM_ID_EN(id, i) |
  1000. QCA8K_REG_GOL_TRUNK_ID_MEM_ID_PORT(id, i),
  1001. !delete << QCA8K_REG_GOL_TRUNK_ID_MEM_ID_SHIFT(id, i) |
  1002. port << QCA8K_REG_GOL_TRUNK_ID_MEM_ID_SHIFT(id, i));
  1003. }
  1004. int qca8k_port_lag_join(struct dsa_switch *ds, int port, struct dsa_lag lag,
  1005. struct netdev_lag_upper_info *info,
  1006. struct netlink_ext_ack *extack)
  1007. {
  1008. int ret;
  1009. if (!qca8k_lag_can_offload(ds, lag, info, extack))
  1010. return -EOPNOTSUPP;
  1011. ret = qca8k_lag_setup_hash(ds, lag, info);
  1012. if (ret)
  1013. return ret;
  1014. return qca8k_lag_refresh_portmap(ds, port, lag, false);
  1015. }
  1016. int qca8k_port_lag_leave(struct dsa_switch *ds, int port,
  1017. struct dsa_lag lag)
  1018. {
  1019. return qca8k_lag_refresh_portmap(ds, port, lag, true);
  1020. }
  1021. int qca8k_read_switch_id(struct qca8k_priv *priv)
  1022. {
  1023. u32 val;
  1024. u8 id;
  1025. int ret;
  1026. if (!priv->info)
  1027. return -ENODEV;
  1028. ret = qca8k_read(priv, QCA8K_REG_MASK_CTRL, &val);
  1029. if (ret < 0)
  1030. return -ENODEV;
  1031. id = QCA8K_MASK_CTRL_DEVICE_ID(val);
  1032. if (id != priv->info->id) {
  1033. dev_err(priv->dev,
  1034. "Switch id detected %x but expected %x",
  1035. id, priv->info->id);
  1036. return -ENODEV;
  1037. }
  1038. priv->switch_id = id;
  1039. /* Save revision to communicate to the internal PHY driver */
  1040. priv->switch_revision = QCA8K_MASK_CTRL_REV_ID(val);
  1041. return 0;
  1042. }