ldpaa_eth.c 25 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034
  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. priv->phydev = NULL;
  499. }
  500. #endif
  501. ldpaa_dpbp_free();
  502. dpni_reset(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
  503. dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
  504. }
  505. static void ldpaa_dpbp_drain_cnt(int count)
  506. {
  507. uint64_t buf_array[7];
  508. void *addr;
  509. int ret, i;
  510. BUG_ON(count > 7);
  511. do {
  512. ret = qbman_swp_acquire(dflt_dpio->sw_portal,
  513. dflt_dpbp->dpbp_attr.bpid,
  514. buf_array, count);
  515. if (ret < 0) {
  516. printf("qbman_swp_acquire() failed\n");
  517. return;
  518. }
  519. for (i = 0; i < ret; i++) {
  520. addr = (void *)buf_array[i];
  521. debug("Free: buffer addr =0x%p\n", addr);
  522. free(addr);
  523. }
  524. } while (ret);
  525. }
  526. static void ldpaa_dpbp_drain(void)
  527. {
  528. int i;
  529. for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7)
  530. ldpaa_dpbp_drain_cnt(7);
  531. }
  532. static int ldpaa_bp_add_7(uint16_t bpid)
  533. {
  534. uint64_t buf_array[7];
  535. u8 *addr;
  536. int i;
  537. struct qbman_release_desc rd;
  538. for (i = 0; i < 7; i++) {
  539. addr = memalign(LDPAA_ETH_BUF_ALIGN, LDPAA_ETH_RX_BUFFER_SIZE);
  540. if (!addr) {
  541. printf("addr allocation failed\n");
  542. goto err_alloc;
  543. }
  544. memset(addr, 0x00, LDPAA_ETH_RX_BUFFER_SIZE);
  545. flush_dcache_range((u64)addr,
  546. (u64)(addr + LDPAA_ETH_RX_BUFFER_SIZE));
  547. buf_array[i] = (uint64_t)addr;
  548. debug("Release: buffer addr =0x%p\n", addr);
  549. }
  550. release_bufs:
  551. /* In case the portal is busy, retry until successful.
  552. * This function is guaranteed to succeed in a reasonable amount
  553. * of time.
  554. */
  555. do {
  556. mdelay(1);
  557. qbman_release_desc_clear(&rd);
  558. qbman_release_desc_set_bpid(&rd, bpid);
  559. } while (qbman_swp_release(dflt_dpio->sw_portal, &rd, buf_array, i));
  560. return i;
  561. err_alloc:
  562. if (i)
  563. goto release_bufs;
  564. return 0;
  565. }
  566. static int ldpaa_dpbp_seed(uint16_t bpid)
  567. {
  568. int i;
  569. int count;
  570. for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7) {
  571. count = ldpaa_bp_add_7(bpid);
  572. if (count < 7)
  573. printf("Buffer Seed= %d\n", count);
  574. }
  575. return 0;
  576. }
  577. static int ldpaa_dpbp_setup(void)
  578. {
  579. int err;
  580. err = dpbp_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_attr.id,
  581. &dflt_dpbp->dpbp_handle);
  582. if (err) {
  583. printf("dpbp_open() failed\n");
  584. goto err_open;
  585. }
  586. err = dpbp_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
  587. if (err) {
  588. printf("dpbp_enable() failed\n");
  589. goto err_enable;
  590. }
  591. err = dpbp_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
  592. dflt_dpbp->dpbp_handle,
  593. &dflt_dpbp->dpbp_attr);
  594. if (err) {
  595. printf("dpbp_get_attributes() failed\n");
  596. goto err_get_attr;
  597. }
  598. err = ldpaa_dpbp_seed(dflt_dpbp->dpbp_attr.bpid);
  599. if (err) {
  600. printf("Buffer seeding failed for DPBP %d (bpid=%d)\n",
  601. dflt_dpbp->dpbp_attr.id, dflt_dpbp->dpbp_attr.bpid);
  602. goto err_seed;
  603. }
  604. return 0;
  605. err_seed:
  606. err_get_attr:
  607. dpbp_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
  608. err_enable:
  609. dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
  610. err_open:
  611. return err;
  612. }
  613. static void ldpaa_dpbp_free(void)
  614. {
  615. ldpaa_dpbp_drain();
  616. dpbp_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
  617. dpbp_reset(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
  618. dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
  619. }
  620. static int ldpaa_dpmac_version_check(struct fsl_mc_io *mc_io,
  621. struct ldpaa_eth_priv *priv)
  622. {
  623. struct dpmac_attr attr;
  624. int error;
  625. memset(&attr, 0, sizeof(struct dpmac_attr));
  626. error = dpmac_get_attributes(mc_io, MC_CMD_NO_FLAGS,
  627. priv->dpmac_handle,
  628. &attr);
  629. if (error == 0) {
  630. if ((attr.version.major != DPMAC_VER_MAJOR) ||
  631. (attr.version.minor != DPMAC_VER_MINOR)) {
  632. printf("DPMAC version mismatch found %u.%u,",
  633. attr.version.major, attr.version.minor);
  634. printf("supported version is %u.%u\n",
  635. DPMAC_VER_MAJOR, DPMAC_VER_MINOR);
  636. }
  637. }
  638. return error;
  639. }
  640. static int ldpaa_dpmac_setup(struct ldpaa_eth_priv *priv)
  641. {
  642. int err = 0;
  643. struct dpmac_cfg dpmac_cfg;
  644. dpmac_cfg.mac_id = priv->dpmac_id;
  645. err = dpmac_create(dflt_mc_io, MC_CMD_NO_FLAGS, &dpmac_cfg,
  646. &priv->dpmac_handle);
  647. if (err)
  648. printf("dpmac_create() failed\n");
  649. err = ldpaa_dpmac_version_check(dflt_mc_io, priv);
  650. if (err < 0)
  651. printf("ldpaa_dpmac_version_check() failed: %d\n", err);
  652. return err;
  653. }
  654. static int ldpaa_dpmac_bind(struct ldpaa_eth_priv *priv)
  655. {
  656. int err = 0;
  657. struct dprc_connection_cfg dprc_connection_cfg = {
  658. /* If both rates are zero the connection */
  659. /* will be configured in "best effort" mode. */
  660. .committed_rate = 0,
  661. .max_rate = 0
  662. };
  663. #ifdef DEBUG
  664. struct dprc_endpoint dbg_endpoint;
  665. int state = 0;
  666. #endif
  667. memset(&dpmac_endpoint, 0, sizeof(struct dprc_endpoint));
  668. strcpy(dpmac_endpoint.type, "dpmac");
  669. dpmac_endpoint.id = priv->dpmac_id;
  670. memset(&dpni_endpoint, 0, sizeof(struct dprc_endpoint));
  671. strcpy(dpni_endpoint.type, "dpni");
  672. dpni_endpoint.id = dflt_dpni->dpni_id;
  673. err = dprc_connect(dflt_mc_io, MC_CMD_NO_FLAGS,
  674. dflt_dprc_handle,
  675. &dpmac_endpoint,
  676. &dpni_endpoint,
  677. &dprc_connection_cfg);
  678. if (err)
  679. printf("dprc_connect() failed\n");
  680. #ifdef DEBUG
  681. err = dprc_get_connection(dflt_mc_io, MC_CMD_NO_FLAGS,
  682. dflt_dprc_handle, &dpni_endpoint,
  683. &dbg_endpoint, &state);
  684. printf("%s, DPMAC Type= %s\n", __func__, dbg_endpoint.type);
  685. printf("%s, DPMAC ID= %d\n", __func__, dbg_endpoint.id);
  686. printf("%s, DPMAC State= %d\n", __func__, state);
  687. memset(&dbg_endpoint, 0, sizeof(struct dprc_endpoint));
  688. err = dprc_get_connection(dflt_mc_io, MC_CMD_NO_FLAGS,
  689. dflt_dprc_handle, &dpmac_endpoint,
  690. &dbg_endpoint, &state);
  691. printf("%s, DPNI Type= %s\n", __func__, dbg_endpoint.type);
  692. printf("%s, DPNI ID= %d\n", __func__, dbg_endpoint.id);
  693. printf("%s, DPNI State= %d\n", __func__, state);
  694. #endif
  695. return err;
  696. }
  697. static int ldpaa_dpni_setup(struct ldpaa_eth_priv *priv)
  698. {
  699. int err;
  700. /* and get a handle for the DPNI this interface is associate with */
  701. err = dpni_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_id,
  702. &dflt_dpni->dpni_handle);
  703. if (err) {
  704. printf("dpni_open() failed\n");
  705. goto err_open;
  706. }
  707. err = dpni_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
  708. dflt_dpni->dpni_handle,
  709. &dflt_dpni->dpni_attrs);
  710. if (err) {
  711. printf("dpni_get_attributes() failed (err=%d)\n", err);
  712. goto err_get_attr;
  713. }
  714. /* Configure our buffers' layout */
  715. dflt_dpni->buf_layout.options = DPNI_BUF_LAYOUT_OPT_PARSER_RESULT |
  716. DPNI_BUF_LAYOUT_OPT_FRAME_STATUS |
  717. DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE |
  718. DPNI_BUF_LAYOUT_OPT_DATA_ALIGN;
  719. dflt_dpni->buf_layout.pass_parser_result = true;
  720. dflt_dpni->buf_layout.pass_frame_status = true;
  721. dflt_dpni->buf_layout.private_data_size = LDPAA_ETH_SWA_SIZE;
  722. /* HW erratum mandates data alignment in multiples of 256 */
  723. dflt_dpni->buf_layout.data_align = LDPAA_ETH_BUF_ALIGN;
  724. /* ...rx, ... */
  725. err = dpni_set_rx_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
  726. dflt_dpni->dpni_handle,
  727. &dflt_dpni->buf_layout);
  728. if (err) {
  729. printf("dpni_set_rx_buffer_layout() failed");
  730. goto err_buf_layout;
  731. }
  732. /* ... tx, ... */
  733. /* remove Rx-only options */
  734. dflt_dpni->buf_layout.options &= ~(DPNI_BUF_LAYOUT_OPT_DATA_ALIGN |
  735. DPNI_BUF_LAYOUT_OPT_PARSER_RESULT);
  736. err = dpni_set_tx_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
  737. dflt_dpni->dpni_handle,
  738. &dflt_dpni->buf_layout);
  739. if (err) {
  740. printf("dpni_set_tx_buffer_layout() failed");
  741. goto err_buf_layout;
  742. }
  743. /* ... tx-confirm. */
  744. dflt_dpni->buf_layout.options &= ~DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE;
  745. err = dpni_set_tx_conf_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
  746. dflt_dpni->dpni_handle,
  747. &dflt_dpni->buf_layout);
  748. if (err) {
  749. printf("dpni_set_tx_conf_buffer_layout() failed");
  750. goto err_buf_layout;
  751. }
  752. /* Now that we've set our tx buffer layout, retrieve the minimum
  753. * required tx data offset.
  754. */
  755. err = dpni_get_tx_data_offset(dflt_mc_io, MC_CMD_NO_FLAGS,
  756. dflt_dpni->dpni_handle,
  757. &priv->tx_data_offset);
  758. if (err) {
  759. printf("dpni_get_tx_data_offset() failed\n");
  760. goto err_data_offset;
  761. }
  762. /* Warn in case TX data offset is not multiple of 64 bytes. */
  763. WARN_ON(priv->tx_data_offset % 64);
  764. /* Accomodate SWA space. */
  765. priv->tx_data_offset += LDPAA_ETH_SWA_SIZE;
  766. debug("priv->tx_data_offset=%d\n", priv->tx_data_offset);
  767. return 0;
  768. err_data_offset:
  769. err_buf_layout:
  770. err_get_attr:
  771. dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
  772. err_open:
  773. return err;
  774. }
  775. static int ldpaa_dpni_bind(struct ldpaa_eth_priv *priv)
  776. {
  777. struct dpni_pools_cfg pools_params;
  778. struct dpni_tx_flow_cfg dflt_tx_flow;
  779. struct dpni_tx_conf_cfg tx_conf_cfg;
  780. int err = 0;
  781. memset(&pools_params, 0, sizeof(pools_params));
  782. pools_params.num_dpbp = 1;
  783. pools_params.pools[0].dpbp_id = (uint16_t)dflt_dpbp->dpbp_attr.id;
  784. pools_params.pools[0].buffer_size = LDPAA_ETH_RX_BUFFER_SIZE;
  785. err = dpni_set_pools(dflt_mc_io, MC_CMD_NO_FLAGS,
  786. dflt_dpni->dpni_handle, &pools_params);
  787. if (err) {
  788. printf("dpni_set_pools() failed\n");
  789. return err;
  790. }
  791. priv->tx_flow_id = DPNI_NEW_FLOW_ID;
  792. memset(&dflt_tx_flow, 0, sizeof(dflt_tx_flow));
  793. dflt_tx_flow.use_common_tx_conf_queue = 0;
  794. err = dpni_set_tx_flow(dflt_mc_io, MC_CMD_NO_FLAGS,
  795. dflt_dpni->dpni_handle, &priv->tx_flow_id,
  796. &dflt_tx_flow);
  797. if (err) {
  798. printf("dpni_set_tx_flow() failed\n");
  799. return err;
  800. }
  801. memset(&tx_conf_cfg, 0, sizeof(struct dpni_tx_conf_cfg));
  802. tx_conf_cfg.errors_only = true;
  803. /*Set tx-conf and error configuration*/
  804. err = dpni_set_tx_conf(dflt_mc_io, MC_CMD_NO_FLAGS,
  805. dflt_dpni->dpni_handle,
  806. priv->tx_flow_id, &tx_conf_cfg);
  807. if (err) {
  808. printf("dpni_set_tx_conf() failed\n");
  809. return err;
  810. }
  811. return 0;
  812. }
  813. static int ldpaa_eth_netdev_init(struct eth_device *net_dev,
  814. phy_interface_t enet_if)
  815. {
  816. int err;
  817. struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
  818. sprintf(net_dev->name, "DPMAC%d@%s", priv->dpmac_id,
  819. phy_interface_strings[enet_if]);
  820. net_dev->iobase = 0;
  821. net_dev->init = ldpaa_eth_open;
  822. net_dev->halt = ldpaa_eth_stop;
  823. net_dev->send = ldpaa_eth_tx;
  824. net_dev->recv = ldpaa_eth_pull_dequeue_rx;
  825. #ifdef CONFIG_PHYLIB
  826. err = init_phy(net_dev);
  827. if (err < 0)
  828. return err;
  829. #endif
  830. err = eth_register(net_dev);
  831. if (err < 0) {
  832. printf("eth_register() = %d\n", err);
  833. return err;
  834. }
  835. return 0;
  836. }
  837. int ldpaa_eth_init(int dpmac_id, phy_interface_t enet_if)
  838. {
  839. struct eth_device *net_dev = NULL;
  840. struct ldpaa_eth_priv *priv = NULL;
  841. int err = 0;
  842. /* Net device */
  843. net_dev = (struct eth_device *)malloc(sizeof(struct eth_device));
  844. if (!net_dev) {
  845. printf("eth_device malloc() failed\n");
  846. return -ENOMEM;
  847. }
  848. memset(net_dev, 0, sizeof(struct eth_device));
  849. /* alloc the ldpaa ethernet private struct */
  850. priv = (struct ldpaa_eth_priv *)malloc(sizeof(struct ldpaa_eth_priv));
  851. if (!priv) {
  852. printf("ldpaa_eth_priv malloc() failed\n");
  853. return -ENOMEM;
  854. }
  855. memset(priv, 0, sizeof(struct ldpaa_eth_priv));
  856. net_dev->priv = (void *)priv;
  857. priv->net_dev = (struct eth_device *)net_dev;
  858. priv->dpmac_id = dpmac_id;
  859. debug("%s dpmac_id=%d\n", __func__, dpmac_id);
  860. err = ldpaa_eth_netdev_init(net_dev, enet_if);
  861. if (err)
  862. goto err_netdev_init;
  863. debug("ldpaa ethernet: Probed interface %s\n", net_dev->name);
  864. return 0;
  865. err_netdev_init:
  866. free(priv);
  867. net_dev->priv = NULL;
  868. free(net_dev);
  869. return err;
  870. }