1 /*
2  * Copyright (c) 2006-2024, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2017-10-10     Tanek        the first version
9  * 2019-5-10      misonyo      add DMA TX and RX function
10  * 2020-10-14     wangqiang    use phy device in phy monitor thread
11  * 2022-08-29     xjy198903    add 1170 rgmii support
12  */
13 
14 #include <rtthread.h>
15 #include <rtdevice.h>
16 
17 #ifdef RT_USING_FINSH
18 #include <finsh.h>
19 #endif
20 
21 #include "fsl_enet.h"
22 
23 #ifdef RT_USING_LWIP
24 
25 #include <netif/ethernetif.h>
26 #include "lwipopts.h"
27 
28 #define DBG_TAG "drv.eth"
29 #define DBG_LVL DBG_INFO
30 #include <rtdbg.h>
31 
32 
33 /* The PHY ID one register */
34 #define PHY_ID1_REG                 0x02U
35 /* The PHY ID two register */
36 #define PHY_ID2_REG                 0x03U
37 /* The PHY auto-negotiate advertise register */
38 #define PHY_AUTONEG_ADVERTISE_REG   0x04U
39 
40 /* The PHY basic control register */
41 #define PHY_BASIC_CONTROL_REG       0x00U
42 #define PHY_RESET_MASK              (1<<15)
43 #define PHY_AUTO_NEGOTIATION_MASK   (1<<12)
44 
45 #define PHY_LINK         (1 << 0)
46 #define PHY_100M         (1 << 1)
47 #define PHY_FULL_DUPLEX  (1 << 2)
48 
49 
50 
51 /* The PHY basic status register */
52 #define PHY_BASIC_STATUS_REG        0x01U
53 #define PHY_LINKED_STATUS_MASK      (1<<2)
54 #define PHY_AUTONEGO_COMPLETE_MASK  (1<<5)
55 
56 
57 /*  The PHY status register. */
58 #define PHY_Status_REG              0x1FU
59 
60 #define PHY_100M_MASK               (1<<3)
61 #define PHY_FULL_DUPLEX_MASK        (1<<4)
62 #define PHY_Status_SPEED_100M(sr)   ((sr) & PHY_100M_MASK)
63 #define PHY_Status_FULL_DUPLEX(sr)  ((sr) & PHY_FULL_DUPLEX_MASK)
64 
65 
66 //extern phy_lan8741_resource_t g_phy_resource;
67 #define EXAMPLE_ENET_BASE    ENET0
68 #define EXAMPLE_PHY_ADDRESS  0x00U
69 #define ENET_EXAMPLE_IRQ     ETHERNET_IRQn
70 #define EXAMPLE_CLOCK_FREQ   (50000000U)
71 #define ENET_RXBD_NUM               (4)
72 #define ENET_TXBD_NUM               (4)
73 #define ENET_RXBUFF_SIZE            (ENET_FRAME_MAX_FRAMELEN)
74 #define ENET_BuffSizeAlign(n)       ENET_ALIGN(n, ENET_BUFF_ALIGNMENT)
75 #define ENET_ALIGN(x, align)        ((unsigned int)((x) + ((align)-1)) & (unsigned int)(~(unsigned int)((align)-1)))
76 
77 
78 rt_align(4) enet_rx_bd_struct_t g_rxBuffDescrip[ENET_RXBD_NUM];
79 rt_align(4) enet_tx_bd_struct_t g_txBuffDescrip[ENET_RXBD_NUM];
80 
81 static enet_tx_reclaim_info_t g_txDirty[ENET_TXBD_NUM];
82 
83 
84 
85 #define MAX_ADDR_LEN 6
86 
87 
88 struct rt_stm32_eth
89 {
90     /* inherit from ethernet device */
91     struct eth_device parent;
92 #ifndef PHY_USING_INTERRUPT_MODE
93     rt_timer_t poll_link_timer;
94 #endif
95 
96     /* interface address info, hw address */
97     rt_uint8_t  dev_addr[MAX_ADDR_LEN];
98     enet_handle_t g_handle;
99     rt_uint32_t    rx_channel;
100 };
101 
102 static struct rt_stm32_eth stm32_eth_device;
103 
104 
105 
ENET_IntCallback(ENET_Type * base,enet_handle_t * handle,enet_event_t event,uint8_t channel,enet_tx_reclaim_info_t * txReclaimInfo,void * param)106 static void ENET_IntCallback(ENET_Type *base, enet_handle_t *handle, enet_event_t event, uint8_t channel, enet_tx_reclaim_info_t *txReclaimInfo, void *param)
107 {
108     rt_err_t result;
109 
110     switch (event)
111     {
112         case kENET_TxIntEvent:
113             /* Get frame info after whole frame transmits out */
114 //            if (txReclaimInfo != NULL)
115 //            {
116 //                rt_free((*txReclaimInfo).context);
117 //            }
118             break;
119         case kENET_RxIntEvent:
120             stm32_eth_device.rx_channel = channel;
121             result = eth_device_ready(&(stm32_eth_device.parent));
122             if (result != RT_EOK)
123             {
124                 LOG_I("_enet_rx_data err = %d", result);
125             }
126         default:
127             break;
128     }
129 }
130 
rt_stm32_eth_init(rt_device_t dev)131 static rt_err_t rt_stm32_eth_init(rt_device_t dev)
132 {
133     uint32_t count = 0;
134     bool link      = false;
135     bool autonego  = false;
136     status_t status;
137     enet_config_t config;
138     int i;
139     uint32_t rxbuffer[ENET_RXBD_NUM];
140 
141     struct rt_stm32_eth *eth = (struct rt_stm32_eth*)dev->user_data;
142 
143     for (i = 0; i < ENET_RXBD_NUM; i++)
144     {
145         /* This is for rx buffers, static alloc and dynamic alloc both ok. use as your wish. */
146         rxbuffer[i] = (uint32_t)rt_malloc(ENET_RXBUFF_SIZE);
147     }
148 
149     /* prepare the buffer configuration. */
150     enet_buffer_config_t buffConfig[1] = {{
151         ENET_RXBD_NUM,
152         ENET_TXBD_NUM,
153         &g_txBuffDescrip[0],
154         &g_txBuffDescrip[0],
155         &g_txDirty[0],
156         &g_rxBuffDescrip[0],
157         &g_rxBuffDescrip[ENET_RXBD_NUM],
158         &rxbuffer[0],
159         ENET_BuffSizeAlign(ENET_RXBUFF_SIZE),
160     }};
161 
162 
163     CLOCK_AttachClk(kNONE_to_ENETRMII);
164     CLOCK_EnableClock(kCLOCK_Enet);
165 
166     ENET_SetSMI(EXAMPLE_ENET_BASE, CLOCK_GetCoreSysClkFreq());
167     ENET_GetDefaultConfig(&config);
168 
169     /* Use the actual speed and duplex when phy success to finish the autonegotiation. */
170     config.miiSpeed  = kENET_MiiSpeed100M;
171     config.miiDuplex = kENET_MiiFullDuplex;
172     config.interrupt = (kENET_DmaRx) | (kENET_DmaTx);
173 
174     ENET_Init(EXAMPLE_ENET_BASE, &config, &stm32_eth_device.dev_addr[0], EXAMPLE_CLOCK_FREQ);
175     ENET_DescriptorInit(EXAMPLE_ENET_BASE, &config, &buffConfig[0]);
176     ENET_CreateHandler(EXAMPLE_ENET_BASE, &eth->g_handle, &config, &buffConfig[0], ENET_IntCallback, NULL);
177     ENET_StartRxTx(EXAMPLE_ENET_BASE, 1, 1);
178 
179     return RT_EOK;
180 }
181 
182 
183 
rt_stm32_eth_control(rt_device_t dev,int cmd,void * args)184 static rt_err_t rt_stm32_eth_control(rt_device_t dev, int cmd, void *args)
185 {
186     switch (cmd)
187     {
188         case NIOCTL_GADDR:
189         /* get mac address */
190         if (args)
191         {
192             SMEMCPY(args, stm32_eth_device.dev_addr, 6);
193         }
194         else
195         {
196             return -RT_ERROR;
197         }
198         break;
199 
200     default :
201         break;
202     }
203 
204     return RT_EOK;
205 }
206 
207 
rt_stm32_eth_tx(rt_device_t dev,struct pbuf * p)208 rt_err_t rt_stm32_eth_tx(rt_device_t dev, struct pbuf *p)
209 {
210     struct pbuf *q;
211     status_t status;
212 
213     struct rt_stm32_eth *eth = (struct rt_stm32_eth*)dev->user_data;
214   //  LOG_D("rt_stm32_eth_tx: len: %d, tot_len:%d", p->len, p->tot_len);
215 
216     enet_buffer_struct_t txBuff[ENET_TXBD_NUM];
217     enet_tx_frame_struct_t txFrame = {0};
218 
219     for (q = p; q != NULL; q = q->next)
220     {
221         txBuff[txFrame.txBuffNum].buffer = q->payload;
222         txBuff[txFrame.txBuffNum].length = q->len;
223         txFrame.txBuffNum++;
224     }
225 
226     txFrame.txBuffArray        = txBuff;
227     txFrame.txConfig.intEnable = true;
228     txFrame.txConfig.tsEnable  = true;
229     txFrame.context            = RT_NULL;
230 
231 
232     status = ENET_SendFrame(EXAMPLE_ENET_BASE, &eth->g_handle, &txFrame, 0);
233 
234     return (status == kStatus_Success);
235 }
236 
rt_stm32_eth_rx(rt_device_t dev)237 struct pbuf *rt_stm32_eth_rx(rt_device_t dev)
238 {
239     struct pbuf *p = RT_NULL;
240     uint32_t len = 0;
241     status_t status;
242 
243     struct rt_stm32_eth *eth = (struct rt_stm32_eth*)dev->user_data;
244 
245     status = ENET_GetRxFrameSize(EXAMPLE_ENET_BASE, &eth->g_handle, &len, eth->rx_channel);
246 
247    // LOG_D("rt_stm32_eth_rx: status:%d, length: %d, channel:%d", status, len, eth->rx_channel);
248 
249     if (len != 0 && (status == kStatus_Success))
250     {
251         /* Received valid frame. Deliver the rx buffer with the size equal to length. */
252         p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
253         if (p != NULL)
254         {
255             status = ENET_ReadFrame(EXAMPLE_ENET_BASE, &eth->g_handle, p->payload, len, eth->rx_channel, NULL);
256 
257             if (status == kStatus_Success)
258             {
259                 return p;
260             }
261             else
262             {
263                 LOG_D(" A frame read failed\n");
264                 pbuf_free(p);
265             }
266         }
267         else
268         {
269             LOG_D(" pbuf_alloc faild\n");
270         }
271     }
272     else if (status == kStatus_ENET_RxFrameError)
273     {
274         /* update the receive buffer. */
275         ENET_ReadFrame(EXAMPLE_ENET_BASE, &eth->g_handle, NULL, 0, eth->rx_channel, NULL);
276     }
277     return RT_NULL;
278 }
279 
280 
281 
phy_monitor_thread_entry(void * parameter)282 static void phy_monitor_thread_entry(void *parameter)
283 {
284     uint8_t phy_addr = 0xFF;
285     uint8_t detected_count = 0;
286 
287     while(phy_addr == 0xFF)
288     {
289         /* phy search */
290         rt_uint16_t i, temp;
291         for (i = 0; i <= 0x1F; i++)
292         {
293            // EthHandle.Init.PhyAddress = i;
294             ENET_MDIORead(EXAMPLE_ENET_BASE, i, PHY_ID1_REG, &temp);
295 
296             if (temp != 0xFFFF && temp != 0x00)
297             {
298                 phy_addr = i;
299                 break;
300             }
301         }
302 
303         detected_count++;
304         rt_thread_mdelay(1000);
305 
306         if (detected_count > 10)
307         {
308             LOG_E("No PHY device was detected, please check hardware!");
309         }
310     }
311 
312     LOG_D("Found a phy, address:0x%02X", phy_addr);
313 
314     /* RESET PHY */
315     LOG_D("RESET PHY!");
316     ENET_MDIOWrite(EXAMPLE_ENET_BASE, phy_addr, PHY_BASIC_CONTROL_REG, PHY_RESET_MASK);
317     rt_thread_mdelay(2000);
318     ENET_MDIOWrite(EXAMPLE_ENET_BASE, phy_addr, PHY_BASIC_CONTROL_REG, PHY_AUTO_NEGOTIATION_MASK);
319 
320     while(1)
321     {
322         static rt_uint8_t phy_speed = 0;
323         uint8_t phy_speed_new = 0;
324         uint16_t status;
325 
326         ENET_MDIORead(EXAMPLE_ENET_BASE, phy_addr, PHY_BASIC_STATUS_REG, &status);
327         LOG_D("phy basic status reg is 0x%X", status);
328 
329         if (status & (PHY_AUTONEGO_COMPLETE_MASK | PHY_LINKED_STATUS_MASK))
330         {
331             uint16_t SR = 0;
332 
333             phy_speed_new |= PHY_LINK;
334 
335             ENET_MDIORead(EXAMPLE_ENET_BASE, phy_addr, PHY_Status_REG, &SR);
336             LOG_D("phy control status reg is 0x%X", SR);
337 
338             if (PHY_Status_SPEED_100M(SR))
339             {
340                 phy_speed_new |= PHY_100M;
341             }
342 
343             if (PHY_Status_FULL_DUPLEX(SR))
344             {
345                 phy_speed_new |= PHY_FULL_DUPLEX;
346             }
347         }
348 
349         if (phy_speed != phy_speed_new)
350         {
351             phy_speed = phy_speed_new;
352             if (phy_speed & PHY_LINK)
353             {
354                 LOG_D("link up");
355                 if (phy_speed & PHY_100M)
356                 {
357                     LOG_D("100Mbps");
358                 }
359                 else
360                 {
361                     LOG_D("10Mbps");
362                 }
363 
364                 if (phy_speed & PHY_FULL_DUPLEX)
365                 {
366                     LOG_D("full-duplex");
367                 }
368                 else
369                 {
370                     LOG_D("half-duplex");
371                 }
372 
373                 /* send link up. */
374                 eth_device_linkchange(&stm32_eth_device.parent, RT_TRUE);
375             }
376             else
377             {
378                 LOG_I("link down");
379                 eth_device_linkchange(&stm32_eth_device.parent, RT_FALSE);
380             }
381         }
382         rt_thread_mdelay(1000);
383     }
384 }
385 
386 
rt_hw_imxrt_eth_init(void)387 static int rt_hw_imxrt_eth_init(void)
388 {
389     rt_err_t state = RT_EOK;
390 
391     stm32_eth_device.dev_addr[0] = 0x00;
392     stm32_eth_device.dev_addr[1] = 0x80;
393     stm32_eth_device.dev_addr[2] = 0xE1;
394     stm32_eth_device.dev_addr[3] = 0x01;
395     stm32_eth_device.dev_addr[4] = 0x02;
396     stm32_eth_device.dev_addr[5] = 0x03;
397 
398     stm32_eth_device.parent.parent.init       = rt_stm32_eth_init;
399     stm32_eth_device.parent.parent.open       = RT_NULL;
400     stm32_eth_device.parent.parent.close      = RT_NULL;
401     stm32_eth_device.parent.parent.read       = RT_NULL;
402     stm32_eth_device.parent.parent.write      = RT_NULL;
403     stm32_eth_device.parent.parent.control    = rt_stm32_eth_control;
404     stm32_eth_device.parent.parent.user_data  = &stm32_eth_device;
405 
406     stm32_eth_device.parent.eth_rx     = rt_stm32_eth_rx;
407     stm32_eth_device.parent.eth_tx     = rt_stm32_eth_tx;
408 
409     /* register eth device */
410     state = eth_device_init(&(stm32_eth_device.parent), "e0");
411     if (RT_EOK != state)
412     {
413         LOG_E("emac device init faild: %d", state);
414         state = -RT_ERROR;
415     }
416 
417     /* start phy monitor */
418     rt_thread_startup(rt_thread_create("phy", phy_monitor_thread_entry, RT_NULL, 1024, RT_THREAD_PRIORITY_MAX - 2, 2));
419     return state;
420 
421 }
422 
423 INIT_DEVICE_EXPORT(rt_hw_imxrt_eth_init);
424 
425 #endif
426