drv_eth.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537
  1. /*
  2. * Copyright (c) 2006-2025, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2018-11-19 SummerGift first version
  9. * 2018-12-25 zylx fix some bugs
  10. * 2019-06-10 SummerGift optimize PHY state detection process
  11. * 2019-09-03 xiaofan optimize link change detection process
  12. * 2025-02-11 kurisaW adaptation for RZ Ethernet driver
  13. * 2025-12-01 yans adaptation for RA8P1 Ethernet driver
  14. */
  15. #include "drv_config.h"
  16. #include "drv_eth.h"
  17. #include <hal_data.h>
  18. #include <netif/ethernetif.h>
  19. #include <lwipopts.h>
  20. /* debug option */
  21. // #define ETH_RX_DUMP
  22. // #define ETH_TX_DUMP
  23. #define MINIMUM_ETHERNET_FRAME_SIZE (60U)
  24. #ifdef SOC_SERIES_R7KA8P1
  25. #define ETH_MAX_PACKET_SIZE (1514U)
  26. #else
  27. #define ETH_MAX_PACKET_SIZE (2048U)
  28. #endif
  29. #define ETHER_GMAC_INTERRUPT_FACTOR_RECEPTION (0x000000C0)
  30. #define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE
  31. #define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE
  32. // #define DRV_DEBUG
  33. #define LOG_TAG "drv.eth"
  34. #ifdef DRV_DEBUG
  35. #define DBG_LVL DBG_LOG
  36. #else
  37. #define DBG_LVL DBG_INFO
  38. #endif /* DRV_DEBUG */
  39. #include <rtdbg.h>
  40. struct rt_eth_dev
  41. {
  42. /* inherit from ethernet device */
  43. struct eth_device parent;
  44. #ifndef PHY_USING_INTERRUPT_MODE
  45. rt_timer_t poll_link_timer;
  46. #endif
  47. };
  48. static rt_uint8_t *Rx_Buff, *Tx_Buff;
  49. // static ETH_HandleTypeDef EthHandle;
  50. static struct rt_eth_dev ra_eth_device;
  51. static uint8_t g_link_change = 0; ///< Link change (bit0:port0, bit1:port1, bit2:port2)
  52. static uint8_t g_link_status = 0; ///< Link status (bit0:port0, bit1:port1, bit2:port2)
  53. static uint8_t previous_link_status = 0;
  54. /* Multi-PHY support structures */
  55. typedef struct
  56. {
  57. #if defined(SOC_SERIES_R7KA8P1)
  58. rmac_phy_instance_ctrl_t *p_ctrl;
  59. #else
  60. ether_phy_instance_ctrl_t *p_ctrl;
  61. #endif
  62. uint8_t port_bit;
  63. const char *name;
  64. } phy_port_info_t;
  65. static const phy_port_info_t phy_ports[] =
  66. {
  67. #if defined(SOC_SERIES_R7KA8P1)
  68. { &g_rmac_phy0_ctrl, 0x01, "PHY0" },
  69. { &g_rmac_phy1_ctrl, 0x02, "PHY1" },
  70. #elif defined(SOC_SERIES_R9A07G0)
  71. { &g_ether_phy0_ctrl, 0x01, "PHY0" },
  72. { &g_ether_phy1_ctrl, 0x02, "PHY1" },
  73. { &g_ether_phy2_ctrl, 0x04, "PHY2" },
  74. #else
  75. { &g_ether_phy0_ctrl, 0x01, "PHY" },
  76. #endif
  77. };
  78. #define PHY_PORTS_COUNT (sizeof(phy_ports) / sizeof(phy_ports[0]))
  79. #if defined(SOC_SERIES_R9A07G0)
  80. #define status_ecsr status_link
  81. #define ETHER_EVENT_INTERRUPT ETHER_EVENT_SBD_INTERRUPT
  82. #define R_ETHER_Open R_GMAC_Open
  83. #define R_ETHER_Write R_GMAC_Write
  84. #define R_ETHER_Read R_GMAC_Read
  85. #define R_ETHER_LinkProcess R_GMAC_LinkProcess
  86. #elif defined(SOC_SERIES_R7KA8P1)
  87. #define R_ETHER_Open R_RMAC_Open
  88. #define R_ETHER_Write R_RMAC_Write
  89. #define R_ETHER_Read R_RMAC_Read
  90. #define R_ETHER_LinkProcess R_RMAC_LinkProcess
  91. #define R_ETHER_PHY_LinkStatusGet R_RMAC_PHY_LinkStatusGet
  92. #endif
  93. #if defined(ETH_RX_DUMP) || defined(ETH_TX_DUMP)
  94. #define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
  95. static void dump_hex(const rt_uint8_t *ptr, rt_size_t buflen)
  96. {
  97. unsigned char *buf = (unsigned char *)ptr;
  98. int i, j;
  99. for (i = 0; i < buflen; i += 16)
  100. {
  101. rt_kprintf("%08X: ", i);
  102. for (j = 0; j < 16; j++)
  103. if (i + j < buflen)
  104. rt_kprintf("%02X ", buf[i + j]);
  105. else
  106. rt_kprintf(" ");
  107. rt_kprintf(" ");
  108. for (j = 0; j < 16; j++)
  109. if (i + j < buflen)
  110. rt_kprintf("%c", __is_print(buf[i + j]) ? buf[i + j] : '.');
  111. rt_kprintf("\n");
  112. }
  113. }
  114. #endif
  115. /* EMAC initialization function */
  116. static rt_err_t rt_ra_eth_init(void)
  117. {
  118. fsp_err_t res;
  119. res = R_ETHER_Open(&g_ether0_ctrl, &g_ether0_cfg);
  120. if (res != FSP_SUCCESS)
  121. LOG_W("R_ETHER_Open failed!, res = %d", res);
  122. return RT_EOK;
  123. }
  124. static rt_err_t rt_ra_eth_open(rt_device_t dev, rt_uint16_t oflag)
  125. {
  126. LOG_D("emac open");
  127. return RT_EOK;
  128. }
  129. static rt_err_t rt_ra_eth_close(rt_device_t dev)
  130. {
  131. LOG_D("emac close");
  132. return RT_EOK;
  133. }
  134. static rt_ssize_t rt_ra_eth_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
  135. {
  136. LOG_D("emac read");
  137. rt_set_errno(-RT_ENOSYS);
  138. return 0;
  139. }
  140. static rt_ssize_t rt_ra_eth_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
  141. {
  142. LOG_D("emac write");
  143. rt_set_errno(-RT_ENOSYS);
  144. return 0;
  145. }
  146. static rt_err_t rt_ra_eth_control(rt_device_t dev, int cmd, void *args)
  147. {
  148. switch (cmd)
  149. {
  150. case NIOCTL_GADDR:
  151. /* get mac address */
  152. if (args)
  153. {
  154. #if defined(SOC_SERIES_R9A07G0)
  155. SMEMCPY(args, g_ether0_ctrl.p_gmac_cfg->p_mac_address, 6);
  156. #elif defined(SOC_SERIES_R7KA8P1)
  157. SMEMCPY(args, g_ether0_ctrl.p_cfg->p_mac_address, 6);
  158. #else
  159. SMEMCPY(args, g_ether0_ctrl.p_ether_cfg->p_mac_address, 6);
  160. #endif
  161. }
  162. else
  163. {
  164. return -RT_ERROR;
  165. }
  166. break;
  167. default:
  168. break;
  169. }
  170. return RT_EOK;
  171. }
  172. /* ethernet device interface */
  173. /* transmit data*/
  174. rt_err_t rt_ra_eth_tx(rt_device_t dev, struct pbuf *p)
  175. {
  176. fsp_err_t res;
  177. struct pbuf *q;
  178. uint8_t *buffer = Tx_Buff;
  179. uint32_t framelength = 0;
  180. uint32_t bufferoffset = 0;
  181. uint32_t byteslefttocopy = 0;
  182. uint32_t payloadoffset = 0;
  183. bufferoffset = 0;
  184. LOG_D("send frame len : %d", p->tot_len);
  185. /* copy frame from pbufs to driver buffers */
  186. for (q = p; q != NULL; q = q->next)
  187. {
  188. /* Get bytes in current lwIP buffer */
  189. byteslefttocopy = q->len;
  190. payloadoffset = 0;
  191. /* Check if the length of data to copy is bigger than Tx buffer size*/
  192. while ((byteslefttocopy + bufferoffset) > ETH_TX_BUF_SIZE)
  193. {
  194. /* Copy data to Tx buffer*/
  195. SMEMCPY((uint8_t *)((uint8_t *)buffer + bufferoffset), (uint8_t *)((uint8_t *)q->payload + payloadoffset), (ETH_TX_BUF_SIZE - bufferoffset));
  196. byteslefttocopy = byteslefttocopy - (ETH_TX_BUF_SIZE - bufferoffset);
  197. payloadoffset = payloadoffset + (ETH_TX_BUF_SIZE - bufferoffset);
  198. framelength = framelength + (ETH_TX_BUF_SIZE - bufferoffset);
  199. bufferoffset = 0;
  200. }
  201. /* Copy the remaining bytes */
  202. SMEMCPY((uint8_t *)((uint8_t *)buffer + bufferoffset), (uint8_t *)((uint8_t *)q->payload + payloadoffset), byteslefttocopy);
  203. bufferoffset = bufferoffset + byteslefttocopy;
  204. framelength = framelength + byteslefttocopy;
  205. }
  206. #ifdef ETH_TX_DUMP
  207. dump_hex(buffer, p->tot_len);
  208. #endif
  209. #ifdef ETH_RX_DUMP
  210. if (p)
  211. {
  212. LOG_E("******p buf frame *********");
  213. for (q = p; q != NULL; q = q->next)
  214. {
  215. dump_hex(q->payload, q->len);
  216. }
  217. }
  218. #endif
  219. #if defined(__DCACHE_PRESENT)
  220. SCB_CleanInvalidateDCache();
  221. #endif
  222. res = R_ETHER_Write(&g_ether0_ctrl, buffer, p->tot_len < MINIMUM_ETHERNET_FRAME_SIZE ? MINIMUM_ETHERNET_FRAME_SIZE : p->tot_len);
  223. if (res != FSP_SUCCESS)
  224. {
  225. LOG_W("R_ETHER_Write failed!, res = %d", res);
  226. return (err_t)ERR_USE;
  227. }
  228. return RT_EOK;
  229. }
  230. /* receive data*/
  231. struct pbuf *rt_ra_eth_rx(rt_device_t dev)
  232. {
  233. struct pbuf *p = NULL;
  234. struct pbuf *q = NULL;
  235. uint32_t len = 0;
  236. uint8_t *buffer = Rx_Buff;
  237. fsp_err_t res;
  238. res = R_ETHER_Read(&g_ether0_ctrl, buffer, &len);
  239. if (res != FSP_SUCCESS)
  240. LOG_D("R_ETHER_Read failed!, res = %d", res);
  241. uint32_t bufferoffset = 0;
  242. uint32_t payloadoffset = 0;
  243. uint32_t byteslefttocopy = 0;
  244. LOG_D("receive frame len : %d", len);
  245. #if defined(__DCACHE_PRESENT)
  246. SCB_CleanInvalidateDCache();
  247. #endif
  248. if (len > 0)
  249. {
  250. /* We allocate a pbuf chain of pbufs from the Lwip buffer pool */
  251. p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
  252. if (p == NULL)
  253. {
  254. LOG_E("Failed to allocate pbuf for %d bytes", len);
  255. return NULL;
  256. }
  257. }
  258. #ifdef ETH_RX_DUMP
  259. if (p)
  260. {
  261. dump_hex(buffer, p->tot_len);
  262. }
  263. #endif
  264. if (p != NULL)
  265. {
  266. bufferoffset = 0;
  267. for (q = p; q != NULL; q = q->next)
  268. {
  269. byteslefttocopy = q->len;
  270. payloadoffset = 0;
  271. /* Check if the length of bytes to copy in current pbuf is bigger than Rx buffer size*/
  272. while ((byteslefttocopy + bufferoffset) > ETH_RX_BUF_SIZE)
  273. {
  274. /* Copy data to pbuf */
  275. SMEMCPY((uint8_t *)((uint8_t *)q->payload + payloadoffset), (uint8_t *)((uint8_t *)buffer + bufferoffset), (ETH_RX_BUF_SIZE - bufferoffset));
  276. byteslefttocopy = byteslefttocopy - (ETH_RX_BUF_SIZE - bufferoffset);
  277. payloadoffset = payloadoffset + (ETH_RX_BUF_SIZE - bufferoffset);
  278. bufferoffset = 0;
  279. }
  280. /* Copy remaining data in pbuf */
  281. SMEMCPY((uint8_t *)((uint8_t *)q->payload + payloadoffset), (uint8_t *)((uint8_t *)buffer + bufferoffset), byteslefttocopy);
  282. bufferoffset = bufferoffset + byteslefttocopy;
  283. }
  284. }
  285. #ifdef ETH_RX_DUMP
  286. if (p)
  287. {
  288. LOG_E("******p buf frame *********");
  289. for (q = p; q != NULL; q = q->next)
  290. {
  291. dump_hex(q->payload, q->len);
  292. }
  293. }
  294. #endif
  295. return p;
  296. }
  297. static void phy_linkchange()
  298. {
  299. fsp_err_t res;
  300. uint8_t port = 0;
  301. uint8_t port_bit = 0;
  302. uint8_t status_change;
  303. uint8_t current_link_status = 0;
  304. uint8_t i;
  305. res = R_ETHER_LinkProcess(&g_ether0_ctrl);
  306. if (res != FSP_SUCCESS)
  307. LOG_D("R_ETHER_LinkProcess failed!, res = %d", res);
  308. #if !defined(SOC_SERIES_R7KA8P1) && !defined(SOC_SERIES_R7FA6M3)
  309. if (0 == g_ether0.p_cfg->p_callback)
  310. #endif
  311. {
  312. /* Check link status for all PHY ports */
  313. for (i = 0; i < PHY_PORTS_COUNT; i++)
  314. {
  315. res = R_ETHER_PHY_LinkStatusGet(phy_ports[i].p_ctrl);
  316. // ETHER_PHY successfully get link partner ability.
  317. if (res == FSP_SUCCESS)
  318. {
  319. current_link_status |= phy_ports[i].port_bit; /* Port link up */
  320. status_change = previous_link_status ^ current_link_status;
  321. if (status_change & phy_ports[i].port_bit)
  322. {
  323. g_link_change |= phy_ports[i].port_bit;
  324. LOG_I("%s Manual Link status changed: UP", phy_ports[i].name);
  325. }
  326. }
  327. // PHY-LSI is not link up.
  328. else if (res == FSP_ERR_ETHER_PHY_ERROR_LINK)
  329. {
  330. current_link_status &= ~(phy_ports[i].port_bit); /* Port link down */
  331. status_change = previous_link_status ^ current_link_status;
  332. if (status_change & phy_ports[i].port_bit)
  333. {
  334. g_link_change |= phy_ports[i].port_bit;
  335. LOG_I("%s Manual Link status changed: DOWN", phy_ports[i].name);
  336. }
  337. }
  338. else
  339. {
  340. LOG_E("%s PHY_Read failed!, res = %d", phy_ports[i].name, res);
  341. }
  342. /* Update global link status */
  343. g_link_status = current_link_status;
  344. }
  345. }
  346. /* Process link changes for all ports */
  347. for (port = 0; port < PHY_PORTS_COUNT; port++)
  348. {
  349. port_bit = phy_ports[port].port_bit;
  350. if (g_link_change & port_bit)
  351. {
  352. /* Link status changed */
  353. g_link_change &= (uint8_t)(~port_bit); /* change bit clear */
  354. if (g_link_status & port_bit)
  355. {
  356. /* Changed to Link-up */
  357. eth_device_linkchange(&ra_eth_device.parent, RT_TRUE);
  358. LOG_I("%s link up", phy_ports[port].name);
  359. }
  360. else
  361. {
  362. /* Changed to Link-down */
  363. eth_device_linkchange(&ra_eth_device.parent, RT_FALSE);
  364. LOG_I("%s link down", phy_ports[port].name);
  365. }
  366. }
  367. }
  368. previous_link_status = g_link_status;
  369. }
  370. void user_ether0_callback(ether_callback_args_t *p_args)
  371. {
  372. rt_interrupt_enter();
  373. switch (p_args->event)
  374. {
  375. case ETHER_EVENT_LINK_ON: ///< Link up detection event/
  376. g_link_status |= (uint8_t)p_args->status_ecsr; ///< status up
  377. g_link_change |= (uint8_t)p_args->status_ecsr; ///< change bit set
  378. break;
  379. case ETHER_EVENT_LINK_OFF: ///< Link down detection event
  380. g_link_status &= (uint8_t)(~p_args->status_ecsr); ///< status down
  381. g_link_change |= (uint8_t)p_args->status_ecsr; ///< change bit set
  382. break;
  383. case ETHER_EVENT_WAKEON_LAN: ///< Magic packet detection event
  384. /* If EDMAC FR (Frame Receive Event) or FDE (Receive Descriptor Empty Event)
  385. * interrupt occurs, send rx mailbox. */
  386. #if defined(SOC_SERIES_R7KA8P1)
  387. case ETHER_EVENT_RX_COMPLETE: ///< BSD Interrupt event
  388. #else
  389. case ETHER_EVENT_INTERRUPT: ///< BSD Interrupt event
  390. #endif
  391. {
  392. rt_err_t result;
  393. result = eth_device_ready(&(ra_eth_device.parent));
  394. if (result != RT_EOK)
  395. rt_kprintf("RX err =%d\n", result);
  396. break;
  397. }
  398. default:
  399. break;
  400. }
  401. rt_interrupt_leave();
  402. }
  403. /* Register the EMAC device */
  404. static int rt_hw_ra_eth_init(void)
  405. {
  406. rt_err_t state = RT_EOK;
  407. /* Prepare receive and send buffers */
  408. Rx_Buff = (rt_uint8_t *)rt_calloc(1, ETH_MAX_PACKET_SIZE);
  409. if (Rx_Buff == RT_NULL)
  410. {
  411. LOG_E("No memory");
  412. state = -RT_ENOMEM;
  413. goto __exit;
  414. }
  415. Tx_Buff = (rt_uint8_t *)rt_calloc(1, ETH_MAX_PACKET_SIZE);
  416. if (Tx_Buff == RT_NULL)
  417. {
  418. LOG_E("No memory");
  419. state = -RT_ENOMEM;
  420. goto __exit;
  421. }
  422. ra_eth_device.parent.parent.init = NULL;
  423. ra_eth_device.parent.parent.open = rt_ra_eth_open;
  424. ra_eth_device.parent.parent.close = rt_ra_eth_close;
  425. ra_eth_device.parent.parent.read = rt_ra_eth_read;
  426. ra_eth_device.parent.parent.write = rt_ra_eth_write;
  427. ra_eth_device.parent.parent.control = rt_ra_eth_control;
  428. ra_eth_device.parent.parent.user_data = RT_NULL;
  429. ra_eth_device.parent.eth_rx = rt_ra_eth_rx;
  430. ra_eth_device.parent.eth_tx = rt_ra_eth_tx;
  431. rt_ra_eth_init();
  432. /* register eth device */
  433. state = eth_device_init(&(ra_eth_device.parent), "e0");
  434. if (RT_EOK == state)
  435. {
  436. LOG_D("emac device init success");
  437. }
  438. else
  439. {
  440. LOG_E("emac device init faild: %d", state);
  441. state = -RT_ERROR;
  442. goto __exit;
  443. }
  444. ra_eth_device.poll_link_timer = rt_timer_create("phylnk", (void (*)(void *))phy_linkchange,
  445. NULL, RT_TICK_PER_SECOND, RT_TIMER_FLAG_PERIODIC);
  446. if (!ra_eth_device.poll_link_timer || rt_timer_start(ra_eth_device.poll_link_timer) != RT_EOK)
  447. {
  448. LOG_E("Start link change detection timer failed");
  449. }
  450. __exit:
  451. if (state != RT_EOK)
  452. {
  453. if (Rx_Buff)
  454. {
  455. rt_free(Rx_Buff);
  456. }
  457. if (Tx_Buff)
  458. {
  459. rt_free(Tx_Buff);
  460. }
  461. }
  462. return state;
  463. }
  464. INIT_DEVICE_EXPORT(rt_hw_ra_eth_init);