ldpaa_eth.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032
  1. /*
  2. * Copyright (C) 2014 Freescale Semiconductor
  3. *
  4. * SPDX-License-Identifier: GPL-2.0+
  5. */
  6. #include <common.h>
  7. #include <asm/io.h>
  8. #include <asm/types.h>
  9. #include <malloc.h>
  10. #include <net.h>
  11. #include <hwconfig.h>
  12. #include <phy.h>
  13. #include <linux/compat.h>
  14. #include <fsl-mc/fsl_dpmac.h>
  15. #include <fsl-mc/ldpaa_wriop.h>
  16. #include "ldpaa_eth.h"
  17. #ifdef CONFIG_PHYLIB
  18. static int init_phy(struct eth_device *dev)
  19. {
  20. struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)dev->priv;
  21. struct phy_device *phydev = NULL;
  22. struct mii_dev *bus;
  23. bus = wriop_get_mdio(priv->dpmac_id);
  24. if (bus == NULL)
  25. return 0;
  26. phydev = phy_connect(bus, wriop_get_phy_address(priv->dpmac_id),
  27. dev, wriop_get_enet_if(priv->dpmac_id));
  28. if (!phydev) {
  29. printf("Failed to connect\n");
  30. return -1;
  31. }
  32. priv->phydev = phydev;
  33. return phy_config(phydev);
  34. }
  35. #endif
  36. #ifdef DEBUG
  37. static void ldpaa_eth_get_dpni_counter(void)
  38. {
  39. int err = 0;
  40. u64 value;
  41. err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
  42. dflt_dpni->dpni_handle,
  43. DPNI_CNT_ING_FRAME,
  44. &value);
  45. if (err < 0) {
  46. printf("dpni_get_counter: DPNI_CNT_ING_FRAME failed\n");
  47. return;
  48. }
  49. printf("DPNI_CNT_ING_FRAME=%lld\n", value);
  50. err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
  51. dflt_dpni->dpni_handle,
  52. DPNI_CNT_ING_BYTE,
  53. &value);
  54. if (err < 0) {
  55. printf("dpni_get_counter: DPNI_CNT_ING_BYTE failed\n");
  56. return;
  57. }
  58. printf("DPNI_CNT_ING_BYTE=%lld\n", value);
  59. err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
  60. dflt_dpni->dpni_handle,
  61. DPNI_CNT_ING_FRAME_DROP ,
  62. &value);
  63. if (err < 0) {
  64. printf("dpni_get_counter: DPNI_CNT_ING_FRAME_DROP failed\n");
  65. return;
  66. }
  67. printf("DPNI_CNT_ING_FRAME_DROP =%lld\n", value);
  68. err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
  69. dflt_dpni->dpni_handle,
  70. DPNI_CNT_ING_FRAME_DISCARD,
  71. &value);
  72. if (err < 0) {
  73. printf("dpni_get_counter: DPNI_CNT_ING_FRAME_DISCARD failed\n");
  74. return;
  75. }
  76. printf("DPNI_CNT_ING_FRAME_DISCARD=%lld\n", value);
  77. err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
  78. dflt_dpni->dpni_handle,
  79. DPNI_CNT_EGR_FRAME,
  80. &value);
  81. if (err < 0) {
  82. printf("dpni_get_counter: DPNI_CNT_EGR_FRAME failed\n");
  83. return;
  84. }
  85. printf("DPNI_CNT_EGR_FRAME=%lld\n", value);
  86. err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
  87. dflt_dpni->dpni_handle,
  88. DPNI_CNT_EGR_BYTE ,
  89. &value);
  90. if (err < 0) {
  91. printf("dpni_get_counter: DPNI_CNT_EGR_BYTE failed\n");
  92. return;
  93. }
  94. printf("DPNI_CNT_EGR_BYTE =%lld\n", value);
  95. err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
  96. dflt_dpni->dpni_handle,
  97. DPNI_CNT_EGR_FRAME_DISCARD ,
  98. &value);
  99. if (err < 0) {
  100. printf("dpni_get_counter: DPNI_CNT_EGR_FRAME_DISCARD failed\n");
  101. return;
  102. }
  103. printf("DPNI_CNT_EGR_FRAME_DISCARD =%lld\n", value);
  104. }
  105. static void ldpaa_eth_get_dpmac_counter(struct eth_device *net_dev)
  106. {
  107. struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
  108. int err = 0;
  109. u64 value;
  110. err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
  111. priv->dpmac_handle,
  112. DPMAC_CNT_ING_BYTE,
  113. &value);
  114. if (err < 0) {
  115. printf("dpmac_get_counter: DPMAC_CNT_ING_BYTE failed\n");
  116. return;
  117. }
  118. printf("DPMAC_CNT_ING_BYTE=%lld\n", value);
  119. err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
  120. priv->dpmac_handle,
  121. DPMAC_CNT_ING_FRAME_DISCARD,
  122. &value);
  123. if (err < 0) {
  124. printf("dpmac_get_counter: DPMAC_CNT_ING_FRAME_DISCARD failed\n");
  125. return;
  126. }
  127. printf("DPMAC_CNT_ING_FRAME_DISCARD=%lld\n", value);
  128. err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
  129. priv->dpmac_handle,
  130. DPMAC_CNT_ING_ALIGN_ERR,
  131. &value);
  132. if (err < 0) {
  133. printf("dpmac_get_counter: DPMAC_CNT_ING_ALIGN_ERR failed\n");
  134. return;
  135. }
  136. printf("DPMAC_CNT_ING_ALIGN_ERR =%lld\n", value);
  137. err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
  138. priv->dpmac_handle,
  139. DPMAC_CNT_ING_BYTE,
  140. &value);
  141. if (err < 0) {
  142. printf("dpmac_get_counter: DPMAC_CNT_ING_BYTE failed\n");
  143. return;
  144. }
  145. printf("DPMAC_CNT_ING_BYTE=%lld\n", value);
  146. err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
  147. priv->dpmac_handle,
  148. DPMAC_CNT_ING_ERR_FRAME,
  149. &value);
  150. if (err < 0) {
  151. printf("dpmac_get_counter: DPMAC_CNT_ING_ERR_FRAME failed\n");
  152. return;
  153. }
  154. printf("DPMAC_CNT_ING_ERR_FRAME=%lld\n", value);
  155. err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
  156. priv->dpmac_handle,
  157. DPMAC_CNT_EGR_BYTE ,
  158. &value);
  159. if (err < 0) {
  160. printf("dpmac_get_counter: DPMAC_CNT_EGR_BYTE failed\n");
  161. return;
  162. }
  163. printf("DPMAC_CNT_EGR_BYTE =%lld\n", value);
  164. err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
  165. priv->dpmac_handle,
  166. DPMAC_CNT_EGR_ERR_FRAME ,
  167. &value);
  168. if (err < 0) {
  169. printf("dpmac_get_counter: DPMAC_CNT_EGR_ERR_FRAME failed\n");
  170. return;
  171. }
  172. printf("DPMAC_CNT_EGR_ERR_FRAME =%lld\n", value);
  173. }
  174. #endif
  175. static void ldpaa_eth_rx(struct ldpaa_eth_priv *priv,
  176. const struct dpaa_fd *fd)
  177. {
  178. u64 fd_addr;
  179. uint16_t fd_offset;
  180. uint32_t fd_length;
  181. struct ldpaa_fas *fas;
  182. uint32_t status, err;
  183. u32 timeo = (CONFIG_SYS_HZ * 2) / 1000;
  184. u32 time_start;
  185. struct qbman_release_desc releasedesc;
  186. struct qbman_swp *swp = dflt_dpio->sw_portal;
  187. fd_addr = ldpaa_fd_get_addr(fd);
  188. fd_offset = ldpaa_fd_get_offset(fd);
  189. fd_length = ldpaa_fd_get_len(fd);
  190. debug("Rx frame:data addr=0x%p size=0x%x\n", (u64 *)fd_addr, fd_length);
  191. if (fd->simple.frc & LDPAA_FD_FRC_FASV) {
  192. /* Read the frame annotation status word and check for errors */
  193. fas = (struct ldpaa_fas *)
  194. ((uint8_t *)(fd_addr) +
  195. dflt_dpni->buf_layout.private_data_size);
  196. status = le32_to_cpu(fas->status);
  197. if (status & LDPAA_ETH_RX_ERR_MASK) {
  198. printf("Rx frame error(s): 0x%08x\n",
  199. status & LDPAA_ETH_RX_ERR_MASK);
  200. goto error;
  201. } else if (status & LDPAA_ETH_RX_UNSUPP_MASK) {
  202. printf("Unsupported feature in bitmask: 0x%08x\n",
  203. status & LDPAA_ETH_RX_UNSUPP_MASK);
  204. goto error;
  205. }
  206. }
  207. debug("Rx frame: To Upper layer\n");
  208. net_process_received_packet((uint8_t *)(fd_addr) + fd_offset,
  209. fd_length);
  210. error:
  211. flush_dcache_range(fd_addr, fd_addr + LDPAA_ETH_RX_BUFFER_SIZE);
  212. qbman_release_desc_clear(&releasedesc);
  213. qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid);
  214. time_start = get_timer(0);
  215. do {
  216. /* Release buffer into the QBMAN */
  217. err = qbman_swp_release(swp, &releasedesc, &fd_addr, 1);
  218. } while (get_timer(time_start) < timeo && err == -EBUSY);
  219. if (err == -EBUSY)
  220. printf("Rx frame: QBMAN buffer release fails\n");
  221. return;
  222. }
  223. static int ldpaa_eth_pull_dequeue_rx(struct eth_device *dev)
  224. {
  225. struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)dev->priv;
  226. const struct ldpaa_dq *dq;
  227. const struct dpaa_fd *fd;
  228. int i = 5, err = 0, status;
  229. u32 timeo = (CONFIG_SYS_HZ * 2) / 1000;
  230. u32 time_start;
  231. static struct qbman_pull_desc pulldesc;
  232. struct qbman_swp *swp = dflt_dpio->sw_portal;
  233. while (--i) {
  234. qbman_pull_desc_clear(&pulldesc);
  235. qbman_pull_desc_set_numframes(&pulldesc, 1);
  236. qbman_pull_desc_set_fq(&pulldesc, priv->rx_dflt_fqid);
  237. err = qbman_swp_pull(swp, &pulldesc);
  238. if (err < 0) {
  239. printf("Dequeue frames error:0x%08x\n", err);
  240. continue;
  241. }
  242. time_start = get_timer(0);
  243. do {
  244. dq = qbman_swp_dqrr_next(swp);
  245. } while (get_timer(time_start) < timeo && !dq);
  246. if (dq) {
  247. /* Check for valid frame. If not sent a consume
  248. * confirmation to QBMAN otherwise give it to NADK
  249. * application and then send consume confirmation to
  250. * QBMAN.
  251. */
  252. status = (uint8_t)ldpaa_dq_flags(dq);
  253. if ((status & LDPAA_DQ_STAT_VALIDFRAME) == 0) {
  254. debug("Dequeue RX frames:");
  255. debug("No frame delivered\n");
  256. qbman_swp_dqrr_consume(swp, dq);
  257. continue;
  258. }
  259. fd = ldpaa_dq_fd(dq);
  260. /* Obtain FD and process it */
  261. ldpaa_eth_rx(priv, fd);
  262. qbman_swp_dqrr_consume(swp, dq);
  263. break;
  264. } else {
  265. err = -ENODATA;
  266. debug("No DQRR entries\n");
  267. break;
  268. }
  269. }
  270. return err;
  271. }
  272. static int ldpaa_eth_tx(struct eth_device *net_dev, void *buf, int len)
  273. {
  274. struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
  275. struct dpaa_fd fd;
  276. u64 buffer_start;
  277. int data_offset, err;
  278. u32 timeo = (CONFIG_SYS_HZ * 10) / 1000;
  279. u32 time_start;
  280. struct qbman_swp *swp = dflt_dpio->sw_portal;
  281. struct qbman_eq_desc ed;
  282. struct qbman_release_desc releasedesc;
  283. /* Setup the FD fields */
  284. memset(&fd, 0, sizeof(fd));
  285. data_offset = priv->tx_data_offset;
  286. do {
  287. err = qbman_swp_acquire(dflt_dpio->sw_portal,
  288. dflt_dpbp->dpbp_attr.bpid,
  289. &buffer_start, 1);
  290. } while (err == -EBUSY);
  291. if (err < 0) {
  292. printf("qbman_swp_acquire() failed\n");
  293. return -ENOMEM;
  294. }
  295. debug("TX data: malloc buffer start=0x%p\n", (u64 *)buffer_start);
  296. memcpy(((uint8_t *)(buffer_start) + data_offset), buf, len);
  297. flush_dcache_range(buffer_start, buffer_start +
  298. LDPAA_ETH_RX_BUFFER_SIZE);
  299. ldpaa_fd_set_addr(&fd, (u64)buffer_start);
  300. ldpaa_fd_set_offset(&fd, (uint16_t)(data_offset));
  301. ldpaa_fd_set_bpid(&fd, dflt_dpbp->dpbp_attr.bpid);
  302. ldpaa_fd_set_len(&fd, len);
  303. fd.simple.ctrl = LDPAA_FD_CTRL_ASAL | LDPAA_FD_CTRL_PTA |
  304. LDPAA_FD_CTRL_PTV1;
  305. qbman_eq_desc_clear(&ed);
  306. qbman_eq_desc_set_no_orp(&ed, 0);
  307. qbman_eq_desc_set_qd(&ed, priv->tx_qdid, priv->tx_flow_id, 0);
  308. time_start = get_timer(0);
  309. while (get_timer(time_start) < timeo) {
  310. err = qbman_swp_enqueue(swp, &ed,
  311. (const struct qbman_fd *)(&fd));
  312. if (err != -EBUSY)
  313. break;
  314. }
  315. if (err < 0) {
  316. printf("error enqueueing Tx frame\n");
  317. goto error;
  318. }
  319. return err;
  320. error:
  321. qbman_release_desc_clear(&releasedesc);
  322. qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid);
  323. time_start = get_timer(0);
  324. do {
  325. /* Release buffer into the QBMAN */
  326. err = qbman_swp_release(swp, &releasedesc, &buffer_start, 1);
  327. } while (get_timer(time_start) < timeo && err == -EBUSY);
  328. if (err == -EBUSY)
  329. printf("TX data: QBMAN buffer release fails\n");
  330. return err;
  331. }
  332. static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd)
  333. {
  334. struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
  335. struct dpni_queue_attr rx_queue_attr;
  336. struct dpmac_link_state dpmac_link_state = { 0 };
  337. #ifdef DEBUG
  338. struct dpni_link_state link_state;
  339. #endif
  340. int err = 0;
  341. struct mii_dev *bus;
  342. phy_interface_t enet_if;
  343. if (net_dev->state == ETH_STATE_ACTIVE)
  344. return 0;
  345. if (get_mc_boot_status() != 0) {
  346. printf("ERROR (MC is not booted)\n");
  347. return -ENODEV;
  348. }
  349. if (get_dpl_apply_status() == 0) {
  350. printf("ERROR (DPL is deployed. No device available)\n");
  351. return -ENODEV;
  352. }
  353. /* DPMAC initialization */
  354. err = ldpaa_dpmac_setup(priv);
  355. if (err < 0)
  356. goto err_dpmac_setup;
  357. #ifdef CONFIG_PHYLIB
  358. if (priv->phydev) {
  359. err = phy_startup(priv->phydev);
  360. if (err) {
  361. printf("%s: Could not initialize\n",
  362. priv->phydev->dev->name);
  363. goto err_dpamc_bind;
  364. }
  365. }
  366. #else
  367. priv->phydev = (struct phy_device *)malloc(sizeof(struct phy_device));
  368. memset(priv->phydev, 0, sizeof(struct phy_device));
  369. priv->phydev->speed = SPEED_1000;
  370. priv->phydev->link = 1;
  371. priv->phydev->duplex = DUPLEX_FULL;
  372. #endif
  373. bus = wriop_get_mdio(priv->dpmac_id);
  374. enet_if = wriop_get_enet_if(priv->dpmac_id);
  375. if ((bus == NULL) &&
  376. (enet_if == PHY_INTERFACE_MODE_XGMII)) {
  377. priv->phydev = (struct phy_device *)
  378. malloc(sizeof(struct phy_device));
  379. memset(priv->phydev, 0, sizeof(struct phy_device));
  380. priv->phydev->speed = SPEED_10000;
  381. priv->phydev->link = 1;
  382. priv->phydev->duplex = DUPLEX_FULL;
  383. }
  384. if (!priv->phydev->link) {
  385. printf("%s: No link.\n", priv->phydev->dev->name);
  386. err = -1;
  387. goto err_dpamc_bind;
  388. }
  389. /* DPMAC binding DPNI */
  390. err = ldpaa_dpmac_bind(priv);
  391. if (err)
  392. goto err_dpamc_bind;
  393. /* DPNI initialization */
  394. err = ldpaa_dpni_setup(priv);
  395. if (err < 0)
  396. goto err_dpni_setup;
  397. err = ldpaa_dpbp_setup();
  398. if (err < 0)
  399. goto err_dpbp_setup;
  400. /* DPNI binding DPBP */
  401. err = ldpaa_dpni_bind(priv);
  402. if (err)
  403. goto err_dpni_bind;
  404. err = dpni_add_mac_addr(dflt_mc_io, MC_CMD_NO_FLAGS,
  405. dflt_dpni->dpni_handle, net_dev->enetaddr);
  406. if (err) {
  407. printf("dpni_add_mac_addr() failed\n");
  408. return err;
  409. }
  410. err = dpni_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
  411. if (err < 0) {
  412. printf("dpni_enable() failed\n");
  413. return err;
  414. }
  415. dpmac_link_state.rate = priv->phydev->speed;
  416. if (priv->phydev->autoneg == AUTONEG_DISABLE)
  417. dpmac_link_state.options &= ~DPMAC_LINK_OPT_AUTONEG;
  418. else
  419. dpmac_link_state.options |= DPMAC_LINK_OPT_AUTONEG;
  420. if (priv->phydev->duplex == DUPLEX_HALF)
  421. dpmac_link_state.options |= DPMAC_LINK_OPT_HALF_DUPLEX;
  422. dpmac_link_state.up = priv->phydev->link;
  423. err = dpmac_set_link_state(dflt_mc_io, MC_CMD_NO_FLAGS,
  424. priv->dpmac_handle, &dpmac_link_state);
  425. if (err < 0) {
  426. printf("dpmac_set_link_state() failed\n");
  427. return err;
  428. }
  429. #ifdef DEBUG
  430. err = dpni_get_link_state(dflt_mc_io, MC_CMD_NO_FLAGS,
  431. dflt_dpni->dpni_handle, &link_state);
  432. if (err < 0) {
  433. printf("dpni_get_link_state() failed\n");
  434. return err;
  435. }
  436. printf("link status: %d - ", link_state.up);
  437. link_state.up == 0 ? printf("down\n") :
  438. link_state.up == 1 ? printf("up\n") : printf("error state\n");
  439. #endif
  440. /* TODO: support multiple Rx flows */
  441. err = dpni_get_rx_flow(dflt_mc_io, MC_CMD_NO_FLAGS,
  442. dflt_dpni->dpni_handle, 0, 0, &rx_queue_attr);
  443. if (err) {
  444. printf("dpni_get_rx_flow() failed\n");
  445. goto err_rx_flow;
  446. }
  447. priv->rx_dflt_fqid = rx_queue_attr.fqid;
  448. err = dpni_get_qdid(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle,
  449. &priv->tx_qdid);
  450. if (err) {
  451. printf("dpni_get_qdid() failed\n");
  452. goto err_qdid;
  453. }
  454. return priv->phydev->link;
  455. err_qdid:
  456. err_rx_flow:
  457. dpni_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
  458. err_dpni_bind:
  459. ldpaa_dpbp_free();
  460. err_dpbp_setup:
  461. dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
  462. err_dpni_setup:
  463. err_dpamc_bind:
  464. dpmac_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle);
  465. err_dpmac_setup:
  466. return err;
  467. }
  468. static void ldpaa_eth_stop(struct eth_device *net_dev)
  469. {
  470. struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
  471. int err = 0;
  472. #ifdef CONFIG_PHYLIB
  473. struct mii_dev *bus = wriop_get_mdio(priv->dpmac_id);
  474. #endif
  475. if ((net_dev->state == ETH_STATE_PASSIVE) ||
  476. (net_dev->state == ETH_STATE_INIT))
  477. return;
  478. #ifdef DEBUG
  479. ldpaa_eth_get_dpni_counter();
  480. ldpaa_eth_get_dpmac_counter(net_dev);
  481. #endif
  482. err = dprc_disconnect(dflt_mc_io, MC_CMD_NO_FLAGS,
  483. dflt_dprc_handle, &dpmac_endpoint);
  484. if (err < 0)
  485. printf("dprc_disconnect() failed dpmac_endpoint\n");
  486. err = dpmac_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle);
  487. if (err < 0)
  488. printf("dpmac_destroy() failed\n");
  489. /* Stop Tx and Rx traffic */
  490. err = dpni_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
  491. if (err < 0)
  492. printf("dpni_disable() failed\n");
  493. #ifdef CONFIG_PHYLIB
  494. if (priv->phydev && bus != NULL)
  495. phy_shutdown(priv->phydev);
  496. else
  497. free(priv->phydev);
  498. #endif
  499. ldpaa_dpbp_free();
  500. dpni_reset(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
  501. dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
  502. }
  503. static void ldpaa_dpbp_drain_cnt(int count)
  504. {
  505. uint64_t buf_array[7];
  506. void *addr;
  507. int ret, i;
  508. BUG_ON(count > 7);
  509. do {
  510. ret = qbman_swp_acquire(dflt_dpio->sw_portal,
  511. dflt_dpbp->dpbp_attr.bpid,
  512. buf_array, count);
  513. if (ret < 0) {
  514. printf("qbman_swp_acquire() failed\n");
  515. return;
  516. }
  517. for (i = 0; i < ret; i++) {
  518. addr = (void *)buf_array[i];
  519. debug("Free: buffer addr =0x%p\n", addr);
  520. free(addr);
  521. }
  522. } while (ret);
  523. }
  524. static void ldpaa_dpbp_drain(void)
  525. {
  526. int i;
  527. for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7)
  528. ldpaa_dpbp_drain_cnt(7);
  529. }
  530. static int ldpaa_bp_add_7(uint16_t bpid)
  531. {
  532. uint64_t buf_array[7];
  533. u8 *addr;
  534. int i;
  535. struct qbman_release_desc rd;
  536. for (i = 0; i < 7; i++) {
  537. addr = memalign(LDPAA_ETH_BUF_ALIGN, LDPAA_ETH_RX_BUFFER_SIZE);
  538. if (!addr) {
  539. printf("addr allocation failed\n");
  540. goto err_alloc;
  541. }
  542. memset(addr, 0x00, LDPAA_ETH_RX_BUFFER_SIZE);
  543. flush_dcache_range((u64)addr,
  544. (u64)(addr + LDPAA_ETH_RX_BUFFER_SIZE));
  545. buf_array[i] = (uint64_t)addr;
  546. debug("Release: buffer addr =0x%p\n", addr);
  547. }
  548. release_bufs:
  549. /* In case the portal is busy, retry until successful.
  550. * This function is guaranteed to succeed in a reasonable amount
  551. * of time.
  552. */
  553. do {
  554. mdelay(1);
  555. qbman_release_desc_clear(&rd);
  556. qbman_release_desc_set_bpid(&rd, bpid);
  557. } while (qbman_swp_release(dflt_dpio->sw_portal, &rd, buf_array, i));
  558. return i;
  559. err_alloc:
  560. if (i)
  561. goto release_bufs;
  562. return 0;
  563. }
  564. static int ldpaa_dpbp_seed(uint16_t bpid)
  565. {
  566. int i;
  567. int count;
  568. for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7) {
  569. count = ldpaa_bp_add_7(bpid);
  570. if (count < 7)
  571. printf("Buffer Seed= %d\n", count);
  572. }
  573. return 0;
  574. }
  575. static int ldpaa_dpbp_setup(void)
  576. {
  577. int err;
  578. err = dpbp_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_attr.id,
  579. &dflt_dpbp->dpbp_handle);
  580. if (err) {
  581. printf("dpbp_open() failed\n");
  582. goto err_open;
  583. }
  584. err = dpbp_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
  585. if (err) {
  586. printf("dpbp_enable() failed\n");
  587. goto err_enable;
  588. }
  589. err = dpbp_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
  590. dflt_dpbp->dpbp_handle,
  591. &dflt_dpbp->dpbp_attr);
  592. if (err) {
  593. printf("dpbp_get_attributes() failed\n");
  594. goto err_get_attr;
  595. }
  596. err = ldpaa_dpbp_seed(dflt_dpbp->dpbp_attr.bpid);
  597. if (err) {
  598. printf("Buffer seeding failed for DPBP %d (bpid=%d)\n",
  599. dflt_dpbp->dpbp_attr.id, dflt_dpbp->dpbp_attr.bpid);
  600. goto err_seed;
  601. }
  602. return 0;
  603. err_seed:
  604. err_get_attr:
  605. dpbp_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
  606. err_enable:
  607. dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
  608. err_open:
  609. return err;
  610. }
  611. static void ldpaa_dpbp_free(void)
  612. {
  613. ldpaa_dpbp_drain();
  614. dpbp_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
  615. dpbp_reset(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
  616. dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
  617. }
  618. static int ldpaa_dpmac_version_check(struct fsl_mc_io *mc_io,
  619. struct ldpaa_eth_priv *priv)
  620. {
  621. struct dpmac_attr attr;
  622. int error;
  623. memset(&attr, 0, sizeof(struct dpmac_attr));
  624. error = dpmac_get_attributes(mc_io, MC_CMD_NO_FLAGS,
  625. priv->dpmac_handle,
  626. &attr);
  627. if (error == 0) {
  628. if ((attr.version.major != DPMAC_VER_MAJOR) ||
  629. (attr.version.minor != DPMAC_VER_MINOR)) {
  630. printf("DPMAC version mismatch found %u.%u,",
  631. attr.version.major, attr.version.minor);
  632. printf("supported version is %u.%u\n",
  633. DPMAC_VER_MAJOR, DPMAC_VER_MINOR);
  634. }
  635. }
  636. return error;
  637. }
  638. static int ldpaa_dpmac_setup(struct ldpaa_eth_priv *priv)
  639. {
  640. int err = 0;
  641. struct dpmac_cfg dpmac_cfg;
  642. dpmac_cfg.mac_id = priv->dpmac_id;
  643. err = dpmac_create(dflt_mc_io, MC_CMD_NO_FLAGS, &dpmac_cfg,
  644. &priv->dpmac_handle);
  645. if (err)
  646. printf("dpmac_create() failed\n");
  647. err = ldpaa_dpmac_version_check(dflt_mc_io, priv);
  648. if (err < 0)
  649. printf("ldpaa_dpmac_version_check() failed: %d\n", err);
  650. return err;
  651. }
  652. static int ldpaa_dpmac_bind(struct ldpaa_eth_priv *priv)
  653. {
  654. int err = 0;
  655. struct dprc_connection_cfg dprc_connection_cfg = {
  656. /* If both rates are zero the connection */
  657. /* will be configured in "best effort" mode. */
  658. .committed_rate = 0,
  659. .max_rate = 0
  660. };
  661. #ifdef DEBUG
  662. struct dprc_endpoint dbg_endpoint;
  663. int state = 0;
  664. #endif
  665. memset(&dpmac_endpoint, 0, sizeof(struct dprc_endpoint));
  666. strcpy(dpmac_endpoint.type, "dpmac");
  667. dpmac_endpoint.id = priv->dpmac_id;
  668. memset(&dpni_endpoint, 0, sizeof(struct dprc_endpoint));
  669. strcpy(dpni_endpoint.type, "dpni");
  670. dpni_endpoint.id = dflt_dpni->dpni_id;
  671. err = dprc_connect(dflt_mc_io, MC_CMD_NO_FLAGS,
  672. dflt_dprc_handle,
  673. &dpmac_endpoint,
  674. &dpni_endpoint,
  675. &dprc_connection_cfg);
  676. if (err)
  677. printf("dprc_connect() failed\n");
  678. #ifdef DEBUG
  679. err = dprc_get_connection(dflt_mc_io, MC_CMD_NO_FLAGS,
  680. dflt_dprc_handle, &dpni_endpoint,
  681. &dbg_endpoint, &state);
  682. printf("%s, DPMAC Type= %s\n", __func__, dbg_endpoint.type);
  683. printf("%s, DPMAC ID= %d\n", __func__, dbg_endpoint.id);
  684. printf("%s, DPMAC State= %d\n", __func__, state);
  685. memset(&dbg_endpoint, 0, sizeof(struct dprc_endpoint));
  686. err = dprc_get_connection(dflt_mc_io, MC_CMD_NO_FLAGS,
  687. dflt_dprc_handle, &dpmac_endpoint,
  688. &dbg_endpoint, &state);
  689. printf("%s, DPNI Type= %s\n", __func__, dbg_endpoint.type);
  690. printf("%s, DPNI ID= %d\n", __func__, dbg_endpoint.id);
  691. printf("%s, DPNI State= %d\n", __func__, state);
  692. #endif
  693. return err;
  694. }
  695. static int ldpaa_dpni_setup(struct ldpaa_eth_priv *priv)
  696. {
  697. int err;
  698. /* and get a handle for the DPNI this interface is associate with */
  699. err = dpni_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_id,
  700. &dflt_dpni->dpni_handle);
  701. if (err) {
  702. printf("dpni_open() failed\n");
  703. goto err_open;
  704. }
  705. err = dpni_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
  706. dflt_dpni->dpni_handle,
  707. &dflt_dpni->dpni_attrs);
  708. if (err) {
  709. printf("dpni_get_attributes() failed (err=%d)\n", err);
  710. goto err_get_attr;
  711. }
  712. /* Configure our buffers' layout */
  713. dflt_dpni->buf_layout.options = DPNI_BUF_LAYOUT_OPT_PARSER_RESULT |
  714. DPNI_BUF_LAYOUT_OPT_FRAME_STATUS |
  715. DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE |
  716. DPNI_BUF_LAYOUT_OPT_DATA_ALIGN;
  717. dflt_dpni->buf_layout.pass_parser_result = true;
  718. dflt_dpni->buf_layout.pass_frame_status = true;
  719. dflt_dpni->buf_layout.private_data_size = LDPAA_ETH_SWA_SIZE;
  720. /* HW erratum mandates data alignment in multiples of 256 */
  721. dflt_dpni->buf_layout.data_align = LDPAA_ETH_BUF_ALIGN;
  722. /* ...rx, ... */
  723. err = dpni_set_rx_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
  724. dflt_dpni->dpni_handle,
  725. &dflt_dpni->buf_layout);
  726. if (err) {
  727. printf("dpni_set_rx_buffer_layout() failed");
  728. goto err_buf_layout;
  729. }
  730. /* ... tx, ... */
  731. /* remove Rx-only options */
  732. dflt_dpni->buf_layout.options &= ~(DPNI_BUF_LAYOUT_OPT_DATA_ALIGN |
  733. DPNI_BUF_LAYOUT_OPT_PARSER_RESULT);
  734. err = dpni_set_tx_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
  735. dflt_dpni->dpni_handle,
  736. &dflt_dpni->buf_layout);
  737. if (err) {
  738. printf("dpni_set_tx_buffer_layout() failed");
  739. goto err_buf_layout;
  740. }
  741. /* ... tx-confirm. */
  742. dflt_dpni->buf_layout.options &= ~DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE;
  743. err = dpni_set_tx_conf_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
  744. dflt_dpni->dpni_handle,
  745. &dflt_dpni->buf_layout);
  746. if (err) {
  747. printf("dpni_set_tx_conf_buffer_layout() failed");
  748. goto err_buf_layout;
  749. }
  750. /* Now that we've set our tx buffer layout, retrieve the minimum
  751. * required tx data offset.
  752. */
  753. err = dpni_get_tx_data_offset(dflt_mc_io, MC_CMD_NO_FLAGS,
  754. dflt_dpni->dpni_handle,
  755. &priv->tx_data_offset);
  756. if (err) {
  757. printf("dpni_get_tx_data_offset() failed\n");
  758. goto err_data_offset;
  759. }
  760. /* Warn in case TX data offset is not multiple of 64 bytes. */
  761. WARN_ON(priv->tx_data_offset % 64);
  762. /* Accomodate SWA space. */
  763. priv->tx_data_offset += LDPAA_ETH_SWA_SIZE;
  764. debug("priv->tx_data_offset=%d\n", priv->tx_data_offset);
  765. return 0;
  766. err_data_offset:
  767. err_buf_layout:
  768. err_get_attr:
  769. dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
  770. err_open:
  771. return err;
  772. }
  773. static int ldpaa_dpni_bind(struct ldpaa_eth_priv *priv)
  774. {
  775. struct dpni_pools_cfg pools_params;
  776. struct dpni_tx_flow_cfg dflt_tx_flow;
  777. struct dpni_tx_conf_cfg tx_conf_cfg;
  778. int err = 0;
  779. memset(&pools_params, 0, sizeof(pools_params));
  780. pools_params.num_dpbp = 1;
  781. pools_params.pools[0].dpbp_id = (uint16_t)dflt_dpbp->dpbp_attr.id;
  782. pools_params.pools[0].buffer_size = LDPAA_ETH_RX_BUFFER_SIZE;
  783. err = dpni_set_pools(dflt_mc_io, MC_CMD_NO_FLAGS,
  784. dflt_dpni->dpni_handle, &pools_params);
  785. if (err) {
  786. printf("dpni_set_pools() failed\n");
  787. return err;
  788. }
  789. priv->tx_flow_id = DPNI_NEW_FLOW_ID;
  790. memset(&dflt_tx_flow, 0, sizeof(dflt_tx_flow));
  791. dflt_tx_flow.use_common_tx_conf_queue = 0;
  792. err = dpni_set_tx_flow(dflt_mc_io, MC_CMD_NO_FLAGS,
  793. dflt_dpni->dpni_handle, &priv->tx_flow_id,
  794. &dflt_tx_flow);
  795. if (err) {
  796. printf("dpni_set_tx_flow() failed\n");
  797. return err;
  798. }
  799. memset(&tx_conf_cfg, 0, sizeof(struct dpni_tx_conf_cfg));
  800. tx_conf_cfg.errors_only = true;
  801. /*Set tx-conf and error configuration*/
  802. err = dpni_set_tx_conf(dflt_mc_io, MC_CMD_NO_FLAGS,
  803. dflt_dpni->dpni_handle,
  804. priv->tx_flow_id, &tx_conf_cfg);
  805. if (err) {
  806. printf("dpni_set_tx_conf() failed\n");
  807. return err;
  808. }
  809. return 0;
  810. }
  811. static int ldpaa_eth_netdev_init(struct eth_device *net_dev,
  812. phy_interface_t enet_if)
  813. {
  814. int err;
  815. struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
  816. sprintf(net_dev->name, "DPMAC%d@%s", priv->dpmac_id,
  817. phy_interface_strings[enet_if]);
  818. net_dev->iobase = 0;
  819. net_dev->init = ldpaa_eth_open;
  820. net_dev->halt = ldpaa_eth_stop;
  821. net_dev->send = ldpaa_eth_tx;
  822. net_dev->recv = ldpaa_eth_pull_dequeue_rx;
  823. #ifdef CONFIG_PHYLIB
  824. err = init_phy(net_dev);
  825. if (err < 0)
  826. return err;
  827. #endif
  828. err = eth_register(net_dev);
  829. if (err < 0) {
  830. printf("eth_register() = %d\n", err);
  831. return err;
  832. }
  833. return 0;
  834. }
  835. int ldpaa_eth_init(int dpmac_id, phy_interface_t enet_if)
  836. {
  837. struct eth_device *net_dev = NULL;
  838. struct ldpaa_eth_priv *priv = NULL;
  839. int err = 0;
  840. /* Net device */
  841. net_dev = (struct eth_device *)malloc(sizeof(struct eth_device));
  842. if (!net_dev) {
  843. printf("eth_device malloc() failed\n");
  844. return -ENOMEM;
  845. }
  846. memset(net_dev, 0, sizeof(struct eth_device));
  847. /* alloc the ldpaa ethernet private struct */
  848. priv = (struct ldpaa_eth_priv *)malloc(sizeof(struct ldpaa_eth_priv));
  849. if (!priv) {
  850. printf("ldpaa_eth_priv malloc() failed\n");
  851. return -ENOMEM;
  852. }
  853. memset(priv, 0, sizeof(struct ldpaa_eth_priv));
  854. net_dev->priv = (void *)priv;
  855. priv->net_dev = (struct eth_device *)net_dev;
  856. priv->dpmac_id = dpmac_id;
  857. debug("%s dpmac_id=%d\n", __func__, dpmac_id);
  858. err = ldpaa_eth_netdev_init(net_dev, enet_if);
  859. if (err)
  860. goto err_netdev_init;
  861. debug("ldpaa ethernet: Probed interface %s\n", net_dev->name);
  862. return 0;
  863. err_netdev_init:
  864. free(priv);
  865. net_dev->priv = NULL;
  866. free(net_dev);
  867. return err;
  868. }