dw_eth_mac.c 22 KB

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