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_GetCoreSysClkFreq() / 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     uint32_t rdes3 = rxDesc->rdes3;
1572     union _frame_error
1573     {
1574         uint32_t data;
1575         enet_rx_frame_error_t frameError;
1576     };
1577     union _frame_error error;
1578 
1579     (void)memset((void *)&error.frameError, 0, sizeof(enet_rx_frame_error_t));
1580 
1581     error.data = ENET_FRAME_RX_ERROR_BITS(rdes3);
1582 }
1583 
ENET_DropFrame(ENET_Type * base,enet_handle_t * handle,uint8_t channel)1584 static void ENET_DropFrame(ENET_Type *base, enet_handle_t *handle, uint8_t channel)
1585 {
1586     enet_rx_bd_ring_t *rxBdRing = (enet_rx_bd_ring_t *)&handle->rxBdRing[channel];
1587     enet_rx_bd_struct_t *rxDesc;
1588     uint16_t index = rxBdRing->rxGenIdx;
1589 #ifdef ENET_PTP1588FEATURE_REQUIRED
1590     bool tsAvailable   = false;
1591     uint32_t buff1Addr = 0;
1592     uint32_t buff2Addr = 0;
1593 #endif /* ENET_PTP1588FEATURE_REQUIRED */
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         ENET_UpdateRxDescriptor(rxDesc, NULL, NULL, handle->rxintEnable, handle->doubleBuffEnable);
1601         rxBdRing->rxGenIdx = ENET_IncreaseIndex(rxBdRing->rxGenIdx, rxBdRing->rxRingLen);
1602 
1603         /* Find the last buffer descriptor for the frame. */
1604         if ((rxDesc->rdes3 & ENET_RXDESCRIP_WR_LD_MASK) != 0U)
1605         {
1606 #ifdef ENET_PTP1588FEATURE_REQUIRED
1607             if ((rxDesc->rdes3 & ENET_RXDESCRIP_WR_RS1V_MASK) != 0U)
1608             {
1609                 if ((rxDesc->rdes1 & ENET_RXDESCRIP_WR_PTPTSA_MASK) != 0U)
1610                 {
1611                     tsAvailable = true;
1612                 }
1613             }
1614 
1615             /* Reinit for the context descriptor which has been updated by DMA. */
1616             rxDesc = &rxBdRing->rxBdBase[rxBdRing->rxGenIdx];
1617 
1618             if (tsAvailable && ((rxDesc->rdes3 & ENET_RXDESCRIP_WR_CTXT_MASK) != 0U))
1619             {
1620                 if (!handle->doubleBuffEnable)
1621                 {
1622                     buff1Addr = handle->rxBufferStartAddr[channel][rxBdRing->rxGenIdx];
1623                     ENET_UpdateRxDescriptor(rxDesc, (void *)(uint8_t *)buff1Addr, NULL, handle->rxintEnable,
1624                                             handle->doubleBuffEnable);
1625                 }
1626                 else
1627                 {
1628                     buff1Addr = handle->rxBufferStartAddr[channel][2U * rxBdRing->rxGenIdx];
1629                     buff2Addr = handle->rxBufferStartAddr[channel][2U * rxBdRing->rxGenIdx + 1U];
1630                     ENET_UpdateRxDescriptor(rxDesc, (void *)(uint8_t *)buff1Addr, (void *)(uint8_t *)buff2Addr,
1631                                             handle->rxintEnable, handle->doubleBuffEnable);
1632                 }
1633                 rxBdRing->rxGenIdx = ENET_IncreaseIndex(rxBdRing->rxGenIdx, rxBdRing->rxRingLen);
1634             }
1635 #endif /*  ENET_PTP1588FEATURE_REQUIRED */
1636             break;
1637         }
1638     } while (rxBdRing->rxGenIdx != index);
1639 
1640     /* Always try to start receive, in case it had stopped */
1641     base->DMA_CH[channel].DMA_CHX_RXDESC_TAIL_PTR = (uint32_t)(uint8_t *)&rxBdRing->rxBdBase[rxBdRing->rxRingLen];
1642 }
1643 
1644 /*!
1645  * brief Receives one frame in specified BD ring with zero copy.
1646  *
1647  * This function will use the user-defined allocate and free callback. Every time application gets one frame through
1648  * this function, driver will allocate new buffers for the BDs whose buffers have been taken by application.
1649  * note This function will drop current frame and update related BDs as available for DMA if new buffers allocating
1650  * fails. Application must provide a memory pool including at least BD number + 1 buffers(+2 if enable double buffer)
1651  * to make this function work normally. If user calls this function in Rx interrupt handler, be careful that this
1652  * function makes Rx BD ready with allocating new buffer(normal) or updating current BD(out of memory). If there's
1653  * always new Rx frame input, Rx interrupt will be triggered forever. Application need to disable Rx interrupt according
1654  * to specific design in this case.
1655  *
1656  * param base   ENET peripheral base address.
1657  * param handle The ENET handler pointer. This is the same handler pointer used in the ENET_Init.
1658  * param rxFrame The received frame information structure provided by user.
1659  * param channel The Rx DMA channel. Shall not be larger than 2.
1660  * retval kStatus_Success  Succeed to get one frame and allocate new memory for Rx buffer.
1661  * retval kStatus_ENET_RxFrameEmpty  There's no Rx frame in the BD.
1662  * retval kStatus_ENET_RxFrameError  There's issue in this receiving. In this function, issue frame will be dropped.
1663  * retval kStatus_ENET_RxFrameDrop  There's no new buffer memory for BD, dropped this frame.
1664  */
ENET_GetRxFrame(ENET_Type * base,enet_handle_t * handle,enet_rx_frame_struct_t * rxFrame,uint8_t channel)1665 status_t ENET_GetRxFrame(ENET_Type *base, enet_handle_t *handle, enet_rx_frame_struct_t *rxFrame, uint8_t channel)
1666 {
1667     assert(handle != NULL);
1668     assert(channel < ENET_RING_NUM_MAX);
1669 
1670     enet_rx_bd_ring_t *rxBdRing = (enet_rx_bd_ring_t *)&handle->rxBdRing[channel];
1671     enet_rx_bd_struct_t *rxDesc = &rxBdRing->rxBdBase[rxBdRing->rxGenIdx];
1672     uint16_t index              = rxBdRing->rxGenIdx;
1673     status_t result             = kStatus_Success;
1674     uint32_t buff1Addr          = 0;
1675     uint32_t buff2Addr          = 0;
1676     uint16_t buff1Len           = 0;
1677     uint16_t buff2Len           = 0;
1678     uint16_t offset             = 0;
1679     void *newBuff1              = NULL;
1680     void *newBuff2              = NULL;
1681     bool isDrop                 = false;
1682     bool isLastBuff             = false;
1683 #ifdef ENET_PTP1588FEATURE_REQUIRED
1684     bool tsAvailable = false;
1685 #endif /* ENET_PTP1588FEATURE_REQUIRED */
1686 
1687     /* Check the frame status. */
1688     do
1689     {
1690         if ((rxDesc->rdes3 & ENET_RXDESCRIP_WR_OWN_MASK) != 0U)
1691         {
1692             result = kStatus_ENET_RxFrameEmpty;
1693             break;
1694         }
1695 
1696         /* Check timestamp and error. */
1697         if ((rxDesc->rdes3 & ENET_RXDESCRIP_WR_LD_MASK) != 0U)
1698         {
1699 #ifdef ENET_PTP1588FEATURE_REQUIRED
1700             if ((rxDesc->rdes3 & ENET_RXDESCRIP_WR_RS1V_MASK) != 0U)
1701             {
1702                 if ((rxDesc->rdes1 & ENET_RXDESCRIP_WR_PTPTSA_MASK) != 0U)
1703                 {
1704                     tsAvailable = true;
1705                 }
1706             }
1707 #endif /* ENET_PTP1588FEATURE_REQUIRED */
1708 
1709             /* Get the frame error if there is. */
1710             if ((rxDesc->rdes3 & ENET_RXDESCRIP_WR_ERRSUM_MASK) != 0U)
1711             {
1712                 ENET_GetRxFrameErr(rxDesc, &rxFrame->rxFrameError);
1713                 result = kStatus_ENET_RxFrameError;
1714             }
1715             else if ((rxDesc->rdes3 & ENET_RXDESCRIP_WR_PACKETLEN_MASK) == 0U)
1716             {
1717                 result = kStatus_ENET_RxFrameEmpty;
1718             }
1719             else
1720             {
1721                 /* Intentional empty */
1722             }
1723             break;
1724         }
1725 
1726         index = ENET_IncreaseIndex(index, rxBdRing->rxRingLen);
1727         if (index == rxBdRing->rxGenIdx)
1728         {
1729             result = kStatus_ENET_RxFrameEmpty;
1730             break;
1731         }
1732         rxDesc = &rxBdRing->rxBdBase[index];
1733     } while (index != rxBdRing->rxGenIdx);
1734 
1735     /* Drop the error frame and return error. */
1736     if (result != kStatus_Success)
1737     {
1738         if (result == kStatus_ENET_RxFrameError)
1739         {
1740             ENET_DropFrame(base, handle, channel);
1741         }
1742         return result;
1743     }
1744 
1745     /* Get the valid frame */
1746     index = 0;
1747     do
1748     {
1749         rxDesc = &rxBdRing->rxBdBase[rxBdRing->rxGenIdx];
1750 
1751         /* Calculate the buffer and frame length. */
1752         if ((rxDesc->rdes3 & ENET_RXDESCRIP_WR_LD_MASK) != 0U)
1753         {
1754             isLastBuff      = true;
1755             rxFrame->totLen = (uint16_t)(rxDesc->rdes3 & ENET_RXDESCRIP_WR_PACKETLEN_MASK);
1756 
1757             if (rxFrame->totLen - offset > (uint16_t)rxBdRing->rxBuffSizeAlign)
1758             {
1759                 buff1Len = (uint16_t)rxBdRing->rxBuffSizeAlign;
1760                 if (handle->doubleBuffEnable)
1761                 {
1762                     buff2Len = rxFrame->totLen - offset - (uint16_t)rxBdRing->rxBuffSizeAlign - ENET_FCS_LEN;
1763                 }
1764             }
1765             else
1766             {
1767                 buff1Len = rxFrame->totLen - offset - ENET_FCS_LEN;
1768             }
1769             rxFrame->totLen -= ENET_FCS_LEN;
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     return result;
1928 }
1929 
1930 /*!
1931  * brief Setup a given Tx descriptor.
1932  *  This function is a low level functional API to setup or prepare
1933  *  a given Tx descriptor.
1934  *
1935  * param txDesc  The given Tx descriptor.
1936  * param buffer1  The first buffer address in the descriptor.
1937  * param bytes1  The bytes in the fist buffer.
1938  * param buffer2  The second buffer address in the descriptor.
1939  * param bytes2  The bytes in the second buffer.
1940  * param framelen  The length of the frame to be transmitted.
1941  * param intEnable Interrupt enable flag.
1942  * param tsEnable The timestamp enable.
1943  * param flag The flag of this Tx desciriptor, see "enet_desc_flag_t" .
1944  * param slotNum The slot num used for AV mode only.
1945  *
1946  * note This must be called after all the ENET initilization.
1947  * And should be called when the ENET receive/transmit is required.
1948  * Transmit buffers are 'zero-copy' buffers, so the buffer must remain in
1949  * memory until the packet has been fully transmitted. The buffers
1950  * should be free or requeued in the transmit interrupt irq handler.
1951  */
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)1952 void ENET_SetupTxDescriptor(enet_tx_bd_struct_t *txDesc,
1953                             void *buffer1,
1954                             uint32_t bytes1,
1955                             void *buffer2,
1956                             uint32_t bytes2,
1957                             uint32_t framelen,
1958                             bool intEnable,
1959                             bool tsEnable,
1960                             enet_desc_flag_t flag,
1961                             uint8_t slotNum)
1962 {
1963     uint32_t control = ENET_TXDESCRIP_RD_BL1(bytes1) | ENET_TXDESCRIP_RD_BL2(bytes2);
1964 
1965     if ((flag == kENET_FirstFlagOnly) || (flag == kENET_FirstLastFlag))
1966     {
1967         if (tsEnable)
1968         {
1969             control |= ENET_TXDESCRIP_RD_TTSE_MASK;
1970         }
1971         else
1972         {
1973             control &= ~ENET_TXDESCRIP_RD_TTSE_MASK;
1974         }
1975     }
1976 
1977     if (intEnable)
1978     {
1979         control |= ENET_TXDESCRIP_RD_IOC_MASK;
1980     }
1981     else
1982     {
1983         control &= ~ENET_TXDESCRIP_RD_IOC_MASK;
1984     }
1985 
1986     /* Preare the descriptor for transmit. */
1987     txDesc->tdes0 = (uint32_t)(uint32_t *)buffer1;
1988     txDesc->tdes1 = (uint32_t)(uint32_t *)buffer2;
1989     txDesc->tdes2 = control;
1990 
1991     control = ENET_TXDESCRIP_RD_SLOT(slotNum) | ENET_TXDESCRIP_RD_FL(framelen) | ENET_TXDESCRIP_RD_LDFD(flag) |
1992               ENET_TXDESCRIP_RD_OWN_MASK;
1993 
1994     txDesc->tdes3 = control;
1995 }
1996 
1997 /*!
1998  * brief Configure a given Tx descriptor.
1999  *  This function is a low level functional API to setup or prepare
2000  *  a given Tx descriptor.
2001  *
2002  * param txDesc  The given Tx descriptor.
2003  * param config The Tx descriptor configuration.
2004  *
2005  * note This must be called after all the ENET initilization.
2006  * And should be called when the ENET receive/transmit is required.
2007  * Transmit buffers are 'zero-copy' buffers, so the buffer must remain in
2008  * memory until the packet has been fully transmitted. The buffers
2009  * should be free or requeued in the transmit interrupt irq handler.
2010  */
ENET_ConfigTxDescriptor(enet_tx_bd_struct_t * txDesc,enet_tx_bd_config_struct_t * config)2011 static void ENET_ConfigTxDescriptor(enet_tx_bd_struct_t *txDesc, enet_tx_bd_config_struct_t *config)
2012 {
2013     uint32_t control                = ENET_TXDESCRIP_RD_BL1(config->bytes1) | ENET_TXDESCRIP_RD_BL2(config->bytes2);
2014     enet_tx_offload_t txOffloadMode = kENET_TxOffloadDisable;
2015 
2016     if ((config->flag == kENET_FirstFlagOnly) || (config->flag == kENET_FirstLastFlag))
2017     {
2018         if (config->tsEnable)
2019         {
2020             control |= ENET_TXDESCRIP_RD_TTSE_MASK;
2021         }
2022         else
2023         {
2024             control &= ~ENET_TXDESCRIP_RD_TTSE_MASK;
2025         }
2026         txOffloadMode = config->txOffloadOps;
2027     }
2028 
2029     if (config->intEnable)
2030     {
2031         control |= ENET_TXDESCRIP_RD_IOC_MASK;
2032     }
2033     else
2034     {
2035         control &= ~ENET_TXDESCRIP_RD_IOC_MASK;
2036     }
2037 
2038     /* Preare the descriptor for transmit. */
2039     txDesc->tdes0 = (uint32_t)(uint32_t *)config->buffer1;
2040     txDesc->tdes1 = (uint32_t)(uint32_t *)config->buffer2;
2041     txDesc->tdes2 = control;
2042 
2043     control = ENET_TXDESCRIP_RD_SLOT(config->slotNum) | ENET_TXDESCRIP_RD_FL(config->framelen) |
2044               ENET_TXDESCRIP_RD_CIC(txOffloadMode) | ENET_TXDESCRIP_RD_LDFD(config->flag) | ENET_TXDESCRIP_RD_OWN_MASK;
2045 
2046     txDesc->tdes3 = control;
2047 }
2048 
2049 /*!
2050  * brief Reclaim Tx descriptors.
2051  *  This function is used to update the Tx descriptor status and
2052  *  store the Tx timestamp when the 1588 feature is enabled.
2053  *  This is called by the transmit interupt IRQ handler after the
2054  *  complete of a frame transmission.
2055  *
2056  * param base    ENET peripheral base address.
2057  * param handle The ENET handler pointer. This is the same handler pointer used in the ENET_Init.
2058  * param channel  The Tx DMA channnel.
2059  *
2060  */
ENET_ReclaimTxDescriptor(ENET_Type * base,enet_handle_t * handle,uint8_t channel)2061 void ENET_ReclaimTxDescriptor(ENET_Type *base, enet_handle_t *handle, uint8_t channel)
2062 {
2063     enet_tx_bd_ring_t *txBdRing       = &handle->txBdRing[channel];
2064     enet_tx_bd_struct_t *txDesc       = txBdRing->txBdBase + txBdRing->txConsumIdx;
2065     enet_tx_dirty_ring_t *txDirtyRing = (enet_tx_dirty_ring_t *)&handle->txDirtyRing[channel];
2066     enet_tx_reclaim_info_t *txDirty   = NULL;
2067 
2068     /* Need to update the first index for transmit buffer free. */
2069     while ((txBdRing->txDescUsed > 0U) && ((txDesc->tdes3 & ENET_TXDESCRIP_RD_OWN_MASK) == 0U))
2070     {
2071         if ((txDesc->tdes3 & ENET_TXDESCRIP_RD_LD_MASK) != 0U)
2072         {
2073             txDirty                  = &txDirtyRing->txDirtyBase[txDirtyRing->txConsumIdx];
2074             txDirtyRing->txConsumIdx = ENET_IncreaseIndex(txDirtyRing->txConsumIdx, txDirtyRing->txRingLen);
2075             txDirty->isTsAvail       = false;
2076 
2077 #ifdef ENET_PTP1588FEATURE_REQUIRED
2078             uint32_t nanosecond = 0;
2079 
2080             if ((txDesc->tdes3 & ENET_TXDESCRIP_WB_TTSS_MASK) != 0U)
2081             {
2082                 /* Get transmit time stamp second. */
2083                 nanosecond = txDesc->tdes0;
2084                 if ((base->MAC_TIMESTAMP_CTRL & ENET_MAC_TIMESTAMP_CTRL_TSCTRLSSR_MASK) == 0U)
2085                 {
2086                     /* Binary rollover. */
2087                     txDirty->timeStamp.nanosecond = ENET_BINARY_ROLLOVER_SCALE(nanosecond);
2088                 }
2089                 else
2090                 {
2091                     txDirty->timeStamp.nanosecond = nanosecond;
2092                 }
2093                 txDirty->timeStamp.second = txDesc->tdes1;
2094                 txDirty->isTsAvail        = true;
2095             }
2096 #endif /* ENET_PTP1588FEATURE_REQUIRED */
2097             /* For Tx buffer free or requeue for each descriptor.
2098              * The Tx interrupt callback should free/requeue the Tx buffer. */
2099             if (handle->callback != NULL)
2100             {
2101                 handle->callback(base, handle, kENET_TxIntEvent, channel, txDirty, handle->userData);
2102             }
2103         }
2104 
2105         /* Update the used Tx descriptor count. */
2106         txBdRing->txDescUsed--;
2107 
2108         /* Update the txConsumIdx/txDesc. */
2109         txBdRing->txConsumIdx = ENET_IncreaseIndex(txBdRing->txConsumIdx, txBdRing->txRingLen);
2110         txDesc                = txBdRing->txBdBase + txBdRing->txConsumIdx;
2111     }
2112 }
2113 
2114 /*!
2115  * brief Transmits an ENET frame.
2116  * note The CRC is automatically appended to the data. Input the data
2117  * to send without the CRC. This API uses input buffer for Tx, application
2118  * should reclaim the buffer after Tx is over.
2119  *
2120  * param base  ENET peripheral base address.
2121  * param handle The ENET handler pointer. This is the same handler pointer used in the ENET_Init.
2122  * param txFrame The Tx frame structure.
2123  * param channel Channel to send the frame, same with queue index.
2124  * retval kStatus_Success  Send frame succeed.
2125  * retval kStatus_ENET_TxFrameBusy  Transmit buffer descriptor is busy under transmission.
2126  *        The transmit busy happens when the data send rate is over the MAC capacity.
2127  *        The waiting mechanism is recommended to be added after each call return with kStatus_ENET_TxFrameBusy.
2128  *        Also need to pay attention to reclaim Tx frame after Tx is over.
2129  * retval kStatus_ENET_TxFrameOverLen  Transmit frme length exceeds the 0x3FFF limit defined by the driver.
2130  */
ENET_SendFrame(ENET_Type * base,enet_handle_t * handle,enet_tx_frame_struct_t * txFrame,uint8_t channel)2131 status_t ENET_SendFrame(ENET_Type *base, enet_handle_t *handle, enet_tx_frame_struct_t *txFrame, uint8_t channel)
2132 {
2133     assert(handle);
2134     assert(handle->txDirtyRing[channel].txDirtyBase != NULL);
2135     assert(txFrame);
2136     assert(txFrame->txBuffNum != 0U);
2137     assert(txFrame->txBuffArray != NULL);
2138 
2139     enet_tx_bd_ring_t *txBdRing       = (enet_tx_bd_ring_t *)&handle->txBdRing[channel];
2140     enet_tx_dirty_ring_t *txDirtyRing = (enet_tx_dirty_ring_t *)&handle->txDirtyRing[channel];
2141     enet_tx_reclaim_info_t *txDirty   = &txDirtyRing->txDirtyBase[txDirtyRing->txGenIdx];
2142     enet_buffer_struct_t *txBuff      = txFrame->txBuffArray;
2143     uint32_t frameLen                 = 0;
2144     uint32_t index                    = 0;
2145     enet_tx_bd_struct_t *txDesc;
2146     enet_desc_flag_t descFlag;
2147     uint32_t leftBuffNum;
2148 
2149     /* Calculate total frame length and the Tx buffer number if it's scattered. */
2150     for (index = 0; index < txFrame->txBuffNum; index++)
2151     {
2152         frameLen += txBuff[index].length;
2153     }
2154 
2155     /* Here use maximum length of single buffer in hardware as transmit length limitation, cause it's long enough.
2156      * And it simplifies the check of buffer length. There's no need to check each buffer length. */
2157     if (frameLen > ENET_FRAME_TX_LEN_LIMITATION)
2158     {
2159         return kStatus_ENET_TxFrameOverLen;
2160     }
2161 
2162     /* Check Tx FIFO whether can store enough frame data. */
2163     if (0U != handle->txLenLimitation[channel])
2164     {
2165         if (frameLen > handle->txLenLimitation[channel])
2166         {
2167             return kStatus_ENET_TxFrameOverLen;
2168         }
2169     }
2170 
2171     /* Check whether the available BD number is enough for Tx data buffer. */
2172     if (txFrame->txBuffNum > (((uint32_t)txBdRing->txRingLen - (uint32_t)txBdRing->txDescUsed) * 2U))
2173     {
2174         return kStatus_ENET_TxFrameBusy;
2175     }
2176 
2177     /* Update the context in Tx dirty ring for reclaim */
2178     txDirty->context      = txFrame->context;
2179     txDirtyRing->txGenIdx = ENET_IncreaseIndex(txDirtyRing->txGenIdx, txDirtyRing->txRingLen);
2180 
2181     index       = 0;
2182     leftBuffNum = txFrame->txBuffNum;
2183     do
2184     {
2185         txDesc = &txBdRing->txBdBase[txBdRing->txGenIdx];
2186 
2187         /* Get the right flag for current BD */
2188         if (leftBuffNum == txFrame->txBuffNum)
2189         {
2190             descFlag = (leftBuffNum > 2U) ? kENET_FirstFlagOnly : kENET_FirstLastFlag;
2191         }
2192         else
2193         {
2194             descFlag = (leftBuffNum > 2U) ? kENET_MiddleFlag : kENET_LastFlagOnly;
2195         }
2196 
2197         enet_tx_bd_config_struct_t txDescConfig = {0};
2198 
2199         txDescConfig.framelen     = frameLen;
2200         txDescConfig.intEnable    = (bool)txFrame->txConfig.intEnable;
2201         txDescConfig.tsEnable     = (bool)txFrame->txConfig.tsEnable;
2202         txDescConfig.txOffloadOps = txFrame->txConfig.txOffloadOps;
2203         txDescConfig.flag         = descFlag;
2204         txDescConfig.slotNum      = txFrame->txConfig.slotNum;
2205 
2206         /* Fill the descriptor. */
2207         txDescConfig.buffer1 = txBuff[index].buffer;
2208         txDescConfig.bytes1  = txBuff[index].length;
2209         if (leftBuffNum < 2U)
2210         {
2211             txDescConfig.buffer2 = NULL;
2212             txDescConfig.bytes2  = 0;
2213             leftBuffNum--;
2214         }
2215         else
2216         {
2217             txDescConfig.buffer2 = txBuff[index + 1U].buffer;
2218             txDescConfig.bytes2  = txBuff[index + 1U].length;
2219             index += 2U;
2220             leftBuffNum -= 2U;
2221         }
2222         ENET_ConfigTxDescriptor(txDesc, &txDescConfig);
2223 
2224         /* Increase the index. */
2225         txBdRing->txGenIdx = ENET_IncreaseIndex(txBdRing->txGenIdx, txBdRing->txRingLen);
2226 
2227         /* Disable interrupt first and then enable interrupt to avoid the race condition. */
2228         (void)DisableIRQ(s_enetIrqId[ENET_GetInstance(base)]);
2229         txBdRing->txDescUsed++;
2230         (void)EnableIRQ(s_enetIrqId[ENET_GetInstance(base)]);
2231     } while (leftBuffNum != 0U);
2232 
2233     /* Update the transmit tail address. */
2234     txDesc = (txBdRing->txGenIdx == 0U) ? (&txBdRing->txBdBase[txBdRing->txRingLen]) :
2235                                           (&txBdRing->txBdBase[txBdRing->txGenIdx]);
2236     base->DMA_CH[channel].DMA_CHX_TXDESC_TAIL_PTR = (uint32_t)txDesc & ~ENET_ADDR_ALIGNMENT;
2237 
2238     return kStatus_Success;
2239 }
2240 
2241 #ifdef ENET_PTP1588FEATURE_REQUIRED
2242 /*!
2243  * brief Gets the current ENET time from the PTP 1588 timer.
2244  *       Interrupts are not disabled.
2245  *
2246  * param base  ENET peripheral base address.
2247  * param second The PTP 1588 system timer second.
2248  * param nanosecond The PTP 1588 system timer nanosecond.
2249  */
ENET_Ptp1588GetTimerNoIrqDisable(ENET_Type * base,uint64_t * second,uint32_t * nanosecond)2250 void ENET_Ptp1588GetTimerNoIrqDisable(ENET_Type *base, uint64_t *second, uint32_t *nanosecond)
2251 {
2252     assert(second);
2253     assert(nanosecond);
2254 
2255     /* Get the current PTP time. */
2256     *second = (((uint64_t)base->MAC_SYS_TIME_HWORD_SCND & ENET_MAC_SYS_TIME_HWORD_SCND_TSHWR_MASK) << 32U) |
2257               base->MAC_SYS_TIME_SCND;
2258     *nanosecond = base->MAC_SYS_TIME_NSCND & ENET_MAC_SYS_TIME_NSCND_TSSS_MASK;
2259     if (!((base->MAC_TIMESTAMP_CTRL & ENET_MAC_TIMESTAMP_CTRL_TSCTRLSSR_MASK) != 0U))
2260     {
2261         /* Binary rollover, the unit of the increment is ~ 0.466 ns. */
2262         *nanosecond = ENET_BINARY_ROLLOVER_SCALE(*nanosecond);
2263     }
2264 }
2265 
2266 /*!
2267  * brief Gets the current ENET time from the PTP 1588 timer.
2268  *
2269  * param base  ENET peripheral base address.
2270  * param second The PTP 1588 system timer second.
2271  * param nanosecond The PTP 1588 system timer nanosecond.
2272  * For the unit of the nanosecond is 1ns. So the nanosecond is the real nanosecond.
2273  */
ENET_Ptp1588GetTimer(ENET_Type * base,uint64_t * second,uint32_t * nanosecond)2274 void ENET_Ptp1588GetTimer(ENET_Type *base, uint64_t *second, uint32_t *nanosecond)
2275 {
2276     assert(second);
2277     assert(nanosecond);
2278 
2279     uint32_t primask;
2280 
2281     /* Disables the interrupt. */
2282     primask = DisableGlobalIRQ();
2283 
2284     ENET_Ptp1588GetTimerNoIrqDisable(base, second, nanosecond);
2285 
2286     /* Enables the interrupt. */
2287     EnableGlobalIRQ(primask);
2288 }
2289 
2290 /*!
2291  * brief Correct the ENET PTP 1588 timer in coarse method.
2292  *
2293  * param base  ENET peripheral base address.
2294  * param operation The system time operation, refer to "enet_systime_op_t"
2295  * param second The correction second.
2296  * param nanosecond The correction nanosecond.
2297  */
ENET_Ptp1588CorrectTimerInCoarse(ENET_Type * base,enet_systime_op_t operation,uint32_t second,uint32_t nanosecond)2298 void ENET_Ptp1588CorrectTimerInCoarse(ENET_Type *base,
2299                                       enet_systime_op_t operation,
2300                                       uint32_t second,
2301                                       uint32_t nanosecond)
2302 {
2303     uint32_t corrSecond = second;
2304     uint32_t corrNanosecond;
2305 
2306     /* Set the system timer. */
2307     if ((base->MAC_TIMESTAMP_CTRL & ENET_MAC_TIMESTAMP_CTRL_TSCTRLSSR_MASK) != 0U)
2308     {
2309         if (operation == kENET_SystimeSubtract)
2310         {
2311             /* Set with the complement of the sub-second. */
2312             corrSecond     = ENET_MAC_SYS_TIME_SCND_UPD_TSS_MASK - (second - 1U);
2313             corrNanosecond = ENET_MAC_SYS_TIME_NSCND_UPD_ADDSUB_MASK |
2314                              ENET_MAC_SYS_TIME_NSCND_UPD_TSSS(ENET_NANOSECS_ONESECOND - nanosecond);
2315         }
2316         else
2317         {
2318             corrNanosecond = ENET_MAC_SYS_TIME_NSCND_UPD_TSSS(nanosecond);
2319         }
2320     }
2321     else
2322     {
2323         nanosecond = ENET_MAC_SYS_TIME_NSCND_UPD_TSSS_MASK / ENET_NANOSECS_ONESECOND * nanosecond;
2324         if (operation == kENET_SystimeSubtract)
2325         {
2326             /* Set with the complement of the sub-second. */
2327             corrSecond     = ENET_MAC_SYS_TIME_SCND_UPD_TSS_MASK - (second - 1U);
2328             corrNanosecond = ENET_MAC_SYS_TIME_NSCND_UPD_ADDSUB_MASK |
2329                              ENET_MAC_SYS_TIME_NSCND_UPD_TSSS(ENET_MAC_SYS_TIME_NSCND_UPD_TSSS_MASK + 1U - nanosecond);
2330         }
2331         else
2332         {
2333             corrNanosecond = ENET_MAC_SYS_TIME_NSCND_UPD_TSSS(nanosecond);
2334         }
2335     }
2336 
2337     base->MAC_SYS_TIME_SCND_UPD  = corrSecond;
2338     base->MAC_SYS_TIME_NSCND_UPD = corrNanosecond;
2339 
2340     /* Update the timer. */
2341     base->MAC_TIMESTAMP_CTRL |= ENET_MAC_TIMESTAMP_CTRL_TSUPDT_MASK;
2342     while ((base->MAC_TIMESTAMP_CTRL & ENET_MAC_TIMESTAMP_CTRL_TSUPDT_MASK) != 0U)
2343     {
2344     }
2345 }
2346 #endif /* ENET_PTP1588FEATURE_REQUIRED */
2347 
2348 /*!
2349  * brief The ENET IRQ handler.
2350  *
2351  * param base  ENET peripheral base address.
2352  * param handle The ENET handler pointer.
2353  */
ENET_IRQHandler(ENET_Type * base,enet_handle_t * handle)2354 void ENET_IRQHandler(ENET_Type *base, enet_handle_t *handle)
2355 {
2356     /* Check for the interrupt source type. */
2357     /* DMA CHANNEL 0. */
2358     if ((base->DMA_INTR_STAT & ENET_DMA_INTR_STAT_DC0IS_MASK) != 0U)
2359     {
2360         uint32_t flag = base->DMA_CH[0].DMA_CHX_STAT;
2361         if ((flag & ENET_DMA_CH_DMA_CHX_STAT_RI_MASK) != 0U)
2362         {
2363             base->DMA_CH[0].DMA_CHX_STAT = ENET_DMA_CH_DMA_CHX_STAT_RI_MASK | ENET_DMA_CH_DMA_CHX_STAT_NIS_MASK;
2364             if (handle->callback != NULL)
2365             {
2366                 handle->callback(base, handle, kENET_RxIntEvent, 0, NULL, handle->userData);
2367             }
2368         }
2369         if ((flag & ENET_DMA_CH_DMA_CHX_STAT_TI_MASK) != 0U)
2370         {
2371             base->DMA_CH[0].DMA_CHX_STAT = ENET_DMA_CH_DMA_CHX_STAT_TI_MASK | ENET_DMA_CH_DMA_CHX_STAT_NIS_MASK;
2372             ENET_ReclaimTxDescriptor(base, handle, 0);
2373         }
2374     }
2375 
2376     /* DMA CHANNEL 1. */
2377     if ((base->DMA_INTR_STAT & ENET_DMA_INTR_STAT_DC1IS_MASK) != 0U)
2378     {
2379         uint32_t flag = base->DMA_CH[1].DMA_CHX_STAT;
2380         if ((flag & ENET_DMA_CH_DMA_CHX_STAT_RI_MASK) != 0U)
2381         {
2382             base->DMA_CH[1].DMA_CHX_STAT = ENET_DMA_CH_DMA_CHX_STAT_RI_MASK | ENET_DMA_CH_DMA_CHX_STAT_NIS_MASK;
2383             if (handle->callback != NULL)
2384             {
2385                 handle->callback(base, handle, kENET_RxIntEvent, 1, NULL, handle->userData);
2386             }
2387         }
2388         if ((flag & ENET_DMA_CH_DMA_CHX_STAT_TI_MASK) != 0U)
2389         {
2390             base->DMA_CH[1].DMA_CHX_STAT = ENET_DMA_CH_DMA_CHX_STAT_TI_MASK | ENET_DMA_CH_DMA_CHX_STAT_NIS_MASK;
2391             ENET_ReclaimTxDescriptor(base, handle, 1);
2392         }
2393     }
2394 
2395 #ifdef ENET_PTP1588FEATURE_REQUIRED
2396     /* MAC TIMESTAMP. */
2397     if ((base->DMA_INTR_STAT & ENET_DMA_INTR_STAT_MACIS_MASK) != 0U)
2398     {
2399         if ((base->MAC_INTR_STAT & ENET_MAC_INTR_STAT_TSIS_MASK) != 0U)
2400         {
2401             if (handle->callback != NULL)
2402             {
2403                 handle->callback(base, handle, kENET_TimeStampIntEvent, 0, NULL, handle->userData);
2404             }
2405         }
2406     }
2407 #endif /* ENET_PTP1588FEATURE_REQUIRED */
2408     SDK_ISR_EXIT_BARRIER;
2409 }
2410 
2411 void ETHERNET_DriverIRQHandler(void);
ETHERNET_DriverIRQHandler(void)2412 void ETHERNET_DriverIRQHandler(void)
2413 {
2414     s_enetIsr(ENET, s_ENETHandle[0]);
2415     SDK_ISR_EXIT_BARRIER;
2416 }
2417