drv_gmac.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  1. /*
  2. * File : drv_gmac.c
  3. * This file is part of GK710X BSP for RT-Thread distribution.
  4. *
  5. * Copyright (c) 2017 GOKE Microelectronics Co., Ltd.
  6. * All rights reserved
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License along
  19. * with this program; if not, write to the Free Software Foundation, Inc.,
  20. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  21. *
  22. * Visit http://www.goke.com to get contact with Goke.
  23. *
  24. * Change Logs:
  25. * Date Author Notes
  26. */
  27. /*****************************************************************************
  28. * Include Section
  29. * add all #include here
  30. *****************************************************************************/
  31. #include <rtthread.h>
  32. #include <rthw.h>
  33. #include <rtdevice.h>
  34. #include <netif/ethernetif.h>
  35. #include "lwipopts.h"
  36. #include "drv_gmac.h"
  37. #include "gtypes.h"
  38. #include "gd_ethernet.h"
  39. #ifdef RT_USING_GMAC
  40. /*****************************************************************************
  41. * Define section
  42. * add all #define here
  43. *****************************************************************************/
  44. #define GMAC_TX_BUFFER_SIZE 2048
  45. #define GMAC_RX_BUFFER_SIZE 2048
  46. #define MAC_ADDR0 0x11
  47. #define MAC_ADDR1 0x10
  48. #define MAC_ADDR2 0xAA
  49. #define MAC_ADDR3 0xBB
  50. #define MAC_ADDR4 0xCC
  51. #define MAC_ADDR5 0x01
  52. /****************************************************************************
  53. * ADT section
  54. * add definition of user defined Data Type that only be used in this file here
  55. ***************************************************************************/
  56. #define MAX_ADDR_LEN 6
  57. typedef struct gk_gmac_object
  58. {
  59. /* inherit from ethernet device */
  60. struct eth_device parent;
  61. GD_ETH_InitParamsT init_param;
  62. GD_ETH_OpenParamsT params;
  63. GD_HANDLE eth_handle;
  64. int link;
  65. struct rt_timer timer;
  66. U8 local_mac_address[MAX_ADDR_LEN];
  67. U8* rx_buffer;
  68. U16 rx_len;
  69. struct rt_semaphore rx_lock;
  70. #if 0
  71. UINT8 local_mac_address[MAX_ADDR_LEN];
  72. unsigned short phy_addr;
  73. int full_duplex; // read only
  74. int speed_100m; // read only
  75. UINT8* rx_ring_original;
  76. UINT8* tx_ring_original;
  77. UINT8* rx_buffer_original;
  78. UINT8* tx_buffer_original;
  79. UINT8* rx_buffer;
  80. UINT8* tx_buffer;
  81. Gmac_Rx_DMA_Descriptors* rx_ring;
  82. Gmac_Tx_DMA_Descriptors* tx_ring;
  83. unsigned long rx_buffer_dma;
  84. unsigned long tx_buffer_dma;
  85. unsigned long rx_ring_dma;
  86. unsigned long tx_ring_dma;
  87. unsigned int tx_stop;
  88. struct rt_semaphore tx_lock;
  89. struct rt_semaphore rx_lock;
  90. struct rt_semaphore tx_ack;
  91. struct rt_semaphore rx_ack;
  92. struct rt_semaphore mdio_bus_lock;
  93. int speed;
  94. int duplex;
  95. int link;
  96. int phy_interface;
  97. struct rt_timer timer;
  98. struct rt_timer rx_poll_timer;
  99. gk_gmac_stats_t stats;
  100. unsigned int rx_cur_desc;
  101. unsigned int tx_cur_desc;
  102. unsigned int get_frame_no;
  103. struct rt_workqueue* rx_queue;
  104. struct rt_work* rx_work;
  105. #endif
  106. } gk_gmac_object_t;
  107. static int recv_state = 0;
  108. static void recv_isr_callback(volatile U8* buffer, U16 len);
  109. /******************************************************************************
  110. * Function prototype section
  111. * add prototypes for all functions called by this file,execepting those
  112. * declared in header file
  113. *****************************************************************************/
  114. int gk_gmac_init(rt_device_t dev)
  115. {
  116. GERR ret = GD_OK;
  117. int open_retry = 3;
  118. GD_ETH_MacT macaddr;
  119. gk_gmac_object_t* gmac;
  120. gmac = (gk_gmac_object_t*)dev->user_data;
  121. // eth init .....
  122. gmac->init_param.bHWReset = GFALSE;
  123. gmac->init_param.phyreset = GD_GPIO_0;
  124. gmac->init_param.phyType = 0;
  125. ret = GD_ETH_Init(&(gmac->init_param));
  126. if (ret != GD_OK)
  127. {
  128. rt_kprintf("GD_ETH_Init error", ret);
  129. return -1;
  130. }
  131. gmac->eth_handle = 0;
  132. // Open eth device.
  133. gmac->params.addr = GD_ETH_PHY_EXTERNAL_AUTO;
  134. gmac->params.workmode.speed = GD_ETH_SPEED_100M;
  135. gmac->params.workmode.duplex = GD_ETH_FULL_DUPLEX;
  136. gmac->params.workmode.loopback = GD_ETH_LOOP_OFF;
  137. gmac->params.workmode.mode = GD_ETH_PHY_IF_MODE_RMII;
  138. ret = GD_ETH_Open(&(gmac->params), &(gmac->eth_handle));
  139. while ((ret != GD_OK) && (open_retry--)) {
  140. rt_kprintf("GD_ETH_Open: device open failed(%ld)"
  141. ", retry %ld\n", ret, open_retry);
  142. rt_thread_delay(10);
  143. ret = GD_ETH_Open(&(gmac->params), &(gmac->eth_handle));
  144. }
  145. if (ret == GD_OK) {
  146. rt_kprintf("GD_ETH_Open: device open successed 0x%x.\n", gmac->eth_handle);
  147. }
  148. ret = GD_ETH_GetMacAddress(gmac->eth_handle, &macaddr);
  149. if (ret != GD_OK) {
  150. rt_kprintf("GD_ETH_GetMacAddress: device getMacAddress failed, use default.\n");
  151. macaddr[0] = MAC_ADDR0;
  152. macaddr[1] = MAC_ADDR1;
  153. macaddr[2] = MAC_ADDR2;
  154. macaddr[3] = MAC_ADDR3;
  155. macaddr[4] = MAC_ADDR4;
  156. macaddr[5] = MAC_ADDR5;
  157. }
  158. rt_memcpy(gmac->local_mac_address, macaddr, MAX_ADDR_LEN);
  159. // set data coming callback.
  160. GD_ETH_SetNetReceiveFuc(recv_isr_callback);
  161. return 0;
  162. }
  163. void gk_gmac_update_link(void* param)
  164. {
  165. gk_gmac_object_t* gmac;
  166. gmac = (gk_gmac_object_t*)param;
  167. rt_device_t dev = &gmac->parent.parent;
  168. GD_ETH_StatParamsT ethstat;
  169. GD_ETH_GetStat(gmac->eth_handle, &ethstat);
  170. if (gmac->link != ethstat.linkup)
  171. {
  172. rt_kprintf("ipc ethif link is %s\n", (ethstat.linkup == GD_ETH_LINKUP ?"UP":"DOWN"));
  173. rt_kprintf(" speed is %d\n", (int)ethstat.speed);
  174. rt_kprintf(" duplex is %d\n", (int)ethstat.duplex);
  175. if (ethstat.linkup == GD_ETH_LINKUP)
  176. {
  177. rt_kprintf("%s: link up\n", dev->parent.name);
  178. eth_device_linkchange(&gmac->parent, RT_TRUE);
  179. }
  180. else
  181. {
  182. rt_kprintf("%s: link down\n", dev->parent.name);
  183. eth_device_linkchange(&gmac->parent, RT_FALSE);
  184. }
  185. gmac->link = ethstat.linkup;
  186. }
  187. }
  188. /*********************
  189. *
  190. * up level use interface
  191. *
  192. *********************/
  193. static rt_err_t rt_gk_gmac_init(rt_device_t dev)
  194. {
  195. int ret;
  196. gk_gmac_object_t* gmac;
  197. gmac = (gk_gmac_object_t*)dev->user_data;
  198. rt_timer_init(&gmac->timer, "link_timer", gk_gmac_update_link, (void*)gmac,
  199. RT_TICK_PER_SECOND, RT_TIMER_FLAG_PERIODIC);
  200. rt_timer_start(&gmac->timer);
  201. return RT_EOK;
  202. }
  203. static rt_err_t rt_gk_gmac_open(rt_device_t dev, rt_uint16_t oflag)
  204. {
  205. return RT_EOK;
  206. }
  207. static rt_err_t rt_gk_gmac_close(rt_device_t dev)
  208. {
  209. gk_gmac_object_t* gmac;
  210. gmac = (gk_gmac_object_t*)dev->user_data;
  211. GD_ETH_Close(&(gmac->eth_handle));
  212. return RT_EOK;
  213. }
  214. static rt_size_t rt_gk_gmac_read(rt_device_t dev, rt_off_t pos, void* buffer,
  215. rt_size_t size)
  216. {
  217. rt_set_errno(-RT_ENOSYS);
  218. return 0;
  219. }
  220. static rt_size_t rt_gk_gmac_write(rt_device_t dev, rt_off_t pos,
  221. const void* buffer, rt_size_t size)
  222. {
  223. rt_set_errno(-RT_ENOSYS);
  224. return 0;
  225. }
  226. static rt_err_t rt_gk_gmac_control(rt_device_t dev, int cmd, void* args)
  227. {
  228. gk_gmac_object_t* gmac;
  229. gmac = (gk_gmac_object_t*)dev->user_data;
  230. switch (cmd)
  231. {
  232. case NIOCTL_GADDR:
  233. /* get mac address */
  234. if (args)
  235. rt_memcpy(args, gmac->local_mac_address, MAX_ADDR_LEN);
  236. else
  237. return -RT_ERROR;
  238. break;
  239. default:
  240. break;
  241. }
  242. return RT_EOK;
  243. }
  244. /* ethernet device interface */
  245. /* transmit packet. */
  246. static rt_uint8_t g_output_buf[PBUF_POOL_BUFSIZE+20];
  247. static rt_err_t rt_gk_gmac_tx(rt_device_t dev, struct pbuf* p)
  248. {
  249. rt_err_t ret = RT_EOK;
  250. struct pbuf *q = NULL;
  251. gk_gmac_object_t* gmac;
  252. gmac = (gk_gmac_object_t*)dev->user_data;
  253. if (p == NULL)
  254. {
  255. rt_kprintf("rt_gk_gmac_tx: out_pbuf is NULL\n");
  256. ret = ERR_MEM;
  257. return ret;
  258. }
  259. if (gmac->eth_handle == 0)
  260. {
  261. rt_kprintf("rt_gk_gmac_tx: eth_handle is 0\n");
  262. ret = ERR_MEM;
  263. return ret;
  264. }
  265. rt_uint8_t *output_bufptr = p->payload;
  266. if (p->len != p->tot_len)
  267. {
  268. rt_uint8_t *bufptr = g_output_buf;
  269. for (q = p; q != NULL; q = q->next)
  270. {
  271. rt_memcpy(bufptr, q->payload, q->len);
  272. bufptr += q->len;
  273. }
  274. output_bufptr = g_output_buf;
  275. }/* (else) write to ethernet, reduce memcpy */
  276. ret = GD_ETH_Write(gmac->eth_handle, (char *) output_bufptr, p->tot_len, GD_ETH_FRAME_END);
  277. if (ret != GD_OK)
  278. {
  279. rt_kprintf("rt_gk_gmac_tx: eth Write error, len = %d, ret = %lu\n", p->tot_len, ret);
  280. ret = RT_EIO;
  281. }
  282. else
  283. {
  284. ret = RT_EOK;
  285. }
  286. return ret;
  287. }
  288. static struct pbuf * _convert_data_to_pbuf(U8 *buffer, U32 len)
  289. {
  290. struct pbuf *p, *q;
  291. U8 *bufptr;
  292. U32 buflen;
  293. if (len <= 0) {
  294. rt_kprintf("_convert_data_to_pbuf: len(%d) <= 0\n", len);
  295. return NULL;
  296. }
  297. buflen = len;
  298. p = pbuf_alloc(PBUF_RAW, buflen, PBUF_POOL);
  299. if (p != NULL) {
  300. bufptr = (U8 *) buffer;
  301. for (q = p; q != NULL; q = q->next) {
  302. SMEMCPY(q->payload, bufptr, q->len);
  303. bufptr += q->len;
  304. }
  305. } else {
  306. rt_kprintf("_convert_data_to_pbuf: can't alloc pbuf(len=%lu)\n", buflen);
  307. return NULL;
  308. }
  309. return p;
  310. }
  311. /* reception packet. */
  312. static struct pbuf* rt_gk_gmac_rx(rt_device_t dev)
  313. {
  314. gk_gmac_object_t* gmac;
  315. gmac = (gk_gmac_object_t*)dev->user_data;
  316. if (!recv_state)
  317. {
  318. return RT_NULL;
  319. }
  320. struct pbuf* temp_pbuf = RT_NULL;
  321. if (gmac->rx_len <= 0)
  322. {
  323. rt_kprintf("rt_gk_gmac_rx: len(%d) <= 0\n", gmac->rx_len);
  324. return RT_NULL;
  325. }
  326. rt_sem_take(&gmac->rx_lock, RT_WAITING_FOREVER);
  327. //rt_kprintf("rt_gk_gmac_rx buffer = 0x%x, len = %d\n", gmac->rx_buffer, gmac->rx_len);
  328. //temp_pbuf = pbuf_alloc(PBUF_LINK, gmac->rx_len, PBUF_RAM);
  329. temp_pbuf = _convert_data_to_pbuf(gmac->rx_buffer, gmac->rx_len);
  330. if (!temp_pbuf)
  331. {
  332. rt_kprintf("alloc pbuf failed\n");
  333. rt_sem_release(&gmac->rx_lock);
  334. return RT_NULL;
  335. }
  336. //rt_memcpy(temp_pbuf->payload, gmac->rx_buffer, gmac->rx_len);
  337. recv_state = 0;
  338. rt_sem_release(&gmac->rx_lock);
  339. return temp_pbuf;
  340. }
  341. static void recv_isr_callback(volatile U8* buffer, U16 len)
  342. {
  343. gk_gmac_object_t* gmac;
  344. int ret_eth;
  345. recv_state = 1;
  346. rt_device_t dev = rt_device_find("e0");
  347. if (dev == RT_NULL)
  348. {
  349. rt_kprintf("rt_device_find e0 == NULL\n");
  350. return;
  351. }
  352. gmac = (gk_gmac_object_t*)dev->user_data;
  353. if (buffer == NULL) {
  354. rt_kprintf("recv_isr_callback: error buffer == NULL\n");
  355. return;
  356. }
  357. if ((len <= 0) || (len > GMAC_RX_BUFFER_SIZE)) {
  358. rt_kprintf("recv_isr_callback: error len = %d(1~%d)\n", len, GMAC_RX_BUFFER_SIZE);
  359. return;
  360. }
  361. gmac->rx_buffer = (U8*)buffer;
  362. gmac->rx_len = len;
  363. //rt_kprintf("recv_isr_callback = 0x%x, len = %d\n", gmac->rx_buffer, gmac->rx_len);
  364. ret_eth = eth_device_ready(&(gmac->parent));
  365. if (ret_eth != RT_EOK)
  366. {
  367. rt_kprintf("eth_device_ready error %d\n",ret_eth);
  368. }
  369. }
  370. int rt_app_gk_gmac_init(void)
  371. {
  372. gk_gmac_object_t* gmac;
  373. GD_ETH_MacT macaddr;
  374. gmac = (gk_gmac_object_t*)rt_malloc(sizeof(*gmac));
  375. if (gmac == NULL)
  376. {
  377. rt_kprintf("gk_eth_initialize: Cannot allocate Gmac_Object %d\n", 1);
  378. return (-1);
  379. }
  380. memset(gmac, 0, sizeof(gk_gmac_object_t));
  381. rt_sem_init(&gmac->rx_lock, "rx_lock", 1, RT_IPC_FLAG_FIFO);
  382. gmac->parent.parent.init = rt_gk_gmac_init;
  383. gmac->parent.parent.open = rt_gk_gmac_open;
  384. gmac->parent.parent.close = rt_gk_gmac_close;
  385. gmac->parent.parent.read = rt_gk_gmac_read;
  386. gmac->parent.parent.write = rt_gk_gmac_write;
  387. gmac->parent.parent.control = rt_gk_gmac_control;
  388. gmac->parent.parent.user_data = (void*)gmac;
  389. gmac->parent.eth_rx = rt_gk_gmac_rx;
  390. gmac->parent.eth_tx = rt_gk_gmac_tx;
  391. gk_gmac_init(&gmac->parent.parent);
  392. eth_device_init(&(gmac->parent), "e0");
  393. return 0;
  394. }
  395. #ifdef RT_USING_FINSH
  396. #include "finsh.h"
  397. void dump_rx_desc(void)
  398. {
  399. int i;
  400. gk_gmac_object_t* gmac;
  401. rt_device_t dev = rt_device_find("e0");
  402. if (dev == RT_NULL) return;
  403. gmac = (gk_gmac_object_t*)dev->user_data;
  404. rt_kprintf("soft current desc is:%d\n", gmac->link);
  405. }
  406. void dump_tx_desc(void)
  407. {
  408. int i;
  409. gk_gmac_object_t* gmac;
  410. rt_device_t dev = rt_device_find("e0");
  411. if (dev == RT_NULL) return;
  412. gmac = (gk_gmac_object_t*)dev->user_data;
  413. rt_kprintf("soft current desc is:%d\n", gmac->link);
  414. }
  415. FINSH_FUNCTION_EXPORT(dump_rx_desc, dump e0 rx desc);
  416. FINSH_FUNCTION_EXPORT(dump_tx_desc, dump e0 tx desc);
  417. #endif
  418. #endif