dw_eth_mac.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717
  1. /*
  2. * Copyright (C) Cvitek Co., Ltd. 2019-2020. All rights reserved.
  3. */
  4. #include <rtthread.h>
  5. #include "dw_eth_mac.h"
  6. #include "cache.h"
  7. #define roundup(x, y) ( \
  8. { \
  9. const typeof(y) __y = y; \
  10. (((x) + (__y - 1)) / __y) * __y; \
  11. } \
  12. )
  13. #define CONFIG_GMAC_NUM 2
  14. static gmac_dev_t gmac_instance[CONFIG_GMAC_NUM];
  15. static int32_t designware_read_hwaddr(eth_mac_handle_t handle)
  16. {
  17. gmac_dev_t *mac_dev = (gmac_dev_t *)handle;
  18. struct dw_gmac_mac_regs *mac_reg = mac_dev->priv->mac_regs_p;
  19. uint32_t macid_lo, macid_hi;
  20. uint8_t mac_id[6] = {0};
  21. macid_hi = mac_reg->macaddr0hi;
  22. macid_lo = mac_reg->macaddr0lo;
  23. mac_id[0] = macid_lo & 0xff;
  24. mac_id[1] = (macid_lo >> 8) & 0xff;
  25. mac_id[2] = (macid_lo >> 16) & 0xff;
  26. mac_id[3] = (macid_lo >> 24) & 0xff;
  27. mac_id[4] = macid_hi & 0xff;
  28. mac_id[5] = (macid_hi >> 8) & 0xff;
  29. memcpy(mac_dev->mac_addr, mac_id, sizeof(mac_id));
  30. return 0;
  31. }
  32. static int32_t designware_write_hwaddr(eth_mac_handle_t handle)
  33. {
  34. gmac_dev_t *mac_dev = (gmac_dev_t *)handle;
  35. struct dw_gmac_mac_regs *mac_reg = mac_dev->priv->mac_regs_p;
  36. uint32_t macid_lo, macid_hi;
  37. uint8_t *mac_id = mac_dev->mac_addr;
  38. macid_lo = mac_id[0] + (mac_id[1] << 8) + (mac_id[2] << 16) +
  39. (mac_id[3] << 24);
  40. macid_hi = mac_id[4] + (mac_id[5] << 8);
  41. mac_reg->macaddr0hi = macid_hi;
  42. mac_reg->macaddr0lo = macid_lo;
  43. return 0;
  44. }
  45. static void tx_descs_init(eth_mac_handle_t handle)
  46. {
  47. gmac_dev_t *mac_dev = (gmac_dev_t *)handle;
  48. struct dw_gmac_priv *priv = mac_dev->priv;
  49. struct dw_gmac_dma_regs *dma_reg = priv->dma_regs_p;
  50. struct dmamacdescr *desc_table_p = &priv->tx_mac_descrtable[0];
  51. char *txbuffs = &priv->txbuffs[0];
  52. struct dmamacdescr *desc_p;
  53. uint32_t idx;
  54. for (idx = 0; idx < CVI_CONFIG_TX_DESCR_NUM; idx++) {
  55. desc_p = &desc_table_p[idx];
  56. desc_p->dmamac_addr = (unsigned long)&txbuffs[idx * CVI_CONFIG_ETH_BUFSIZE];
  57. desc_p->dmamac_next = (unsigned long)&desc_table_p[idx + 1];
  58. #if defined(CONFIG_DW_ALTDESCRIPTOR)
  59. desc_p->txrx_status &= ~(CVI_DESC_TXSTS_TXINT | CVI_DESC_TXSTS_TXLAST |
  60. CVI_DESC_TXSTS_TXFIRST | CVI_DESC_TXSTS_TXCRCDIS |
  61. CVI_DESC_TXSTS_TXCHECKINSCTRL |
  62. CVI_DESC_TXSTS_TXRINGEND | CVI_DESC_TXSTS_TXPADDIS);
  63. desc_p->txrx_status |= CVI_DESC_TXSTS_TXCHAIN;
  64. desc_p->dmamac_cntl = 0;
  65. desc_p->txrx_status &= ~(CVI_DESC_TXSTS_MSK | CVI_DESC_TXSTS_OWNBYDMA);
  66. #else
  67. desc_p->dmamac_cntl = CVI_DESC_TXCTRL_TXCHAIN;
  68. desc_p->txrx_status = 0;
  69. #endif
  70. }
  71. /* Correcting the last pointer of the chain */
  72. desc_p->dmamac_next = (unsigned long)&desc_table_p[0];
  73. /* Flush all Tx buffer descriptors at once */
  74. rt_hw_cpu_dcache_clean((unsigned long)priv->tx_mac_descrtable, sizeof(priv->tx_mac_descrtable));
  75. dma_reg->txdesclistaddr = (unsigned long)&desc_table_p[0];
  76. priv->tx_currdescnum = 0;
  77. }
  78. static void rx_descs_init(eth_mac_handle_t handle)
  79. {
  80. gmac_dev_t *mac_dev = (gmac_dev_t *)handle;
  81. struct dw_gmac_priv *priv = mac_dev->priv;
  82. struct dw_gmac_dma_regs *dma_reg = priv->dma_regs_p;
  83. struct dmamacdescr *desc_table_p = &priv->rx_mac_descrtable[0];
  84. char *rxbuffs = &priv->rxbuffs[0];
  85. struct dmamacdescr *desc_p;
  86. uint32_t idx;
  87. /* Before passing buffers to GMAC we need to make sure zeros
  88. * written there right after "priv" structure allocation were
  89. * flushed into RAM.
  90. * Otherwise there's a chance to get some of them flushed in RAM when
  91. * GMAC is already pushing data to RAM via DMA. This way incoming from
  92. * GMAC data will be corrupted. */
  93. rt_hw_cpu_dcache_clean((unsigned long)rxbuffs, CVI_RX_TOTAL_BUFSIZE);
  94. for (idx = 0; idx < CVI_CONFIG_RX_DESCR_NUM; idx++) {
  95. desc_p = &desc_table_p[idx];
  96. desc_p->dmamac_addr = (unsigned long)&rxbuffs[idx * CVI_CONFIG_ETH_BUFSIZE];
  97. desc_p->dmamac_next = (unsigned long)&desc_table_p[idx + 1];
  98. desc_p->dmamac_cntl =
  99. (CVI_MAC_MAX_FRAME_SZ & CVI_DESC_RXCTRL_SIZE1MASK) |
  100. CVI_DESC_RXCTRL_RXCHAIN;
  101. desc_p->txrx_status = CVI_DESC_RXSTS_OWNBYDMA;
  102. }
  103. /* Correcting the last pointer of the chain */
  104. desc_p->dmamac_next = (unsigned long)&desc_table_p[0];
  105. /* Flush all Rx buffer descriptors at once */
  106. rt_hw_cpu_dcache_clean((unsigned long)priv->rx_mac_descrtable, sizeof(priv->rx_mac_descrtable));
  107. dma_reg->rxdesclistaddr = (unsigned long)&desc_table_p[0];
  108. priv->rx_currdescnum = 0;
  109. }
  110. static int32_t designware_adjust_link(eth_mac_handle_t handle)
  111. {
  112. gmac_dev_t *mac_dev = (gmac_dev_t *)handle;
  113. struct dw_gmac_priv *priv = mac_dev->priv;
  114. struct dw_gmac_mac_regs *mac_reg = priv->mac_regs_p;
  115. eth_link_info_t *link_info = &mac_dev->phy_dev->priv->link_info;
  116. eth_link_state_t link_state = mac_dev->phy_dev->link_state;
  117. uint32_t conf = mac_reg->conf | CVI_FRAMEBURSTENABLE | CVI_DISABLERXOWN;
  118. if (!link_state) {
  119. rt_kprintf("eth No link.\n");
  120. return 0;
  121. }
  122. if (link_info->speed != CSI_ETH_SPEED_1G)
  123. conf |= CVI_MII_PORTSELECT;
  124. else
  125. conf &= ~CVI_MII_PORTSELECT;
  126. if (link_info->speed == CSI_ETH_SPEED_100M)
  127. conf |= CVI_FES_100;
  128. if (link_info->duplex)
  129. conf |= CVI_FULLDPLXMODE;
  130. mac_reg->conf = conf;
  131. rt_kprintf("Speed: %s, duplex: %s\n",
  132. (link_info->speed) ? "100M" : "10M",
  133. (link_info->duplex) ? "full" : "half");
  134. return 0;
  135. }
  136. static int32_t designware_eth_init(eth_mac_handle_t handle)
  137. {
  138. gmac_dev_t *mac_dev = (gmac_dev_t *)handle;
  139. struct dw_gmac_mac_regs *mac_reg = mac_dev->priv->mac_regs_p;
  140. struct dw_gmac_dma_regs *dma_reg = mac_dev->priv->dma_regs_p;
  141. uint32_t start;
  142. dma_reg->busmode |= CVI_DMAMAC_SRST;
  143. start = rt_tick_get_millisecond();
  144. while (dma_reg->busmode & CVI_DMAMAC_SRST) {
  145. if ((rt_tick_get_millisecond() - start) >= CVI_CONFIG_MACRESET_TIMEOUT) {
  146. rt_kprintf("DMA reset timeout\n");
  147. return -ETIMEDOUT;
  148. }
  149. rt_thread_mdelay(100);
  150. };
  151. /*
  152. * Soft reset above clears HW address registers.
  153. * So we have to set it here once again.
  154. */
  155. // designware_read_hwaddr(handle);
  156. // designware_write_hwaddr(handle);
  157. rx_descs_init(handle);
  158. tx_descs_init(handle);
  159. dma_reg->busmode = (CVI_FIXEDBURST | CVI_PRIORXTX_41 | CVI_DMA_PBL);
  160. // mac_reg->framefilt = 0x10;
  161. // mac_reg->flowcontrol = 0x8;
  162. // dma_reg->wdtforri = 0xff;
  163. // dma_reg->axibus = 0x0012100F;
  164. #ifndef CONFIG_DW_MAC_FORCE_THRESHOLD_MODE
  165. dma_reg->opmode |= (CVI_FLUSHTXFIFO | CVI_STOREFORWARD);
  166. #else
  167. dma_reg->opmode |= CVI_FLUSHTXFIFO;
  168. #endif
  169. dma_reg->opmode |= (CVI_RXSTART | CVI_TXSTART);
  170. dma_reg->opmode = 0x2202906;
  171. dma_reg->busmode = 0x3900800;
  172. mac_reg->conf = 0x41cc00;
  173. dma_reg->intenable = 0x10040;
  174. #ifdef CONFIG_DW_AXI_BURST_LEN
  175. dma_reg->axibus = (CONFIG_DW_AXI_BURST_LEN & 0x1FF >> 1);
  176. #endif
  177. /* Start up the PHY */
  178. /* adjust link */
  179. return 0;
  180. }
  181. static int32_t designware_eth_enable(eth_mac_handle_t handle, int32_t control)
  182. {
  183. gmac_dev_t *mac_dev = (gmac_dev_t *)handle;
  184. struct dw_gmac_mac_regs *mac_reg = mac_dev->priv->mac_regs_p;
  185. eth_link_state_t link_state = mac_dev->phy_dev->link_state;
  186. if (link_state == ETH_LINK_DOWN)
  187. return -1;
  188. switch (control) {
  189. case CSI_ETH_MAC_CONTROL_TX:
  190. mac_reg->conf |= CVI_TXENABLE;
  191. break;
  192. case CSI_ETH_MAC_CONTROL_RX:
  193. mac_reg->conf |= CVI_RXENABLE;
  194. break;
  195. default:
  196. break;
  197. }
  198. return 0;
  199. }
  200. static int32_t designware_eth_disable(eth_mac_handle_t handle, int32_t arg)
  201. {
  202. gmac_dev_t *mac_dev = (gmac_dev_t *)handle;
  203. struct dw_gmac_mac_regs *mac_reg = mac_dev->priv->mac_regs_p;
  204. switch (arg) {
  205. case CSI_ETH_MAC_CONTROL_TX:
  206. mac_reg->conf &= ~CVI_TXENABLE;
  207. break;
  208. case CSI_ETH_MAC_CONTROL_RX:
  209. mac_reg->conf &= ~CVI_RXENABLE;
  210. break;
  211. default:
  212. break;
  213. }
  214. return 0;
  215. }
  216. static int32_t designware_eth_start(eth_mac_handle_t handle)
  217. {
  218. int32_t ret;
  219. ret = designware_eth_init(handle);
  220. if (ret)
  221. return ret;
  222. return 0;
  223. }
  224. void designware_eth_stop(eth_mac_handle_t handle)
  225. {
  226. gmac_dev_t *mac_dev = (gmac_dev_t *)handle;
  227. struct dw_gmac_mac_regs *mac_reg = mac_dev->priv->mac_regs_p;
  228. struct dw_gmac_dma_regs *dma_reg = mac_dev->priv->dma_regs_p;
  229. mac_reg->conf &= ~(CVI_RXENABLE | CVI_TXENABLE);
  230. dma_reg->opmode &= ~(CVI_RXSTART | CVI_TXSTART);
  231. //phy_shutdown(priv->phydev);
  232. }
  233. static int32_t designware_eth_send(eth_mac_handle_t handle, const uint8_t *frame, uint32_t length)
  234. {
  235. gmac_dev_t *mac_dev = (gmac_dev_t *)handle;
  236. struct dw_gmac_priv *priv = mac_dev->priv;
  237. struct dw_gmac_dma_regs *dma_reg = mac_dev->priv->dma_regs_p;
  238. uint32_t desc_num = priv->tx_currdescnum;
  239. struct dmamacdescr *desc_p = &priv->tx_mac_descrtable[desc_num];
  240. uint64_t desc_start = (uint64_t)desc_p;
  241. uint64_t desc_end = desc_start + roundup(sizeof(*desc_p), DW_GMAC_DMA_ALIGN);
  242. uint64_t data_start = desc_p->dmamac_addr;
  243. uint64_t data_end = data_start + roundup(length, DW_GMAC_DMA_ALIGN);
  244. uint32_t count = 0;
  245. /*
  246. * Strictly we only need to invalidate the "txrx_status" field
  247. * for the following check, but on some platforms we cannot
  248. * invalidate only 4 bytes, so we flush the entire descriptor,
  249. * which is 16 bytes in total. This is safe because the
  250. * individual descriptors in the array are each aligned to
  251. * DW_GMAC_DMA_ALIGN and padded appropriately.
  252. */
  253. /* Check if the descriptor is owned by CPU */
  254. while (1) {
  255. rt_hw_cpu_dcache_invalidate(desc_start, desc_end - desc_start);
  256. if (!(desc_p->txrx_status & CVI_DESC_TXSTS_OWNBYDMA)) {
  257. break;
  258. }
  259. if (count > 1000) {
  260. rt_kprintf("desc onwer is DMA\n");
  261. return -1;
  262. }
  263. count ++;
  264. rt_thread_mdelay(1);
  265. }
  266. memcpy((void *)data_start, frame, length);
  267. /* Flush data to be sent */
  268. rt_hw_cpu_dcache_clean(data_start, data_end - data_start);
  269. #if defined(CONFIG_DW_ALTDESCRIPTOR)
  270. desc_p->txrx_status |= CVI_DESC_TXSTS_TXFIRST | CVI_DESC_TXSTS_TXLAST;
  271. desc_p->dmamac_cntl &= ~CVI_DESC_TXCTRL_SIZE1MASK;
  272. desc_p->dmamac_cntl |= (length << CVI_DESC_TXCTRL_SIZE1SHFT) &
  273. CVI_DESC_TXCTRL_SIZE1MASK;
  274. desc_p->txrx_status &= ~(CVI_DESC_TXSTS_MSK);
  275. desc_p->txrx_status |= CVI_DESC_TXSTS_OWNBYDMA;
  276. #else
  277. desc_p->dmamac_cntl &= ~CVI_DESC_TXCTRL_SIZE1MASK;
  278. desc_p->dmamac_cntl |= ((length << CVI_DESC_TXCTRL_SIZE1SHFT) &
  279. CVI_DESC_TXCTRL_SIZE1MASK) | CVI_DESC_TXCTRL_TXLAST |
  280. CVI_DESC_TXCTRL_TXFIRST;
  281. desc_p->txrx_status = CVI_DESC_TXSTS_OWNBYDMA;
  282. #endif
  283. /* Flush modified buffer descriptor */
  284. rt_hw_cpu_dcache_clean(desc_start, desc_end - desc_start);
  285. /* Test the wrap-around condition. */
  286. if (++desc_num >= CVI_CONFIG_TX_DESCR_NUM)
  287. desc_num = 0;
  288. priv->tx_currdescnum = desc_num;
  289. /* Start the transmission */
  290. dma_reg->txpolldemand = CVI_POLL_DATA;
  291. return 0;
  292. }
  293. static int32_t designware_eth_recv(eth_mac_handle_t handle, uint8_t **packetp)
  294. {
  295. gmac_dev_t *mac_dev = (gmac_dev_t *)handle;
  296. struct dw_gmac_priv *priv = mac_dev->priv;
  297. uint32_t status, desc_num = priv->rx_currdescnum;
  298. struct dmamacdescr *desc_p = &priv->rx_mac_descrtable[desc_num];
  299. int32_t length = -1;
  300. uint64_t desc_start = (uint64_t)desc_p;
  301. uint64_t desc_end = desc_start +
  302. roundup(sizeof(*desc_p), DW_GMAC_DMA_ALIGN);
  303. uint64_t data_start = desc_p->dmamac_addr;
  304. uint64_t data_end;
  305. /* Invalidate entire buffer descriptor */
  306. rt_hw_cpu_dcache_invalidate(desc_start, desc_end - desc_start);
  307. status = desc_p->txrx_status;
  308. /* Check if the owner is the CPU */
  309. if (!(status & CVI_DESC_RXSTS_OWNBYDMA)) {
  310. length = (status & CVI_DESC_RXSTS_FRMLENMSK) >>
  311. CVI_DESC_RXSTS_FRMLENSHFT;
  312. /* Invalidate received data */
  313. data_end = data_start + roundup(length, DW_GMAC_DMA_ALIGN);
  314. rt_hw_cpu_dcache_invalidate(data_start, data_end - data_start);
  315. *packetp = (uint8_t *)((uint64_t)desc_p->dmamac_addr);
  316. }
  317. return length;
  318. }
  319. static int32_t designware_free_pkt(eth_mac_handle_t handle)
  320. {
  321. gmac_dev_t *mac_dev = (gmac_dev_t *)handle;
  322. struct dw_gmac_priv *priv = mac_dev->priv;
  323. uint32_t desc_num = priv->rx_currdescnum;
  324. struct dmamacdescr *desc_p = &priv->rx_mac_descrtable[desc_num];
  325. uint64_t desc_start = (uint64_t)desc_p;
  326. uint64_t desc_end = desc_start +
  327. roundup(sizeof(*desc_p), DW_GMAC_DMA_ALIGN);
  328. /*
  329. * Make the current descriptor valid again and go to
  330. * the next one
  331. */
  332. desc_p->txrx_status |= CVI_DESC_RXSTS_OWNBYDMA;
  333. /* Flush only status field - others weren't changed */
  334. rt_hw_cpu_dcache_clean(desc_start, desc_end - desc_start);
  335. /* Test the wrap-around condition. */
  336. if (++desc_num >= CVI_CONFIG_RX_DESCR_NUM)
  337. desc_num = 0;
  338. priv->rx_currdescnum = desc_num;
  339. return 0;
  340. }
  341. /**
  342. \brief Connect phy device to mac device.
  343. \param[in] handle_mac mac handle
  344. \param[in] handle_phy phy handle
  345. */
  346. void dw_eth_mac_connect_phy(eth_mac_handle_t handle_mac, eth_phy_handle_t handle_phy)
  347. {
  348. RT_ASSERT(handle_mac);
  349. RT_ASSERT(handle_phy);
  350. gmac_dev_t *mac_dev = (gmac_dev_t *)handle_mac;
  351. eth_phy_dev_t *phy_dev = (eth_phy_dev_t *)handle_phy;
  352. mac_dev->phy_dev = phy_dev;
  353. }
  354. /**
  355. \brief Read Ethernet PHY Register through Management Interface.
  356. \param[in] handle ethernet handle
  357. \param[in] phy_addr 5-bit device address
  358. \param[in] reg_addr 5-bit register address
  359. \param[out] data Pointer where the result is written to
  360. \return error code
  361. */
  362. int32_t dw_eth_mac_phy_read(eth_mac_handle_t handle, uint8_t phy_addr, uint8_t reg_addr, uint16_t *data)
  363. {
  364. RT_ASSERT(handle);
  365. RT_ASSERT(data);
  366. gmac_dev_t *mac_dev = (gmac_dev_t *)handle;
  367. struct dw_gmac_priv *priv = mac_dev->priv;
  368. struct dw_gmac_mac_regs *mac_reg = priv->mac_regs_p;
  369. uint16_t miiaddr;
  370. int32_t start;
  371. miiaddr = ((phy_addr << CVI_MIIADDRSHIFT) & CVI_MII_ADDRMSK) |
  372. ((reg_addr << CVI_MIIREGSHIFT) & CVI_MII_REGMSK);
  373. mac_reg->miiaddr = (miiaddr | CVI_MII_CLKRANGE_150_250M | CVI_MII_BUSY);
  374. start = rt_tick_get_millisecond();
  375. while ((rt_tick_get_millisecond() - start) < CVI_CONFIG_MDIO_TIMEOUT) {
  376. if (!(mac_reg->miiaddr & CVI_MII_BUSY)) {
  377. *data = mac_reg->miidata;
  378. return 0;
  379. }
  380. rt_hw_us_delay(10);
  381. };
  382. return -1;
  383. }
  384. /**
  385. \brief Write Ethernet PHY Register through Management Interface.
  386. \param[in] handle ethernet handle
  387. \param[in] phy_addr 5-bit device address
  388. \param[in] reg_addr 5-bit register address
  389. \param[in] data 16-bit data to write
  390. \return error code
  391. */
  392. int32_t dw_eth_mac_phy_write(eth_mac_handle_t handle, uint8_t phy_addr, uint8_t reg_addr, uint16_t data)
  393. {
  394. RT_ASSERT(handle);
  395. gmac_dev_t *mac_dev = (gmac_dev_t *)handle;
  396. struct dw_gmac_priv *priv = mac_dev->priv;
  397. struct dw_gmac_mac_regs *mac_reg = priv->mac_regs_p;
  398. uint16_t miiaddr;
  399. int32_t start;
  400. mac_reg->miidata = data;
  401. miiaddr = ((phy_addr << CVI_MIIADDRSHIFT) & CVI_MII_ADDRMSK) |
  402. ((reg_addr << CVI_MIIREGSHIFT) & CVI_MII_REGMSK) | CVI_MII_WRITE;
  403. mac_reg->miiaddr = (miiaddr | CVI_MII_CLKRANGE_150_250M | CVI_MII_BUSY);
  404. start = rt_tick_get_millisecond();
  405. while ((rt_tick_get_millisecond() - start) < CVI_CONFIG_MDIO_TIMEOUT) {
  406. if (!(mac_reg->miiaddr & CVI_MII_BUSY)) {
  407. return 0;
  408. }
  409. rt_hw_us_delay(10);
  410. };
  411. return -1;
  412. }
  413. /**
  414. \brief Control Ethernet Interface.
  415. \param[in] handle ethernet handle
  416. \param[in] control Operation
  417. \param[in] arg Argument of operation (optional)
  418. \return error code
  419. */
  420. int32_t cvi_eth_mac_control(eth_mac_handle_t handle, uint32_t control, uint32_t arg)
  421. {
  422. RT_ASSERT(handle);
  423. gmac_dev_t *mac_dev = (gmac_dev_t *)handle;
  424. int32_t ret = 0;
  425. RT_ASSERT(mac_dev->phy_dev);
  426. switch (control) {
  427. case CSI_ETH_MAC_CONFIGURE:
  428. if (arg) {
  429. /* startup mac */
  430. ret = designware_eth_start(handle);
  431. } else {
  432. /* stop mac */
  433. designware_eth_stop(handle);
  434. }
  435. break;
  436. case DRV_ETH_MAC_ADJUST_LINK:
  437. ret = designware_adjust_link(handle);
  438. break;
  439. case CSI_ETH_MAC_CONTROL_TX:
  440. if (arg) {
  441. /* enable TX */
  442. ret = designware_eth_enable(handle, CSI_ETH_MAC_CONTROL_TX);
  443. } else {
  444. /* disable TX */
  445. ret = designware_eth_disable(handle, CSI_ETH_MAC_CONTROL_TX);
  446. }
  447. break;
  448. case CSI_ETH_MAC_CONTROL_RX:
  449. if (arg) {
  450. /* enable RX */
  451. ret = designware_eth_enable(handle, CSI_ETH_MAC_CONTROL_RX);
  452. } else {
  453. /* disable RX */
  454. ret = designware_eth_disable(handle, CSI_ETH_MAC_CONTROL_RX);
  455. }
  456. break;
  457. case DRV_ETH_MAC_CONTROL_IRQ:
  458. if (arg) {
  459. /* enable interrupt */
  460. } else {
  461. /* disable interrupt */
  462. }
  463. break;
  464. default:
  465. break;
  466. };
  467. return ret;
  468. }
  469. /**
  470. \brief Get Ethernet MAC Address.
  471. \param[in] handle ethernet handle
  472. \param[in] mac Pointer to address
  473. \return error code
  474. */
  475. int32_t cvi_eth_mac_get_macaddr(eth_mac_handle_t handle, eth_mac_addr_t *mac)
  476. {
  477. RT_ASSERT(handle);
  478. RT_ASSERT(mac);
  479. gmac_dev_t *mac_dev = (gmac_dev_t *)handle;
  480. designware_read_hwaddr(handle);
  481. memcpy(mac->b, mac_dev->mac_addr, sizeof(mac_dev->mac_addr));
  482. return 0;
  483. }
  484. /**
  485. \brief Set Ethernet MAC Address.
  486. \param[in] handle ethernet handle
  487. \param[in] mac Pointer to address
  488. \return error code
  489. */
  490. int32_t cvi_eth_mac_set_macaddr(eth_mac_handle_t handle, const eth_mac_addr_t *mac)
  491. {
  492. RT_ASSERT(handle);
  493. RT_ASSERT(mac);
  494. gmac_dev_t *mac_dev = (gmac_dev_t *)handle;
  495. memcpy(mac_dev->mac_addr, mac->b, sizeof(mac->b));
  496. designware_write_hwaddr(handle);
  497. return 0;
  498. }
  499. /**
  500. \brief Send Ethernet frame.
  501. \param[in] handle ethernet handle
  502. \param[in] frame Pointer to frame buffer with data to send
  503. \param[in] len Frame buffer length in bytes
  504. \param[in] flags Frame transmit flags (see CSI_ETH_MAC_TX_FRAME_...)
  505. \return error code
  506. */
  507. int32_t cvi_eth_mac_send_frame(eth_mac_handle_t handle, const uint8_t *frame, uint32_t len, uint32_t flags)
  508. {
  509. RT_ASSERT(handle);
  510. RT_ASSERT(frame);
  511. return designware_eth_send(handle, frame, len);
  512. }
  513. /**
  514. \brief Read data of received Ethernet frame.
  515. \param[in] handle ethernet handle
  516. \param[in] frame Pointer to frame buffer for data to read into
  517. \param[in] len Frame buffer length in bytes
  518. \return number of data bytes read or execution status
  519. - value >= 0: number of data bytes read
  520. - value < 0: error occurred, value is execution status as defined with execution_status
  521. */
  522. int32_t cvi_eth_mac_read_frame(eth_mac_handle_t handle, uint8_t *frame, uint32_t len)
  523. {
  524. RT_ASSERT(handle);
  525. RT_ASSERT(frame);
  526. uint8_t *packet = NULL;
  527. int32_t actual_length;
  528. actual_length = designware_eth_recv(handle, &packet);
  529. if (actual_length < 0) {
  530. return -1;
  531. }
  532. /* process received packet */
  533. actual_length = (actual_length > len) ? len : actual_length;
  534. if (packet != NULL) {
  535. memcpy(frame, packet, actual_length);
  536. }
  537. designware_free_pkt(handle);
  538. return actual_length;
  539. }
  540. /**
  541. \brief This function is used to initialize Ethernet device and register an event callback.
  542. \param[in] idx device id
  543. \param[in] cb callback to handle ethernet event
  544. \return return ethernet handle if success
  545. */
  546. eth_mac_handle_t cvi_eth_mac_init(unsigned int *base)
  547. {
  548. gmac_dev_t *mac_dev = &gmac_instance[0];
  549. struct dw_gmac_priv *priv, *priv_unalign;
  550. mac_dev->base = (unsigned long)base;
  551. // mac_dev->irq = (uint8_t)DW_MAC_IRQ;
  552. // mac_dev->cb_event = cb_event;
  553. priv = memalign(DW_GMAC_DMA_ALIGN, sizeof(struct dw_gmac_priv), (void **)&priv_unalign);
  554. if (!priv)
  555. {
  556. rt_kprintf("malloc fail\n");
  557. return NULL;
  558. }
  559. memset(priv_unalign, 0, sizeof(struct dw_gmac_priv) + DW_GMAC_DMA_ALIGN);
  560. priv->mac_regs_p = (struct dw_gmac_mac_regs *)mac_dev->base;
  561. priv->dma_regs_p = (struct dw_gmac_dma_regs *)(mac_dev->base + CVI_DW_DMA_BASE_OFFSET);
  562. mac_dev->priv_unalign = priv_unalign;
  563. mac_dev->priv = priv;
  564. return (eth_mac_handle_t)mac_dev;
  565. }
  566. /**
  567. \brief This function is used to de-initialize Ethernet device.
  568. \param[in] handle ethernet handle
  569. \return error code
  570. */
  571. void de_eth_gmac_deinit(eth_mac_handle_t handle)
  572. {
  573. RT_ASSERT(handle);
  574. gmac_dev_t *mac_dev = (gmac_dev_t *)handle;
  575. if (mac_dev->priv_unalign)
  576. {
  577. rt_free(mac_dev->priv_unalign);
  578. mac_dev->priv_unalign = RT_NULL;
  579. }
  580. }