1 /*
2  * Copyright (c) 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2023 NXP
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include <math.h>
9 #include "fsl_enet.h"
10 
11 /*******************************************************************************
12  * Definitions
13  ******************************************************************************/
14 
15 /* Component ID definition, used by tools. */
16 #ifndef FSL_COMPONENT_ID
17 #define FSL_COMPONENT_ID "platform.drivers.lpc_enet"
18 #endif
19 
20 /*! @brief Defines 10^9 nanosecond. */
21 #define ENET_NANOSECS_ONESECOND (1000000000U)
22 /*! @brief Defines 10^6 microsecond.*/
23 #define ENET_MICRSECS_ONESECOND (1000000U)
24 
25 /*! @brief Rx buffer LSB ignore bits. */
26 #define ENET_RXBUFF_IGNORELSB_BITS (2U)
27 /*! @brief ENET FIFO size unit. */
28 #define ENET_FIFOSIZE_UNIT (256U)
29 /*! @brief ENET half-dulpex default IPG. */
30 #define ENET_HALFDUPLEX_DEFAULTIPG (4U)
31 /*! @brief ENET miminum ring length. */
32 #define ENET_MIN_RINGLEN (4U)
33 /*! @brief ENET wakeup filter numbers. */
34 #define ENET_WAKEUPFILTER_NUM (8U)
35 /*! @brief Requried systime timer frequency. */
36 #define ENET_SYSTIME_REQUIRED_CLK_MHZ (50U)
37 /*! @brief Ethernet VLAN tag length. */
38 #define ENET_FRAME_VLAN_TAGLEN 4U
39 
40 /*! @brief AVB TYPE */
41 #define ENET_AVBTYPE             0x22F0U
42 #define ENET_HEAD_TYPE_OFFSET    (12)
43 #define ENET_HEAD_AVBTYPE_OFFSET (16)
44 
45 /*! @brief Binary rollover mode count convert */
46 #define ENET_BINARY_ROLLOVER_SCALE(x) (uint32_t)((uint64_t)(x)*46566U / 100000U)
47 
48 /*******************************************************************************
49  * Prototypes
50  ******************************************************************************/
51 
52 /*!
53  * @brief Increase the index in the ring.
54  *
55  * @param index The current index.
56  * @param max The size.
57  * @return the increased index.
58  */
59 static uint16_t ENET_IncreaseIndex(uint16_t index, uint16_t max);
60 
61 /*!
62  * @brief Set ENET system configuration.
63  *  This function reset the ethernet module and set the phy selection.
64  *  It should be called before any other ethernet operation.
65  *
66  * @param miiMode  The MII/RMII mode for interface between the phy and ethernet.
67  */
68 static void ENET_SetSYSControl(enet_mii_mode_t miiMode);
69 
70 /*!
71  * @brief Set ENET DMA controller with the configuration.
72  *
73  * @param base ENET peripheral base address.
74  * @param config ENET Mac configuration.
75  */
76 static void ENET_SetDMAControl(ENET_Type *base, const enet_config_t *config);
77 
78 /*!
79  * @brief Set ENET MAC controller with the configuration.
80  *
81  * @param base ENET peripheral base address.
82  * @param config ENET Mac configuration.
83  * @param macAddr ENET six-byte mac address.
84  */
85 static void ENET_SetMacControl(ENET_Type *base, const enet_config_t *config, uint8_t *macAddr);
86 /*!
87  * @brief Set ENET MTL with the configuration.
88  *
89  * @param base ENET peripheral base address.
90  * @param config ENET Mac configuration.
91  */
92 static void ENET_SetMTL(ENET_Type *base, const enet_config_t *config);
93 
94 /*!
95  * @brief Set ENET DMA transmit buffer descriptors for one channel.
96  *
97  * @param base ENET peripheral base address.
98  * @param bufferConfig ENET buffer configuration.
99  * @param channel The channel number, 0 , 1.
100  */
101 static status_t ENET_TxDescriptorsInit(ENET_Type *base, const enet_buffer_config_t *bufferConfig, uint8_t channel);
102 
103 /*!
104  * @brief Set ENET DMA receive buffer descriptors for one channel.
105  *
106  * @param base ENET peripheral base address.
107  * @param config The ENET configuration.
108  * @param bufferConfig ENET buffer configuration.
109  * @param channel The channel number, 0 , 1.
110  */
111 static status_t ENET_RxDescriptorsInit(ENET_Type *base,
112                                        enet_config_t *config,
113                                        const enet_buffer_config_t *bufferConfig,
114                                        uint8_t channel);
115 
116 /*!
117  * @brief Drop one frame in specified BD channel.
118  *
119  * @param base ENET peripheral base address.
120  * @param handle ENET handler.
121  * @param channel The channel number, 0 , 1.
122  */
123 static void ENET_DropFrame(ENET_Type *base, enet_handle_t *handle, uint8_t channel);
124 
125 #ifdef ENET_PTP1588FEATURE_REQUIRED
126 /*!
127  * @brief Sets the ENET 1588 feature.
128  *
129  * Enable the enhacement 1588 buffer descriptor mode and start
130  * the 1588 timer.
131  *
132  * @param base ENET peripheral base address.
133  * @param config The ENET configuration.
134  * @param refClk_Hz The reference clock for ptp 1588.
135  */
136 static void ENET_SetPtp1588(ENET_Type *base, const enet_config_t *config, uint32_t refClk_Hz);
137 #endif /* ENET_PTP1588FEATURE_REQUIRED */
138 
139 /*******************************************************************************
140  * Variables
141  ******************************************************************************/
142 
143 /*! @brief Pointers to enet handles for each instance. */
144 static enet_handle_t *s_ENETHandle[FSL_FEATURE_SOC_LPC_ENET_COUNT] = {NULL};
145 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
146 /*! @brief Pointers to enet clocks for each instance. */
147 const clock_ip_name_t s_enetClock[FSL_FEATURE_SOC_LPC_ENET_COUNT] = ETH_CLOCKS;
148 #endif /*  FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
149 
150 /*! @brief Pointers to enet bases for each instance. */
151 static ENET_Type *const s_enetBases[] = ENET_BASE_PTRS;
152 
153 /*! @brief Pointers to enet IRQ number for each instance. */
154 static const IRQn_Type s_enetIrqId[] = ENET_IRQS;
155 
156 /* ENET ISR for transactional APIs. */
157 #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
158 static enet_isr_t s_enetIsr = (enet_isr_t)DefaultISR;
159 #else
160 static enet_isr_t s_enetIsr;
161 #endif
162 /*******************************************************************************
163  * Code
164  ******************************************************************************/
ENET_IncreaseIndex(uint16_t index,uint16_t max)165 static uint16_t ENET_IncreaseIndex(uint16_t index, uint16_t max)
166 {
167     /* Increase the index. */
168     index++;
169     if (index >= max)
170     {
171         index = 0;
172     }
173     return index;
174 }
175 
ENET_SetSYSControl(enet_mii_mode_t miiMode)176 static void ENET_SetSYSControl(enet_mii_mode_t miiMode)
177 {
178 #ifdef SYSCON_ETHPHYSEL_PHY_SEL_MASK
179     /* Reset first. */
180     SYSCON->PRESETCTRL[2] = SYSCON_PRESETCTRL_ETH_RST_MASK;
181     SYSCON->PRESETCTRL[2] &= ~SYSCON_PRESETCTRL_ETH_RST_MASK;
182     /* Set MII/RMII before the peripheral ethernet dma reset. */
183     SYSCON->ETHPHYSEL = (SYSCON->ETHPHYSEL & ~SYSCON_ETHPHYSEL_PHY_SEL_MASK) | SYSCON_ETHPHYSEL_PHY_SEL(miiMode);
184 #else
185     /* Reset first. */
186     SYSCON0->PRESETCTRL2 = SYSCON_PRESETCTRL2_ENET_RST_MASK;
187     SYSCON0->PRESETCTRL2 &= ~SYSCON_PRESETCTRL2_ENET_RST_MASK;
188     /* Set MII/RMII before the peripheral ethernet dma reset. */
189     SYSCON0->ENET_PHY_INTF_SEL = (SYSCON0->ENET_PHY_INTF_SEL & ~SYSCON_ENET_PHY_INTF_SEL_PHY_SEL_MASK) |
190                                  SYSCON_ENET_PHY_INTF_SEL_PHY_SEL(miiMode);
191 #endif
192 }
193 
ENET_SetDMAControl(ENET_Type * base,const enet_config_t * config)194 static void ENET_SetDMAControl(ENET_Type *base, const enet_config_t *config)
195 {
196     assert(config);
197 
198     uint8_t index;
199     uint32_t reg;
200     uint32_t burstLen;
201 
202     /* Reset first and wait for the complete
203      * The reset bit will automatically be cleared after complete. */
204     base->DMA_MODE |= ENET_DMA_MODE_SWR_MASK;
205     while ((base->DMA_MODE & ENET_DMA_MODE_SWR_MASK) != 0U)
206     {
207     }
208 
209     /* Set the burst length. */
210     for (index = 0; index < ENET_RING_NUM_MAX; index++)
211     {
212         burstLen = (uint32_t)kENET_BurstLen1;
213         if (config->multiqueueCfg != NULL)
214         {
215             burstLen = (uint32_t)config->multiqueueCfg->burstLen;
216         }
217         base->DMA_CH[index].DMA_CHX_CTRL = burstLen & ENET_DMA_CH_DMA_CHX_CTRL_PBLx8_MASK;
218 
219         reg = base->DMA_CH[index].DMA_CHX_TX_CTRL & ~ENET_DMA_CH_DMA_CHX_TX_CTRL_TxPBL_MASK;
220         base->DMA_CH[index].DMA_CHX_TX_CTRL = reg | ENET_DMA_CH_DMA_CHX_TX_CTRL_TxPBL(burstLen & 0x3FU);
221 
222         reg = base->DMA_CH[index].DMA_CHX_RX_CTRL & ~ENET_DMA_CH_DMA_CHX_RX_CTRL_RxPBL_MASK;
223         base->DMA_CH[index].DMA_CHX_RX_CTRL = reg | ENET_DMA_CH_DMA_CHX_RX_CTRL_RxPBL(burstLen & 0x3FU);
224     }
225 }
226 
ENET_SetMTL(ENET_Type * base,const enet_config_t * config)227 static void ENET_SetMTL(ENET_Type *base, const enet_config_t *config)
228 {
229     assert(config);
230 
231     uint32_t txqOpreg                   = 0;
232     uint32_t rxqOpReg                   = 0;
233     enet_multiqueue_config_t *multiqCfg = config->multiqueueCfg;
234     uint8_t index;
235 
236     /* Set transmit operation mode. */
237     if ((config->specialControl & (uint16_t)kENET_StoreAndForward) != 0U)
238     {
239         txqOpreg = ENET_MTL_QUEUE_MTL_TXQX_OP_MODE_TSF_MASK;
240         rxqOpReg = ENET_MTL_QUEUE_MTL_RXQX_OP_MODE_RSF_MASK;
241     }
242     txqOpreg |= ENET_MTL_QUEUE_MTL_TXQX_OP_MODE_FTQ_MASK |
243                 ENET_MTL_QUEUE_MTL_TXQX_OP_MODE_TQS(ENET_MTL_TXFIFOSIZE / ENET_FIFOSIZE_UNIT - 1UL);
244     base->MTL_QUEUE[0].MTL_TXQX_OP_MODE = txqOpreg | ENET_MTL_QUEUE_MTL_TXQX_OP_MODE_TXQEN(2);
245     base->MTL_QUEUE[1].MTL_TXQX_OP_MODE = txqOpreg;
246 
247     /* Set receive operation mode. */
248     rxqOpReg |= ENET_MTL_QUEUE_MTL_RXQX_OP_MODE_FUP_MASK |
249                 ENET_MTL_QUEUE_MTL_RXQX_OP_MODE_RQS(ENET_MTL_RXFIFOSIZE / ENET_FIFOSIZE_UNIT - 1UL);
250     base->MTL_QUEUE[0].MTL_RXQX_OP_MODE = rxqOpReg;
251 
252     /* Set the schedule/arbitration(set for multiple queues). */
253     if (multiqCfg != NULL)
254     {
255         base->MTL_OP_MODE = ENET_MTL_OP_MODE_SCHALG(multiqCfg->mtltxSche) | ENET_MTL_OP_MODE_RAA(multiqCfg->mtlrxSche);
256         /* Set the Rx queue mapping to dma channel. */
257         base->MTL_RXQ_DMA_MAP = (uint32_t)multiqCfg->mtlrxQuemap;
258         /* Set the Tx/Rx queue operation mode for multi-queue. */
259         base->MTL_QUEUE[1].MTL_TXQX_OP_MODE |= ENET_MTL_QUEUE_MTL_TXQX_OP_MODE_TXQEN(2);
260         base->MTL_QUEUE[1].MTL_RXQX_OP_MODE = rxqOpReg;
261 
262         /* Set the Tx/Rx queue weight. */
263         for (index = 0; index < ENET_RING_NUM_MAX; index++)
264         {
265             base->MTL_QUEUE[index].MTL_TXQX_QNTM_WGHT = multiqCfg->txqueweight[index];
266             base->MTL_QUEUE[index].MTL_RXQX_CTRL = ENET_MTL_QUEUE_MTL_RXQX_CTRL_RXQ_WEGT(multiqCfg->rxqueweight[index]);
267         }
268     }
269 }
270 
ENET_SetMacControl(ENET_Type * base,const enet_config_t * config,uint8_t * macAddr)271 static void ENET_SetMacControl(ENET_Type *base, const enet_config_t *config, uint8_t *macAddr)
272 {
273     assert(config);
274 
275     uint32_t reg = 0;
276 
277     /* Set Macaddr */
278     /* The dma channel 0 is set as to which the Rx packet
279      * whose DA matches the MAC address content is routed. */
280     if (macAddr != NULL)
281     {
282         ENET_SetMacAddr(base, macAddr);
283     }
284 
285     /* Set the receive filter. */
286     reg = ENET_MAC_FRAME_FILTER_PR(!((config->specialControl & (uint16_t)kENET_PromiscuousEnable) == 0U)) |
287           ENET_MAC_FRAME_FILTER_DBF(!((config->specialControl & (uint16_t)kENET_BroadCastRxDisable) == 0U)) |
288           ENET_MAC_FRAME_FILTER_PM(!((config->specialControl & (uint16_t)kENET_MulticastAllEnable) == 0U));
289     base->MAC_FRAME_FILTER = reg;
290     /* Flow control. */
291     if ((config->specialControl & (uint16_t)kENET_FlowControlEnable) != 0U)
292     {
293         base->MAC_RX_FLOW_CTRL      = ENET_MAC_RX_FLOW_CTRL_RFE_MASK | ENET_MAC_RX_FLOW_CTRL_UP_MASK;
294         base->MAC_TX_FLOW_CTRL_Q[0] = ENET_MAC_TX_FLOW_CTRL_Q_PT(config->pauseDuration);
295         base->MAC_TX_FLOW_CTRL_Q[1] = ENET_MAC_TX_FLOW_CTRL_Q_PT(config->pauseDuration);
296     }
297 
298     /* Set the 1us ticket. */
299     reg                      = CLOCK_GetCoreSysClkFreq() / ENET_MICRSECS_ONESECOND - 1U;
300     base->MAC_1US_TIC_COUNTR = ENET_MAC_1US_TIC_COUNTR_TIC_1US_CNTR(reg);
301 
302     /* Set the speed and duplex. */
303     reg = ENET_MAC_CONFIG_ECRSFD_MASK | ENET_MAC_CONFIG_PS_MASK | ENET_MAC_CONFIG_DM(config->miiDuplex) |
304           ENET_MAC_CONFIG_FES(config->miiSpeed) |
305           ENET_MAC_CONFIG_S2KP((config->specialControl & (uint16_t)kENET_8023AS2KPacket) != 0U) |
306           ENET_MAC_CONFIG_IPC((config->specialControl & (uint16_t)kENET_RxChecksumOffloadEnable) != 0U);
307     if (config->miiDuplex == kENET_MiiHalfDuplex)
308     {
309         reg |= ENET_MAC_CONFIG_IPG(ENET_HALFDUPLEX_DEFAULTIPG);
310     }
311     base->MAC_CONFIG = reg;
312 
313     /* Enable channel. */
314     base->MAC_RXQ_CTRL[0] = ENET_MAC_RXQ_CTRL_RXQ0EN(1) | ENET_MAC_RXQ_CTRL_RXQ1EN(1);
315 }
316 
ENET_TxDescriptorsInit(ENET_Type * base,const enet_buffer_config_t * bufferConfig,uint8_t channel)317 static status_t ENET_TxDescriptorsInit(ENET_Type *base, const enet_buffer_config_t *bufferConfig, uint8_t channel)
318 {
319     uint16_t j;
320     enet_tx_bd_struct_t *txbdPtr;
321     const enet_buffer_config_t *buffCfg = bufferConfig;
322 
323     if (buffCfg == NULL)
324     {
325         return kStatus_InvalidArgument;
326     }
327 
328     /* Check the ring length. */
329     if (buffCfg->txRingLen < ENET_MIN_RINGLEN)
330     {
331         return kStatus_InvalidArgument;
332     }
333     /* Set the Tx descriptor start/tail pointer, shall be word aligned. */
334     base->DMA_CH[channel].DMA_CHX_TXDESC_LIST_ADDR =
335         (uint32_t)buffCfg->txDescStartAddrAlign & ENET_DMA_CH_DMA_CHX_TXDESC_LIST_ADDR_STL_MASK;
336     base->DMA_CH[channel].DMA_CHX_TXDESC_TAIL_PTR =
337         (uint32_t)buffCfg->txDescTailAddrAlign & ENET_DMA_CH_DMA_CHX_TXDESC_LIST_ADDR_STL_MASK;
338     /* Set the Tx ring length. */
339     base->DMA_CH[channel].DMA_CHX_TXDESC_RING_LENGTH =
340         ((uint32_t)buffCfg->txRingLen - 1U) & ENET_DMA_CH_DMA_CHX_TXDESC_RING_LENGTH_TDRL_MASK;
341 
342     /* Init the txbdPtr to the transmit descriptor start address. */
343     txbdPtr = (enet_tx_bd_struct_t *)(buffCfg->txDescStartAddrAlign);
344     for (j = 0; j < buffCfg->txRingLen; j++)
345     {
346         txbdPtr->tdes0 = 0;
347         txbdPtr->tdes1 = 0;
348         txbdPtr->tdes2 = 0;
349         txbdPtr->tdes3 = 0;
350         txbdPtr++;
351     }
352 
353     return kStatus_Success;
354 }
355 
ENET_RxDescriptorsInit(ENET_Type * base,enet_config_t * config,const enet_buffer_config_t * bufferConfig,uint8_t channel)356 static status_t ENET_RxDescriptorsInit(ENET_Type *base,
357                                        enet_config_t *config,
358                                        const enet_buffer_config_t *bufferConfig,
359                                        uint8_t channel)
360 {
361     uint16_t j;
362     uint32_t reg;
363     enet_rx_bd_struct_t *rxbdPtr;
364     uint16_t index;
365     bool doubleBuffEnable = ((config->specialControl & (uint16_t)kENET_DescDoubleBuffer) != 0U) ? true : false;
366     const enet_buffer_config_t *buffCfg = bufferConfig;
367     uint32_t control                    = ENET_RXDESCRIP_RD_BUFF1VALID_MASK;
368 
369     if (buffCfg == NULL)
370     {
371         return kStatus_InvalidArgument;
372     }
373 
374     if (0U != (config->interrupt & (uint32_t)kENET_DmaRx))
375     {
376         control |= ENET_RXDESCRIP_RD_IOC_MASK;
377     }
378 
379     if (doubleBuffEnable)
380     {
381         control |= ENET_RXDESCRIP_RD_BUFF2VALID_MASK;
382     }
383 
384     /* Not give ownership to DMA before Rx buffer is ready */
385     if ((config->rxBuffAlloc == NULL) || (config->rxBuffFree == NULL))
386     {
387         control |= ENET_RXDESCRIP_WR_OWN_MASK;
388     }
389 
390     /* Check the ring length. */
391     if (buffCfg->rxRingLen < ENET_MIN_RINGLEN)
392     {
393         return kStatus_InvalidArgument;
394     }
395 
396     /* Set the Rx descriptor start/tail pointer, shall be word aligned. */
397     base->DMA_CH[channel].DMA_CHX_RXDESC_LIST_ADDR =
398         (uint32_t)buffCfg->rxDescStartAddrAlign & ENET_DMA_CH_DMA_CHX_RXDESC_LIST_ADDR_SRL_MASK;
399     base->DMA_CH[channel].DMA_CHX_RXDESC_TAIL_PTR =
400         (uint32_t)buffCfg->rxDescTailAddrAlign & ENET_DMA_CH_DMA_CHX_RXDESC_LIST_ADDR_SRL_MASK;
401     base->DMA_CH[channel].DMA_CHX_RXDESC_RING_LENGTH =
402         ((uint32_t)buffCfg->rxRingLen - 1U) & ENET_DMA_CH_DMA_CHX_RXDESC_RING_LENGTH_RDRL_MASK;
403     reg = base->DMA_CH[channel].DMA_CHX_RX_CTRL & ~ENET_DMA_CH_DMA_CHX_RX_CTRL_RBSZ_MASK;
404     reg |= ENET_DMA_CH_DMA_CHX_RX_CTRL_RBSZ(buffCfg->rxBuffSizeAlign >> ENET_RXBUFF_IGNORELSB_BITS);
405     base->DMA_CH[channel].DMA_CHX_RX_CTRL = reg;
406 
407     /* Init the rxbdPtr to the receive descriptor start address. */
408     rxbdPtr = (enet_rx_bd_struct_t *)(buffCfg->rxDescStartAddrAlign);
409 
410     for (j = 0; j < buffCfg->rxRingLen; j++)
411     {
412         if ((config->rxBuffAlloc == NULL) || (config->rxBuffFree == NULL))
413         {
414             if (doubleBuffEnable)
415             {
416                 index = 2U * j;
417             }
418             else
419             {
420                 index = j;
421             }
422             rxbdPtr->rdes0 = buffCfg->rxBufferStartAddr[index];
423             /* The second buffer is set with 0 because it is not required for normal case. */
424             if (doubleBuffEnable)
425             {
426                 rxbdPtr->rdes2 = buffCfg->rxBufferStartAddr[index + 1U];
427             }
428             else
429             {
430                 rxbdPtr->rdes2 = 0;
431             }
432         }
433 
434         /* Set the valid and DMA own flag.*/
435         rxbdPtr->rdes3 = control;
436         rxbdPtr++;
437     }
438 
439     return kStatus_Success;
440 }
441 
442 #ifdef ENET_PTP1588FEATURE_REQUIRED
ENET_SetPtp1588(ENET_Type * base,const enet_config_t * config,uint32_t refClk_Hz)443 static void ENET_SetPtp1588(ENET_Type *base, const enet_config_t *config, uint32_t refClk_Hz)
444 {
445     assert(config);
446     assert(config->ptpConfig);
447     assert(refClk_Hz);
448 
449     uint32_t control;
450     enet_ptp_config_t *ptpConfig = config->ptpConfig;
451 
452     /* Clear the timestamp interrupt first. */
453     base->MAC_INTR_EN &= ~ENET_MAC_INTR_EN_TSIE_MASK;
454 
455     if (ptpConfig->fineUpdateEnable)
456     {
457         base->MAC_TIMESTAMP_CTRL |= ENET_MAC_TIMESTAMP_CTRL_TSCFUPDT_MASK;
458         /* Set the initial added value for the fine update. */
459         control = 100000000U / (refClk_Hz / ENET_MICRSECS_ONESECOND / ENET_SYSTIME_REQUIRED_CLK_MHZ);
460         base->MAC_SYS_TIMESTMP_ADDEND = control;
461         base->MAC_TIMESTAMP_CTRL |= ENET_MAC_TIMESTAMP_CTRL_TADDREG_MASK;
462         while ((base->MAC_TIMESTAMP_CTRL & ENET_MAC_TIMESTAMP_CTRL_TADDREG_MASK) != 0U)
463         {
464         }
465     }
466 
467     /* Enable the IEEE 1588 timestamping and snapshot for event message. */
468     control = ENET_MAC_TIMESTAMP_CTRL_TSENA_MASK | ENET_MAC_TIMESTAMP_CTRL_TSIPV4ENA_MASK |
469               ENET_MAC_TIMESTAMP_CTRL_TSIPV6ENA_MASK | ENET_MAC_TIMESTAMP_CTRL_TSENALL_MASK |
470               ENET_MAC_TIMESTAMP_CTRL_TSEVTENA_MASK | ENET_MAC_TIMESTAMP_CTRL_SNAPTYPSEL_MASK |
471               ENET_MAC_TIMESTAMP_CTRL_TSCTRLSSR(ptpConfig->tsRollover);
472 
473     if (ptpConfig->ptp1588V2Enable)
474     {
475         control |= ENET_MAC_TIMESTAMP_CTRL_TSVER2ENA_MASK | ENET_MAC_TIMESTAMP_CTRL_TSIPENA_MASK;
476     }
477 
478     /* Initialize the sub-second increment register. */
479     if (ptpConfig->tsRollover != kENET_BinaryRollover)
480     {
481         base->MAC_SUB_SCND_INCR      = ENET_MAC_SUB_SCND_INCR_SSINC(ENET_NANOSECS_ONESECOND / refClk_Hz);
482         base->MAC_SYS_TIME_NSCND_UPD = 0;
483     }
484     else
485     {
486         /* round up. */
487         uint32_t data                = ENET_MAC_SYS_TIME_NSCND_TSSS_MASK / refClk_Hz;
488         base->MAC_SUB_SCND_INCR      = ENET_MAC_SUB_SCND_INCR_SSINC(data);
489         base->MAC_SYS_TIME_NSCND_UPD = 0;
490     }
491     /* Set the second.*/
492     base->MAC_SYS_TIME_SCND_UPD   = 0;
493     base->MAC_SYS_TIME_HWORD_SCND = 0;
494 
495     /* Initialize the system timer. */
496     base->MAC_TIMESTAMP_CTRL = control | ENET_MAC_TIMESTAMP_CTRL_TSINIT_MASK;
497 }
498 #endif /* ENET_PTP1588FEATURE_REQUIRED */
499 
ENET_GetInstance(ENET_Type * base)500 uint32_t ENET_GetInstance(ENET_Type *base)
501 {
502     uint32_t instance;
503 
504     /* Find the instance index from base address mappings. */
505     for (instance = 0U; instance < (uint32_t)FSL_FEATURE_SOC_LPC_ENET_COUNT; instance++)
506     {
507         if (s_enetBases[instance] == base)
508         {
509             break;
510         }
511     }
512 
513     assert(instance < (uint32_t)FSL_FEATURE_SOC_LPC_ENET_COUNT);
514 
515     return instance;
516 }
517 
518 /*!
519  * brief Gets the ENET default configuration structure.
520  *
521  * The purpose of this API is to get the default ENET configure
522  * structure for ENET_Init(). User may use the initialized
523  * structure unchanged in ENET_Init(), or modify some fields of the
524  * structure before calling ENET_Init().
525  * Example:
526    code
527    enet_config_t config;
528    ENET_GetDefaultConfig(&config);
529    endcode
530  * param config The ENET mac controller configuration structure pointer.
531  */
ENET_GetDefaultConfig(enet_config_t * config)532 void ENET_GetDefaultConfig(enet_config_t *config)
533 {
534     /* Checks input parameter. */
535     assert(config);
536 
537     /* Initializes the configure structure to zero. */
538     (void)memset(config, 0, sizeof(*config));
539 
540     /* Sets MII mode, full duplex, 100Mbps for MAC and PHY data interface. */
541     config->miiMode   = kENET_RmiiMode;
542     config->miiSpeed  = kENET_MiiSpeed100M;
543     config->miiDuplex = kENET_MiiFullDuplex;
544 
545     /* Sets default configuration for other options. */
546     config->specialControl = 0U;
547     config->multiqueueCfg  = NULL;
548     config->pauseDuration  = 0;
549 
550 #ifdef ENET_PTP1588FEATURE_REQUIRED
551     config->ptpConfig = NULL;
552 #endif /* ENET_PTP1588FEATURE_REQUIRED */
553 }
554 
555 /*!
556  * brief Initializes the ENET module.
557  *
558  * This function ungates the module clock and initializes it with the ENET basic
559  * configuration.
560  * note As our transactional transmit API use the zero-copy transmit buffer.
561  * So there are two thing we emphasize here:
562  *  1. Tx buffer free/requeue for application should be done in the Tx
563  *  interrupt handler. Please set callback: kENET_TxIntEvent with Tx buffer free/requeue
564  *  process APIs.
565  *  2. The Tx interrupt is forced to open.
566  *
567  * param base    ENET peripheral base address.
568  * param config  ENET mac configuration structure pointer.
569  *        The "enet_config_t" type mac configuration return from ENET_GetDefaultConfig
570  *        can be used directly. It is also possible to verify the Mac configuration using other methods.
571  * param macAddr  ENET mac address of Ethernet device. This MAC address should be
572  *        provided.
573  * param refclkSrc_Hz ENET input reference clock.
574  */
ENET_Init(ENET_Type * base,const enet_config_t * config,uint8_t * macAddr,uint32_t refclkSrc_Hz)575 void ENET_Init(ENET_Type *base, const enet_config_t *config, uint8_t *macAddr, uint32_t refclkSrc_Hz)
576 {
577     assert(config);
578 
579     uint32_t instance = ENET_GetInstance(base);
580 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
581     /* Ungate ENET clock. */
582     CLOCK_EnableClock(s_enetClock[instance]);
583 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
584     /* System configure fistly. */
585     ENET_SetSYSControl(config->miiMode);
586 
587     /* Initializes the ENET DMA with basic function. */
588     ENET_SetDMAControl(base, config);
589 
590     /* Initializes the ENET MTL with basic function. */
591     ENET_SetMTL(base, config);
592 
593     /* Initializes the ENET MAC with basic function. */
594     ENET_SetMacControl(base, config, macAddr);
595 
596 #ifdef ENET_PTP1588FEATURE_REQUIRED
597     ENET_SetPtp1588(base, config, refclkSrc_Hz);
598 #endif /* ENET_PTP1588FEATURE_REQUIRED */
599 
600     /* Force to enable Tx interrupt for use transactional API to do Tx buffer free/requeue. */
601     ENET_EnableInterrupts(base, (config->interrupt | (uint32_t)kENET_DmaTx));
602 }
603 
604 /*!
605  * brief Deinitializes the ENET module.
606 
607  * This function gates the module clock and disables the ENET module.
608  *
609  * param base  ENET peripheral base address.
610  */
ENET_Deinit(ENET_Type * base)611 void ENET_Deinit(ENET_Type *base)
612 {
613     /* Reset first and wait for the complete
614      * The reset bit will automatically be cleared after complete. */
615     base->DMA_MODE |= ENET_DMA_MODE_SWR_MASK;
616     while ((base->DMA_MODE & ENET_DMA_MODE_SWR_MASK) != 0U)
617     {
618     }
619 
620 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
621     /* Disables the clock source. */
622     CLOCK_DisableClock(s_enetClock[ENET_GetInstance(base)]);
623 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
624 }
625 
626 /*!
627  * brief Initialize for all ENET descriptors.
628  *
629  * note This function finishes all Tx/Rx descriptors initialization. The descriptor initialization
630  * should be called after ENET_Init().
631  *
632  * param base  ENET peripheral base address.
633  * param config The configuration for ENET.
634  * param bufferConfig All buffers configuration.
635  */
ENET_DescriptorInit(ENET_Type * base,enet_config_t * config,enet_buffer_config_t * bufferConfig)636 status_t ENET_DescriptorInit(ENET_Type *base, enet_config_t *config, enet_buffer_config_t *bufferConfig)
637 {
638     assert(config);
639     assert(bufferConfig);
640 
641     uint8_t ringNum = config->multiqueueCfg == NULL ? 1U : 2U;
642     uint8_t channel;
643 
644     for (channel = 0; channel < ringNum; channel++)
645     {
646         if (ENET_TxDescriptorsInit(base, bufferConfig, channel) != kStatus_Success)
647         {
648             return kStatus_Fail;
649         }
650 
651         if (ENET_RxDescriptorsInit(base, config, bufferConfig, channel) != kStatus_Success)
652         {
653             return kStatus_Fail;
654         }
655 
656         bufferConfig++;
657     }
658     return kStatus_Success;
659 }
660 
661 /*!
662  * brief Starts the ENET Tx/Rx.
663  *  This function enable the Tx/Rx and starts the Tx/Rx DMA.
664  * This shall be set after ENET initialization and before
665  * starting to receive the data.
666  *
667  * param base  ENET peripheral base address.
668  * param rxRingNum  The number of the used Rx rings. It shall not be
669  * larger than the ENET_RING_NUM_MAX(2). If the ringNum is set with
670  * 1, the ring 0 will be used.
671  * param txRingNum  The number of the used Tx rings. It shall not be
672  * larger than the ENET_RING_NUM_MAX(2). If the ringNum is set with
673  * 1, the ring 0 will be used.
674  *
675  * note This must be called after all the ENET initilization.
676  * And should be called when the ENET receive/transmit is required.
677  */
ENET_StartRxTx(ENET_Type * base,uint8_t txRingNum,uint8_t rxRingNum)678 void ENET_StartRxTx(ENET_Type *base, uint8_t txRingNum, uint8_t rxRingNum)
679 {
680     assert(txRingNum);
681     assert(rxRingNum);
682 
683     uint8_t index;
684 
685     if (txRingNum > ENET_RING_NUM_MAX)
686     {
687         txRingNum = ENET_RING_NUM_MAX;
688     }
689     if (rxRingNum > ENET_RING_NUM_MAX)
690     {
691         rxRingNum = ENET_RING_NUM_MAX;
692     }
693     /* Start/Acive the DMA first. */
694     for (index = 0; index < rxRingNum; index++)
695     {
696         base->DMA_CH[index].DMA_CHX_RX_CTRL |= ENET_DMA_CH_DMA_CHX_RX_CTRL_SR_MASK;
697     }
698     for (index = 0; index < txRingNum; index++)
699     {
700         base->DMA_CH[index].DMA_CHX_TX_CTRL |= ENET_DMA_CH_DMA_CHX_TX_CTRL_ST_MASK;
701     }
702 
703     /* Enable the RX and TX at same time. */
704     base->MAC_CONFIG |= (ENET_MAC_CONFIG_TE_MASK | ENET_MAC_CONFIG_RE_MASK);
705 }
706 
707 /*!
708  * brief Set the second level IRQ handler
709  *
710  * param base ENET peripheral base address.
711  * param ISRHandler The handler to install.
712  */
ENET_SetISRHandler(ENET_Type * base,enet_isr_t ISRHandler)713 void ENET_SetISRHandler(ENET_Type *base, enet_isr_t ISRHandler)
714 {
715     s_enetIsr = ISRHandler;
716     (void)EnableIRQ(s_enetIrqId[ENET_GetInstance(base)]);
717 }
718 
719 /*!
720  * brief Enables the ENET DMA and MAC interrupts.
721  *
722  * This function enables the ENET interrupt according to the provided mask. The mask
723  * is a logical OR of enet_dma_interrupt_enable_t and enet_mac_interrupt_enable_t.
724  * For example, to enable the dma and mac interrupt, do the following.
725  * code
726  *     ENET_EnableInterrupts(ENET, kENET_DmaRx | kENET_DmaTx | kENET_MacPmt);
727  * endcode
728  *
729  * param base  ENET peripheral base address.
730  * param mask  ENET interrupts to enable. This is a logical OR of both
731  *             enumeration :: enet_dma_interrupt_enable_t and enet_mac_interrupt_enable_t.
732  */
ENET_EnableInterrupts(ENET_Type * base,uint32_t mask)733 void ENET_EnableInterrupts(ENET_Type *base, uint32_t mask)
734 {
735     uint32_t interrupt = mask & 0xFFFFU;
736     uint8_t index;
737 
738     /* For dma interrupt. */
739     if (interrupt != 0U)
740     {
741         for (index = 0; index < ENET_RING_NUM_MAX; index++)
742         {
743             /* Set for all abnormal interrupts. */
744             if ((ENET_ABNORM_INT_MASK & interrupt) != 0U)
745             {
746                 interrupt |= ENET_DMA_CH_DMA_CHX_INT_EN_AIE_MASK;
747             }
748             /* Set for all normal interrupts. */
749             if ((ENET_NORM_INT_MASK & interrupt) != 0U)
750             {
751                 interrupt |= ENET_DMA_CH_DMA_CHX_INT_EN_NIE_MASK;
752             }
753             base->DMA_CH[index].DMA_CHX_INT_EN = interrupt;
754         }
755     }
756     interrupt = mask >> ENET_MACINT_ENUM_OFFSET;
757     if (interrupt != 0U)
758     {
759         /* MAC interrupt */
760         base->MAC_INTR_EN |= interrupt;
761     }
762 }
763 
764 /*!
765  * brief Clears the ENET mac interrupt events status flag.
766  *
767  * This function clears enabled ENET interrupts according to the provided mask. The mask
768  * is a logical OR of enumeration members. See the ref enet_mac_interrupt_enable_t.
769  * For example, to clear the TX frame interrupt and RX frame interrupt, do the following.
770  * code
771  *     ENET_ClearMacInterruptStatus(ENET, kENET_MacPmt);
772  * endcode
773  *
774  * param base  ENET peripheral base address.
775  * param mask  ENET interrupt source to be cleared.
776  * This is the logical OR of members of the enumeration :: enet_mac_interrupt_enable_t.
777  */
ENET_ClearMacInterruptStatus(ENET_Type * base,uint32_t mask)778 void ENET_ClearMacInterruptStatus(ENET_Type *base, uint32_t mask)
779 {
780     volatile uint32_t dummy;
781 
782     if ((mask & (uint32_t)kENET_MacTimestamp) != 0U)
783     {
784         dummy = base->MAC_SYS_TIMESTMP_STAT;
785     }
786     else if ((mask & (uint32_t)kENET_MacPmt) != 0U)
787     {
788         dummy = base->MAC_PMT_CRTL_STAT;
789     }
790     else
791     {
792         /* Add for avoid the misra 2004 rule 14.10 */
793     }
794     (void)dummy;
795 }
796 
797 /*!
798  * brief Disables the ENET DMA and MAC interrupts.
799  *
800  * This function disables the ENET interrupt according to the provided mask. The mask
801  * is a logical OR of enet_dma_interrupt_enable_t and enet_mac_interrupt_enable_t.
802  * For example, to disable the dma and mac interrupt, do the following.
803  * code
804  *     ENET_DisableInterrupts(ENET, kENET_DmaRx | kENET_DmaTx | kENET_MacPmt);
805  * endcode
806  *
807  * param base  ENET peripheral base address.
808  * param mask  ENET interrupts to disables. This is a logical OR of both
809  *             enumeration :: enet_dma_interrupt_enable_t and enet_mac_interrupt_enable_t.
810  */
ENET_DisableInterrupts(ENET_Type * base,uint32_t mask)811 void ENET_DisableInterrupts(ENET_Type *base, uint32_t mask)
812 {
813     uint32_t interrupt = mask & 0xFFFFU;
814     uint8_t index;
815 
816     /* For dma interrupt. */
817     if (interrupt != 0U)
818     {
819         for (index = 0; index < ENET_RING_NUM_MAX; index++)
820         {
821             /* Set for all abnormal interrupts. */
822             if ((ENET_ABNORM_INT_MASK & interrupt) != 0U)
823             {
824                 interrupt |= ENET_DMA_CH_DMA_CHX_INT_EN_AIE_MASK;
825             }
826             /* Set for all normal interrupts. */
827             if ((ENET_NORM_INT_MASK & interrupt) != 0U)
828             {
829                 interrupt |= ENET_DMA_CH_DMA_CHX_INT_EN_NIE_MASK;
830             }
831             base->DMA_CH[index].DMA_CHX_INT_EN &= ~interrupt;
832         }
833     }
834     interrupt = mask >> ENET_MACINT_ENUM_OFFSET;
835     if (interrupt != 0U)
836     {
837         /* MAC interrupt */
838         base->MAC_INTR_EN &= ~interrupt;
839     }
840 }
841 
842 /*!
843  * brief Create ENET Handler
844  *
845  * This is a transactional API and it's provided to store all datas which are needed
846  * during the whole transactional process. This API should not be used when you use
847  * functional APIs to do data Tx/Rx. This is funtion will store many data/flag for
848  * transactional use.
849  *
850  * param base  ENET peripheral base address.
851  * param handle ENET handler.
852  * param config ENET configuration.
853  * param bufferConfig ENET buffer configuration.
854  * param callback The callback function.
855  * param userData The application data.
856  */
ENET_CreateHandler(ENET_Type * base,enet_handle_t * handle,enet_config_t * config,enet_buffer_config_t * bufferConfig,enet_callback_t callback,void * userData)857 void ENET_CreateHandler(ENET_Type *base,
858                         enet_handle_t *handle,
859                         enet_config_t *config,
860                         enet_buffer_config_t *bufferConfig,
861                         enet_callback_t callback,
862                         void *userData)
863 {
864     assert(config);
865     assert(bufferConfig);
866     assert(callback);
867 
868     uint8_t ringNum                  = 1;
869     uint8_t count                    = 0;
870     uint8_t rxIntEnable              = 0;
871     enet_buffer_config_t *buffConfig = bufferConfig;
872     uint32_t txFifoSize;
873     uint32_t pbl;
874 
875     /* Store transfer parameters in handle pointer. */
876     (void)memset(handle, 0, sizeof(enet_handle_t));
877     if ((config->specialControl & (uint32_t)kENET_DescDoubleBuffer) != 0U)
878     {
879         handle->doubleBuffEnable = true;
880     }
881     if (config->multiqueueCfg != NULL)
882     {
883         ringNum                = 2;
884         handle->multiQueEnable = true;
885     }
886     for (count = 0; count < ringNum; count++)
887     {
888         handle->rxBdRing[count].rxBdBase        = buffConfig->rxDescStartAddrAlign;
889         handle->rxBdRing[count].rxGenIdx        = 0;
890         handle->rxBdRing[count].rxRingLen       = buffConfig->rxRingLen;
891         handle->rxBdRing[count].rxBuffSizeAlign = buffConfig->rxBuffSizeAlign;
892 
893         handle->txBdRing[count].txBdBase    = buffConfig->txDescStartAddrAlign;
894         handle->txBdRing[count].txRingLen   = buffConfig->txRingLen;
895         handle->txBdRing[count].txGenIdx    = 0;
896         handle->txBdRing[count].txConsumIdx = 0;
897         handle->txBdRing[count].txDescUsed  = 0;
898 
899         handle->txDirtyRing[count].txDirtyBase = buffConfig->txDirtyStartAddr;
900         handle->txDirtyRing[count].txRingLen   = buffConfig->txRingLen;
901         handle->txDirtyRing[count].txGenIdx    = 0;
902         handle->txDirtyRing[count].txConsumIdx = 0;
903 
904         handle->rxBufferStartAddr[count] = buffConfig->rxBufferStartAddr;
905 
906         /* Check if the Rx interrrupt is enabled. */
907         rxIntEnable |= (uint8_t)(uint32_t)(base->DMA_CH[count].DMA_CHX_INT_EN & ENET_DMA_CH_DMA_CHX_INT_EN_RIE_MASK);
908 
909         /* Calculate the reserved space for Tx in certain cases. */
910         if (0U != (base->MTL_QUEUE[count].MTL_TXQX_OP_MODE & ENET_MTL_QUEUE_MTL_TXQX_OP_MODE_TSF_MASK))
911         {
912             pbl = (base->DMA_CH[count].DMA_CHX_TX_CTRL & ENET_DMA_CH_DMA_CHX_TX_CTRL_TxPBL_MASK) >>
913                   ENET_DMA_CH_DMA_CHX_TX_CTRL_TxPBL_SHIFT;
914             pbl = ((base->DMA_CH[count].DMA_CHX_CTRL & ENET_DMA_CH_DMA_CHX_CTRL_PBLx8_MASK) != 0U) ? (8U * pbl) : pbl;
915             txFifoSize = (uint32_t)pow(
916                 (double)2, (double)(uint32_t)(((base->MAC_HW_FEAT[1] & ENET_MAC_HW_FEAT_TXFIFOSIZE_MASK) >> ENET_MAC_HW_FEAT_TXFIFOSIZE_SHIFT) +
917                     7U));
918             handle->txLenLimitation[count] = txFifoSize - (pbl + 6U) * (32U / 8U);
919         }
920 
921         buffConfig++;
922     }
923 
924     handle->rxintEnable = (rxIntEnable != 0U);
925 
926     /* Save the handle pointer in the global variables. */
927     s_ENETHandle[ENET_GetInstance(base)] = handle;
928 
929     /* Set Rx alloc/free callback. */
930     handle->rxBuffAlloc = config->rxBuffAlloc;
931     handle->rxBuffFree  = config->rxBuffFree;
932 
933     /* Set callback and userData. */
934     handle->callback = callback;
935     handle->userData = userData;
936 
937     /* Set up interrupt and its handler. */
938     ENET_SetISRHandler(base, ENET_IRQHandler);
939 }
940 
941 /*!
942  * brief Gets the ENET module Mac address.
943  *
944  * param base  ENET peripheral base address.
945  * param macAddr The six-byte Mac address pointer.
946  *        The pointer is allocated by application and input into the API.
947  */
ENET_GetMacAddr(ENET_Type * base,uint8_t * macAddr)948 void ENET_GetMacAddr(ENET_Type *base, uint8_t *macAddr)
949 {
950     assert(macAddr);
951 
952     uint32_t address = base->MAC_ADDR_LOW;
953 
954     /* Get from physical address lower register. */
955     macAddr[2] = (uint8_t)(0xFFU & (address >> 24U));
956     macAddr[3] = (uint8_t)(0xFFU & (address >> 16U));
957     macAddr[4] = (uint8_t)(0xFFU & (address >> 8U));
958     macAddr[5] = (uint8_t)(0xFFU & address);
959 
960     /* Get from physical address high register. */
961     address    = base->MAC_ADDR_HIGH;
962     macAddr[0] = (uint8_t)(0xFFU & (address >> 8U));
963     macAddr[1] = (uint8_t)(0xFFU & address);
964 }
965 
966 /*!
967  * brief Sets the ENET SMI(serial management interface)- MII management interface.
968  *
969  * param base  ENET peripheral base address.
970  */
ENET_SetSMI(ENET_Type * base)971 void ENET_SetSMI(ENET_Type *base)
972 {
973     uint32_t crDiv       = 0;
974     uint32_t srcClock_Hz = CLOCK_GetFreq(kCLOCK_BusClk) / 1000000U;
975 
976     assert((srcClock_Hz >= 20U) && (srcClock_Hz < 250U));
977 
978     if (srcClock_Hz < 35U)
979     {
980         crDiv = 2;
981     }
982     else if (srcClock_Hz < 60U)
983     {
984         crDiv = 3;
985     }
986     else if (srcClock_Hz < 100U)
987     {
988         crDiv = 0;
989     }
990     else if (srcClock_Hz < 150U)
991     {
992         crDiv = 1;
993     }
994     else if (srcClock_Hz < 250U)
995     {
996         crDiv = 4;
997     }
998     else
999     {
1000         /* Intentional empty */
1001     }
1002 
1003     base->MAC_MDIO_ADDR = ENET_MAC_MDIO_ADDR_CR(crDiv);
1004 }
1005 
1006 /*!
1007  * brief Starts a SMI write command.
1008  * support both MDIO IEEE802.3 Clause 22 and clause 45.
1009  *
1010  * param base  ENET peripheral base address.
1011  * param phyAddr The PHY address.
1012  * param regAddr The PHY register.
1013  * param data The data written to PHY.
1014  */
ENET_StartSMIWrite(ENET_Type * base,uint8_t phyAddr,uint8_t regAddr,uint16_t data)1015 void ENET_StartSMIWrite(ENET_Type *base, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
1016 {
1017     uint32_t reg = base->MAC_MDIO_ADDR & ENET_MAC_MDIO_ADDR_CR_MASK;
1018 
1019     /* Build MII write command. */
1020     base->MAC_MDIO_ADDR = reg | ENET_MAC_MDIO_ADDR_MOC(kENET_MiiWriteFrame) | ENET_MAC_MDIO_ADDR_PA(phyAddr) |
1021                           ENET_MAC_MDIO_ADDR_RDA(regAddr);
1022     base->MAC_MDIO_DATA = data;
1023     base->MAC_MDIO_ADDR |= ENET_MAC_MDIO_ADDR_MB_MASK;
1024 }
1025 
1026 /*!
1027  * brief Starts an SMI read command.
1028  * support both MDIO IEEE802.3 Clause 22 and clause 45.
1029  *
1030  * param base  ENET peripheral base address.
1031  * param phyAddr The PHY address.
1032  * param regAddr The PHY register.
1033  */
ENET_StartSMIRead(ENET_Type * base,uint8_t phyAddr,uint8_t regAddr)1034 void ENET_StartSMIRead(ENET_Type *base, uint8_t phyAddr, uint8_t regAddr)
1035 {
1036     uint32_t reg = base->MAC_MDIO_ADDR & ENET_MAC_MDIO_ADDR_CR_MASK;
1037 
1038     /* Build MII read command. */
1039     base->MAC_MDIO_ADDR = reg | ENET_MAC_MDIO_ADDR_MOC(kENET_MiiReadFrame) | ENET_MAC_MDIO_ADDR_PA(phyAddr) |
1040                           ENET_MAC_MDIO_ADDR_RDA(regAddr);
1041     base->MAC_MDIO_ADDR |= ENET_MAC_MDIO_ADDR_MB_MASK;
1042 }
1043 
ENET_QOS_MDIOWaitTransferOver(ENET_Type * base)1044 static status_t ENET_QOS_MDIOWaitTransferOver(ENET_Type *base)
1045 {
1046     status_t result = kStatus_Success;
1047 #ifdef ENET_MDIO_TIMEOUT_COUNT
1048     uint32_t counter;
1049 #endif
1050 
1051 #ifdef ENET_QOS_MDIO_TIMEOUT_COUNT
1052     for (counter = ENET_MDIO_TIMEOUT_COUNT; counter > 0U; counter--)
1053     {
1054         if (!ENET_IsSMIBusy(base))
1055         {
1056             break;
1057         }
1058     }
1059     /* Check for timeout. */
1060     if (0U == counter)
1061     {
1062         result = kStatus_Timeout;
1063     }
1064 #else
1065     while (ENET_IsSMIBusy(base))
1066     {
1067     }
1068 #endif
1069     return result;
1070 }
1071 
1072 /*!
1073  * @brief MDIO write.
1074  *
1075  * @param base  ENET peripheral base address.
1076  * @param phyAddr The PHY address.
1077  * @param regAddr The PHY register.
1078  * @param data The data written to PHY.
1079  * @return kStatus_Success  MDIO access succeeds.
1080  * @return kStatus_Timeout  MDIO access timeout.
1081  */
ENET_MDIOWrite(ENET_Type * base,uint8_t phyAddr,uint8_t regAddr,uint16_t data)1082 status_t ENET_MDIOWrite(ENET_Type *base, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
1083 {
1084     ENET_StartSMIWrite(base, phyAddr, regAddr, data);
1085 
1086     return ENET_QOS_MDIOWaitTransferOver(base);
1087 }
1088 
1089 /*!
1090  * @brief MDIO read.
1091  *
1092  * @param base  ENET peripheral base address.
1093  * @param phyAddr The PHY address.
1094  * @param regAddr The PHY register.
1095  * @param pData  The data read from PHY.
1096  * @return kStatus_Success  MDIO access succeeds.
1097  * @return kStatus_Timeout  MDIO access timeout.
1098  */
ENET_MDIORead(ENET_Type * base,uint8_t phyAddr,uint8_t regAddr,uint16_t * pData)1099 status_t ENET_MDIORead(ENET_Type *base, uint8_t phyAddr, uint8_t regAddr, uint16_t *pData)
1100 {
1101     assert(pData);
1102 
1103     status_t result;
1104 
1105     ENET_StartSMIRead(base, phyAddr, regAddr);
1106 
1107     result = ENET_QOS_MDIOWaitTransferOver(base);
1108     if (result != kStatus_Success)
1109     {
1110         return result;
1111     }
1112     *pData = ENET_ReadSMIData(base);
1113 
1114     return result;
1115 }
1116 
1117 /*!
1118  * brief Set the MAC to enter into power down mode.
1119  * the remote power wake up frame and magic frame can wake up
1120  * the ENET from the power down mode.
1121  *
1122  * param base    ENET peripheral base address.
1123  * param wakeFilter  The wakeFilter provided to configure the wake up frame fitlter.
1124  *  Set the wakeFilter to NULL is not required. But if you have the filter requirement,
1125  *  please make sure the wakeFilter pointer shall be eight continous
1126  *  32-bits configuration.
1127  */
ENET_EnterPowerDown(ENET_Type * base,uint32_t * wakeFilter)1128 void ENET_EnterPowerDown(ENET_Type *base, uint32_t *wakeFilter)
1129 {
1130     uint8_t index;
1131     uint32_t *reg = wakeFilter;
1132 
1133     /* Disable the Tx dma. */
1134     base->DMA_CH[0].DMA_CHX_TX_CTRL &= ~ENET_DMA_CH_DMA_CHX_TX_CTRL_ST_MASK;
1135     base->DMA_CH[1].DMA_CHX_TX_CTRL &= ~ENET_DMA_CH_DMA_CHX_TX_CTRL_ST_MASK;
1136 
1137     /* Disable the mac Tx/Rx. */
1138     base->MAC_CONFIG &= ~(ENET_MAC_CONFIG_RE_MASK | ENET_MAC_CONFIG_TE_MASK);
1139     /* Enable the remote wakeup packet and enable the power down mode. */
1140     if (wakeFilter != NULL)
1141     {
1142         for (index = 0; index < ENET_WAKEUPFILTER_NUM; index++)
1143         {
1144             base->MAC_RWAKE_FRFLT = *reg;
1145             reg++;
1146         }
1147     }
1148     base->MAC_PMT_CRTL_STAT = ENET_MAC_PMT_CRTL_STAT_MGKPKTEN_MASK | ENET_MAC_PMT_CRTL_STAT_RWKPKTEN_MASK |
1149                               ENET_MAC_PMT_CRTL_STAT_PWRDWN_MASK;
1150 
1151     /* Enable the MAC Rx. */
1152     base->MAC_CONFIG |= ENET_MAC_CONFIG_RE_MASK;
1153 }
1154 
1155 /*!
1156  * brief Gets the size of the read frame.
1157  * This function gets a received frame size from the ENET buffer descriptors.
1158  * note The FCS of the frame is automatically removed by MAC and the size is the length without the FCS.
1159  * After calling ENET_GetRxFrameSize, ENET_ReadFrame() should be called to update the
1160  * receive buffers If the result is not "kStatus_ENET_RxFrameEmpty".
1161  *
1162  * param handle The ENET handler structure. This is the same handler pointer used in the ENET_Init.
1163  * param length The length of the valid frame received.
1164  * param channel The DMAC channel for the Rx.
1165  * retval kStatus_ENET_RxFrameEmpty No frame received. Should not call ENET_ReadFrame to read frame.
1166  * retval kStatus_ENET_RxFrameError Data error happens. ENET_ReadFrame should be called with NULL data
1167  *         and NULL length to update the receive buffers.
1168  * retval kStatus_Success Receive a frame Successfully then the ENET_ReadFrame
1169  *         should be called with the right data buffer and the captured data length input.
1170  */
ENET_GetRxFrameSize(ENET_Type * base,enet_handle_t * handle,uint32_t * length,uint8_t channel)1171 status_t ENET_GetRxFrameSize(ENET_Type *base, enet_handle_t *handle, uint32_t *length, uint8_t channel)
1172 {
1173     assert(handle);
1174     assert(length);
1175 
1176     enet_rx_bd_ring_t *rxBdRing = (enet_rx_bd_ring_t *)&handle->rxBdRing[channel];
1177     enet_rx_bd_struct_t *rxDesc = rxBdRing->rxBdBase + rxBdRing->rxGenIdx;
1178     uint16_t index              = rxBdRing->rxGenIdx;
1179 
1180     /* Reset the length to zero. */
1181     *length = 0;
1182 
1183     if ((rxDesc->rdes3 & ENET_RXDESCRIP_WR_OWN_MASK) != 0U)
1184     {
1185         return kStatus_ENET_RxFrameEmpty;
1186     }
1187     else
1188     {
1189         do
1190         {
1191             /* Application owns the buffer descriptor, get the length. */
1192             if ((rxDesc->rdes3 & ENET_RXDESCRIP_WR_LD_MASK) != 0U)
1193             {
1194                 if ((rxDesc->rdes3 & ENET_RXDESCRIP_WR_ERRSUM_MASK) != 0U)
1195                 {
1196                     return kStatus_ENET_RxFrameError;
1197                 }
1198                 *length = (rxDesc->rdes3 & ENET_RXDESCRIP_WR_PACKETLEN_MASK) - ENET_FCS_LEN;
1199                 return kStatus_Success;
1200             }
1201 
1202             index  = ENET_IncreaseIndex(index, rxBdRing->rxRingLen);
1203             rxDesc = rxBdRing->rxBdBase + index;
1204         } while (index != rxBdRing->rxGenIdx);
1205 
1206         return kStatus_ENET_RxFrameError;
1207     }
1208 }
1209 
1210 /*!
1211  * brief Reads a frame from the ENET device.
1212  * This function reads a frame from the ENET DMA descriptors.
1213  * The ENET_GetRxFrameSize should be used to get the size of the prepared data buffer.
1214  * For example use Rx dma channel 0:
1215  * code
1216  *       uint32_t length;
1217  *       enet_handle_t g_handle;
1218  *       Comment: Get the received frame size firstly.
1219  *       status = ENET_GetRxFrameSize(&g_handle, &length, 0);
1220  *       if (length != 0)
1221  *       {
1222  *           Comment: Allocate memory here with the size of "length"
1223  *           uint8_t *data = memory allocate interface;
1224  *           if (!data)
1225  *           {
1226  *               ENET_ReadFrame(ENET, &g_handle, NULL, 0, 0);
1227  *           }
1228  *           else
1229  *           {
1230  *              status = ENET_ReadFrame(ENET, &g_handle, data, length, 0);
1231  *           }
1232  *       }
1233  *       else if (status == kStatus_ENET_RxFrameError)
1234  *       {
1235  *           Comment: Update the received buffer when a error frame is received.
1236  *           ENET_ReadFrame(ENET, &g_handle, NULL, 0, 0);
1237  *       }
1238  * endcode
1239  * param base  ENET peripheral base address.
1240  * param handle The ENET handler structure. This is the same handler pointer used in the ENET_Init.
1241  * param data The data buffer provided by user to store the frame which memory size should be at least "length".
1242  * param length The size of the data buffer which is still the length of the received frame.
1243  * param channel The Rx DMA channel. shall not be larger than 2.
1244  * param timestamp The timestamp address to store received timestamp.
1245  * return The execute status, successful or failure.
1246  */
ENET_ReadFrame(ENET_Type * base,enet_handle_t * handle,uint8_t * data,uint32_t length,uint8_t channel,enet_ptp_time_t * timestamp)1247 status_t ENET_ReadFrame(
1248     ENET_Type *base, enet_handle_t *handle, uint8_t *data, uint32_t length, uint8_t channel, enet_ptp_time_t *timestamp)
1249 {
1250     assert(handle);
1251 
1252     enet_rx_bd_ring_t *rxBdRing = (enet_rx_bd_ring_t *)&handle->rxBdRing[channel];
1253     uint32_t len                = 0;
1254     uint32_t offset             = 0;
1255     bool isLastBuff             = false;
1256     status_t result             = kStatus_Fail;
1257     bool suspend                = false;
1258     enet_rx_bd_struct_t *rxDesc;
1259 #ifdef ENET_PTP1588FEATURE_REQUIRED
1260     uint32_t buffer;
1261     uint32_t bufferAdd;
1262 #endif /* ENET_PTP1588FEATURE_REQUIRED */
1263 
1264     /* Suspend and command for Rx. */
1265     if ((base->DMA_CH[channel].DMA_CHX_STAT & ENET_DMA_CH_DMA_CHX_STAT_RBU_MASK) != 0U)
1266     {
1267         suspend = true;
1268     }
1269 
1270     /* For data-NULL input, only update the buffer descriptor. */
1271     if (data == NULL)
1272     {
1273         ENET_DropFrame(base, handle, channel);
1274         result = kStatus_Success;
1275     }
1276     else
1277     {
1278         while (!isLastBuff)
1279         {
1280             /* The last buffer descriptor of a frame. */
1281             rxDesc             = rxBdRing->rxBdBase + rxBdRing->rxGenIdx;
1282             rxBdRing->rxGenIdx = ENET_IncreaseIndex(rxBdRing->rxGenIdx, rxBdRing->rxRingLen);
1283 
1284             if ((rxDesc->rdes3 & ENET_RXDESCRIP_WR_LD_MASK) != 0U)
1285             {
1286                 /* This is a valid frame. */
1287                 isLastBuff = true;
1288                 if (length == ((rxDesc->rdes3 & ENET_RXDESCRIP_WR_PACKETLEN_MASK) - ENET_FCS_LEN))
1289                 {
1290                     /* Copy the frame to user's buffer. */
1291                     len = length - offset;
1292                     if (len > rxBdRing->rxBuffSizeAlign)
1293                     {
1294                         (void)memcpy((void *)(uint32_t *)(uint32_t)(data + offset), (void *)(uint32_t *)rxDesc->rdes0,
1295                                      rxBdRing->rxBuffSizeAlign);
1296                         offset += rxBdRing->rxBuffSizeAlign;
1297                         (void)memcpy((void *)(uint32_t *)(uint32_t)(data + offset), (void *)(uint32_t *)rxDesc->rdes2,
1298                                      len - rxBdRing->rxBuffSizeAlign);
1299                     }
1300                     else
1301                     {
1302                         (void)memcpy((void *)(uint32_t *)(uint32_t)(data + offset), (void *)(uint32_t *)rxDesc->rdes0,
1303                                      len);
1304                     }
1305 
1306                     result = kStatus_Success;
1307                 }
1308 
1309                 /* Updates the receive buffer descriptors. */
1310                 ENET_UpdateRxDescriptor(rxDesc, NULL, NULL, handle->rxintEnable, handle->doubleBuffEnable);
1311 #ifdef ENET_PTP1588FEATURE_REQUIRED
1312                 /* Store the Rx timestamp which is in the next buffer descriptor of the last
1313                  * descriptor of a frame. */
1314                 rxDesc = rxBdRing->rxBdBase + rxBdRing->rxGenIdx;
1315 
1316                 /* Reinit for the context descritor which has been updated by DMA. */
1317                 if ((rxDesc->rdes3 & ENET_RXDESCRIP_WR_CTXT_MASK) != 0U)
1318                 {
1319                     if (timestamp != NULL)
1320                     {
1321                         uint32_t timerCount;
1322 
1323                         /* Get receive frame timestamp. */
1324                         timestamp->second = rxDesc->rdes1;
1325                         timerCount        = rxDesc->rdes0;
1326                         if ((base->MAC_TIMESTAMP_CTRL & ENET_MAC_TIMESTAMP_CTRL_TSCTRLSSR_MASK) == 0U)
1327                         {
1328                             /* Binary rollover. */
1329                             timestamp->nanosecond = ENET_BINARY_ROLLOVER_SCALE(timerCount);
1330                         }
1331                         else
1332                         {
1333                             timestamp->nanosecond = timerCount;
1334                         }
1335                     }
1336 
1337                     if (!handle->doubleBuffEnable)
1338                     {
1339                         buffer = handle->rxBufferStartAddr[channel][rxBdRing->rxGenIdx];
1340                         ENET_UpdateRxDescriptor(rxDesc, (void *)(uint32_t *)buffer, NULL, handle->rxintEnable,
1341                                                 handle->doubleBuffEnable);
1342                     }
1343                     else
1344                     {
1345                         buffer    = handle->rxBufferStartAddr[channel][2U * rxBdRing->rxGenIdx];
1346                         bufferAdd = handle->rxBufferStartAddr[channel][2U * rxBdRing->rxGenIdx + 1U];
1347                         ENET_UpdateRxDescriptor(rxDesc, (void *)(uint32_t *)buffer, (void *)(uint32_t *)bufferAdd,
1348                                                 handle->rxintEnable, handle->doubleBuffEnable);
1349                     }
1350                     rxBdRing->rxGenIdx = ENET_IncreaseIndex(rxBdRing->rxGenIdx, rxBdRing->rxRingLen);
1351                 }
1352                 base->DMA_CH[channel].DMA_CHX_RXDESC_TAIL_PTR = base->DMA_CH[channel].DMA_CHX_RXDESC_TAIL_PTR;
1353 #endif /* ENET_PTP1588FEATURE_REQUIRED */
1354             }
1355             else
1356             {
1357                 /* Store a frame on several buffer descriptors. */
1358                 isLastBuff = false;
1359                 /* Length check. */
1360                 if (offset >= length)
1361                 {
1362                     /* Updates the receive buffer descriptors. */
1363                     ENET_UpdateRxDescriptor(rxDesc, NULL, NULL, handle->rxintEnable, handle->doubleBuffEnable);
1364                     break;
1365                 }
1366 
1367                 (void)memcpy((void *)(uint32_t *)(uint32_t)(data + offset), (void *)(uint32_t *)rxDesc->rdes0,
1368                              rxBdRing->rxBuffSizeAlign);
1369                 offset += rxBdRing->rxBuffSizeAlign;
1370                 if (((rxDesc->rdes2) != 0U) && (handle->doubleBuffEnable))
1371                 {
1372                     (void)memcpy((void *)(uint32_t *)(uint32_t)(data + offset), (void *)(uint32_t *)rxDesc->rdes2,
1373                                  rxBdRing->rxBuffSizeAlign);
1374                     offset += rxBdRing->rxBuffSizeAlign;
1375                 }
1376 
1377                 /* Updates the receive buffer descriptors. */
1378                 ENET_UpdateRxDescriptor(rxDesc, NULL, NULL, handle->rxintEnable, handle->doubleBuffEnable);
1379             }
1380         }
1381     }
1382 
1383     /* Set command for Rx when it is suspend. */
1384     if (suspend)
1385     {
1386         base->DMA_CH[channel].DMA_CHX_RXDESC_TAIL_PTR = base->DMA_CH[channel].DMA_CHX_RXDESC_TAIL_PTR;
1387     }
1388 
1389     return result;
1390 }
1391 
1392 /*!
1393  * brief Updates the buffers and the own status for a given Rx descriptor.
1394  *  This function is a low level functional API to Updates the
1395  *  buffers and the own status for a given Rx descriptor.
1396  *
1397  * param rxDesc  The given Rx descriptor.
1398  * param buffer1  The first buffer address in the descriptor.
1399  * param buffer2  The second buffer address in the descriptor.
1400  * param intEnable Interrupt enable flag.
1401  * param doubleBuffEnable The double buffer enable flag.
1402  *
1403  * note This must be called after all the ENET initilization.
1404  * And should be called when the ENET receive/transmit is required.
1405  */
ENET_UpdateRxDescriptor(enet_rx_bd_struct_t * rxDesc,void * buffer1,void * buffer2,bool intEnable,bool doubleBuffEnable)1406 void ENET_UpdateRxDescriptor(
1407     enet_rx_bd_struct_t *rxDesc, void *buffer1, void *buffer2, bool intEnable, bool doubleBuffEnable)
1408 {
1409     assert(rxDesc);
1410     uint32_t control = ENET_RXDESCRIP_RD_OWN_MASK | ENET_RXDESCRIP_RD_BUFF1VALID_MASK;
1411 
1412     if (intEnable)
1413     {
1414         control |= ENET_RXDESCRIP_RD_IOC_MASK;
1415     }
1416 
1417     if (doubleBuffEnable)
1418     {
1419         control |= ENET_RXDESCRIP_RD_BUFF2VALID_MASK;
1420     }
1421 
1422     /* Update the buffer if needed. */
1423     if (buffer1 != NULL)
1424     {
1425         rxDesc->rdes0 = (uint32_t)(uint32_t *)buffer1;
1426     }
1427     if (buffer2 != NULL)
1428     {
1429         rxDesc->rdes2 = (uint32_t)(uint32_t *)buffer2;
1430     }
1431     else
1432     {
1433         rxDesc->rdes2 = 0;
1434     }
1435 
1436     rxDesc->rdes1 = 0;
1437     rxDesc->rdes3 = control;
1438 }
1439 
1440 /*!
1441  * brief Allocates Rx buffers for all BDs.
1442  * It's used for zero copy Rx. In zero copy Rx case, Rx buffers are dynamic. This function
1443  * will populate initial buffers in all BDs for receiving. Then ENET_GetRxFrame() is used
1444  * to get Rx frame with zero copy, it will allocate new buffer to replace the buffer in BD taken
1445  * by application, application should free those buffers after they're used.
1446  *
1447  * note This function should be called after ENET_CreateHandler() and buffer allocating callback
1448  * function should be ready.
1449  *
1450  * param base  ENET peripheral base address.
1451  * param handle The ENET handler structure. This is the same handler pointer used in the ENET_Init.
1452  */
ENET_RxBufferAllocAll(ENET_Type * base,enet_handle_t * handle)1453 status_t ENET_RxBufferAllocAll(ENET_Type *base, enet_handle_t *handle)
1454 {
1455     status_t result = kStatus_Success;
1456     enet_rx_bd_struct_t *rxbdPtr;
1457     uint32_t buffAddr;
1458     uint8_t channel;
1459     uint16_t index;
1460     uint16_t j;
1461     uint8_t ringNum = (handle->multiQueEnable) ? 2U : 1U;
1462 
1463     if ((handle->rxBuffAlloc == NULL) || (handle->rxBuffFree == NULL))
1464     {
1465         return kStatus_ENET_InitMemoryFail;
1466     }
1467 
1468     for (channel = 0; channel < ringNum; channel++)
1469     {
1470         /* Init the rxbdPtr to the receive descriptor start address. */
1471         rxbdPtr = handle->rxBdRing[channel].rxBdBase;
1472         for (j = 0U; j < handle->rxBdRing[channel].rxRingLen; j++)
1473         {
1474             if (handle->doubleBuffEnable)
1475             {
1476                 index = 2U * j;
1477             }
1478             else
1479             {
1480                 index = j;
1481             }
1482 
1483             buffAddr = (uint32_t)(uint32_t *)handle->rxBuffAlloc(base, handle->userData, channel);
1484             if (buffAddr == 0U)
1485             {
1486                 result = kStatus_ENET_InitMemoryFail;
1487                 break;
1488             }
1489 
1490             rxbdPtr->rdes0                            = buffAddr;
1491             handle->rxBufferStartAddr[channel][index] = buffAddr;
1492 
1493             /* The second buffer is set with 0 because it is not required for normal case. */
1494             if (handle->doubleBuffEnable)
1495             {
1496                 buffAddr = (uint32_t)(uint32_t *)handle->rxBuffAlloc(base, handle->userData, channel);
1497                 if (buffAddr == 0U)
1498                 {
1499                     result = kStatus_ENET_InitMemoryFail;
1500                     break;
1501                 }
1502 
1503                 rxbdPtr->rdes2                                 = buffAddr;
1504                 handle->rxBufferStartAddr[channel][index + 1U] = buffAddr;
1505             }
1506             else
1507             {
1508                 rxbdPtr->rdes2 = 0;
1509             }
1510 
1511             /* Set the valid and DMA own flag.*/
1512             rxbdPtr->rdes3 |= ENET_RXDESCRIP_WR_OWN_MASK;
1513             rxbdPtr++;
1514         }
1515     }
1516 
1517     if (result == kStatus_ENET_InitMemoryFail)
1518     {
1519         ENET_RxBufferFreeAll(base, handle);
1520     }
1521 
1522     return result;
1523 }
1524 
1525 /*!
1526  * brief Frees Rx buffers in all BDs.
1527  * It's used for zero copy Rx. In zero copy Rx case, Rx buffers are dynamic. This function
1528  * frees left buffers in all BDs.
1529  *
1530  * param base  ENET peripheral base address.
1531  * param handle The ENET handler structure. This is the same handler pointer used in the ENET_Init.
1532  */
ENET_RxBufferFreeAll(ENET_Type * base,enet_handle_t * handle)1533 void ENET_RxBufferFreeAll(ENET_Type *base, enet_handle_t *handle)
1534 {
1535     uint8_t ringNum = (handle->multiQueEnable) ? 2U : 1U;
1536     uint8_t channel;
1537     uint32_t buffAddr;
1538     uint16_t index;
1539     uint16_t j;
1540 
1541     if (handle->rxBuffFree != NULL)
1542     {
1543         for (channel = 0; channel < ringNum; channel++)
1544         {
1545             for (j = 0U; j < handle->rxBdRing[channel].rxRingLen; j++)
1546             {
1547                 index = (handle->doubleBuffEnable) ? (2U * j) : j;
1548 
1549                 buffAddr = (uint32_t)handle->rxBufferStartAddr[channel][index];
1550                 if (buffAddr != 0U)
1551                 {
1552                     handle->rxBuffFree(base, (void *)(uint32_t *)buffAddr, handle->userData, channel);
1553                 }
1554 
1555                 /* The second buffer is set with 0 because it is not required for normal case. */
1556                 if (handle->doubleBuffEnable)
1557                 {
1558                     buffAddr = (uint32_t)handle->rxBufferStartAddr[channel][index + 1U];
1559                     if (buffAddr != 0U)
1560                     {
1561                         handle->rxBuffFree(base, (void *)(uint32_t *)buffAddr, handle->userData, channel);
1562                     }
1563                 }
1564             }
1565         }
1566     }
1567 }
1568 
ENET_GetRxFrameErr(enet_rx_bd_struct_t * rxDesc,enet_rx_frame_error_t * rxFrameError)1569 static inline void ENET_GetRxFrameErr(enet_rx_bd_struct_t *rxDesc, enet_rx_frame_error_t *rxFrameError)
1570 {
1571     union _frame_error
1572     {
1573         uint32_t data;
1574         enet_rx_frame_error_t frameError;
1575     };
1576     union _frame_error error;
1577 
1578     error.data = ENET_FRAME_RX_ERROR_BITS(rxDesc->rdes3);
1579     *rxFrameError = error.frameError;
1580 }
1581 
ENET_DropFrame(ENET_Type * base,enet_handle_t * handle,uint8_t channel)1582 static void ENET_DropFrame(ENET_Type *base, enet_handle_t *handle, uint8_t channel)
1583 {
1584     enet_rx_bd_ring_t *rxBdRing = (enet_rx_bd_ring_t *)&handle->rxBdRing[channel];
1585     enet_rx_bd_struct_t *rxDesc;
1586     uint16_t index = rxBdRing->rxGenIdx;
1587 #ifdef ENET_PTP1588FEATURE_REQUIRED
1588     bool tsAvailable   = false;
1589     uint32_t buff1Addr = 0;
1590     uint32_t buff2Addr = 0;
1591     uint32_t rdes1;
1592 #endif /* ENET_PTP1588FEATURE_REQUIRED */
1593     uint32_t rdes3;
1594 
1595     /* Not check DMA ownership here, assume there's at least one valid frame left in BD ring */
1596     do
1597     {
1598         /* Update the BD to idle status. */
1599         rxDesc = &rxBdRing->rxBdBase[rxBdRing->rxGenIdx];
1600 #ifdef ENET_PTP1588FEATURE_REQUIRED
1601         rdes1 = rxDesc->rdes1;
1602 #endif
1603         rdes3 = rxDesc->rdes3;
1604         ENET_UpdateRxDescriptor(rxDesc, NULL, NULL, handle->rxintEnable, handle->doubleBuffEnable);
1605         rxBdRing->rxGenIdx = ENET_IncreaseIndex(rxBdRing->rxGenIdx, rxBdRing->rxRingLen);
1606 
1607         /* Find the last buffer descriptor for the frame. */
1608         if ((rdes3 & ENET_RXDESCRIP_WR_LD_MASK) != 0U)
1609         {
1610 #ifdef ENET_PTP1588FEATURE_REQUIRED
1611             if ((rdes3 & ENET_RXDESCRIP_WR_RS1V_MASK) != 0U)
1612             {
1613                 if ((rdes1 & ENET_RXDESCRIP_WR_PTPTSA_MASK) != 0U)
1614                 {
1615                     tsAvailable = true;
1616                 }
1617             }
1618 
1619             /* Reinit for the context descriptor which has been updated by DMA. */
1620             rxDesc = &rxBdRing->rxBdBase[rxBdRing->rxGenIdx];
1621 
1622             if (tsAvailable && ((rxDesc->rdes3 & ENET_RXDESCRIP_WR_CTXT_MASK) != 0U))
1623             {
1624                 if (!handle->doubleBuffEnable)
1625                 {
1626                     buff1Addr = handle->rxBufferStartAddr[channel][rxBdRing->rxGenIdx];
1627                     ENET_UpdateRxDescriptor(rxDesc, (void *)(uint8_t *)buff1Addr, NULL, handle->rxintEnable,
1628                                             handle->doubleBuffEnable);
1629                 }
1630                 else
1631                 {
1632                     buff1Addr = handle->rxBufferStartAddr[channel][2U * rxBdRing->rxGenIdx];
1633                     buff2Addr = handle->rxBufferStartAddr[channel][2U * rxBdRing->rxGenIdx + 1U];
1634                     ENET_UpdateRxDescriptor(rxDesc, (void *)(uint8_t *)buff1Addr, (void *)(uint8_t *)buff2Addr,
1635                                             handle->rxintEnable, handle->doubleBuffEnable);
1636                 }
1637                 rxBdRing->rxGenIdx = ENET_IncreaseIndex(rxBdRing->rxGenIdx, rxBdRing->rxRingLen);
1638             }
1639 #endif /*  ENET_PTP1588FEATURE_REQUIRED */
1640             break;
1641         }
1642     } while (rxBdRing->rxGenIdx != index);
1643 
1644     /* Always try to start receive, in case it had stopped */
1645     base->DMA_CH[channel].DMA_CHX_RXDESC_TAIL_PTR = (uint32_t)(uint8_t *)&rxBdRing->rxBdBase[rxBdRing->rxRingLen];
1646 }
1647 
1648 /*!
1649  * brief Receives one frame in specified BD ring with zero copy.
1650  *
1651  * This function will use the user-defined allocate and free callback. Every time application gets one frame through
1652  * this function, driver will allocate new buffers for the BDs whose buffers have been taken by application.
1653  * note This function will drop current frame and update related BDs as available for DMA if new buffers allocating
1654  * fails. Application must provide a memory pool including at least BD number + 1 buffers(+2 if enable double buffer)
1655  * to make this function work normally.
1656  *
1657  * param base   ENET peripheral base address.
1658  * param handle The ENET handler pointer. This is the same handler pointer used in the ENET_Init.
1659  * param rxFrame The received frame information structure provided by user.
1660  * param channel The Rx DMA channel. Shall not be larger than 2.
1661  * retval kStatus_Success  Succeed to get one frame and allocate new memory for Rx buffer.
1662  * retval kStatus_ENET_RxFrameEmpty  There's no Rx frame in the BD.
1663  * retval kStatus_ENET_RxFrameError  There's issue in this receiving. In this function, issue frame will be dropped.
1664  * retval kStatus_ENET_RxFrameDrop  There's no new buffer memory for BD, dropped this frame.
1665  */
ENET_GetRxFrame(ENET_Type * base,enet_handle_t * handle,enet_rx_frame_struct_t * rxFrame,uint8_t channel)1666 status_t ENET_GetRxFrame(ENET_Type *base, enet_handle_t *handle, enet_rx_frame_struct_t *rxFrame, uint8_t channel)
1667 {
1668     assert(handle != NULL);
1669     assert(channel < ENET_RING_NUM_MAX);
1670 
1671     enet_rx_bd_ring_t *rxBdRing = (enet_rx_bd_ring_t *)&handle->rxBdRing[channel];
1672     enet_rx_bd_struct_t *rxDesc = &rxBdRing->rxBdBase[rxBdRing->rxGenIdx];
1673     uint16_t index              = rxBdRing->rxGenIdx;
1674     status_t result             = kStatus_Success;
1675     uint32_t buff1Addr          = 0;
1676     uint32_t buff2Addr          = 0;
1677     uint16_t buff1Len           = 0;
1678     uint16_t buff2Len           = 0;
1679     uint16_t offset             = 0;
1680     void *newBuff1              = NULL;
1681     void *newBuff2              = NULL;
1682     bool isDrop                 = false;
1683     bool isLastBuff             = false;
1684 #ifdef ENET_PTP1588FEATURE_REQUIRED
1685     bool tsAvailable = false;
1686 #endif /* ENET_PTP1588FEATURE_REQUIRED */
1687 
1688     /* Check the frame status. */
1689     do
1690     {
1691         if ((rxDesc->rdes3 & ENET_RXDESCRIP_WR_OWN_MASK) != 0U)
1692         {
1693             result = kStatus_ENET_RxFrameEmpty;
1694             break;
1695         }
1696 
1697         /* Check timestamp and error. */
1698         if ((rxDesc->rdes3 & ENET_RXDESCRIP_WR_LD_MASK) != 0U)
1699         {
1700 #ifdef ENET_PTP1588FEATURE_REQUIRED
1701             if ((rxDesc->rdes3 & ENET_RXDESCRIP_WR_RS1V_MASK) != 0U)
1702             {
1703                 if ((rxDesc->rdes1 & ENET_RXDESCRIP_WR_PTPTSA_MASK) != 0U)
1704                 {
1705                     tsAvailable = true;
1706                 }
1707             }
1708 #endif /* ENET_PTP1588FEATURE_REQUIRED */
1709 
1710             /* Get the frame error if there is. */
1711             if ((rxDesc->rdes3 & ENET_RXDESCRIP_WR_ERRSUM_MASK) != 0U)
1712             {
1713                 ENET_GetRxFrameErr(rxDesc, &rxFrame->rxFrameError);
1714                 result = kStatus_ENET_RxFrameError;
1715             }
1716             else if ((rxDesc->rdes3 & ENET_RXDESCRIP_WR_PACKETLEN_MASK) == 0U)
1717             {
1718                 result = kStatus_ENET_RxFrameEmpty;
1719             }
1720             else
1721             {
1722                 /* Intentional empty */
1723             }
1724             break;
1725         }
1726 
1727         index = ENET_IncreaseIndex(index, rxBdRing->rxRingLen);
1728         if (index == rxBdRing->rxGenIdx)
1729         {
1730             result = kStatus_ENET_RxFrameEmpty;
1731             break;
1732         }
1733         rxDesc = &rxBdRing->rxBdBase[index];
1734     } while (index != rxBdRing->rxGenIdx);
1735 
1736     /* Drop the error frame and return error. */
1737     if (result != kStatus_Success)
1738     {
1739         if (result == kStatus_ENET_RxFrameError)
1740         {
1741             ENET_DropFrame(base, handle, channel);
1742         }
1743         return result;
1744     }
1745 
1746     /* Get the valid frame */
1747     index = 0;
1748     do
1749     {
1750         rxDesc = &rxBdRing->rxBdBase[rxBdRing->rxGenIdx];
1751 
1752         /* Calculate the buffer and frame length. */
1753         if ((rxDesc->rdes3 & ENET_RXDESCRIP_WR_LD_MASK) != 0U)
1754         {
1755             isLastBuff      = true;
1756             rxFrame->totLen = (uint16_t)(rxDesc->rdes3 & ENET_RXDESCRIP_WR_PACKETLEN_MASK);
1757 
1758             if (rxFrame->totLen - offset > (uint16_t)rxBdRing->rxBuffSizeAlign)
1759             {
1760                 /* Here must be double buffer. */
1761                 assert(handle->doubleBuffEnable);
1762 
1763                 buff1Len = (uint16_t)rxBdRing->rxBuffSizeAlign;
1764                 buff2Len = rxFrame->totLen - offset - (uint16_t)rxBdRing->rxBuffSizeAlign;
1765             }
1766             else
1767             {
1768                 buff1Len = rxFrame->totLen - offset;
1769             }
1770         }
1771         else
1772         {
1773             if (!handle->doubleBuffEnable)
1774             {
1775                 buff1Len = (uint16_t)rxBdRing->rxBuffSizeAlign;
1776                 offset += buff1Len;
1777             }
1778             else
1779             {
1780                 buff1Len = (uint16_t)rxBdRing->rxBuffSizeAlign;
1781                 buff2Len = (uint16_t)rxBdRing->rxBuffSizeAlign;
1782                 offset += buff1Len + buff2Len;
1783             }
1784         }
1785 
1786         /* Allocate new buffer to replace the buffer taken by application */
1787         newBuff1 = handle->rxBuffAlloc(base, handle->userData, channel);
1788         if (newBuff1 == NULL)
1789         {
1790             isDrop = true;
1791         }
1792         else if (handle->doubleBuffEnable && (buff2Len != 0U))
1793         {
1794             newBuff2 = handle->rxBuffAlloc(base, handle->userData, channel);
1795             if (newBuff2 == NULL)
1796             {
1797                 handle->rxBuffFree(base, newBuff1, handle->userData, channel);
1798                 isDrop = true;
1799             }
1800         }
1801         else
1802         {
1803             /* Intentional empty */
1804         }
1805 
1806         if (!isDrop)
1807         {
1808             /* Get the frame data information into Rx frame structure. */
1809             if (!handle->doubleBuffEnable)
1810             {
1811                 buff1Addr                          = handle->rxBufferStartAddr[channel][rxBdRing->rxGenIdx];
1812                 rxFrame->rxBuffArray[index].buffer = (void *)(uint32_t *)buff1Addr;
1813                 rxFrame->rxBuffArray[index].length = buff1Len;
1814                 index++;
1815             }
1816             else
1817             {
1818                 buff1Addr                          = handle->rxBufferStartAddr[channel][2U * rxBdRing->rxGenIdx];
1819                 rxFrame->rxBuffArray[index].buffer = (void *)(uint32_t *)buff1Addr;
1820                 rxFrame->rxBuffArray[index].length = buff1Len;
1821                 index++;
1822 
1823                 /* If there's no data in buffer2, not add it into rxFrame */
1824                 if (buff2Len != 0U)
1825                 {
1826                     buff2Addr = handle->rxBufferStartAddr[channel][2U * rxBdRing->rxGenIdx + 1U];
1827                     rxFrame->rxBuffArray[index].buffer = (void *)(uint32_t *)buff2Addr;
1828                     rxFrame->rxBuffArray[index].length = buff2Len;
1829                     index++;
1830                 }
1831             }
1832 
1833             /* Give new buffer from application to BD */
1834             if (!handle->doubleBuffEnable)
1835             {
1836                 buff1Addr                                              = (uint32_t)(uint32_t *)newBuff1;
1837                 handle->rxBufferStartAddr[channel][rxBdRing->rxGenIdx] = buff1Addr;
1838                 ENET_UpdateRxDescriptor(rxDesc, (void *)(uint32_t *)buff1Addr, NULL, handle->rxintEnable,
1839                                         handle->doubleBuffEnable);
1840             }
1841             else
1842             {
1843                 buff1Addr                                                   = (uint32_t)(uint32_t *)newBuff1;
1844                 handle->rxBufferStartAddr[channel][2U * rxBdRing->rxGenIdx] = buff1Addr;
1845 
1846                 if (buff2Len != 0U)
1847                 {
1848                     buff2Addr                                                        = (uint32_t)(uint32_t *)newBuff2;
1849                     handle->rxBufferStartAddr[channel][2U * rxBdRing->rxGenIdx + 1U] = buff2Addr;
1850                 }
1851                 else
1852                 {
1853                     /* If there's no data in buffer2, keep it */
1854                     buff2Addr = handle->rxBufferStartAddr[channel][2U * rxBdRing->rxGenIdx + 1U];
1855                 }
1856 
1857                 ENET_UpdateRxDescriptor(rxDesc, (void *)(uint32_t *)buff1Addr, (void *)(uint32_t *)buff2Addr,
1858                                         handle->rxintEnable, handle->doubleBuffEnable);
1859             }
1860             rxBdRing->rxGenIdx = ENET_IncreaseIndex(rxBdRing->rxGenIdx, rxBdRing->rxRingLen);
1861 
1862 #ifdef ENET_PTP1588FEATURE_REQUIRED
1863             /* Update context BD if there is */
1864             if (isLastBuff && tsAvailable)
1865             {
1866                 rxDesc = &rxBdRing->rxBdBase[rxBdRing->rxGenIdx];
1867                 if ((rxDesc->rdes3 & ENET_RXDESCRIP_WR_CTXT_MASK) != 0U)
1868                 {
1869                     uint32_t timerCount;
1870 
1871                     /* Get receive frame timestamp. */
1872                     rxFrame->rxAttribute.timestamp.second = rxDesc->rdes1;
1873                     timerCount                            = rxDesc->rdes0;
1874                     if ((base->MAC_TIMESTAMP_CTRL & ENET_MAC_TIMESTAMP_CTRL_TSCTRLSSR_MASK) == 0U)
1875                     {
1876                         /* Binary rollover. */
1877                         rxFrame->rxAttribute.timestamp.nanosecond = ENET_BINARY_ROLLOVER_SCALE(timerCount);
1878                     }
1879                     else
1880                     {
1881                         rxFrame->rxAttribute.timestamp.nanosecond = timerCount;
1882                     }
1883                     rxFrame->rxAttribute.isTsAvail = true;
1884 
1885                     if (!handle->doubleBuffEnable)
1886                     {
1887                         buff1Addr = handle->rxBufferStartAddr[channel][rxBdRing->rxGenIdx];
1888                         ENET_UpdateRxDescriptor(rxDesc, (void *)(uint8_t *)buff1Addr, NULL, handle->rxintEnable,
1889                                                 handle->doubleBuffEnable);
1890                     }
1891                     else
1892                     {
1893                         buff1Addr = handle->rxBufferStartAddr[channel][2U * rxBdRing->rxGenIdx];
1894                         buff2Addr = handle->rxBufferStartAddr[channel][2U * rxBdRing->rxGenIdx + 1U];
1895                         ENET_UpdateRxDescriptor(rxDesc, (void *)(uint8_t *)buff1Addr, (void *)(uint8_t *)buff2Addr,
1896                                                 handle->rxintEnable, handle->doubleBuffEnable);
1897                     }
1898                     rxBdRing->rxGenIdx = ENET_IncreaseIndex(rxBdRing->rxGenIdx, rxBdRing->rxRingLen);
1899                 }
1900             }
1901 #else
1902             rxFrame->rxAttribute.isTsAvail = false;
1903 #endif /* ENET_PTP1588FEATURE_REQUIRED */
1904 
1905             /* Always try to start receive, in case it had stopped */
1906             base->DMA_CH[channel].DMA_CHX_RXDESC_TAIL_PTR =
1907                 (uint32_t)(uint8_t *)&rxBdRing->rxBdBase[rxBdRing->rxRingLen];
1908         }
1909         else
1910         {
1911             /* Drop frame if there's no new buffer memory */
1912 
1913             /* Free the incomplete frame buffers. */
1914             while (index-- != 0U)
1915             {
1916                 handle->rxBuffFree(base, rxFrame->rxBuffArray[index].buffer, handle->userData, channel);
1917             }
1918 
1919             /* Update all left BDs of this frame from current index. */
1920             ENET_DropFrame(base, handle, channel);
1921 
1922             result = kStatus_ENET_RxFrameDrop;
1923             break;
1924         }
1925     } while (!isLastBuff);
1926 
1927     /* Remove 4 bytes FCS. */
1928     if (result == kStatus_Success)
1929     {
1930         /* Find the last 4 bytes in the linked buffers and remove these FCS data. */
1931         buff1Len = rxFrame->rxBuffArray[--index].length;
1932         if (buff1Len > ENET_FCS_LEN)
1933         {
1934             rxFrame->rxBuffArray[index].length -= ENET_FCS_LEN;
1935         }
1936         else
1937         {
1938             rxFrame->rxBuffArray[index].length = 0;
1939             handle->rxBuffFree(base, rxFrame->rxBuffArray[index].buffer, handle->userData, channel);
1940             if (buff1Len < ENET_FCS_LEN)
1941             {
1942                 rxFrame->rxBuffArray[--index].length -= (ENET_FCS_LEN - buff1Len);
1943             }
1944         }
1945         rxFrame->totLen -= ENET_FCS_LEN;
1946     }
1947 
1948     return result;
1949 }
1950 
1951 /*!
1952  * brief Setup a given Tx descriptor.
1953  *  This function is a low level functional API to setup or prepare
1954  *  a given Tx descriptor.
1955  *
1956  * param txDesc  The given Tx descriptor.
1957  * param buffer1  The first buffer address in the descriptor.
1958  * param bytes1  The bytes in the fist buffer.
1959  * param buffer2  The second buffer address in the descriptor.
1960  * param bytes2  The bytes in the second buffer.
1961  * param framelen  The length of the frame to be transmitted.
1962  * param intEnable Interrupt enable flag.
1963  * param tsEnable The timestamp enable.
1964  * param flag The flag of this Tx desciriptor, see "enet_desc_flag_t" .
1965  * param slotNum The slot num used for AV mode only.
1966  *
1967  * note This must be called after all the ENET initilization.
1968  * And should be called when the ENET receive/transmit is required.
1969  * Transmit buffers are 'zero-copy' buffers, so the buffer must remain in
1970  * memory until the packet has been fully transmitted. The buffers
1971  * should be free or requeued in the transmit interrupt irq handler.
1972  */
ENET_SetupTxDescriptor(enet_tx_bd_struct_t * txDesc,void * buffer1,uint32_t bytes1,void * buffer2,uint32_t bytes2,uint32_t framelen,bool intEnable,bool tsEnable,enet_desc_flag_t flag,uint8_t slotNum)1973 void ENET_SetupTxDescriptor(enet_tx_bd_struct_t *txDesc,
1974                             void *buffer1,
1975                             uint32_t bytes1,
1976                             void *buffer2,
1977                             uint32_t bytes2,
1978                             uint32_t framelen,
1979                             bool intEnable,
1980                             bool tsEnable,
1981                             enet_desc_flag_t flag,
1982                             uint8_t slotNum)
1983 {
1984     uint32_t control = ENET_TXDESCRIP_RD_BL1(bytes1) | ENET_TXDESCRIP_RD_BL2(bytes2);
1985 
1986     if ((flag == kENET_FirstFlagOnly) || (flag == kENET_FirstLastFlag))
1987     {
1988         if (tsEnable)
1989         {
1990             control |= ENET_TXDESCRIP_RD_TTSE_MASK;
1991         }
1992         else
1993         {
1994             control &= ~ENET_TXDESCRIP_RD_TTSE_MASK;
1995         }
1996     }
1997 
1998     if (intEnable)
1999     {
2000         control |= ENET_TXDESCRIP_RD_IOC_MASK;
2001     }
2002     else
2003     {
2004         control &= ~ENET_TXDESCRIP_RD_IOC_MASK;
2005     }
2006 
2007     /* Preare the descriptor for transmit. */
2008     txDesc->tdes0 = (uint32_t)(uint32_t *)buffer1;
2009     txDesc->tdes1 = (uint32_t)(uint32_t *)buffer2;
2010     txDesc->tdes2 = control;
2011 
2012     control = ENET_TXDESCRIP_RD_SLOT(slotNum) | ENET_TXDESCRIP_RD_FL(framelen) | ENET_TXDESCRIP_RD_LDFD(flag) |
2013               ENET_TXDESCRIP_RD_OWN_MASK;
2014 
2015     txDesc->tdes3 = control;
2016 }
2017 
2018 /*!
2019  * brief Configure a given Tx descriptor.
2020  *  This function is a low level functional API to setup or prepare
2021  *  a given Tx descriptor.
2022  *
2023  * param txDesc  The given Tx descriptor.
2024  * param config The Tx descriptor configuration.
2025  *
2026  * note This must be called after all the ENET initilization.
2027  * And should be called when the ENET receive/transmit is required.
2028  * Transmit buffers are 'zero-copy' buffers, so the buffer must remain in
2029  * memory until the packet has been fully transmitted. The buffers
2030  * should be free or requeued in the transmit interrupt irq handler.
2031  */
ENET_ConfigTxDescriptor(enet_tx_bd_struct_t * txDesc,enet_tx_bd_config_struct_t * config)2032 static void ENET_ConfigTxDescriptor(enet_tx_bd_struct_t *txDesc, enet_tx_bd_config_struct_t *config)
2033 {
2034     uint32_t control                = ENET_TXDESCRIP_RD_BL1(config->bytes1) | ENET_TXDESCRIP_RD_BL2(config->bytes2);
2035     enet_tx_offload_t txOffloadMode = kENET_TxOffloadDisable;
2036 
2037     if ((config->flag == kENET_FirstFlagOnly) || (config->flag == kENET_FirstLastFlag))
2038     {
2039         if (config->tsEnable)
2040         {
2041             control |= ENET_TXDESCRIP_RD_TTSE_MASK;
2042         }
2043         else
2044         {
2045             control &= ~ENET_TXDESCRIP_RD_TTSE_MASK;
2046         }
2047         txOffloadMode = config->txOffloadOps;
2048     }
2049 
2050     if (config->intEnable)
2051     {
2052         control |= ENET_TXDESCRIP_RD_IOC_MASK;
2053     }
2054     else
2055     {
2056         control &= ~ENET_TXDESCRIP_RD_IOC_MASK;
2057     }
2058 
2059     /* Preare the descriptor for transmit. */
2060     txDesc->tdes0 = (uint32_t)(uint32_t *)config->buffer1;
2061     txDesc->tdes1 = (uint32_t)(uint32_t *)config->buffer2;
2062     txDesc->tdes2 = control;
2063 
2064     control = ENET_TXDESCRIP_RD_SLOT(config->slotNum) | ENET_TXDESCRIP_RD_FL(config->framelen) |
2065               ENET_TXDESCRIP_RD_CIC(txOffloadMode) | ENET_TXDESCRIP_RD_LDFD(config->flag) | ENET_TXDESCRIP_RD_OWN_MASK;
2066 
2067     txDesc->tdes3 = control;
2068 }
2069 
2070 /*!
2071  * brief Reclaim Tx descriptors.
2072  *  This function is used to update the Tx descriptor status and
2073  *  store the Tx timestamp when the 1588 feature is enabled.
2074  *  This is called by the transmit interupt IRQ handler after the
2075  *  complete of a frame transmission.
2076  *
2077  * param base    ENET peripheral base address.
2078  * param handle The ENET handler pointer. This is the same handler pointer used in the ENET_Init.
2079  * param channel  The Tx DMA channnel.
2080  *
2081  */
ENET_ReclaimTxDescriptor(ENET_Type * base,enet_handle_t * handle,uint8_t channel)2082 void ENET_ReclaimTxDescriptor(ENET_Type *base, enet_handle_t *handle, uint8_t channel)
2083 {
2084     enet_tx_bd_ring_t *txBdRing       = &handle->txBdRing[channel];
2085     enet_tx_bd_struct_t *txDesc       = txBdRing->txBdBase + txBdRing->txConsumIdx;
2086     enet_tx_dirty_ring_t *txDirtyRing = (enet_tx_dirty_ring_t *)&handle->txDirtyRing[channel];
2087     enet_tx_reclaim_info_t *txDirty   = NULL;
2088 
2089     /* Need to update the first index for transmit buffer free. */
2090     while ((txBdRing->txDescUsed > 0U) && ((txDesc->tdes3 & ENET_TXDESCRIP_RD_OWN_MASK) == 0U))
2091     {
2092         if ((txDesc->tdes3 & ENET_TXDESCRIP_RD_LD_MASK) != 0U)
2093         {
2094             txDirty                  = &txDirtyRing->txDirtyBase[txDirtyRing->txConsumIdx];
2095             txDirtyRing->txConsumIdx = ENET_IncreaseIndex(txDirtyRing->txConsumIdx, txDirtyRing->txRingLen);
2096             txDirty->isTsAvail       = false;
2097 
2098 #ifdef ENET_PTP1588FEATURE_REQUIRED
2099             uint32_t nanosecond = 0;
2100 
2101             if ((txDesc->tdes3 & ENET_TXDESCRIP_WB_TTSS_MASK) != 0U)
2102             {
2103                 /* Get transmit time stamp second. */
2104                 nanosecond = txDesc->tdes0;
2105                 if ((base->MAC_TIMESTAMP_CTRL & ENET_MAC_TIMESTAMP_CTRL_TSCTRLSSR_MASK) == 0U)
2106                 {
2107                     /* Binary rollover. */
2108                     txDirty->timeStamp.nanosecond = ENET_BINARY_ROLLOVER_SCALE(nanosecond);
2109                 }
2110                 else
2111                 {
2112                     txDirty->timeStamp.nanosecond = nanosecond;
2113                 }
2114                 txDirty->timeStamp.second = txDesc->tdes1;
2115                 txDirty->isTsAvail        = true;
2116             }
2117 #endif /* ENET_PTP1588FEATURE_REQUIRED */
2118             /* For Tx buffer free or requeue for each descriptor.
2119              * The Tx interrupt callback should free/requeue the Tx buffer. */
2120             if (handle->callback != NULL)
2121             {
2122                 handle->callback(base, handle, kENET_TxIntEvent, channel, txDirty, handle->userData);
2123             }
2124         }
2125 
2126         /* Update the used Tx descriptor count. */
2127         txBdRing->txDescUsed--;
2128 
2129         /* Update the txConsumIdx/txDesc. */
2130         txBdRing->txConsumIdx = ENET_IncreaseIndex(txBdRing->txConsumIdx, txBdRing->txRingLen);
2131         txDesc                = txBdRing->txBdBase + txBdRing->txConsumIdx;
2132     }
2133 }
2134 
2135 /*!
2136  * brief Transmits an ENET frame.
2137  * note The CRC is automatically appended to the data. Input the data
2138  * to send without the CRC. This API uses input buffer for Tx, application
2139  * should reclaim the buffer after Tx is over.
2140  *
2141  * param base  ENET peripheral base address.
2142  * param handle The ENET handler pointer. This is the same handler pointer used in the ENET_Init.
2143  * param txFrame The Tx frame structure.
2144  * param channel Channel to send the frame, same with queue index.
2145  * retval kStatus_Success  Send frame succeed.
2146  * retval kStatus_ENET_TxFrameBusy  Transmit buffer descriptor is busy under transmission.
2147  *        The transmit busy happens when the data send rate is over the MAC capacity.
2148  *        The waiting mechanism is recommended to be added after each call return with kStatus_ENET_TxFrameBusy.
2149  *        Also need to pay attention to reclaim Tx frame after Tx is over.
2150  * retval kStatus_ENET_TxFrameOverLen  Transmit frme length exceeds the 0x3FFF limit defined by the driver.
2151  */
ENET_SendFrame(ENET_Type * base,enet_handle_t * handle,enet_tx_frame_struct_t * txFrame,uint8_t channel)2152 status_t ENET_SendFrame(ENET_Type *base, enet_handle_t *handle, enet_tx_frame_struct_t *txFrame, uint8_t channel)
2153 {
2154     assert(handle);
2155     assert(handle->txDirtyRing[channel].txDirtyBase != NULL);
2156     assert(txFrame);
2157     assert(txFrame->txBuffNum != 0U);
2158     assert(txFrame->txBuffArray != NULL);
2159 
2160     enet_tx_bd_ring_t *txBdRing       = (enet_tx_bd_ring_t *)&handle->txBdRing[channel];
2161     enet_tx_dirty_ring_t *txDirtyRing = (enet_tx_dirty_ring_t *)&handle->txDirtyRing[channel];
2162     enet_tx_reclaim_info_t *txDirty   = &txDirtyRing->txDirtyBase[txDirtyRing->txGenIdx];
2163     enet_buffer_struct_t *txBuff      = txFrame->txBuffArray;
2164     uint32_t frameLen                 = 0;
2165     uint32_t index                    = 0;
2166     enet_tx_bd_struct_t *txDesc;
2167     enet_desc_flag_t descFlag;
2168     uint32_t leftBuffNum;
2169 
2170     /* Calculate total frame length and the Tx buffer number if it's scattered. */
2171     for (index = 0; index < txFrame->txBuffNum; index++)
2172     {
2173         frameLen += txBuff[index].length;
2174     }
2175 
2176     /* Here use maximum length of single buffer in hardware as transmit length limitation, cause it's long enough.
2177      * And it simplifies the check of buffer length. There's no need to check each buffer length. */
2178     if (frameLen > ENET_FRAME_TX_LEN_LIMITATION)
2179     {
2180         return kStatus_ENET_TxFrameOverLen;
2181     }
2182 
2183     /* Check Tx FIFO whether can store enough frame data. */
2184     if (0U != handle->txLenLimitation[channel])
2185     {
2186         if (frameLen > handle->txLenLimitation[channel])
2187         {
2188             return kStatus_ENET_TxFrameOverLen;
2189         }
2190     }
2191 
2192     /* Check whether the available BD number is enough for Tx data buffer. */
2193     if (txFrame->txBuffNum > (((uint32_t)txBdRing->txRingLen - (uint32_t)txBdRing->txDescUsed) * 2U))
2194     {
2195         return kStatus_ENET_TxFrameBusy;
2196     }
2197 
2198     /* Update the context in Tx dirty ring for reclaim */
2199     txDirty->context      = txFrame->context;
2200     txDirtyRing->txGenIdx = ENET_IncreaseIndex(txDirtyRing->txGenIdx, txDirtyRing->txRingLen);
2201 
2202     index       = 0;
2203     leftBuffNum = txFrame->txBuffNum;
2204     do
2205     {
2206         txDesc = &txBdRing->txBdBase[txBdRing->txGenIdx];
2207 
2208         /* Get the right flag for current BD */
2209         if (leftBuffNum == txFrame->txBuffNum)
2210         {
2211             descFlag = (leftBuffNum > 2U) ? kENET_FirstFlagOnly : kENET_FirstLastFlag;
2212         }
2213         else
2214         {
2215             descFlag = (leftBuffNum > 2U) ? kENET_MiddleFlag : kENET_LastFlagOnly;
2216         }
2217 
2218         enet_tx_bd_config_struct_t txDescConfig = {0};
2219 
2220         txDescConfig.framelen     = frameLen;
2221         txDescConfig.intEnable    = (bool)txFrame->txConfig.intEnable;
2222         txDescConfig.tsEnable     = (bool)txFrame->txConfig.tsEnable;
2223         txDescConfig.txOffloadOps = txFrame->txConfig.txOffloadOps;
2224         txDescConfig.flag         = descFlag;
2225         txDescConfig.slotNum      = txFrame->txConfig.slotNum;
2226 
2227         /* Fill the descriptor. */
2228         txDescConfig.buffer1 = txBuff[index].buffer;
2229         txDescConfig.bytes1  = txBuff[index].length;
2230         if (leftBuffNum < 2U)
2231         {
2232             txDescConfig.buffer2 = NULL;
2233             txDescConfig.bytes2  = 0;
2234             leftBuffNum--;
2235         }
2236         else
2237         {
2238             txDescConfig.buffer2 = txBuff[index + 1U].buffer;
2239             txDescConfig.bytes2  = txBuff[index + 1U].length;
2240             index += 2U;
2241             leftBuffNum -= 2U;
2242         }
2243         ENET_ConfigTxDescriptor(txDesc, &txDescConfig);
2244 
2245         /* Increase the index. */
2246         txBdRing->txGenIdx = ENET_IncreaseIndex(txBdRing->txGenIdx, txBdRing->txRingLen);
2247 
2248         /* Disable interrupt first and then enable interrupt to avoid the race condition. */
2249         (void)DisableIRQ(s_enetIrqId[ENET_GetInstance(base)]);
2250         txBdRing->txDescUsed++;
2251         (void)EnableIRQ(s_enetIrqId[ENET_GetInstance(base)]);
2252     } while (leftBuffNum != 0U);
2253 
2254     /* Update the transmit tail address. */
2255     txDesc = (txBdRing->txGenIdx == 0U) ? (&txBdRing->txBdBase[txBdRing->txRingLen]) :
2256                                           (&txBdRing->txBdBase[txBdRing->txGenIdx]);
2257     base->DMA_CH[channel].DMA_CHX_TXDESC_TAIL_PTR = (uint32_t)txDesc & ~ENET_ADDR_ALIGNMENT;
2258 
2259     return kStatus_Success;
2260 }
2261 
2262 #ifdef ENET_PTP1588FEATURE_REQUIRED
2263 /*!
2264  * brief Gets the current ENET time from the PTP 1588 timer.
2265  *       Interrupts are not disabled.
2266  *
2267  * param base  ENET peripheral base address.
2268  * param second The PTP 1588 system timer second.
2269  * param nanosecond The PTP 1588 system timer nanosecond.
2270  */
ENET_Ptp1588GetTimerNoIrqDisable(ENET_Type * base,uint64_t * second,uint32_t * nanosecond)2271 void ENET_Ptp1588GetTimerNoIrqDisable(ENET_Type *base, uint64_t *second, uint32_t *nanosecond)
2272 {
2273     assert(second);
2274     assert(nanosecond);
2275 
2276     /* Get the current PTP time. */
2277     *second = (((uint64_t)base->MAC_SYS_TIME_HWORD_SCND & ENET_MAC_SYS_TIME_HWORD_SCND_TSHWR_MASK) << 32U) |
2278               base->MAC_SYS_TIME_SCND;
2279     *nanosecond = base->MAC_SYS_TIME_NSCND & ENET_MAC_SYS_TIME_NSCND_TSSS_MASK;
2280     if (!((base->MAC_TIMESTAMP_CTRL & ENET_MAC_TIMESTAMP_CTRL_TSCTRLSSR_MASK) != 0U))
2281     {
2282         /* Binary rollover, the unit of the increment is ~ 0.466 ns. */
2283         *nanosecond = ENET_BINARY_ROLLOVER_SCALE(*nanosecond);
2284     }
2285 }
2286 
2287 /*!
2288  * brief Gets the current ENET time from the PTP 1588 timer.
2289  *
2290  * param base  ENET peripheral base address.
2291  * param second The PTP 1588 system timer second.
2292  * param nanosecond The PTP 1588 system timer nanosecond.
2293  * For the unit of the nanosecond is 1ns. So the nanosecond is the real nanosecond.
2294  */
ENET_Ptp1588GetTimer(ENET_Type * base,uint64_t * second,uint32_t * nanosecond)2295 void ENET_Ptp1588GetTimer(ENET_Type *base, uint64_t *second, uint32_t *nanosecond)
2296 {
2297     assert(second);
2298     assert(nanosecond);
2299 
2300     uint32_t primask;
2301 
2302     /* Disables the interrupt. */
2303     primask = DisableGlobalIRQ();
2304 
2305     ENET_Ptp1588GetTimerNoIrqDisable(base, second, nanosecond);
2306 
2307     /* Enables the interrupt. */
2308     EnableGlobalIRQ(primask);
2309 }
2310 
2311 /*!
2312  * brief Correct the ENET PTP 1588 timer in coarse method.
2313  *
2314  * param base  ENET peripheral base address.
2315  * param operation The system time operation, refer to "enet_systime_op_t"
2316  * param second The correction second.
2317  * param nanosecond The correction nanosecond.
2318  */
ENET_Ptp1588CorrectTimerInCoarse(ENET_Type * base,enet_systime_op_t operation,uint32_t second,uint32_t nanosecond)2319 void ENET_Ptp1588CorrectTimerInCoarse(ENET_Type *base,
2320                                       enet_systime_op_t operation,
2321                                       uint32_t second,
2322                                       uint32_t nanosecond)
2323 {
2324     uint32_t corrSecond = second;
2325     uint32_t corrNanosecond;
2326 
2327     /* Set the system timer. */
2328     if ((base->MAC_TIMESTAMP_CTRL & ENET_MAC_TIMESTAMP_CTRL_TSCTRLSSR_MASK) != 0U)
2329     {
2330         if (operation == kENET_SystimeSubtract)
2331         {
2332             /* Set with the complement of the sub-second. */
2333             corrSecond     = ENET_MAC_SYS_TIME_SCND_UPD_TSS_MASK - (second - 1U);
2334             corrNanosecond = ENET_MAC_SYS_TIME_NSCND_UPD_ADDSUB_MASK |
2335                              ENET_MAC_SYS_TIME_NSCND_UPD_TSSS(ENET_NANOSECS_ONESECOND - nanosecond);
2336         }
2337         else
2338         {
2339             corrNanosecond = ENET_MAC_SYS_TIME_NSCND_UPD_TSSS(nanosecond);
2340         }
2341     }
2342     else
2343     {
2344         nanosecond = ENET_MAC_SYS_TIME_NSCND_UPD_TSSS_MASK / ENET_NANOSECS_ONESECOND * nanosecond;
2345         if (operation == kENET_SystimeSubtract)
2346         {
2347             /* Set with the complement of the sub-second. */
2348             corrSecond     = ENET_MAC_SYS_TIME_SCND_UPD_TSS_MASK - (second - 1U);
2349             corrNanosecond = ENET_MAC_SYS_TIME_NSCND_UPD_ADDSUB_MASK |
2350                              ENET_MAC_SYS_TIME_NSCND_UPD_TSSS(ENET_MAC_SYS_TIME_NSCND_UPD_TSSS_MASK + 1U - nanosecond);
2351         }
2352         else
2353         {
2354             corrNanosecond = ENET_MAC_SYS_TIME_NSCND_UPD_TSSS(nanosecond);
2355         }
2356     }
2357 
2358     base->MAC_SYS_TIME_SCND_UPD  = corrSecond;
2359     base->MAC_SYS_TIME_NSCND_UPD = corrNanosecond;
2360 
2361     /* Update the timer. */
2362     base->MAC_TIMESTAMP_CTRL |= ENET_MAC_TIMESTAMP_CTRL_TSUPDT_MASK;
2363     while ((base->MAC_TIMESTAMP_CTRL & ENET_MAC_TIMESTAMP_CTRL_TSUPDT_MASK) != 0U)
2364     {
2365     }
2366 }
2367 #endif /* ENET_PTP1588FEATURE_REQUIRED */
2368 
2369 /*!
2370  * brief The ENET IRQ handler.
2371  *
2372  * param base  ENET peripheral base address.
2373  * param handle The ENET handler pointer.
2374  */
ENET_IRQHandler(ENET_Type * base,enet_handle_t * handle)2375 void ENET_IRQHandler(ENET_Type *base, enet_handle_t *handle)
2376 {
2377     /* Check for the interrupt source type. */
2378     /* DMA CHANNEL 0. */
2379     if ((base->DMA_INTR_STAT & ENET_DMA_INTR_STAT_DC0IS_MASK) != 0U)
2380     {
2381         uint32_t flag = base->DMA_CH[0].DMA_CHX_STAT;
2382         if ((flag & ENET_DMA_CH_DMA_CHX_STAT_RI_MASK) != 0U)
2383         {
2384             base->DMA_CH[0].DMA_CHX_STAT = ENET_DMA_CH_DMA_CHX_STAT_RI_MASK | ENET_DMA_CH_DMA_CHX_STAT_NIS_MASK;
2385             if (handle->callback != NULL)
2386             {
2387                 handle->callback(base, handle, kENET_RxIntEvent, 0, NULL, handle->userData);
2388             }
2389         }
2390         if ((flag & ENET_DMA_CH_DMA_CHX_STAT_TI_MASK) != 0U)
2391         {
2392             base->DMA_CH[0].DMA_CHX_STAT = ENET_DMA_CH_DMA_CHX_STAT_TI_MASK | ENET_DMA_CH_DMA_CHX_STAT_NIS_MASK;
2393             ENET_ReclaimTxDescriptor(base, handle, 0);
2394         }
2395     }
2396 
2397     /* DMA CHANNEL 1. */
2398     if ((base->DMA_INTR_STAT & ENET_DMA_INTR_STAT_DC1IS_MASK) != 0U)
2399     {
2400         uint32_t flag = base->DMA_CH[1].DMA_CHX_STAT;
2401         if ((flag & ENET_DMA_CH_DMA_CHX_STAT_RI_MASK) != 0U)
2402         {
2403             base->DMA_CH[1].DMA_CHX_STAT = ENET_DMA_CH_DMA_CHX_STAT_RI_MASK | ENET_DMA_CH_DMA_CHX_STAT_NIS_MASK;
2404             if (handle->callback != NULL)
2405             {
2406                 handle->callback(base, handle, kENET_RxIntEvent, 1, NULL, handle->userData);
2407             }
2408         }
2409         if ((flag & ENET_DMA_CH_DMA_CHX_STAT_TI_MASK) != 0U)
2410         {
2411             base->DMA_CH[1].DMA_CHX_STAT = ENET_DMA_CH_DMA_CHX_STAT_TI_MASK | ENET_DMA_CH_DMA_CHX_STAT_NIS_MASK;
2412             ENET_ReclaimTxDescriptor(base, handle, 1);
2413         }
2414     }
2415 
2416 #ifdef ENET_PTP1588FEATURE_REQUIRED
2417     /* MAC TIMESTAMP. */
2418     if ((base->DMA_INTR_STAT & ENET_DMA_INTR_STAT_MACIS_MASK) != 0U)
2419     {
2420         if ((base->MAC_INTR_STAT & ENET_MAC_INTR_STAT_TSIS_MASK) != 0U)
2421         {
2422             if (handle->callback != NULL)
2423             {
2424                 handle->callback(base, handle, kENET_TimeStampIntEvent, 0, NULL, handle->userData);
2425             }
2426         }
2427     }
2428 #endif /* ENET_PTP1588FEATURE_REQUIRED */
2429     SDK_ISR_EXIT_BARRIER;
2430 }
2431 
2432 void ETHERNET_DriverIRQHandler(void);
ETHERNET_DriverIRQHandler(void)2433 void ETHERNET_DriverIRQHandler(void)
2434 {
2435     s_enetIsr(ENET, s_ENETHandle[0]);
2436     SDK_ISR_EXIT_BARRIER;
2437 }
2438