drv_eth.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. /*
  2. * Copyright (c) 2021, WangHuachen
  3. *
  4. * SPDX-License-Identifier: MIT
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2021-5-10 WangHuachen the first version
  9. */
  10. #include "board.h"
  11. #include <netif/ethernetif.h>
  12. #include "lwipopts.h"
  13. #include "lwip/opt.h"
  14. #include "drv_eth.h"
  15. #include "lwip/netif.h"
  16. #include "netif/xadapter.h"
  17. #include "netif/xemacpsif.h"
  18. #include "xparameters.h"
  19. #include "xemacps.h"
  20. #define DBG_TAG "drv.emac"
  21. #define DBG_LEVEL DBG_INFO
  22. #include <rtdbg.h>
  23. #define MAC_BASE_ADDR XPAR_PSU_ETHERNET_3_BASEADDR
  24. #define MAX_ADDR_LEN 6
  25. struct rt_zynqmp_eth
  26. {
  27. /* inherit from ethernet device */
  28. struct eth_device parent;
  29. /* interface address info, hw address */
  30. rt_uint8_t dev_addr[MAX_ADDR_LEN];
  31. struct xemac_s *xemac;
  32. };
  33. static struct rt_zynqmp_eth zynqmp_eth_device;
  34. extern XEmacPs_Config *mac_config;
  35. extern struct netif *NetIf;
  36. static void rt_hw_eth_isr(int irqno, void *param)
  37. {
  38. struct rt_zynqmp_eth *eth_dev = (struct rt_zynqmp_eth *)param;
  39. xemacpsif_s *xemacpsif = (xemacpsif_s *)eth_dev->xemac->state;
  40. XEmacPs_IntrHandler(&xemacpsif->emacps);
  41. }
  42. extern enum ethernet_link_status eth_link_status;
  43. extern u32_t phy_link_detect(XEmacPs *xemacp, u32_t phy_addr);
  44. extern u32_t phy_autoneg_status(XEmacPs *xemacp, u32_t phy_addr);
  45. extern u32_t phyaddrforemac;
  46. void rt_zynqmp_eth_link_detect(struct rt_zynqmp_eth *eth_dev)
  47. {
  48. u32_t link_speed, phy_link_status;
  49. struct xemac_s *xemac = eth_dev->xemac;
  50. xemacpsif_s *xemacs = (xemacpsif_s *)(xemac->state);
  51. XEmacPs *xemacp = &xemacs->emacps;
  52. if ((xemacp->IsReady != (u32)XIL_COMPONENT_IS_READY) ||
  53. (eth_link_status == ETH_LINK_UNDEFINED))
  54. return;
  55. phy_link_status = phy_link_detect(xemacp, phyaddrforemac);
  56. if ((eth_link_status == ETH_LINK_UP) && (!phy_link_status))
  57. eth_link_status = ETH_LINK_DOWN;
  58. switch (eth_link_status) {
  59. case ETH_LINK_UNDEFINED:
  60. case ETH_LINK_UP:
  61. return;
  62. case ETH_LINK_DOWN:
  63. eth_device_linkchange(&zynqmp_eth_device.parent, RT_FALSE);
  64. eth_link_status = ETH_LINK_NEGOTIATING;
  65. LOG_D("Ethernet Link down");
  66. break;
  67. case ETH_LINK_NEGOTIATING:
  68. if (phy_link_status &&
  69. phy_autoneg_status(xemacp, phyaddrforemac)) {
  70. /* Initiate Phy setup to get link speed */
  71. link_speed = phy_setup_emacps(xemacp,
  72. phyaddrforemac);
  73. XEmacPs_SetOperatingSpeed(xemacp, link_speed);
  74. eth_device_linkchange(&zynqmp_eth_device.parent, RT_TRUE);
  75. eth_link_status = ETH_LINK_UP;
  76. LOG_D("Ethernet Link up");
  77. }
  78. break;
  79. }
  80. }
  81. static void phy_monitor_thread(void *parameter)
  82. {
  83. struct rt_zynqmp_eth *eth_dev = (struct rt_zynqmp_eth *)parameter;
  84. while (1)
  85. {
  86. rt_zynqmp_eth_link_detect(eth_dev);
  87. rt_thread_delay(RT_TICK_PER_SECOND);
  88. }
  89. }
  90. static rt_err_t rt_zynqmp_eth_init(rt_device_t dev)
  91. {
  92. struct rt_zynqmp_eth *eth_dev = (struct rt_zynqmp_eth *)dev->user_data;
  93. struct netif *netif = eth_dev->parent.netif;
  94. struct xemac_s *xemac;
  95. xemacpsif_s *xemacpsif;
  96. u32 dmacrreg;
  97. s32_t status = XST_SUCCESS;
  98. struct xtopology_t *xtopologyp;
  99. if (eth_dev->xemac != RT_NULL)
  100. {
  101. LOG_W("rt_zynqmp_eth_init: device has been initialized");
  102. return -RT_ERROR;
  103. }
  104. NetIf = netif;
  105. xemacpsif = rt_malloc(sizeof *xemacpsif);
  106. if (xemacpsif == NULL)
  107. {
  108. LOG_E("rt_zynqmp_eth_init: out of memory");
  109. return -RT_ENOMEM;
  110. }
  111. xemac = rt_malloc(sizeof *xemac);
  112. if (xemac == NULL)
  113. {
  114. LOG_E("rt_zynqmp_eth_init: out of memory");
  115. return -RT_ENOMEM;
  116. }
  117. xemac->state = (void *)xemacpsif;
  118. xemac->topology_index = xtopology_find_index(MAC_BASE_ADDR);
  119. xemac->type = xemac_type_emacps;
  120. xemac->rt_eth_device = &eth_dev->parent;
  121. xemacpsif->send_q = NULL;
  122. xemacpsif->recv_q = pq_create_queue();
  123. if (!xemacpsif->recv_q)
  124. return -RT_ENOMEM;
  125. eth_dev->xemac = xemac;
  126. /* obtain config of this emac */
  127. mac_config = (XEmacPs_Config *)xemacps_lookup_config(MAC_BASE_ADDR);
  128. status = XEmacPs_CfgInitialize(&xemacpsif->emacps, mac_config,
  129. mac_config->BaseAddress);
  130. if (status != XST_SUCCESS)
  131. {
  132. LOG_W("In %s:EmacPs Configuration Failed....", __func__);
  133. return -RT_ERROR;
  134. }
  135. /* initialize the mac */
  136. init_emacps(xemacpsif, netif);
  137. dmacrreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
  138. XEMACPS_DMACR_OFFSET);
  139. dmacrreg = dmacrreg | (0x00000010);
  140. XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
  141. XEMACPS_DMACR_OFFSET, dmacrreg);
  142. setup_isr(xemac);
  143. init_dma(xemac);
  144. xtopologyp = &xtopology[xemac->topology_index];
  145. /*
  146. * Connect the device driver handler that will be called when an
  147. * interrupt for the device occurs, the handler defined above performs
  148. * the specific interrupt processing for the device.
  149. */
  150. rt_hw_interrupt_install(xtopologyp->scugic_emac_intr, rt_hw_eth_isr, (void *)eth_dev, "eth");
  151. /*
  152. * Enable the interrupt for emacps.
  153. */
  154. rt_hw_interrupt_umask(xtopologyp->scugic_emac_intr);
  155. start_emacps(xemacpsif);
  156. if (eth_link_status == ETH_LINK_UP)
  157. eth_device_linkchange(&eth_dev->parent, RT_TRUE);
  158. rt_thread_t tid;
  159. tid = rt_thread_create("phylnk",
  160. phy_monitor_thread,
  161. eth_dev,
  162. 1024,
  163. RT_THREAD_PRIORITY_MAX - 2,
  164. 2);
  165. if (tid != RT_NULL)
  166. rt_thread_startup(tid);
  167. else
  168. return -RT_ERROR;
  169. return RT_EOK;
  170. }
  171. static rt_err_t rt_zynqmp_eth_open(rt_device_t dev, rt_uint16_t oflag)
  172. {
  173. LOG_D("emac open");
  174. return RT_EOK;
  175. }
  176. static rt_err_t rt_zynqmp_eth_close(rt_device_t dev)
  177. {
  178. LOG_D("emac close");
  179. return RT_EOK;
  180. }
  181. static rt_size_t rt_zynqmp_eth_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
  182. {
  183. LOG_D("emac read");
  184. rt_set_errno(-RT_ENOSYS);
  185. return 0;
  186. }
  187. static rt_size_t rt_zynqmp_eth_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
  188. {
  189. LOG_D("emac write");
  190. rt_set_errno(-RT_ENOSYS);
  191. return 0;
  192. }
  193. static rt_err_t rt_zynqmp_eth_control(rt_device_t dev, int cmd, void *args)
  194. {
  195. struct rt_zynqmp_eth *eth_dev = (struct rt_zynqmp_eth *)dev->user_data;
  196. switch (cmd)
  197. {
  198. case NIOCTL_GADDR:
  199. /* get mac address */
  200. if (args) rt_memcpy(args, eth_dev->dev_addr, 6);
  201. else return -RT_ERROR;
  202. break;
  203. default :
  204. break;
  205. }
  206. return RT_EOK;
  207. }
  208. extern err_t _unbuffered_low_level_output(xemacpsif_s *xemacpsif, struct pbuf *p);
  209. rt_err_t rt_zynqmp_eth_tx(rt_device_t dev, struct pbuf *p)
  210. {
  211. rt_base_t lev;
  212. rt_err_t err;
  213. XEmacPs_BdRing *txring;
  214. struct rt_zynqmp_eth *eth_dev = (struct rt_zynqmp_eth *)dev->user_data;
  215. struct xemac_s *xemac = eth_dev->xemac;
  216. xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state);
  217. lev = rt_hw_interrupt_disable();
  218. txring = &(XEmacPs_GetTxRing(&xemacpsif->emacps));
  219. process_sent_bds(xemacpsif, txring);
  220. if (is_tx_space_available(xemacpsif))
  221. {
  222. _unbuffered_low_level_output(xemacpsif, p);
  223. err = RT_EOK;
  224. }
  225. else
  226. {
  227. #if LINK_STATS
  228. lwip_stats.link.drop++;
  229. #endif
  230. LOG_D("pack dropped, no space");
  231. err = -RT_ENOMEM;
  232. }
  233. rt_hw_interrupt_enable(lev);
  234. return err;
  235. }
  236. struct pbuf *rt_zynqmp_eth_rx(rt_device_t dev)
  237. {
  238. rt_base_t lev;
  239. struct rt_zynqmp_eth *eth_dev = (struct rt_zynqmp_eth *)dev->user_data;
  240. struct xemac_s *xemac = eth_dev->xemac;
  241. xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state);
  242. struct pbuf *p;
  243. lev = rt_hw_interrupt_disable();
  244. /* see if there is data to process */
  245. if (pq_qlength(xemacpsif->recv_q) == 0)
  246. return NULL;
  247. /* return one packet from receive q */
  248. p = (struct pbuf *)pq_dequeue(xemacpsif->recv_q);
  249. rt_hw_interrupt_enable(lev);
  250. return p;
  251. }
  252. static int rt_hw_zynqmp_eth_init(void)
  253. {
  254. rt_err_t state = RT_EOK;
  255. zynqmp_eth_device.xemac = RT_NULL;
  256. zynqmp_eth_device.dev_addr[0] = 0x00;
  257. zynqmp_eth_device.dev_addr[1] = 0x0A;
  258. zynqmp_eth_device.dev_addr[2] = 0x35;
  259. zynqmp_eth_device.dev_addr[3] = 0x00;
  260. zynqmp_eth_device.dev_addr[4] = 0x01;
  261. zynqmp_eth_device.dev_addr[5] = 0x02;
  262. zynqmp_eth_device.parent.parent.init = rt_zynqmp_eth_init;
  263. zynqmp_eth_device.parent.parent.open = rt_zynqmp_eth_open;
  264. zynqmp_eth_device.parent.parent.close = rt_zynqmp_eth_close;
  265. zynqmp_eth_device.parent.parent.read = rt_zynqmp_eth_read;
  266. zynqmp_eth_device.parent.parent.write = rt_zynqmp_eth_write;
  267. zynqmp_eth_device.parent.parent.control = rt_zynqmp_eth_control;
  268. zynqmp_eth_device.parent.parent.user_data = &zynqmp_eth_device;
  269. zynqmp_eth_device.parent.eth_rx = rt_zynqmp_eth_rx;
  270. zynqmp_eth_device.parent.eth_tx = rt_zynqmp_eth_tx;
  271. /* register eth device */
  272. state = eth_device_init(&(zynqmp_eth_device.parent), "e0");
  273. if (RT_EOK == state)
  274. {
  275. LOG_D("emac device init success");
  276. }
  277. else
  278. {
  279. LOG_E("emac device init faild: %d", state);
  280. state = -RT_ERROR;
  281. return state;
  282. }
  283. return state;
  284. }
  285. INIT_DEVICE_EXPORT(rt_hw_zynqmp_eth_init);