netdev_renesas.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. /*
  2. * Copyright (c) 2025, sakumisu
  3. * Copyright (c) 2025, yans
  4. *
  5. * SPDX-License-Identifier: Apache-2.0
  6. */
  7. #include <hal_data.h>
  8. #include "ec_master.h"
  9. ec_netdev_t g_netdev;
  10. #if !defined(SOC_SERIES_R7KA8P1) && !defined(SOC_SERIES_R9A07G0)
  11. #error "Ethercat master only supports for R7KA8P1 and RZN2L"
  12. #endif
  13. #if !defined(CONFIG_EC_PHY_CUSTOM)
  14. #error "CONFIG_EC_PHY_CUSTOM must be defined for Renesas MCUs"
  15. #endif
  16. #if defined(SOC_SERIES_R7KA8P1)
  17. #define ETHER_BUFFER_PLACE_IN_SECTION BSP_PLACE_IN_SECTION(".ram_nocache")
  18. #define ETHER_EVENT_INTERRUPT ETHER_EVENT_RX_COMPLETE
  19. #define R_ETHER_Open R_RMAC_Open
  20. #define R_ETHER_Write R_RMAC_Write
  21. #define R_ETHER_Read R_RMAC_Read
  22. #define R_ETHER_LinkProcess R_RMAC_LinkProcess
  23. #define R_ETHER_BufferRelease R_RMAC_BufferRelease
  24. void rmac_phy_target_rtl8211_initialize(rmac_phy_instance_ctrl_t *phydev)
  25. {
  26. #define RTL_8211F_PAGE_SELECT 0x1F
  27. #define RTL_8211F_EEELCR_ADDR 0x11
  28. #define RTL_8211F_LED_PAGE 0xD04
  29. #define RTL_8211F_LCR_ADDR 0x10
  30. uint32_t val1, val2 = 0;
  31. /* switch to led page */
  32. R_RMAC_PHY_Write(phydev, RTL_8211F_PAGE_SELECT, RTL_8211F_LED_PAGE);
  33. /* set led1(green) Link 10/100/1000M, and set led2(yellow) Link 10/100/1000M+Active */
  34. R_RMAC_PHY_Read(phydev, RTL_8211F_LCR_ADDR, &val1);
  35. val1 |= (1 << 5);
  36. val1 |= (1 << 8);
  37. val1 &= (~(1 << 9));
  38. val1 |= (1 << 10);
  39. val1 |= (1 << 11);
  40. R_RMAC_PHY_Write(phydev, RTL_8211F_LCR_ADDR, val1);
  41. /* set led1(green) EEE LED function disabled so it can keep on when linked */
  42. R_RMAC_PHY_Read(phydev, RTL_8211F_EEELCR_ADDR, &val2);
  43. val2 &= (~(1 << 2));
  44. R_RMAC_PHY_Write(phydev, RTL_8211F_EEELCR_ADDR, val2);
  45. /* switch back to page0 */
  46. R_RMAC_PHY_Write(phydev, RTL_8211F_PAGE_SELECT, 0xa42);
  47. }
  48. bool rmac_phy_target_rtl8211_is_support_link_partner_ability(rmac_phy_instance_ctrl_t *p_instance_ctrl,
  49. uint32_t line_speed_duplex)
  50. {
  51. FSP_PARAMETER_NOT_USED(p_instance_ctrl);
  52. FSP_PARAMETER_NOT_USED(line_speed_duplex);
  53. /* This PHY-LSI supports half and full duplex mode. */
  54. return true;
  55. }
  56. /* Multi-PHY support structures */
  57. typedef struct {
  58. rmac_phy_instance_ctrl_t *p_ctrl;
  59. uint8_t port_bit;
  60. const char *name;
  61. } phy_port_info_t;
  62. static const phy_port_info_t phy_ports[] = {
  63. { &g_rmac_phy0_ctrl, 0x01, "PHY0" },
  64. { &g_rmac_phy1_ctrl, 0x02, "PHY1" }
  65. };
  66. #define PHY_PORTS_COUNT (sizeof(phy_ports) / sizeof(phy_ports[0]))
  67. #elif defined(SOC_SERIES_R9A07G0)
  68. #if !defined(CONFIG_EC_TIMESTAMP_CUSTOM)
  69. #error "CONFIG_EC_TIMESTAMP_CUSTOM must be defined for R9A07G0"
  70. #endif
  71. #define ETHER_BUFFER_PLACE_IN_SECTION BSP_PLACE_IN_SECTION(".noncache_buffer.eth")
  72. #define status_ecsr status_link
  73. #define ETHER_EVENT_INTERRUPT ETHER_EVENT_SBD_INTERRUPT
  74. #define R_ETHER_Open R_GMAC_Open
  75. #define R_ETHER_Write R_GMAC_Write
  76. #define R_ETHER_Read R_GMAC_Read
  77. #define R_ETHER_LinkProcess R_GMAC_LinkProcess
  78. #define R_ETHER_BufferRelease R_GMAC_BufferRelease
  79. static int phy_rtl8211f_led_fixup(ether_phy_instance_ctrl_t *phydev)
  80. {
  81. #define RTL_8211F_PAGE_SELECT 0x1F
  82. #define RTL_8211F_EEELCR_ADDR 0x11
  83. #define RTL_8211F_LED_PAGE 0xD04
  84. #define RTL_8211F_LCR_ADDR 0x10
  85. uint32_t val1, val2 = 0;
  86. /* switch to led page */
  87. R_ETHER_PHY_Write(phydev, RTL_8211F_PAGE_SELECT, RTL_8211F_LED_PAGE);
  88. /* set led1(green) Link 10/100/1000M, and set led2(yellow) Link 10/100/1000M+Active */
  89. R_ETHER_PHY_Read(phydev, RTL_8211F_LCR_ADDR, &val1);
  90. val1 |= (1 << 5);
  91. val1 |= (1 << 8);
  92. val1 &= (~(1 << 9));
  93. val1 |= (1 << 10);
  94. val1 |= (1 << 11);
  95. R_ETHER_PHY_Write(phydev, RTL_8211F_LCR_ADDR, val1);
  96. /* set led1(green) EEE LED function disabled so it can keep on when linked */
  97. R_ETHER_PHY_Read(phydev, RTL_8211F_EEELCR_ADDR, &val2);
  98. val2 &= (~(1 << 2));
  99. R_ETHER_PHY_Write(phydev, RTL_8211F_EEELCR_ADDR, val2);
  100. /* switch back to page0 */
  101. R_ETHER_PHY_Write(phydev, RTL_8211F_PAGE_SELECT, 0xa42);
  102. return 0;
  103. }
  104. void ether_phy_targets_initialize_rtl8211_rgmii(ether_phy_instance_ctrl_t *p_instance_ctrl)
  105. {
  106. ec_osal_msleep(100);
  107. phy_rtl8211f_led_fixup(p_instance_ctrl);
  108. }
  109. #define PHY_PORTS_COUNT (3) ///< Count of port
  110. #endif
  111. __attribute__((__aligned__(32))) uint8_t tx_buffer[CONFIG_EC_MAX_ENET_TXBUF_COUNT][1536] ETHER_BUFFER_PLACE_IN_SECTION;
  112. extern uint32_t SystemCoreClock;
  113. static uint8_t g_link_change = 0; ///< Link change (bit0:port0, bit1:port1, bit2:port2)
  114. static uint8_t g_link_status = 0; ///< Link status (bit0:port0, bit1:port1, bit2:port2)
  115. static uint8_t previous_link_status = 0;
  116. ec_netdev_t *ec_netdev_low_level_init(uint8_t netdev_index)
  117. {
  118. fsp_err_t res;
  119. EC_ASSERT_MSG(g_ether0_cfg.zerocopy == ETHER_ZEROCOPY_ENABLE, "zerocopy must be enabled");
  120. EC_ASSERT_MSG(g_ether0_cfg.multicast == ETHER_MULTICAST_DISABLE, "multicast must be disabled");
  121. EC_ASSERT_MSG(g_ether0_cfg.promiscuous == ETHER_PROMISCUOUS_ENABLE, "promiscuous must be enabled");
  122. EC_ASSERT_MSG(g_ether0_cfg.num_tx_descriptors == CONFIG_EC_MAX_ENET_TXBUF_COUNT, "num_tx_descriptors must be the same as \
  123. CONFIG_EC_MAX_ENET_TXBUF_COUNT");
  124. EC_ASSERT_MSG(g_ether0_cfg.num_rx_descriptors == CONFIG_EC_MAX_ENET_RXBUF_COUNT, "num_rx_descriptors must be the same as \
  125. CONFIG_EC_MAX_ENET_RXBUF_COUNT");
  126. res = R_ETHER_Open(&g_ether0_ctrl, &g_ether0_cfg);
  127. if (res != FSP_SUCCESS)
  128. EC_LOG_ERR("R_ETHER_Open failed!, res = %d", res);
  129. ec_memcpy(g_netdev.mac_addr, g_ether0_cfg.p_mac_address, 6);
  130. for (uint32_t i = 0; i < g_ether0_cfg.num_tx_descriptors; i++) {
  131. for (uint8_t j = 0; j < 6; j++) { // dst MAC
  132. EC_WRITE_U8(&tx_buffer[i][j], 0xFF);
  133. }
  134. for (uint8_t j = 0; j < 6; j++) { // src MAC
  135. EC_WRITE_U8(&tx_buffer[i][6 + j], g_ether0_cfg.p_mac_address[j]);
  136. }
  137. EC_WRITE_U16(&tx_buffer[i][12], ec_htons(0x88a4));
  138. }
  139. res = R_GPT_Open(&g_timer0_ctrl, &g_timer0_cfg);
  140. if (res != FSP_SUCCESS) {
  141. EC_LOG_ERR("R_GPT_Open failed!, res = %d", res);
  142. }
  143. return &g_netdev;
  144. }
  145. #if defined(SOC_SERIES_R7KA8P1)
  146. void ec_netdev_low_level_poll_link_state(ec_netdev_t *netdev)
  147. {
  148. fsp_err_t res;
  149. uint8_t port;
  150. uint8_t port_bit;
  151. uint8_t status_change;
  152. uint32_t phy_data;
  153. uint8_t current_link_status = 0;
  154. uint8_t i;
  155. res = R_ETHER_LinkProcess(&g_ether0_ctrl);
  156. /* Check link status for all PHY ports */
  157. for (i = 0; i < PHY_PORTS_COUNT; i++) {
  158. res = R_RMAC_PHY_Read(phy_ports[i].p_ctrl, 0x1, &phy_data);
  159. if (res == FSP_SUCCESS) {
  160. if (phy_data & 0x04) /* PHY Basic Status Register Link Status bit */
  161. {
  162. current_link_status |= phy_ports[i].port_bit; /* Port link up */
  163. }
  164. status_change = previous_link_status ^ current_link_status;
  165. if (status_change & phy_ports[i].port_bit) {
  166. g_link_change |= phy_ports[i].port_bit;
  167. }
  168. } else {
  169. EC_LOG_ERR("%s PHY_Read failed!, res = %d", phy_ports[i].name, res);
  170. }
  171. }
  172. /* Update global link status */
  173. g_link_status = current_link_status;
  174. /* Process link changes for all ports */
  175. for (port = 0; port < PHY_PORTS_COUNT; port++) {
  176. port_bit = phy_ports[port].port_bit;
  177. if (g_link_change & port_bit) {
  178. /* Link status changed */
  179. g_link_change &= (uint8_t)(~port_bit); /* change bit clear */
  180. if (g_link_status & port_bit) {
  181. /* Changed to Link-up */
  182. netdev->link_state = true;
  183. } else {
  184. /* Changed to Link-down */
  185. netdev->link_state = false;
  186. }
  187. }
  188. }
  189. previous_link_status = g_link_status;
  190. }
  191. #elif defined(SOC_SERIES_R9A07G0)
  192. void ec_netdev_low_level_poll_link_state(ec_netdev_t *netdev)
  193. {
  194. fsp_err_t res;
  195. gmac_link_status_t port_status;
  196. uint8_t port = 0;
  197. uint8_t port_bit = 0;
  198. res = R_GMAC_LinkProcess(&g_ether0_ctrl);
  199. if (0 == g_ether0.p_cfg->p_callback) {
  200. for (port = 0; port < PHY_PORTS_COUNT; port++) {
  201. res = R_GMAC_GetLinkStatus(&g_ether0_ctrl, port, &port_status);
  202. if (FSP_SUCCESS != res) {
  203. /* An error has occurred */
  204. EC_LOG_ERR("R_GMAC_GetLinkStatus failed!, res = %d", res);
  205. break;
  206. }
  207. if (GMAC_LINK_STATUS_DOWN != port_status) {
  208. /* Set link up */
  209. g_link_status |= (uint8_t)(1U << port);
  210. }
  211. }
  212. if (FSP_SUCCESS == res) {
  213. /* Set changed link status */
  214. g_link_change = previous_link_status ^ g_link_status;
  215. }
  216. }
  217. previous_link_status = g_link_status;
  218. if (FSP_SUCCESS == res) {
  219. for (port = 0; port < PHY_PORTS_COUNT; port++) {
  220. port_bit = (uint8_t)(1U << port);
  221. if (g_link_change & port_bit) {
  222. /* Link status changed */
  223. g_link_change &= (uint8_t)(~port_bit); // change bit clear
  224. if (g_link_status & port_bit) {
  225. /* Changed to Link-up */
  226. netdev->link_state = true;
  227. } else {
  228. /* Changed to Link-down */
  229. netdev->link_state = false;
  230. }
  231. }
  232. }
  233. }
  234. }
  235. #endif
  236. EC_FAST_CODE_SECTION uint8_t *ec_netdev_low_level_get_txbuf(ec_netdev_t *netdev)
  237. {
  238. return (uint8_t *)tx_buffer[netdev->tx_frame_index];
  239. }
  240. EC_FAST_CODE_SECTION int ec_netdev_low_level_output(ec_netdev_t *netdev, uint32_t size)
  241. {
  242. fsp_err_t res;
  243. res = R_ETHER_Write(&g_ether0_ctrl, tx_buffer[netdev->tx_frame_index], size);
  244. if (res != FSP_SUCCESS) {
  245. return -1;
  246. }
  247. netdev->tx_frame_index++;
  248. netdev->tx_frame_index %= g_ether0_cfg.num_tx_descriptors;
  249. return 0;
  250. }
  251. EC_FAST_CODE_SECTION int ec_netdev_low_level_input(ec_netdev_t *netdev)
  252. {
  253. fsp_err_t res;
  254. uint8_t *buffer;
  255. uint32_t len = 0;
  256. res = R_ETHER_Read(&g_ether0_ctrl, (void *)&buffer, &len);
  257. if (res != FSP_SUCCESS) {
  258. return -1;
  259. }
  260. ec_netdev_receive(netdev, buffer, len);
  261. R_ETHER_BufferRelease(&g_ether0_ctrl);
  262. return 0;
  263. }
  264. static ec_htimer_cb g_ec_htimer_cb = NULL;
  265. static void *g_ec_htimer_arg = NULL;
  266. static uint32_t g_timer_reload_us_div = 0;
  267. void timer0_esc_callback(timer_callback_args_t *p_args)
  268. {
  269. rt_interrupt_enter();
  270. if (TIMER_EVENT_CYCLE_END == p_args->event) {
  271. if (g_ec_htimer_cb) {
  272. g_ec_htimer_cb(g_ec_htimer_arg);
  273. }
  274. }
  275. rt_interrupt_leave();
  276. }
  277. void ec_htimer_start(uint32_t us, ec_htimer_cb cb, void *arg)
  278. {
  279. fsp_err_t fsp_err = FSP_SUCCESS;
  280. timer_info_t time_info;
  281. R_GPT_InfoGet(&g_timer0_ctrl, &time_info);
  282. g_timer_reload_us_div = time_info.clock_frequency / 1000000;
  283. g_ec_htimer_cb = cb;
  284. g_ec_htimer_arg = arg;
  285. fsp_err |= R_GPT_CounterSet(&g_timer0_ctrl, 0);
  286. fsp_err |= R_GPT_PeriodSet(&g_timer0_ctrl, us * g_timer_reload_us_div);
  287. fsp_err |= R_GPT_Start(&g_timer0_ctrl);
  288. if (fsp_err != FSP_SUCCESS) {
  289. EC_LOG_ERR("ec_htimer_start failed!, res = %d", fsp_err);
  290. }
  291. }
  292. void ec_htimer_stop(void)
  293. {
  294. R_GPT_Stop(&g_timer0_ctrl);
  295. }
  296. EC_FAST_CODE_SECTION void ec_htimer_update(uint32_t us)
  297. {
  298. R_GPT_PeriodSet(&g_timer0_ctrl, us * g_timer_reload_us_div);
  299. }
  300. void user_ether0_callback(ether_callback_args_t *p_args)
  301. {
  302. rt_interrupt_enter();
  303. switch (p_args->event) {
  304. case ETHER_EVENT_LINK_ON: ///< Link up detection event/
  305. g_link_status |= (uint8_t)p_args->status_ecsr; ///< status up
  306. g_link_change |= (uint8_t)p_args->status_ecsr; ///< change bit set
  307. break;
  308. case ETHER_EVENT_LINK_OFF: ///< Link down detection event
  309. g_link_status &= (uint8_t)(~p_args->status_ecsr); ///< status down
  310. g_link_change |= (uint8_t)p_args->status_ecsr; ///< change bit set
  311. break;
  312. case ETHER_EVENT_WAKEON_LAN: ///< Magic packet detection event
  313. /* If EDMAC FR (Frame Receive Event) or FDE (Receive Descriptor Empty Event)
  314. * interrupt occurs, send rx mailbox. */
  315. case ETHER_EVENT_INTERRUPT: ///< BSD Interrupt event
  316. {
  317. while (ec_netdev_low_level_input(&g_netdev) == 0) {
  318. }
  319. break;
  320. }
  321. default:
  322. break;
  323. }
  324. rt_interrupt_leave();
  325. }
  326. #ifndef CONFIG_EC_TIMESTAMP_CUSTOM
  327. uint32_t ec_get_cpu_frequency(void)
  328. {
  329. return SystemCoreClock;
  330. }
  331. #endif
  332. #if defined(SOC_SERIES_R9A07G0)
  333. volatile uint64_t mtu3_overflow_count = 0;
  334. void g_mtu3_callback(timer_callback_args_t *p_args)
  335. {
  336. rt_interrupt_enter();
  337. if (TIMER_EVENT_CYCLE_END == p_args->event) {
  338. mtu3_overflow_count++;
  339. }
  340. rt_interrupt_leave();
  341. }
  342. uint64_t gpt_get_count(void)
  343. {
  344. mtu3_status_t status;
  345. uint64_t high;
  346. uint64_t low;
  347. do {
  348. high = mtu3_overflow_count;
  349. R_MTU3_StatusGet(&g_mtu3_ctrl, &status);
  350. low = status.counter;
  351. } while (high != mtu3_overflow_count);
  352. return (high << 16) | low;
  353. }
  354. void ec_timestamp_init(void)
  355. {
  356. fsp_err_t fsp_err = FSP_SUCCESS;
  357. fsp_err = R_MTU3_Open(&g_mtu3_ctrl, &g_mtu3_cfg);
  358. fsp_err |= R_MTU3_Start(&g_mtu3_ctrl);
  359. if (fsp_err != FSP_SUCCESS) {
  360. EC_LOG_ERR("R_GPT_Open failed!, res = %d", fsp_err);
  361. }
  362. }
  363. EC_FAST_CODE_SECTION uint64_t ec_timestamp_get_time_ns(void)
  364. {
  365. return (uint64_t)(gpt_get_count() * 5ULL);
  366. }
  367. #endif