bcmasp.c 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Broadcom STB ASP 2.0 Driver
  4. *
  5. * Copyright (c) 2023 Broadcom
  6. */
  7. #include <linux/etherdevice.h>
  8. #include <linux/if_vlan.h>
  9. #include <linux/init.h>
  10. #include <linux/interrupt.h>
  11. #include <linux/module.h>
  12. #include <linux/kernel.h>
  13. #include <linux/platform_device.h>
  14. #include <linux/of.h>
  15. #include <linux/of_address.h>
  16. #include <linux/of_platform.h>
  17. #include <linux/clk.h>
  18. #include "bcmasp.h"
  19. #include "bcmasp_intf_defs.h"
  20. static void _intr2_mask_clear(struct bcmasp_priv *priv, u32 mask)
  21. {
  22. intr2_core_wl(priv, mask, ASP_INTR2_MASK_CLEAR);
  23. priv->irq_mask &= ~mask;
  24. }
  25. static void _intr2_mask_set(struct bcmasp_priv *priv, u32 mask)
  26. {
  27. intr2_core_wl(priv, mask, ASP_INTR2_MASK_SET);
  28. priv->irq_mask |= mask;
  29. }
  30. void bcmasp_enable_phy_irq(struct bcmasp_intf *intf, int en)
  31. {
  32. struct bcmasp_priv *priv = intf->parent;
  33. /* Only supported with internal phys */
  34. if (!intf->internal_phy)
  35. return;
  36. if (en)
  37. _intr2_mask_clear(priv, ASP_INTR2_PHY_EVENT(intf->channel));
  38. else
  39. _intr2_mask_set(priv, ASP_INTR2_PHY_EVENT(intf->channel));
  40. }
  41. void bcmasp_enable_tx_irq(struct bcmasp_intf *intf, int en)
  42. {
  43. struct bcmasp_priv *priv = intf->parent;
  44. if (en)
  45. _intr2_mask_clear(priv, ASP_INTR2_TX_DESC(intf->channel));
  46. else
  47. _intr2_mask_set(priv, ASP_INTR2_TX_DESC(intf->channel));
  48. }
  49. EXPORT_SYMBOL_GPL(bcmasp_enable_tx_irq);
  50. void bcmasp_enable_rx_irq(struct bcmasp_intf *intf, int en)
  51. {
  52. struct bcmasp_priv *priv = intf->parent;
  53. if (en)
  54. _intr2_mask_clear(priv, ASP_INTR2_RX_ECH(intf->channel));
  55. else
  56. _intr2_mask_set(priv, ASP_INTR2_RX_ECH(intf->channel));
  57. }
  58. EXPORT_SYMBOL_GPL(bcmasp_enable_rx_irq);
  59. static void bcmasp_intr2_mask_set_all(struct bcmasp_priv *priv)
  60. {
  61. _intr2_mask_set(priv, 0xffffffff);
  62. priv->irq_mask = 0xffffffff;
  63. }
  64. static void bcmasp_intr2_clear_all(struct bcmasp_priv *priv)
  65. {
  66. intr2_core_wl(priv, 0xffffffff, ASP_INTR2_CLEAR);
  67. }
  68. static void bcmasp_intr2_handling(struct bcmasp_intf *intf, u32 status)
  69. {
  70. if (status & ASP_INTR2_RX_ECH(intf->channel)) {
  71. if (likely(napi_schedule_prep(&intf->rx_napi))) {
  72. bcmasp_enable_rx_irq(intf, 0);
  73. __napi_schedule_irqoff(&intf->rx_napi);
  74. }
  75. }
  76. if (status & ASP_INTR2_TX_DESC(intf->channel)) {
  77. if (likely(napi_schedule_prep(&intf->tx_napi))) {
  78. bcmasp_enable_tx_irq(intf, 0);
  79. __napi_schedule_irqoff(&intf->tx_napi);
  80. }
  81. }
  82. if (status & ASP_INTR2_PHY_EVENT(intf->channel))
  83. phy_mac_interrupt(intf->ndev->phydev);
  84. }
  85. static irqreturn_t bcmasp_isr(int irq, void *data)
  86. {
  87. struct bcmasp_priv *priv = data;
  88. struct bcmasp_intf *intf;
  89. u32 status;
  90. status = intr2_core_rl(priv, ASP_INTR2_STATUS) &
  91. ~intr2_core_rl(priv, ASP_INTR2_MASK_STATUS);
  92. intr2_core_wl(priv, status, ASP_INTR2_CLEAR);
  93. if (unlikely(status == 0)) {
  94. dev_warn(&priv->pdev->dev, "l2 spurious interrupt\n");
  95. return IRQ_NONE;
  96. }
  97. /* Handle intferfaces */
  98. list_for_each_entry(intf, &priv->intfs, list)
  99. bcmasp_intr2_handling(intf, status);
  100. return IRQ_HANDLED;
  101. }
  102. void bcmasp_flush_rx_port(struct bcmasp_intf *intf)
  103. {
  104. struct bcmasp_priv *priv = intf->parent;
  105. u32 mask;
  106. switch (intf->port) {
  107. case 0:
  108. mask = ASP_CTRL_UMAC0_FLUSH_MASK;
  109. break;
  110. case 1:
  111. mask = ASP_CTRL_UMAC1_FLUSH_MASK;
  112. break;
  113. case 2:
  114. mask = ASP_CTRL_SPB_FLUSH_MASK;
  115. break;
  116. default:
  117. /* Not valid port */
  118. return;
  119. }
  120. rx_ctrl_core_wl(priv, mask, priv->hw_info->rx_ctrl_flush);
  121. }
  122. static void bcmasp_netfilt_hw_en_wake(struct bcmasp_priv *priv,
  123. struct bcmasp_net_filter *nfilt)
  124. {
  125. rx_filter_core_wl(priv, ASP_RX_FILTER_NET_OFFSET_L3_1(64),
  126. ASP_RX_FILTER_NET_OFFSET(nfilt->hw_index));
  127. rx_filter_core_wl(priv, ASP_RX_FILTER_NET_OFFSET_L2(32) |
  128. ASP_RX_FILTER_NET_OFFSET_L3_0(32) |
  129. ASP_RX_FILTER_NET_OFFSET_L3_1(96) |
  130. ASP_RX_FILTER_NET_OFFSET_L4(32),
  131. ASP_RX_FILTER_NET_OFFSET(nfilt->hw_index + 1));
  132. rx_filter_core_wl(priv, ASP_RX_FILTER_NET_CFG_CH(nfilt->port + 8) |
  133. ASP_RX_FILTER_NET_CFG_EN |
  134. ASP_RX_FILTER_NET_CFG_L2_EN |
  135. ASP_RX_FILTER_NET_CFG_L3_EN |
  136. ASP_RX_FILTER_NET_CFG_L4_EN |
  137. ASP_RX_FILTER_NET_CFG_L3_FRM(2) |
  138. ASP_RX_FILTER_NET_CFG_L4_FRM(2) |
  139. ASP_RX_FILTER_NET_CFG_UMC(nfilt->port),
  140. ASP_RX_FILTER_NET_CFG(nfilt->hw_index));
  141. rx_filter_core_wl(priv, ASP_RX_FILTER_NET_CFG_CH(nfilt->port + 8) |
  142. ASP_RX_FILTER_NET_CFG_EN |
  143. ASP_RX_FILTER_NET_CFG_L2_EN |
  144. ASP_RX_FILTER_NET_CFG_L3_EN |
  145. ASP_RX_FILTER_NET_CFG_L4_EN |
  146. ASP_RX_FILTER_NET_CFG_L3_FRM(2) |
  147. ASP_RX_FILTER_NET_CFG_L4_FRM(2) |
  148. ASP_RX_FILTER_NET_CFG_UMC(nfilt->port),
  149. ASP_RX_FILTER_NET_CFG(nfilt->hw_index + 1));
  150. }
  151. #define MAX_WAKE_FILTER_SIZE 256
  152. enum asp_netfilt_reg_type {
  153. ASP_NETFILT_MATCH = 0,
  154. ASP_NETFILT_MASK,
  155. ASP_NETFILT_MAX
  156. };
  157. static int bcmasp_netfilt_get_reg_offset(struct bcmasp_priv *priv,
  158. struct bcmasp_net_filter *nfilt,
  159. enum asp_netfilt_reg_type reg_type,
  160. u32 offset)
  161. {
  162. u32 block_index, filter_sel;
  163. if (offset < 32) {
  164. block_index = ASP_RX_FILTER_NET_L2;
  165. filter_sel = nfilt->hw_index;
  166. } else if (offset < 64) {
  167. block_index = ASP_RX_FILTER_NET_L2;
  168. filter_sel = nfilt->hw_index + 1;
  169. } else if (offset < 96) {
  170. block_index = ASP_RX_FILTER_NET_L3_0;
  171. filter_sel = nfilt->hw_index;
  172. } else if (offset < 128) {
  173. block_index = ASP_RX_FILTER_NET_L3_0;
  174. filter_sel = nfilt->hw_index + 1;
  175. } else if (offset < 160) {
  176. block_index = ASP_RX_FILTER_NET_L3_1;
  177. filter_sel = nfilt->hw_index;
  178. } else if (offset < 192) {
  179. block_index = ASP_RX_FILTER_NET_L3_1;
  180. filter_sel = nfilt->hw_index + 1;
  181. } else if (offset < 224) {
  182. block_index = ASP_RX_FILTER_NET_L4;
  183. filter_sel = nfilt->hw_index;
  184. } else if (offset < 256) {
  185. block_index = ASP_RX_FILTER_NET_L4;
  186. filter_sel = nfilt->hw_index + 1;
  187. } else {
  188. return -EINVAL;
  189. }
  190. switch (reg_type) {
  191. case ASP_NETFILT_MATCH:
  192. return ASP_RX_FILTER_NET_PAT(filter_sel, block_index,
  193. (offset % 32));
  194. case ASP_NETFILT_MASK:
  195. return ASP_RX_FILTER_NET_MASK(filter_sel, block_index,
  196. (offset % 32));
  197. default:
  198. return -EINVAL;
  199. }
  200. }
  201. static void bcmasp_netfilt_wr(struct bcmasp_priv *priv,
  202. struct bcmasp_net_filter *nfilt,
  203. enum asp_netfilt_reg_type reg_type,
  204. u32 val, u32 offset)
  205. {
  206. int reg_offset;
  207. /* HW only accepts 4 byte aligned writes */
  208. if (!IS_ALIGNED(offset, 4) || offset > MAX_WAKE_FILTER_SIZE)
  209. return;
  210. reg_offset = bcmasp_netfilt_get_reg_offset(priv, nfilt, reg_type,
  211. offset);
  212. rx_filter_core_wl(priv, val, reg_offset);
  213. }
  214. static u32 bcmasp_netfilt_rd(struct bcmasp_priv *priv,
  215. struct bcmasp_net_filter *nfilt,
  216. enum asp_netfilt_reg_type reg_type,
  217. u32 offset)
  218. {
  219. int reg_offset;
  220. /* HW only accepts 4 byte aligned writes */
  221. if (!IS_ALIGNED(offset, 4) || offset > MAX_WAKE_FILTER_SIZE)
  222. return 0;
  223. reg_offset = bcmasp_netfilt_get_reg_offset(priv, nfilt, reg_type,
  224. offset);
  225. return rx_filter_core_rl(priv, reg_offset);
  226. }
  227. static int bcmasp_netfilt_wr_m_wake(struct bcmasp_priv *priv,
  228. struct bcmasp_net_filter *nfilt,
  229. u32 offset, void *match, void *mask,
  230. size_t size)
  231. {
  232. u32 shift, mask_val = 0, match_val = 0;
  233. bool first_byte = true;
  234. if ((offset + size) > MAX_WAKE_FILTER_SIZE)
  235. return -EINVAL;
  236. while (size--) {
  237. /* The HW only accepts 4 byte aligned writes, so if we
  238. * begin unaligned or if remaining bytes less than 4,
  239. * we need to read then write to avoid losing current
  240. * register state
  241. */
  242. if (first_byte && (!IS_ALIGNED(offset, 4) || size < 3)) {
  243. match_val = bcmasp_netfilt_rd(priv, nfilt,
  244. ASP_NETFILT_MATCH,
  245. ALIGN_DOWN(offset, 4));
  246. mask_val = bcmasp_netfilt_rd(priv, nfilt,
  247. ASP_NETFILT_MASK,
  248. ALIGN_DOWN(offset, 4));
  249. }
  250. shift = (3 - (offset % 4)) * 8;
  251. match_val &= ~GENMASK(shift + 7, shift);
  252. mask_val &= ~GENMASK(shift + 7, shift);
  253. match_val |= (u32)(*((u8 *)match) << shift);
  254. mask_val |= (u32)(*((u8 *)mask) << shift);
  255. /* If last byte or last byte of word, write to reg */
  256. if (!size || ((offset % 4) == 3)) {
  257. bcmasp_netfilt_wr(priv, nfilt, ASP_NETFILT_MATCH,
  258. match_val, ALIGN_DOWN(offset, 4));
  259. bcmasp_netfilt_wr(priv, nfilt, ASP_NETFILT_MASK,
  260. mask_val, ALIGN_DOWN(offset, 4));
  261. first_byte = true;
  262. } else {
  263. first_byte = false;
  264. }
  265. offset++;
  266. match++;
  267. mask++;
  268. }
  269. return 0;
  270. }
  271. static void bcmasp_netfilt_reset_hw(struct bcmasp_priv *priv,
  272. struct bcmasp_net_filter *nfilt)
  273. {
  274. int i;
  275. for (i = 0; i < MAX_WAKE_FILTER_SIZE; i += 4) {
  276. bcmasp_netfilt_wr(priv, nfilt, ASP_NETFILT_MATCH, 0, i);
  277. bcmasp_netfilt_wr(priv, nfilt, ASP_NETFILT_MASK, 0, i);
  278. }
  279. }
  280. static void bcmasp_netfilt_tcpip4_wr(struct bcmasp_priv *priv,
  281. struct bcmasp_net_filter *nfilt,
  282. struct ethtool_tcpip4_spec *match,
  283. struct ethtool_tcpip4_spec *mask,
  284. u32 offset)
  285. {
  286. __be16 val_16, mask_16;
  287. val_16 = htons(ETH_P_IP);
  288. mask_16 = htons(0xFFFF);
  289. bcmasp_netfilt_wr_m_wake(priv, nfilt, (ETH_ALEN * 2) + offset,
  290. &val_16, &mask_16, sizeof(val_16));
  291. bcmasp_netfilt_wr_m_wake(priv, nfilt, ETH_HLEN + offset + 1,
  292. &match->tos, &mask->tos,
  293. sizeof(match->tos));
  294. bcmasp_netfilt_wr_m_wake(priv, nfilt, ETH_HLEN + offset + 12,
  295. &match->ip4src, &mask->ip4src,
  296. sizeof(match->ip4src));
  297. bcmasp_netfilt_wr_m_wake(priv, nfilt, ETH_HLEN + offset + 16,
  298. &match->ip4dst, &mask->ip4dst,
  299. sizeof(match->ip4dst));
  300. bcmasp_netfilt_wr_m_wake(priv, nfilt, ETH_HLEN + offset + 20,
  301. &match->psrc, &mask->psrc,
  302. sizeof(match->psrc));
  303. bcmasp_netfilt_wr_m_wake(priv, nfilt, ETH_HLEN + offset + 22,
  304. &match->pdst, &mask->pdst,
  305. sizeof(match->pdst));
  306. }
  307. static void bcmasp_netfilt_tcpip6_wr(struct bcmasp_priv *priv,
  308. struct bcmasp_net_filter *nfilt,
  309. struct ethtool_tcpip6_spec *match,
  310. struct ethtool_tcpip6_spec *mask,
  311. u32 offset)
  312. {
  313. __be16 val_16, mask_16;
  314. val_16 = htons(ETH_P_IPV6);
  315. mask_16 = htons(0xFFFF);
  316. bcmasp_netfilt_wr_m_wake(priv, nfilt, (ETH_ALEN * 2) + offset,
  317. &val_16, &mask_16, sizeof(val_16));
  318. val_16 = htons(match->tclass << 4);
  319. mask_16 = htons(mask->tclass << 4);
  320. bcmasp_netfilt_wr_m_wake(priv, nfilt, ETH_HLEN + offset,
  321. &val_16, &mask_16, sizeof(val_16));
  322. bcmasp_netfilt_wr_m_wake(priv, nfilt, ETH_HLEN + offset + 8,
  323. &match->ip6src, &mask->ip6src,
  324. sizeof(match->ip6src));
  325. bcmasp_netfilt_wr_m_wake(priv, nfilt, ETH_HLEN + offset + 24,
  326. &match->ip6dst, &mask->ip6dst,
  327. sizeof(match->ip6dst));
  328. bcmasp_netfilt_wr_m_wake(priv, nfilt, ETH_HLEN + offset + 40,
  329. &match->psrc, &mask->psrc,
  330. sizeof(match->psrc));
  331. bcmasp_netfilt_wr_m_wake(priv, nfilt, ETH_HLEN + offset + 42,
  332. &match->pdst, &mask->pdst,
  333. sizeof(match->pdst));
  334. }
  335. static int bcmasp_netfilt_wr_to_hw(struct bcmasp_priv *priv,
  336. struct bcmasp_net_filter *nfilt)
  337. {
  338. struct ethtool_rx_flow_spec *fs = &nfilt->fs;
  339. unsigned int offset = 0;
  340. __be16 val_16, mask_16;
  341. u8 val_8, mask_8;
  342. /* Currently only supports wake filters */
  343. if (!nfilt->wake_filter)
  344. return -EINVAL;
  345. bcmasp_netfilt_reset_hw(priv, nfilt);
  346. if (fs->flow_type & FLOW_MAC_EXT) {
  347. bcmasp_netfilt_wr_m_wake(priv, nfilt, 0, &fs->h_ext.h_dest,
  348. &fs->m_ext.h_dest,
  349. sizeof(fs->h_ext.h_dest));
  350. }
  351. if ((fs->flow_type & FLOW_EXT) &&
  352. (fs->m_ext.vlan_etype || fs->m_ext.vlan_tci)) {
  353. bcmasp_netfilt_wr_m_wake(priv, nfilt, (ETH_ALEN * 2),
  354. &fs->h_ext.vlan_etype,
  355. &fs->m_ext.vlan_etype,
  356. sizeof(fs->h_ext.vlan_etype));
  357. bcmasp_netfilt_wr_m_wake(priv, nfilt, ((ETH_ALEN * 2) + 2),
  358. &fs->h_ext.vlan_tci,
  359. &fs->m_ext.vlan_tci,
  360. sizeof(fs->h_ext.vlan_tci));
  361. offset += VLAN_HLEN;
  362. }
  363. switch (fs->flow_type & ~(FLOW_EXT | FLOW_MAC_EXT)) {
  364. case ETHER_FLOW:
  365. bcmasp_netfilt_wr_m_wake(priv, nfilt, 0,
  366. &fs->h_u.ether_spec.h_dest,
  367. &fs->m_u.ether_spec.h_dest,
  368. sizeof(fs->h_u.ether_spec.h_dest));
  369. bcmasp_netfilt_wr_m_wake(priv, nfilt, ETH_ALEN,
  370. &fs->h_u.ether_spec.h_source,
  371. &fs->m_u.ether_spec.h_source,
  372. sizeof(fs->h_u.ether_spec.h_source));
  373. bcmasp_netfilt_wr_m_wake(priv, nfilt, (ETH_ALEN * 2) + offset,
  374. &fs->h_u.ether_spec.h_proto,
  375. &fs->m_u.ether_spec.h_proto,
  376. sizeof(fs->h_u.ether_spec.h_proto));
  377. break;
  378. case IP_USER_FLOW:
  379. val_16 = htons(ETH_P_IP);
  380. mask_16 = htons(0xFFFF);
  381. bcmasp_netfilt_wr_m_wake(priv, nfilt, (ETH_ALEN * 2) + offset,
  382. &val_16, &mask_16, sizeof(val_16));
  383. bcmasp_netfilt_wr_m_wake(priv, nfilt, ETH_HLEN + offset + 1,
  384. &fs->h_u.usr_ip4_spec.tos,
  385. &fs->m_u.usr_ip4_spec.tos,
  386. sizeof(fs->h_u.usr_ip4_spec.tos));
  387. bcmasp_netfilt_wr_m_wake(priv, nfilt, ETH_HLEN + offset + 9,
  388. &fs->h_u.usr_ip4_spec.proto,
  389. &fs->m_u.usr_ip4_spec.proto,
  390. sizeof(fs->h_u.usr_ip4_spec.proto));
  391. bcmasp_netfilt_wr_m_wake(priv, nfilt, ETH_HLEN + offset + 12,
  392. &fs->h_u.usr_ip4_spec.ip4src,
  393. &fs->m_u.usr_ip4_spec.ip4src,
  394. sizeof(fs->h_u.usr_ip4_spec.ip4src));
  395. bcmasp_netfilt_wr_m_wake(priv, nfilt, ETH_HLEN + offset + 16,
  396. &fs->h_u.usr_ip4_spec.ip4dst,
  397. &fs->m_u.usr_ip4_spec.ip4dst,
  398. sizeof(fs->h_u.usr_ip4_spec.ip4dst));
  399. if (!fs->m_u.usr_ip4_spec.l4_4_bytes)
  400. break;
  401. /* Only supports 20 byte IPv4 header */
  402. val_8 = 0x45;
  403. mask_8 = 0xFF;
  404. bcmasp_netfilt_wr_m_wake(priv, nfilt, ETH_HLEN + offset,
  405. &val_8, &mask_8, sizeof(val_8));
  406. bcmasp_netfilt_wr_m_wake(priv, nfilt,
  407. ETH_HLEN + 20 + offset,
  408. &fs->h_u.usr_ip4_spec.l4_4_bytes,
  409. &fs->m_u.usr_ip4_spec.l4_4_bytes,
  410. sizeof(fs->h_u.usr_ip4_spec.l4_4_bytes)
  411. );
  412. break;
  413. case TCP_V4_FLOW:
  414. val_8 = IPPROTO_TCP;
  415. mask_8 = 0xFF;
  416. bcmasp_netfilt_tcpip4_wr(priv, nfilt, &fs->h_u.tcp_ip4_spec,
  417. &fs->m_u.tcp_ip4_spec, offset);
  418. bcmasp_netfilt_wr_m_wake(priv, nfilt, ETH_HLEN + offset + 9,
  419. &val_8, &mask_8, sizeof(val_8));
  420. break;
  421. case UDP_V4_FLOW:
  422. val_8 = IPPROTO_UDP;
  423. mask_8 = 0xFF;
  424. bcmasp_netfilt_tcpip4_wr(priv, nfilt, &fs->h_u.udp_ip4_spec,
  425. &fs->m_u.udp_ip4_spec, offset);
  426. bcmasp_netfilt_wr_m_wake(priv, nfilt, ETH_HLEN + offset + 9,
  427. &val_8, &mask_8, sizeof(val_8));
  428. break;
  429. case TCP_V6_FLOW:
  430. val_8 = IPPROTO_TCP;
  431. mask_8 = 0xFF;
  432. bcmasp_netfilt_tcpip6_wr(priv, nfilt, &fs->h_u.tcp_ip6_spec,
  433. &fs->m_u.tcp_ip6_spec, offset);
  434. bcmasp_netfilt_wr_m_wake(priv, nfilt, ETH_HLEN + offset + 6,
  435. &val_8, &mask_8, sizeof(val_8));
  436. break;
  437. case UDP_V6_FLOW:
  438. val_8 = IPPROTO_UDP;
  439. mask_8 = 0xFF;
  440. bcmasp_netfilt_tcpip6_wr(priv, nfilt, &fs->h_u.udp_ip6_spec,
  441. &fs->m_u.udp_ip6_spec, offset);
  442. bcmasp_netfilt_wr_m_wake(priv, nfilt, ETH_HLEN + offset + 6,
  443. &val_8, &mask_8, sizeof(val_8));
  444. break;
  445. }
  446. bcmasp_netfilt_hw_en_wake(priv, nfilt);
  447. return 0;
  448. }
  449. void bcmasp_netfilt_suspend(struct bcmasp_intf *intf)
  450. {
  451. struct bcmasp_priv *priv = intf->parent;
  452. bool write = false;
  453. int ret, i;
  454. /* Write all filters to HW */
  455. for (i = 0; i < NUM_NET_FILTERS; i++) {
  456. /* If the filter does not match the port, skip programming. */
  457. if (!priv->net_filters[i].claimed ||
  458. priv->net_filters[i].port != intf->port)
  459. continue;
  460. if (i > 0 && (i % 2) &&
  461. priv->net_filters[i].wake_filter &&
  462. priv->net_filters[i - 1].wake_filter)
  463. continue;
  464. ret = bcmasp_netfilt_wr_to_hw(priv, &priv->net_filters[i]);
  465. if (!ret)
  466. write = true;
  467. }
  468. /* Successfully programmed at least one wake filter
  469. * so enable top level wake config
  470. */
  471. if (write)
  472. rx_filter_core_wl(priv, (ASP_RX_FILTER_OPUT_EN |
  473. ASP_RX_FILTER_LNR_MD |
  474. ASP_RX_FILTER_GEN_WK_EN |
  475. ASP_RX_FILTER_NT_FLT_EN),
  476. ASP_RX_FILTER_BLK_CTRL);
  477. }
  478. int bcmasp_netfilt_get_all_active(struct bcmasp_intf *intf, u32 *rule_locs,
  479. u32 *rule_cnt)
  480. {
  481. struct bcmasp_priv *priv = intf->parent;
  482. int j = 0, i;
  483. for (i = 0; i < NUM_NET_FILTERS; i++) {
  484. if (!priv->net_filters[i].claimed ||
  485. priv->net_filters[i].port != intf->port)
  486. continue;
  487. if (i > 0 && (i % 2) &&
  488. priv->net_filters[i].wake_filter &&
  489. priv->net_filters[i - 1].wake_filter)
  490. continue;
  491. if (j == *rule_cnt)
  492. return -EMSGSIZE;
  493. rule_locs[j++] = priv->net_filters[i].fs.location;
  494. }
  495. *rule_cnt = j;
  496. return 0;
  497. }
  498. int bcmasp_netfilt_get_active(struct bcmasp_intf *intf)
  499. {
  500. struct bcmasp_priv *priv = intf->parent;
  501. int cnt = 0, i;
  502. for (i = 0; i < NUM_NET_FILTERS; i++) {
  503. if (!priv->net_filters[i].claimed ||
  504. priv->net_filters[i].port != intf->port)
  505. continue;
  506. /* Skip over a wake filter pair */
  507. if (i > 0 && (i % 2) &&
  508. priv->net_filters[i].wake_filter &&
  509. priv->net_filters[i - 1].wake_filter)
  510. continue;
  511. cnt++;
  512. }
  513. return cnt;
  514. }
  515. bool bcmasp_netfilt_check_dup(struct bcmasp_intf *intf,
  516. struct ethtool_rx_flow_spec *fs)
  517. {
  518. struct bcmasp_priv *priv = intf->parent;
  519. struct ethtool_rx_flow_spec *cur;
  520. size_t fs_size = 0;
  521. int i;
  522. for (i = 0; i < NUM_NET_FILTERS; i++) {
  523. if (!priv->net_filters[i].claimed ||
  524. priv->net_filters[i].port != intf->port)
  525. continue;
  526. cur = &priv->net_filters[i].fs;
  527. if (cur->flow_type != fs->flow_type ||
  528. cur->ring_cookie != fs->ring_cookie)
  529. continue;
  530. switch (fs->flow_type & ~(FLOW_EXT | FLOW_MAC_EXT)) {
  531. case ETHER_FLOW:
  532. fs_size = sizeof(struct ethhdr);
  533. break;
  534. case IP_USER_FLOW:
  535. fs_size = sizeof(struct ethtool_usrip4_spec);
  536. break;
  537. case TCP_V6_FLOW:
  538. case UDP_V6_FLOW:
  539. fs_size = sizeof(struct ethtool_tcpip6_spec);
  540. break;
  541. case TCP_V4_FLOW:
  542. case UDP_V4_FLOW:
  543. fs_size = sizeof(struct ethtool_tcpip4_spec);
  544. break;
  545. default:
  546. continue;
  547. }
  548. if (memcmp(&cur->h_u, &fs->h_u, fs_size) ||
  549. memcmp(&cur->m_u, &fs->m_u, fs_size))
  550. continue;
  551. if (cur->flow_type & FLOW_EXT) {
  552. if (cur->h_ext.vlan_etype != fs->h_ext.vlan_etype ||
  553. cur->m_ext.vlan_etype != fs->m_ext.vlan_etype ||
  554. cur->h_ext.vlan_tci != fs->h_ext.vlan_tci ||
  555. cur->m_ext.vlan_tci != fs->m_ext.vlan_tci ||
  556. cur->h_ext.data[0] != fs->h_ext.data[0])
  557. continue;
  558. }
  559. if (cur->flow_type & FLOW_MAC_EXT) {
  560. if (memcmp(&cur->h_ext.h_dest,
  561. &fs->h_ext.h_dest, ETH_ALEN) ||
  562. memcmp(&cur->m_ext.h_dest,
  563. &fs->m_ext.h_dest, ETH_ALEN))
  564. continue;
  565. }
  566. return true;
  567. }
  568. return false;
  569. }
  570. /* If no network filter found, return open filter.
  571. * If no more open filters return NULL
  572. */
  573. struct bcmasp_net_filter *bcmasp_netfilt_get_init(struct bcmasp_intf *intf,
  574. u32 loc, bool wake_filter,
  575. bool init)
  576. {
  577. struct bcmasp_net_filter *nfilter = NULL;
  578. struct bcmasp_priv *priv = intf->parent;
  579. int i, open_index = -1;
  580. /* Check whether we exceed the filter table capacity */
  581. if (loc != RX_CLS_LOC_ANY && loc >= NUM_NET_FILTERS)
  582. return ERR_PTR(-EINVAL);
  583. /* If the filter location is busy (already claimed) and we are initializing
  584. * the filter (insertion), return a busy error code.
  585. */
  586. if (loc != RX_CLS_LOC_ANY && init && priv->net_filters[loc].claimed)
  587. return ERR_PTR(-EBUSY);
  588. /* We need two filters for wake-up, so we cannot use an odd filter */
  589. if (wake_filter && loc != RX_CLS_LOC_ANY && (loc % 2))
  590. return ERR_PTR(-EINVAL);
  591. /* Initialize the loop index based on the desired location or from 0 */
  592. i = loc == RX_CLS_LOC_ANY ? 0 : loc;
  593. for ( ; i < NUM_NET_FILTERS; i++) {
  594. /* Found matching network filter */
  595. if (!init &&
  596. priv->net_filters[i].claimed &&
  597. priv->net_filters[i].hw_index == i &&
  598. priv->net_filters[i].port == intf->port)
  599. return &priv->net_filters[i];
  600. /* If we don't need a new filter or new filter already found */
  601. if (!init || open_index >= 0)
  602. continue;
  603. /* Wake filter conslidates two filters to cover more bytes
  604. * Wake filter is open if...
  605. * 1. It is an even filter
  606. * 2. The current and next filter is not claimed
  607. */
  608. if (wake_filter && !(i % 2) && !priv->net_filters[i].claimed &&
  609. !priv->net_filters[i + 1].claimed)
  610. open_index = i;
  611. else if (!priv->net_filters[i].claimed)
  612. open_index = i;
  613. }
  614. if (open_index >= 0) {
  615. nfilter = &priv->net_filters[open_index];
  616. nfilter->claimed = true;
  617. nfilter->port = intf->port;
  618. nfilter->hw_index = open_index;
  619. }
  620. if (wake_filter && open_index >= 0) {
  621. /* Claim next filter */
  622. priv->net_filters[open_index + 1].claimed = true;
  623. priv->net_filters[open_index + 1].wake_filter = true;
  624. nfilter->wake_filter = true;
  625. }
  626. return nfilter ? nfilter : ERR_PTR(-EINVAL);
  627. }
  628. void bcmasp_netfilt_release(struct bcmasp_intf *intf,
  629. struct bcmasp_net_filter *nfilt)
  630. {
  631. struct bcmasp_priv *priv = intf->parent;
  632. if (nfilt->wake_filter) {
  633. memset(&priv->net_filters[nfilt->hw_index + 1], 0,
  634. sizeof(struct bcmasp_net_filter));
  635. }
  636. memset(nfilt, 0, sizeof(struct bcmasp_net_filter));
  637. }
  638. static void bcmasp_addr_to_uint(unsigned char *addr, u32 *high, u32 *low)
  639. {
  640. *high = (u32)(addr[0] << 8 | addr[1]);
  641. *low = (u32)(addr[2] << 24 | addr[3] << 16 | addr[4] << 8 |
  642. addr[5]);
  643. }
  644. static void bcmasp_set_mda_filter(struct bcmasp_intf *intf,
  645. const unsigned char *addr,
  646. unsigned char *mask,
  647. unsigned int i)
  648. {
  649. struct bcmasp_priv *priv = intf->parent;
  650. u32 addr_h, addr_l, mask_h, mask_l;
  651. /* Set local copy */
  652. ether_addr_copy(priv->mda_filters[i].mask, mask);
  653. ether_addr_copy(priv->mda_filters[i].addr, addr);
  654. /* Write to HW */
  655. bcmasp_addr_to_uint(priv->mda_filters[i].mask, &mask_h, &mask_l);
  656. bcmasp_addr_to_uint(priv->mda_filters[i].addr, &addr_h, &addr_l);
  657. rx_filter_core_wl(priv, addr_h, ASP_RX_FILTER_MDA_PAT_H(i));
  658. rx_filter_core_wl(priv, addr_l, ASP_RX_FILTER_MDA_PAT_L(i));
  659. rx_filter_core_wl(priv, mask_h, ASP_RX_FILTER_MDA_MSK_H(i));
  660. rx_filter_core_wl(priv, mask_l, ASP_RX_FILTER_MDA_MSK_L(i));
  661. }
  662. static void bcmasp_en_mda_filter(struct bcmasp_intf *intf, bool en,
  663. unsigned int i)
  664. {
  665. struct bcmasp_priv *priv = intf->parent;
  666. if (priv->mda_filters[i].en == en)
  667. return;
  668. priv->mda_filters[i].en = en;
  669. priv->mda_filters[i].port = intf->port;
  670. rx_filter_core_wl(priv, ((intf->channel + 8) |
  671. (en << ASP_RX_FILTER_MDA_CFG_EN_SHIFT) |
  672. ASP_RX_FILTER_MDA_CFG_UMC_SEL(intf->port)),
  673. ASP_RX_FILTER_MDA_CFG(i));
  674. }
  675. /* There are 32 MDA filters shared between all ports, we reserve 4 filters per
  676. * port for the following.
  677. * - Promisc: Filter to allow all packets when promisc is enabled
  678. * - All Multicast
  679. * - Broadcast
  680. * - Own address
  681. *
  682. * The reserved filters are identified as so.
  683. * - Promisc: (index * 4) + 0
  684. * - All Multicast: (index * 4) + 1
  685. * - Broadcast: (index * 4) + 2
  686. * - Own address: (index * 4) + 3
  687. */
  688. enum asp_rx_filter_id {
  689. ASP_RX_FILTER_MDA_PROMISC = 0,
  690. ASP_RX_FILTER_MDA_ALLMULTI,
  691. ASP_RX_FILTER_MDA_BROADCAST,
  692. ASP_RX_FILTER_MDA_OWN_ADDR,
  693. ASP_RX_FILTER_MDA_RES_MAX,
  694. };
  695. #define ASP_RX_FILT_MDA(intf, name) (((intf)->index * \
  696. ASP_RX_FILTER_MDA_RES_MAX) \
  697. + ASP_RX_FILTER_MDA_##name)
  698. static int bcmasp_total_res_mda_cnt(struct bcmasp_priv *priv)
  699. {
  700. return list_count_nodes(&priv->intfs) * ASP_RX_FILTER_MDA_RES_MAX;
  701. }
  702. void bcmasp_set_promisc(struct bcmasp_intf *intf, bool en)
  703. {
  704. unsigned int i = ASP_RX_FILT_MDA(intf, PROMISC);
  705. unsigned char promisc[ETH_ALEN];
  706. eth_zero_addr(promisc);
  707. /* Set mask to 00:00:00:00:00:00 to match all packets */
  708. bcmasp_set_mda_filter(intf, promisc, promisc, i);
  709. bcmasp_en_mda_filter(intf, en, i);
  710. }
  711. void bcmasp_set_allmulti(struct bcmasp_intf *intf, bool en)
  712. {
  713. unsigned char allmulti[] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00};
  714. unsigned int i = ASP_RX_FILT_MDA(intf, ALLMULTI);
  715. /* Set mask to 01:00:00:00:00:00 to match all multicast */
  716. bcmasp_set_mda_filter(intf, allmulti, allmulti, i);
  717. bcmasp_en_mda_filter(intf, en, i);
  718. }
  719. void bcmasp_set_broad(struct bcmasp_intf *intf, bool en)
  720. {
  721. unsigned int i = ASP_RX_FILT_MDA(intf, BROADCAST);
  722. unsigned char addr[ETH_ALEN];
  723. eth_broadcast_addr(addr);
  724. bcmasp_set_mda_filter(intf, addr, addr, i);
  725. bcmasp_en_mda_filter(intf, en, i);
  726. }
  727. void bcmasp_set_oaddr(struct bcmasp_intf *intf, const unsigned char *addr,
  728. bool en)
  729. {
  730. unsigned char mask[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
  731. unsigned int i = ASP_RX_FILT_MDA(intf, OWN_ADDR);
  732. bcmasp_set_mda_filter(intf, addr, mask, i);
  733. bcmasp_en_mda_filter(intf, en, i);
  734. }
  735. void bcmasp_disable_all_filters(struct bcmasp_intf *intf)
  736. {
  737. struct bcmasp_priv *priv = intf->parent;
  738. unsigned int i;
  739. int res_count;
  740. res_count = bcmasp_total_res_mda_cnt(intf->parent);
  741. /* Disable all filters held by this port */
  742. for (i = res_count; i < NUM_MDA_FILTERS; i++) {
  743. if (priv->mda_filters[i].en &&
  744. priv->mda_filters[i].port == intf->port)
  745. bcmasp_en_mda_filter(intf, 0, i);
  746. }
  747. }
  748. static int bcmasp_combine_set_filter(struct bcmasp_intf *intf,
  749. unsigned char *addr, unsigned char *mask,
  750. int i)
  751. {
  752. struct bcmasp_priv *priv = intf->parent;
  753. u64 addr1, addr2, mask1, mask2, mask3;
  754. /* Switch to u64 to help with the calculations */
  755. addr1 = ether_addr_to_u64(priv->mda_filters[i].addr);
  756. mask1 = ether_addr_to_u64(priv->mda_filters[i].mask);
  757. addr2 = ether_addr_to_u64(addr);
  758. mask2 = ether_addr_to_u64(mask);
  759. /* Check if one filter resides within the other */
  760. mask3 = mask1 & mask2;
  761. if (mask3 == mask1 && ((addr1 & mask1) == (addr2 & mask1))) {
  762. /* Filter 2 resides within filter 1, so everything is good */
  763. return 0;
  764. } else if (mask3 == mask2 && ((addr1 & mask2) == (addr2 & mask2))) {
  765. /* Filter 1 resides within filter 2, so swap filters */
  766. bcmasp_set_mda_filter(intf, addr, mask, i);
  767. return 0;
  768. }
  769. /* Unable to combine */
  770. return -EINVAL;
  771. }
  772. int bcmasp_set_en_mda_filter(struct bcmasp_intf *intf, unsigned char *addr,
  773. unsigned char *mask)
  774. {
  775. struct bcmasp_priv *priv = intf->parent;
  776. int ret, res_count;
  777. unsigned int i;
  778. res_count = bcmasp_total_res_mda_cnt(intf->parent);
  779. for (i = res_count; i < NUM_MDA_FILTERS; i++) {
  780. /* If filter not enabled or belongs to another port skip */
  781. if (!priv->mda_filters[i].en ||
  782. priv->mda_filters[i].port != intf->port)
  783. continue;
  784. /* Attempt to combine filters */
  785. ret = bcmasp_combine_set_filter(intf, addr, mask, i);
  786. if (!ret) {
  787. intf->mib.filters_combine_cnt++;
  788. return 0;
  789. }
  790. }
  791. /* Create new filter if possible */
  792. for (i = res_count; i < NUM_MDA_FILTERS; i++) {
  793. if (priv->mda_filters[i].en)
  794. continue;
  795. bcmasp_set_mda_filter(intf, addr, mask, i);
  796. bcmasp_en_mda_filter(intf, 1, i);
  797. return 0;
  798. }
  799. /* No room for new filter */
  800. return -EINVAL;
  801. }
  802. static void bcmasp_core_init_filters(struct bcmasp_priv *priv)
  803. {
  804. unsigned int i;
  805. /* Disable all filters and reset software view since the HW
  806. * can lose context while in deep sleep suspend states
  807. */
  808. for (i = 0; i < NUM_MDA_FILTERS; i++) {
  809. rx_filter_core_wl(priv, 0x0, ASP_RX_FILTER_MDA_CFG(i));
  810. priv->mda_filters[i].en = 0;
  811. }
  812. for (i = 0; i < NUM_NET_FILTERS; i++)
  813. rx_filter_core_wl(priv, 0x0, ASP_RX_FILTER_NET_CFG(i));
  814. /* Top level filter enable bit should be enabled at all times, set
  815. * GEN_WAKE_CLEAR to clear the network filter wake-up which would
  816. * otherwise be sticky
  817. */
  818. rx_filter_core_wl(priv, (ASP_RX_FILTER_OPUT_EN |
  819. ASP_RX_FILTER_MDA_EN |
  820. ASP_RX_FILTER_GEN_WK_CLR |
  821. ASP_RX_FILTER_NT_FLT_EN),
  822. ASP_RX_FILTER_BLK_CTRL);
  823. }
  824. /* ASP core initialization */
  825. static void bcmasp_core_init(struct bcmasp_priv *priv)
  826. {
  827. tx_analytics_core_wl(priv, 0x0, ASP_TX_ANALYTICS_CTRL);
  828. rx_analytics_core_wl(priv, 0x4, ASP_RX_ANALYTICS_CTRL);
  829. rx_edpkt_core_wl(priv, (ASP_EDPKT_HDR_SZ_128 << ASP_EDPKT_HDR_SZ_SHIFT),
  830. ASP_EDPKT_HDR_CFG);
  831. rx_edpkt_core_wl(priv,
  832. (ASP_EDPKT_ENDI_BT_SWP_WD << ASP_EDPKT_ENDI_DESC_SHIFT),
  833. ASP_EDPKT_ENDI);
  834. rx_edpkt_core_wl(priv, 0x1b, ASP_EDPKT_BURST_BUF_PSCAL_TOUT);
  835. rx_edpkt_core_wl(priv, 0x3e8, ASP_EDPKT_BURST_BUF_WRITE_TOUT);
  836. rx_edpkt_core_wl(priv, 0x3e8, ASP_EDPKT_BURST_BUF_READ_TOUT);
  837. rx_edpkt_core_wl(priv, ASP_EDPKT_ENABLE_EN, ASP_EDPKT_ENABLE);
  838. /* Disable and clear both UniMAC's wake-up interrupts to avoid
  839. * sticky interrupts.
  840. */
  841. _intr2_mask_set(priv, ASP_INTR2_UMC0_WAKE | ASP_INTR2_UMC1_WAKE);
  842. intr2_core_wl(priv, ASP_INTR2_UMC0_WAKE | ASP_INTR2_UMC1_WAKE,
  843. ASP_INTR2_CLEAR);
  844. }
  845. static void bcmasp_core_clock_select_many(struct bcmasp_priv *priv, bool slow)
  846. {
  847. u32 reg;
  848. reg = ctrl2_core_rl(priv, ASP_CTRL2_CORE_CLOCK_SELECT);
  849. if (slow)
  850. reg &= ~ASP_CTRL2_CORE_CLOCK_SELECT_MAIN;
  851. else
  852. reg |= ASP_CTRL2_CORE_CLOCK_SELECT_MAIN;
  853. ctrl2_core_wl(priv, reg, ASP_CTRL2_CORE_CLOCK_SELECT);
  854. reg = ctrl2_core_rl(priv, ASP_CTRL2_CPU_CLOCK_SELECT);
  855. if (slow)
  856. reg &= ~ASP_CTRL2_CPU_CLOCK_SELECT_MAIN;
  857. else
  858. reg |= ASP_CTRL2_CPU_CLOCK_SELECT_MAIN;
  859. ctrl2_core_wl(priv, reg, ASP_CTRL2_CPU_CLOCK_SELECT);
  860. }
  861. static void bcmasp_core_clock_select_one(struct bcmasp_priv *priv, bool slow)
  862. {
  863. u32 reg;
  864. reg = ctrl_core_rl(priv, ASP_CTRL_CORE_CLOCK_SELECT);
  865. if (slow)
  866. reg &= ~ASP_CTRL_CORE_CLOCK_SELECT_MAIN;
  867. else
  868. reg |= ASP_CTRL_CORE_CLOCK_SELECT_MAIN;
  869. ctrl_core_wl(priv, reg, ASP_CTRL_CORE_CLOCK_SELECT);
  870. }
  871. static void bcmasp_core_clock_set_ll(struct bcmasp_priv *priv, u32 clr, u32 set)
  872. {
  873. u32 reg;
  874. reg = ctrl_core_rl(priv, ASP_CTRL_CLOCK_CTRL);
  875. reg &= ~clr;
  876. reg |= set;
  877. ctrl_core_wl(priv, reg, ASP_CTRL_CLOCK_CTRL);
  878. reg = ctrl_core_rl(priv, ASP_CTRL_SCRATCH_0);
  879. reg &= ~clr;
  880. reg |= set;
  881. ctrl_core_wl(priv, reg, ASP_CTRL_SCRATCH_0);
  882. }
  883. static void bcmasp_core_clock_set(struct bcmasp_priv *priv, u32 clr, u32 set)
  884. {
  885. unsigned long flags;
  886. spin_lock_irqsave(&priv->clk_lock, flags);
  887. bcmasp_core_clock_set_ll(priv, clr, set);
  888. spin_unlock_irqrestore(&priv->clk_lock, flags);
  889. }
  890. void bcmasp_core_clock_set_intf(struct bcmasp_intf *intf, bool en)
  891. {
  892. u32 intf_mask = ASP_CTRL_CLOCK_CTRL_ASP_RGMII_DIS(intf->port);
  893. struct bcmasp_priv *priv = intf->parent;
  894. unsigned long flags;
  895. u32 reg;
  896. /* When enabling an interface, if the RX or TX clocks were not enabled,
  897. * enable them. Conversely, while disabling an interface, if this is
  898. * the last one enabled, we can turn off the shared RX and TX clocks as
  899. * well. We control enable bits which is why we test for equality on
  900. * the RGMII clock bit mask.
  901. */
  902. spin_lock_irqsave(&priv->clk_lock, flags);
  903. if (en) {
  904. intf_mask |= ASP_CTRL_CLOCK_CTRL_ASP_TX_DISABLE |
  905. ASP_CTRL_CLOCK_CTRL_ASP_RX_DISABLE;
  906. bcmasp_core_clock_set_ll(priv, intf_mask, 0);
  907. } else {
  908. reg = ctrl_core_rl(priv, ASP_CTRL_SCRATCH_0) | intf_mask;
  909. if ((reg & ASP_CTRL_CLOCK_CTRL_ASP_RGMII_MASK) ==
  910. ASP_CTRL_CLOCK_CTRL_ASP_RGMII_MASK)
  911. intf_mask |= ASP_CTRL_CLOCK_CTRL_ASP_TX_DISABLE |
  912. ASP_CTRL_CLOCK_CTRL_ASP_RX_DISABLE;
  913. bcmasp_core_clock_set_ll(priv, 0, intf_mask);
  914. }
  915. spin_unlock_irqrestore(&priv->clk_lock, flags);
  916. }
  917. static irqreturn_t bcmasp_isr_wol(int irq, void *data)
  918. {
  919. struct bcmasp_priv *priv = data;
  920. u32 status;
  921. /* No L3 IRQ, so we good */
  922. if (priv->wol_irq <= 0)
  923. goto irq_handled;
  924. status = wakeup_intr2_core_rl(priv, ASP_WAKEUP_INTR2_STATUS) &
  925. ~wakeup_intr2_core_rl(priv, ASP_WAKEUP_INTR2_MASK_STATUS);
  926. wakeup_intr2_core_wl(priv, status, ASP_WAKEUP_INTR2_CLEAR);
  927. irq_handled:
  928. pm_wakeup_event(&priv->pdev->dev, 0);
  929. return IRQ_HANDLED;
  930. }
  931. static int bcmasp_get_and_request_irq(struct bcmasp_priv *priv, int i)
  932. {
  933. struct platform_device *pdev = priv->pdev;
  934. int irq, ret;
  935. irq = platform_get_irq_optional(pdev, i);
  936. if (irq < 0)
  937. return irq;
  938. ret = devm_request_irq(&pdev->dev, irq, bcmasp_isr_wol, 0,
  939. pdev->name, priv);
  940. if (ret)
  941. return ret;
  942. return irq;
  943. }
  944. static void bcmasp_init_wol_shared(struct bcmasp_priv *priv)
  945. {
  946. struct platform_device *pdev = priv->pdev;
  947. struct device *dev = &pdev->dev;
  948. int irq;
  949. irq = bcmasp_get_and_request_irq(priv, 1);
  950. if (irq < 0) {
  951. dev_warn(dev, "Failed to init WoL irq: %d\n", irq);
  952. return;
  953. }
  954. priv->wol_irq = irq;
  955. priv->wol_irq_enabled_mask = 0;
  956. device_set_wakeup_capable(&pdev->dev, 1);
  957. }
  958. static void bcmasp_enable_wol_shared(struct bcmasp_intf *intf, bool en)
  959. {
  960. struct bcmasp_priv *priv = intf->parent;
  961. struct device *dev = &priv->pdev->dev;
  962. if (en) {
  963. if (priv->wol_irq_enabled_mask) {
  964. set_bit(intf->port, &priv->wol_irq_enabled_mask);
  965. return;
  966. }
  967. /* First enable */
  968. set_bit(intf->port, &priv->wol_irq_enabled_mask);
  969. enable_irq_wake(priv->wol_irq);
  970. device_set_wakeup_enable(dev, 1);
  971. } else {
  972. if (!priv->wol_irq_enabled_mask)
  973. return;
  974. clear_bit(intf->port, &priv->wol_irq_enabled_mask);
  975. if (priv->wol_irq_enabled_mask)
  976. return;
  977. /* Last disable */
  978. disable_irq_wake(priv->wol_irq);
  979. device_set_wakeup_enable(dev, 0);
  980. }
  981. }
  982. static void bcmasp_wol_irq_destroy_shared(struct bcmasp_priv *priv)
  983. {
  984. if (priv->wol_irq > 0)
  985. free_irq(priv->wol_irq, priv);
  986. }
  987. static void bcmasp_init_wol_per_intf(struct bcmasp_priv *priv)
  988. {
  989. struct platform_device *pdev = priv->pdev;
  990. struct device *dev = &pdev->dev;
  991. struct bcmasp_intf *intf;
  992. int irq;
  993. list_for_each_entry(intf, &priv->intfs, list) {
  994. irq = bcmasp_get_and_request_irq(priv, intf->port + 1);
  995. if (irq < 0) {
  996. dev_warn(dev, "Failed to init WoL irq(port %d): %d\n",
  997. intf->port, irq);
  998. continue;
  999. }
  1000. intf->wol_irq = irq;
  1001. intf->wol_irq_enabled = false;
  1002. device_set_wakeup_capable(&pdev->dev, 1);
  1003. }
  1004. }
  1005. static void bcmasp_enable_wol_per_intf(struct bcmasp_intf *intf, bool en)
  1006. {
  1007. struct device *dev = &intf->parent->pdev->dev;
  1008. if (en ^ intf->wol_irq_enabled)
  1009. irq_set_irq_wake(intf->wol_irq, en);
  1010. intf->wol_irq_enabled = en;
  1011. device_set_wakeup_enable(dev, en);
  1012. }
  1013. static void bcmasp_wol_irq_destroy_per_intf(struct bcmasp_priv *priv)
  1014. {
  1015. struct bcmasp_intf *intf;
  1016. list_for_each_entry(intf, &priv->intfs, list) {
  1017. if (intf->wol_irq > 0)
  1018. free_irq(intf->wol_irq, priv);
  1019. }
  1020. }
  1021. static void bcmasp_eee_fixup(struct bcmasp_intf *intf, bool en)
  1022. {
  1023. u32 reg, phy_lpi_overwrite;
  1024. reg = rx_edpkt_core_rl(intf->parent, ASP_EDPKT_SPARE_REG);
  1025. phy_lpi_overwrite = intf->internal_phy ? ASP_EDPKT_SPARE_REG_EPHY_LPI :
  1026. ASP_EDPKT_SPARE_REG_GPHY_LPI;
  1027. if (en)
  1028. reg |= phy_lpi_overwrite;
  1029. else
  1030. reg &= ~phy_lpi_overwrite;
  1031. rx_edpkt_core_wl(intf->parent, reg, ASP_EDPKT_SPARE_REG);
  1032. usleep_range(50, 100);
  1033. }
  1034. static struct bcmasp_hw_info v20_hw_info = {
  1035. .rx_ctrl_flush = ASP_RX_CTRL_FLUSH,
  1036. .umac2fb = UMAC2FB_OFFSET,
  1037. .rx_ctrl_fb_out_frame_count = ASP_RX_CTRL_FB_OUT_FRAME_COUNT,
  1038. .rx_ctrl_fb_filt_out_frame_count = ASP_RX_CTRL_FB_FILT_OUT_FRAME_COUNT,
  1039. .rx_ctrl_fb_rx_fifo_depth = ASP_RX_CTRL_FB_RX_FIFO_DEPTH,
  1040. };
  1041. static const struct bcmasp_plat_data v20_plat_data = {
  1042. .init_wol = bcmasp_init_wol_per_intf,
  1043. .enable_wol = bcmasp_enable_wol_per_intf,
  1044. .destroy_wol = bcmasp_wol_irq_destroy_per_intf,
  1045. .core_clock_select = bcmasp_core_clock_select_one,
  1046. .hw_info = &v20_hw_info,
  1047. };
  1048. static struct bcmasp_hw_info v21_hw_info = {
  1049. .rx_ctrl_flush = ASP_RX_CTRL_FLUSH_2_1,
  1050. .umac2fb = UMAC2FB_OFFSET_2_1,
  1051. .rx_ctrl_fb_out_frame_count = ASP_RX_CTRL_FB_OUT_FRAME_COUNT_2_1,
  1052. .rx_ctrl_fb_filt_out_frame_count =
  1053. ASP_RX_CTRL_FB_FILT_OUT_FRAME_COUNT_2_1,
  1054. .rx_ctrl_fb_rx_fifo_depth = ASP_RX_CTRL_FB_RX_FIFO_DEPTH_2_1,
  1055. };
  1056. static const struct bcmasp_plat_data v21_plat_data = {
  1057. .init_wol = bcmasp_init_wol_shared,
  1058. .enable_wol = bcmasp_enable_wol_shared,
  1059. .destroy_wol = bcmasp_wol_irq_destroy_shared,
  1060. .core_clock_select = bcmasp_core_clock_select_one,
  1061. .hw_info = &v21_hw_info,
  1062. };
  1063. static const struct bcmasp_plat_data v22_plat_data = {
  1064. .init_wol = bcmasp_init_wol_shared,
  1065. .enable_wol = bcmasp_enable_wol_shared,
  1066. .destroy_wol = bcmasp_wol_irq_destroy_shared,
  1067. .core_clock_select = bcmasp_core_clock_select_many,
  1068. .hw_info = &v21_hw_info,
  1069. .eee_fixup = bcmasp_eee_fixup,
  1070. };
  1071. static void bcmasp_set_pdata(struct bcmasp_priv *priv, const struct bcmasp_plat_data *pdata)
  1072. {
  1073. priv->init_wol = pdata->init_wol;
  1074. priv->enable_wol = pdata->enable_wol;
  1075. priv->destroy_wol = pdata->destroy_wol;
  1076. priv->core_clock_select = pdata->core_clock_select;
  1077. priv->eee_fixup = pdata->eee_fixup;
  1078. priv->hw_info = pdata->hw_info;
  1079. }
  1080. static const struct of_device_id bcmasp_of_match[] = {
  1081. { .compatible = "brcm,asp-v2.0", .data = &v20_plat_data },
  1082. { .compatible = "brcm,asp-v2.1", .data = &v21_plat_data },
  1083. { .compatible = "brcm,asp-v2.2", .data = &v22_plat_data },
  1084. { /* sentinel */ },
  1085. };
  1086. MODULE_DEVICE_TABLE(of, bcmasp_of_match);
  1087. static const struct of_device_id bcmasp_mdio_of_match[] = {
  1088. { .compatible = "brcm,asp-v2.2-mdio", },
  1089. { .compatible = "brcm,asp-v2.1-mdio", },
  1090. { .compatible = "brcm,asp-v2.0-mdio", },
  1091. { /* sentinel */ },
  1092. };
  1093. MODULE_DEVICE_TABLE(of, bcmasp_mdio_of_match);
  1094. static void bcmasp_remove_intfs(struct bcmasp_priv *priv)
  1095. {
  1096. struct bcmasp_intf *intf, *n;
  1097. list_for_each_entry_safe(intf, n, &priv->intfs, list) {
  1098. list_del(&intf->list);
  1099. bcmasp_interface_destroy(intf);
  1100. }
  1101. }
  1102. static int bcmasp_probe(struct platform_device *pdev)
  1103. {
  1104. const struct bcmasp_plat_data *pdata;
  1105. struct device *dev = &pdev->dev;
  1106. struct device_node *ports_node;
  1107. struct bcmasp_priv *priv;
  1108. struct bcmasp_intf *intf;
  1109. int ret = 0, count = 0;
  1110. unsigned int i;
  1111. priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
  1112. if (!priv)
  1113. return -ENOMEM;
  1114. priv->irq = platform_get_irq(pdev, 0);
  1115. if (priv->irq <= 0)
  1116. return -EINVAL;
  1117. priv->clk = devm_clk_get_optional_enabled(dev, "sw_asp");
  1118. if (IS_ERR(priv->clk))
  1119. return dev_err_probe(dev, PTR_ERR(priv->clk),
  1120. "failed to request clock\n");
  1121. /* Base from parent node */
  1122. priv->base = devm_platform_ioremap_resource(pdev, 0);
  1123. if (IS_ERR(priv->base))
  1124. return dev_err_probe(dev, PTR_ERR(priv->base), "failed to iomap\n");
  1125. ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(40));
  1126. if (ret)
  1127. return dev_err_probe(dev, ret, "unable to set DMA mask: %d\n", ret);
  1128. dev_set_drvdata(&pdev->dev, priv);
  1129. priv->pdev = pdev;
  1130. spin_lock_init(&priv->mda_lock);
  1131. spin_lock_init(&priv->clk_lock);
  1132. mutex_init(&priv->wol_lock);
  1133. mutex_init(&priv->net_lock);
  1134. INIT_LIST_HEAD(&priv->intfs);
  1135. pdata = device_get_match_data(&pdev->dev);
  1136. if (!pdata)
  1137. return dev_err_probe(dev, -EINVAL, "unable to find platform data\n");
  1138. bcmasp_set_pdata(priv, pdata);
  1139. /* Enable all clocks to ensure successful probing */
  1140. bcmasp_core_clock_set(priv, ASP_CTRL_CLOCK_CTRL_ASP_ALL_DISABLE, 0);
  1141. /* Switch to the main clock */
  1142. priv->core_clock_select(priv, false);
  1143. bcmasp_intr2_mask_set_all(priv);
  1144. bcmasp_intr2_clear_all(priv);
  1145. ret = devm_request_irq(&pdev->dev, priv->irq, bcmasp_isr, 0,
  1146. pdev->name, priv);
  1147. if (ret)
  1148. return dev_err_probe(dev, ret, "failed to request ASP interrupt: %d", ret);
  1149. /* Register mdio child nodes */
  1150. of_platform_populate(dev->of_node, bcmasp_mdio_of_match, NULL, dev);
  1151. /* ASP specific initialization, Needs to be done regardless of
  1152. * how many interfaces come up.
  1153. */
  1154. bcmasp_core_init(priv);
  1155. bcmasp_core_init_filters(priv);
  1156. ports_node = of_find_node_by_name(dev->of_node, "ethernet-ports");
  1157. if (!ports_node) {
  1158. dev_warn(dev, "No ports found\n");
  1159. return -EINVAL;
  1160. }
  1161. i = 0;
  1162. for_each_available_child_of_node_scoped(ports_node, intf_node) {
  1163. intf = bcmasp_interface_create(priv, intf_node, i);
  1164. if (!intf) {
  1165. dev_err(dev, "Cannot create eth interface %d\n", i);
  1166. bcmasp_remove_intfs(priv);
  1167. ret = -ENOMEM;
  1168. goto of_put_exit;
  1169. }
  1170. list_add_tail(&intf->list, &priv->intfs);
  1171. i++;
  1172. }
  1173. /* Check and enable WoL */
  1174. priv->init_wol(priv);
  1175. /* Drop the clock reference count now and let ndo_open()/ndo_close()
  1176. * manage it for us from now on.
  1177. */
  1178. bcmasp_core_clock_set(priv, 0, ASP_CTRL_CLOCK_CTRL_ASP_ALL_DISABLE);
  1179. clk_disable_unprepare(priv->clk);
  1180. /* Now do the registration of the network ports which will take care
  1181. * of managing the clock properly.
  1182. */
  1183. list_for_each_entry(intf, &priv->intfs, list) {
  1184. ret = register_netdev(intf->ndev);
  1185. if (ret) {
  1186. netdev_err(intf->ndev,
  1187. "failed to register net_device: %d\n", ret);
  1188. priv->destroy_wol(priv);
  1189. bcmasp_remove_intfs(priv);
  1190. goto of_put_exit;
  1191. }
  1192. count++;
  1193. }
  1194. dev_info(dev, "Initialized %d port(s)\n", count);
  1195. of_put_exit:
  1196. of_node_put(ports_node);
  1197. return ret;
  1198. }
  1199. static void bcmasp_remove(struct platform_device *pdev)
  1200. {
  1201. struct bcmasp_priv *priv = dev_get_drvdata(&pdev->dev);
  1202. if (!priv)
  1203. return;
  1204. priv->destroy_wol(priv);
  1205. bcmasp_remove_intfs(priv);
  1206. }
  1207. static void bcmasp_shutdown(struct platform_device *pdev)
  1208. {
  1209. bcmasp_remove(pdev);
  1210. }
  1211. static int __maybe_unused bcmasp_suspend(struct device *d)
  1212. {
  1213. struct bcmasp_priv *priv = dev_get_drvdata(d);
  1214. struct bcmasp_intf *intf;
  1215. int ret;
  1216. list_for_each_entry(intf, &priv->intfs, list) {
  1217. ret = bcmasp_interface_suspend(intf);
  1218. if (ret)
  1219. break;
  1220. }
  1221. ret = clk_prepare_enable(priv->clk);
  1222. if (ret)
  1223. return ret;
  1224. /* Whether Wake-on-LAN is enabled or not, we can always disable
  1225. * the shared TX clock
  1226. */
  1227. bcmasp_core_clock_set(priv, 0, ASP_CTRL_CLOCK_CTRL_ASP_TX_DISABLE);
  1228. priv->core_clock_select(priv, true);
  1229. clk_disable_unprepare(priv->clk);
  1230. return ret;
  1231. }
  1232. static int __maybe_unused bcmasp_resume(struct device *d)
  1233. {
  1234. struct bcmasp_priv *priv = dev_get_drvdata(d);
  1235. struct bcmasp_intf *intf;
  1236. int ret;
  1237. ret = clk_prepare_enable(priv->clk);
  1238. if (ret)
  1239. return ret;
  1240. /* Switch to the main clock domain */
  1241. priv->core_clock_select(priv, false);
  1242. /* Re-enable all clocks for re-initialization */
  1243. bcmasp_core_clock_set(priv, ASP_CTRL_CLOCK_CTRL_ASP_ALL_DISABLE, 0);
  1244. bcmasp_core_init(priv);
  1245. bcmasp_core_init_filters(priv);
  1246. /* And disable them to let the network devices take care of them */
  1247. bcmasp_core_clock_set(priv, 0, ASP_CTRL_CLOCK_CTRL_ASP_ALL_DISABLE);
  1248. clk_disable_unprepare(priv->clk);
  1249. list_for_each_entry(intf, &priv->intfs, list) {
  1250. ret = bcmasp_interface_resume(intf);
  1251. if (ret)
  1252. break;
  1253. }
  1254. return ret;
  1255. }
  1256. static SIMPLE_DEV_PM_OPS(bcmasp_pm_ops,
  1257. bcmasp_suspend, bcmasp_resume);
  1258. static struct platform_driver bcmasp_driver = {
  1259. .probe = bcmasp_probe,
  1260. .remove_new = bcmasp_remove,
  1261. .shutdown = bcmasp_shutdown,
  1262. .driver = {
  1263. .name = "brcm,asp-v2",
  1264. .of_match_table = bcmasp_of_match,
  1265. .pm = &bcmasp_pm_ops,
  1266. },
  1267. };
  1268. module_platform_driver(bcmasp_driver);
  1269. MODULE_DESCRIPTION("Broadcom ASP 2.0 Ethernet controller driver");
  1270. MODULE_ALIAS("platform:brcm,asp-v2");
  1271. MODULE_LICENSE("GPL");