1 /*
2  * Copyright 2021-2023 NXP
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include "fsl_netc_hw_port.h"
8 
NETC_PortIsPseudo(NETC_PORT_Type * base)9 bool NETC_PortIsPseudo(NETC_PORT_Type *base)
10 {
11     return ((base->PCAPR & NETC_PORT_PCAPR_LINK_TYPE_MASK) != 0U);
12 }
13 
NETC_PortSetMacAddr(NETC_PORT_Type * base,const uint8_t * macAddr)14 void NETC_PortSetMacAddr(NETC_PORT_Type *base, const uint8_t *macAddr)
15 {
16     uint32_t address;
17 
18     /* Set physical address lower register. */
19     address     = ((uint32_t *)(uintptr_t)macAddr)[0];
20     base->PMAR0 = address;
21 
22     /* Set physical address high register. */
23     address     = ((uint32_t)macAddr[5] << 8U) | (uint32_t)macAddr[4];
24     base->PMAR1 = NETC_PORT_PMAR1_PRIM_MAC_ADDR(address);
25 }
26 
NETC_PortConfig(NETC_PORT_Type * base,const netc_port_common_t * config)27 status_t NETC_PortConfig(NETC_PORT_Type *base, const netc_port_common_t *config)
28 {
29     status_t result;
30 
31     NETC_PortSetParser(base, &config->parser);
32     NETC_PortSetVlanClassify(base, &config->acceptTpid);
33 
34     result = NETC_PortSetQosClassify(base, &config->qosMode);
35     if (result != kStatus_Success)
36     {
37         return result;
38     }
39 
40     (void)NETC_PortConfigTGS(base, &config->timeGate);
41     NETC_PortSetIPF(base, &config->ipfCfg);
42     NETC_PortSetMacAddr(base, &config->macAddr[0]);
43     base->PCR = NETC_PORT_PCR_PSPEED(config->pSpeed) |
44 #if (defined(FSL_FEATURE_NETC_HAS_PORT_FCSEA) && FSL_FEATURE_NETC_HAS_PORT_FCSEA)
45                 NETC_PORT_PCR_FCSEA(!config->stompFcs) |
46 #endif
47                 NETC_PORT_PCR_TIMER_CS(config->rxTsSelect);
48     base->PSGCR = NETC_PORT_PSGCR_OGC(config->ogcMode) | NETC_PORT_PSGCR_PDELAY(config->pDelay);
49 
50     /* Configure Port SDU overhead */
51     base->PRXSDUOR =
52         NETC_PORT_PRXSDUOR_MACSEC_BCO(config->rxMacsecBco) | NETC_PORT_PRXSDUOR_PPDU_BCO(config->rxPpduBco);
53     base->PTXSDUOR =
54         NETC_PORT_PTXSDUOR_MACSEC_BCO(config->txMacsecBco) | NETC_PORT_PTXSDUOR_PPDU_BCO(config->txPpduBco);
55     return kStatus_Success;
56 }
57 
NETC_PortSetMII(NETC_ETH_LINK_Type * base,netc_hw_mii_mode_t miiMode,netc_hw_mii_speed_t speed,netc_hw_mii_duplex_t duplex)58 status_t NETC_PortSetMII(NETC_ETH_LINK_Type *base,
59                          netc_hw_mii_mode_t miiMode,
60                          netc_hw_mii_speed_t speed,
61                          netc_hw_mii_duplex_t duplex)
62 {
63     uint32_t reg = base->PM0_IF_MODE;
64 
65     /* Set MAC interface mode */
66     reg &= ~NETC_ETH_LINK_PM0_IF_MODE_IFMODE_MASK;
67     reg |= NETC_ETH_LINK_PM0_IF_MODE_IFMODE(miiMode);
68 
69     /* Set MAC speed and duplex */
70     if ((miiMode == kNETC_MiiMode) || (miiMode == kNETC_RmiiMode))
71     {
72         if (speed == kNETC_MiiSpeed10M)
73         {
74             reg |= NETC_ETH_LINK_PM0_IF_MODE_M10_MASK;
75         }
76         else if (speed == kNETC_MiiSpeed100M)
77         {
78             reg &= ~NETC_ETH_LINK_PM0_IF_MODE_M10_MASK;
79         }
80         else
81         {
82             return kStatus_Fail;
83         }
84         reg &= ~NETC_ETH_LINK_PM0_IF_MODE_HD_MASK;
85         reg |= NETC_ETH_LINK_PM0_IF_MODE_HD(duplex != kNETC_MiiFullDuplex);
86     }
87     else if (miiMode == kNETC_RgmiiMode)
88     {
89         reg &= ~NETC_ETH_LINK_PM0_IF_MODE_SSP_MASK;
90         reg &= ~NETC_ETH_LINK_PM0_IF_MODE_HD_MASK;
91         if (speed == kNETC_MiiSpeed1000M)
92         {
93             reg |= NETC_ETH_LINK_PM0_IF_MODE_SSP(speed);
94             reg |= NETC_ETH_LINK_PM0_IF_MODE_HD(0);
95         }
96         else
97         {
98             reg |= NETC_ETH_LINK_PM0_IF_MODE_SSP(speed != kNETC_MiiSpeed100M);
99             reg |= NETC_ETH_LINK_PM0_IF_MODE_HD(duplex != kNETC_MiiFullDuplex);
100         }
101     }
102     else /* kNETC_GmiiMode, force 1Gbps and full speed */
103     {
104         if ((speed < kNETC_MiiSpeed1000M) || (duplex != kNETC_MiiFullDuplex))
105         {
106             return kStatus_InvalidArgument;
107         }
108     }
109     base->PM0_IF_MODE = reg;
110     base->PM1_IF_MODE = reg;
111 
112     return kStatus_Success;
113 }
114 
NETC_PortSetMaxFrameSize(NETC_ETH_LINK_Type * base,uint16_t size)115 status_t NETC_PortSetMaxFrameSize(NETC_ETH_LINK_Type *base, uint16_t size)
116 {
117     /* The MAC supports reception of any frame size up to 2000 bytes. */
118     if (size > NETC_PORT_MAX_FRAME_SIZE)
119     {
120         return kStatus_InvalidArgument;
121     }
122 
123     base->PM0_MAXFRM = NETC_ETH_LINK_PM0_MAXFRM_MAXFRM(size);
124     base->PM1_MAXFRM = NETC_ETH_LINK_PM1_MAXFRM_MAXFRM(size);
125 
126     return kStatus_Success;
127 }
128 
NETC_PortConfigEthMac(NETC_ETH_LINK_Type * base,const netc_port_ethmac_t * config)129 status_t NETC_PortConfigEthMac(NETC_ETH_LINK_Type *base, const netc_port_ethmac_t *config)
130 {
131     uint32_t reg = 0;
132     status_t result;
133 
134     if ((config->rxMinFrameSize < NETC_PORT_MIN_FRAME_SIZE) || (config->rxMaxFrameSize > NETC_PORT_MAX_FRAME_SIZE) ||
135         (config->rxMinFrameSize > config->rxMaxFrameSize))
136     {
137         return kStatus_InvalidArgument;
138     }
139 
140     /* Set Rx Frame Maximum/Minimum Length */
141     result = NETC_PortSetMaxFrameSize(base, config->rxMaxFrameSize);
142     if (result != kStatus_Success)
143     {
144         return result;
145     }
146 #if defined(NETC_ETH_LINK_PM0_MINFRM_NUM_BYTES_MASK)
147     base->PM0_MINFRM = NETC_ETH_LINK_PM0_MINFRM_NUM_BYTES(config->rxMinFrameSize);
148 #endif
149 #if defined(NETC_ETH_LINK_PM1_MINFRM_NUM_BYTES_MASK)
150     base->PM1_MINFRM = NETC_ETH_LINK_PM1_MINFRM_NUM_BYTES(config->rxMinFrameSize);
151 #endif
152 
153     /* Set MAC interface mode, speed and duplex */
154     result = NETC_PortSetMII(base, config->miiMode, config->miiSpeed, config->miiDuplex);
155     if (result != kStatus_Success)
156     {
157         return result;
158     }
159 
160     /* Enable reverse mode */
161     reg = base->PM0_IF_MODE;
162     if (config->enableRevMii)
163     {
164         reg |= NETC_ETH_LINK_PM0_IF_MODE_REVMII_MASK;
165     }
166     else
167     {
168         reg &= ~NETC_ETH_LINK_PM0_IF_MODE_REVMII_MASK;
169     }
170     /* Enable RGMII Tx clock stop status during low power idle.  */
171     if (config->rgmiiClkStop)
172     {
173         reg |= NETC_ETH_LINK_PM0_IF_MODE_CLK_STOP_MASK;
174     }
175     else
176     {
177         reg &= ~NETC_ETH_LINK_PM0_IF_MODE_CLK_STOP_MASK;
178     }
179     base->PM0_IF_MODE = reg;
180     base->PM1_IF_MODE = reg;
181 
182     base->MAC_MERGE_MMCSR = NETC_ETH_LINK_MAC_MERGE_MMCSR_VT(config->mergeVerifyTime) |
183                             NETC_ETH_LINK_MAC_MERGE_MMCSR_VDIS(!config->enMergeVerify) |
184                             NETC_ETH_LINK_MAC_MERGE_MMCSR_ME(config->preemptMode);
185 
186 #if !(defined(FSL_FEATURE_NETC_HAS_ERRATA_051255) && FSL_FEATURE_NETC_HAS_ERRATA_051255)
187     reg = NETC_ETH_LINK_PM0_SINGLE_STEP_CH(config->enChUpdate) |
188           NETC_ETH_LINK_PM0_SINGLE_STEP_OFFSET(config->oneStepOffset) |
189           NETC_ETH_LINK_PM0_SINGLE_STEP_EN(config->enOneStepTS);
190     base->PM0_SINGLE_STEP = reg;
191     base->PM1_SINGLE_STEP = reg;
192 #endif
193 
194     /* Enable Tx/Rx */
195     reg = NETC_ETH_LINK_PM0_COMMAND_CONFIG_TX_EN_MASK | NETC_ETH_LINK_PM0_COMMAND_CONFIG_RX_EN_MASK |
196           NETC_ETH_LINK_PM0_COMMAND_CONFIG_TS_MODE(config->txTsSelect) |
197           NETC_ETH_LINK_PM0_COMMAND_CONFIG_TS_PNT(config->isTsPointPhy) |
198 #if defined(NETC_ETH_LINK_PM0_COMMAND_CONFIG_HD_FCEN_MASK)
199           NETC_ETH_LINK_PM0_COMMAND_CONFIG_HD_FCEN(config->enableHalfDuplexFlowCtrl) |
200 #endif
201           NETC_ETH_LINK_PM0_COMMAND_CONFIG_TXP(config->enTxPad);
202     base->PM0_COMMAND_CONFIG = reg;
203     base->PM1_COMMAND_CONFIG = reg;
204 
205     if (config->enableHalfDuplexFlowCtrl)
206     {
207         assert((config->maxBackPressOn <= 3036U) && (config->minBackPressOff <= 20U));
208         reg = NETC_ETH_LINK_PM0_HD_FLOW_CTRL_HD_BP_ON_MAX(config->maxBackPressOn) |
209               NETC_ETH_LINK_PM0_HD_FLOW_CTRL_HD_BP_OFF_MIN(config->minBackPressOff);
210         base->PM0_HD_FLOW_CTRL = reg;
211         base->PM1_HD_FLOW_CTRL = reg;
212     }
213 
214     return kStatus_Success;
215 }
216 
NETC_GetPortMacInterruptFlags(NETC_ETH_LINK_Type * base,netc_port_phy_mac_type_t macType)217 uint32_t NETC_GetPortMacInterruptFlags(NETC_ETH_LINK_Type *base, netc_port_phy_mac_type_t macType)
218 {
219     if (macType == kNETC_ExpressMAC)
220     {
221         return base->PM0_IEVENT;
222     }
223     else
224     {
225         return base->PM1_IEVENT;
226     }
227 }
228 
NETC_ClearPortMacInterruptFlags(NETC_ETH_LINK_Type * base,netc_port_phy_mac_type_t macType,uint32_t mask)229 void NETC_ClearPortMacInterruptFlags(NETC_ETH_LINK_Type *base, netc_port_phy_mac_type_t macType, uint32_t mask)
230 {
231     if (macType == kNETC_ExpressMAC)
232     {
233         base->PM0_IEVENT |= mask;
234     }
235     else
236     {
237         base->PM1_IEVENT |= mask;
238     }
239 }
240 
NETC_EnablePortMacInterrupts(NETC_ETH_LINK_Type * base,netc_port_phy_mac_type_t macType,uint32_t mask,bool enable)241 void NETC_EnablePortMacInterrupts(NETC_ETH_LINK_Type *base, netc_port_phy_mac_type_t macType, uint32_t mask, bool enable)
242 {
243     if (macType == kNETC_ExpressMAC)
244     {
245         if (enable)
246         {
247             base->PM0_IMASK |= mask;
248         }
249         else
250         {
251             base->PM0_IMASK &= ~mask;
252         }
253     }
254     else
255     {
256         if (enable)
257         {
258             base->PM1_IMASK |= mask;
259         }
260         else
261         {
262             base->PM1_IMASK &= ~mask;
263         }
264     }
265 }
266 
NETC_PortEnableLoopback(NETC_ETH_LINK_Type * base,netc_port_loopback_mode_t loopMode,bool enable)267 status_t NETC_PortEnableLoopback(NETC_ETH_LINK_Type *base, netc_port_loopback_mode_t loopMode, bool enable)
268 {
269     uint32_t reg = base->PM0_COMMAND_CONFIG;
270 
271     if (enable)
272     {
273         reg &= ~NETC_ETH_LINK_PM0_COMMAND_CONFIG_LPBK_MODE_MASK;
274         reg |= NETC_ETH_LINK_PM0_COMMAND_CONFIG_LOOP_ENA_MASK | NETC_ETH_LINK_PM0_COMMAND_CONFIG_LPBK_MODE(loopMode);
275     }
276     else
277     {
278         reg &= ~NETC_ETH_LINK_PM0_COMMAND_CONFIG_LOOP_ENA_MASK;
279     }
280 
281     base->PM0_COMMAND_CONFIG = reg;
282     base->PM1_COMMAND_CONFIG = reg;
283 
284     return kStatus_Success;
285 }
286 
NETC_PortGetDiscardStatistic(NETC_PORT_Type * base,netc_port_discard_tpye_t discardType,netc_port_discard_statistic_t * statistic)287 void NETC_PortGetDiscardStatistic(NETC_PORT_Type *base,
288                                   netc_port_discard_tpye_t discardType,
289                                   netc_port_discard_statistic_t *statistic)
290 {
291     switch (discardType)
292     {
293         case kNETC_RxDiscard:
294             statistic->count   = base->PRXDCR;
295             statistic->reason0 = base->PRXDCRR0;
296             statistic->reason1 = base->PRXDCRR1;
297             break;
298 #if !(defined(FSL_FEATURE_NETC_HAS_NO_SWITCH) && FSL_FEATURE_NETC_HAS_NO_SWITCH)
299         case kNETC_TxDiscard:
300             statistic->count   = base->PTXDCR;
301             statistic->reason0 = base->PTXDCRR0;
302             statistic->reason1 = base->PTXDCRR1;
303             break;
304         case kNETC_BridgeDiscard:
305             statistic->count   = base->BPDCR;
306             statistic->reason0 = base->BPDCRR0;
307             statistic->reason1 = base->BPDCRR1;
308             break;
309 #endif
310         default:
311             assert(false);
312             break;
313     }
314 }
315 
NETC_PortClearDiscardReason(NETC_PORT_Type * base,netc_port_discard_tpye_t discardType,uint32_t reason0,uint32_t reason1)316 void NETC_PortClearDiscardReason(NETC_PORT_Type *base,
317                                  netc_port_discard_tpye_t discardType,
318                                  uint32_t reason0,
319                                  uint32_t reason1)
320 {
321     switch (discardType)
322     {
323         case kNETC_RxDiscard:
324             base->PRXDCRR0 = reason0;
325             base->PRXDCRR1 = reason1;
326             break;
327 #if !(defined(FSL_FEATURE_NETC_HAS_NO_SWITCH) && FSL_FEATURE_NETC_HAS_NO_SWITCH)
328         case kNETC_TxDiscard:
329             base->PTXDCRR0 = reason0;
330             base->PTXDCRR1 = reason1;
331             break;
332         case kNETC_BridgeDiscard:
333             base->BPDCRR0 = reason0;
334             base->BPDCRR1 = reason1;
335             break;
336 #endif
337         default:
338             assert(false);
339             break;
340     }
341 }
342 
NETC_PortGetPhyMacTxStatistic(NETC_ETH_LINK_Type * base,netc_port_phy_mac_type_t macType,netc_port_phy_mac_traffic_statistic_t * statistic)343 void NETC_PortGetPhyMacTxStatistic(NETC_ETH_LINK_Type *base,
344                                    netc_port_phy_mac_type_t macType,
345                                    netc_port_phy_mac_traffic_statistic_t *statistic)
346 {
347 #if (defined(FSL_FEATURE_NETC_HAS_ERRATA_050679) && FSL_FEATURE_NETC_HAS_ERRATA_050679)
348     uint32_t primask;
349 
350     primask = DisableGlobalIRQ();
351 #endif
352     statistic->rxMinPacket = 0;
353     if (macType == kNETC_ExpressMAC)
354     {
355 #if defined(FSL_FEATURE_NETC_HAS_ERRATA_051711) && FSL_FEATURE_NETC_HAS_ERRATA_051711
356         /* ERRATA051711: MAC statistic counters TEOCT and TOCT are inaccurate after Pause frames are transmitted with
357            flexible preamble enabled (PM0_TX_IPG_PREAMBLE[FLEX_PREAMBLE_EN] = 1) and flexible preamble count
358            (PM0_TX_IPG_PREAMBLE[FLEX_PREAMBLE_CNT]) set to less than 7. */
359         uint32_t flexPreambleCnt = (base->PM0_TX_IPG_PREAMBLE & NETC_ETH_LINK_PM0_TX_IPG_PREAMBLE_FLEX_PREAMBLE_CNT_MASK) >> NETC_ETH_LINK_PM0_TX_IPG_PREAMBLE_FLEX_PREAMBLE_CNT_SHIFT;
360         if ((base->PM0_TX_IPG_PREAMBLE & NETC_ETH_LINK_PM0_TX_IPG_PREAMBLE_FLEX_PREAMBLE_EN_MASK) != 0U)
361         {
362             statistic->totalOctet = base->PM0_TEOCTN - base->PM0_TXPFN * ((uint64_t)7U - flexPreambleCnt);
363             statistic->validOctet = base->PM0_TOCTN - base->PM0_TXPFN * ((uint64_t)7U - flexPreambleCnt);
364         }
365         else
366         {
367             statistic->totalOctet = base->PM0_TEOCTN;
368             statistic->validOctet = base->PM0_TOCTN;
369         }
370 #else
371         statistic->totalOctet = base->PM0_TEOCTN;
372         statistic->validOctet = base->PM0_TOCTN;
373 #endif
374         statistic->pauseFrame             = base->PM0_TXPFN;
375 #if defined(FSL_FEATURE_NETC_HAS_ERRATA_051710) && FSL_FEATURE_NETC_HAS_ERRATA_051710
376         /* ERRATA051710: After one or more late collision or excessive collision events, counters PMa_TOCTn and PMa_TFRMn will be higher than
377            expected. The accurate value cannot be recovered for PMa_TOCTn, but PMa_TRFMn can be recovered as follows formula. */
378         statistic->validFrame             = base->PM0_TFRMN - base->PM0_TLCOLN - base->PM0_TECOLN;
379 #else
380         statistic->validFrame             = base->PM0_TFRMN;
381 #endif
382         statistic->vlanFrame              = base->PM0_TVLANN;
383         statistic->unicastFrame           = base->PM0_TUCAN;
384         statistic->multicastFrame         = base->PM0_TMCAN;
385         statistic->boradcastFrame         = base->PM0_TBCAN;
386         statistic->totalPacket            = base->PM0_TPKTN;
387         statistic->total64BPacket         = base->PM0_T64N;
388         statistic->total65To127BPacket    = base->PM0_T127N;
389         statistic->total128To255BPacket   = base->PM0_T255N;
390         statistic->total256To511BPacket   = base->PM0_T511N;
391         statistic->total511To1023BPacket  = base->PM0_T1023N;
392         statistic->total1024To1522BPacket = base->PM0_T1522N;
393         statistic->total1523ToMaxBPacket  = base->PM0_T1523XN;
394         statistic->controlPacket          = base->PM0_TCNPN;
395     }
396     else if (macType == kNETC_PreemptableMAC)
397     {
398         statistic->totalOctet             = base->PM1_TEOCTN;
399         statistic->validOctet             = base->PM1_TOCTN;
400         statistic->pauseFrame             = base->PM1_TXPFN;
401 #if defined(FSL_FEATURE_NETC_HAS_ERRATA_051710) && FSL_FEATURE_NETC_HAS_ERRATA_051710
402         /* ERRATA051710: After one or more late collision or excessive collision events, counters PMa_TOCTn and PMa_TFRMn will be higher than
403            expected. The accurate value cannot be recovered for PMa_TOCTn, but PMa_TRFMn can be recovered as follows formula. */
404         statistic->validFrame             = base->PM1_TFRMN - base->PM1_TLCOLN - base->PM1_TECOLN;
405 #else
406         statistic->validFrame             = base->PM1_TFRMN;
407 #endif
408         statistic->vlanFrame              = base->PM1_TVLANN;
409         statistic->unicastFrame           = base->PM1_TUCAN;
410         statistic->multicastFrame         = base->PM1_TMCAN;
411         statistic->boradcastFrame         = base->PM1_TBCAN;
412         statistic->totalPacket            = base->PM1_TPKTN;
413         statistic->total64BPacket         = base->PM1_T64N;
414         statistic->total65To127BPacket    = base->PM1_T127N;
415         statistic->total128To255BPacket   = base->PM1_T255N;
416         statistic->total256To511BPacket   = base->PM1_T511N;
417         statistic->total511To1023BPacket  = base->PM1_T1023N;
418         statistic->total1024To1522BPacket = base->PM1_T1522N;
419         statistic->total1523ToMaxBPacket  = base->PM1_T1523XN;
420         statistic->controlPacket          = base->PM1_TCNPN;
421     }
422     else
423     {
424         ; /* Intentional empty */
425     }
426 
427 #if (defined(FSL_FEATURE_NETC_HAS_ERRATA_050679) && FSL_FEATURE_NETC_HAS_ERRATA_050679)
428     EnableGlobalIRQ(primask);
429 #endif
430 }
431 
NETC_PortGetPhyMacRxStatistic(NETC_ETH_LINK_Type * base,netc_port_phy_mac_type_t macType,netc_port_phy_mac_traffic_statistic_t * statistic)432 void NETC_PortGetPhyMacRxStatistic(NETC_ETH_LINK_Type *base,
433                                    netc_port_phy_mac_type_t macType,
434                                    netc_port_phy_mac_traffic_statistic_t *statistic)
435 {
436 #if (defined(FSL_FEATURE_NETC_HAS_ERRATA_050679) && FSL_FEATURE_NETC_HAS_ERRATA_050679)
437     uint32_t primask;
438 
439     primask = DisableGlobalIRQ();
440 #endif
441 
442     if (macType == kNETC_ExpressMAC)
443     {
444         statistic->totalOctet             = base->PM0_REOCTN;
445         statistic->validOctet             = base->PM0_ROCTN;
446         statistic->pauseFrame             = base->PM0_RXPFN;
447         statistic->validFrame             = base->PM0_RFRMN;
448         statistic->vlanFrame              = base->PM0_RVLANN;
449         statistic->unicastFrame           = base->PM0_RUCAN;
450         statistic->multicastFrame         = base->PM0_RMCAN;
451         statistic->boradcastFrame         = base->PM0_RBCAN;
452         statistic->totalPacket            = base->PM0_RPKTN;
453         statistic->total64BPacket         = base->PM0_R64N;
454         statistic->total65To127BPacket    = base->PM0_R127N;
455         statistic->total128To255BPacket   = base->PM0_R255N;
456         statistic->total256To511BPacket   = base->PM0_R511N;
457         statistic->total511To1023BPacket  = base->PM0_R1023N;
458         statistic->total1024To1522BPacket = base->PM0_R1522N;
459         statistic->total1523ToMaxBPacket  = base->PM0_R1523XN;
460         statistic->controlPacket          = base->PM0_RCNPN;
461 #if defined(NETC_ETH_LINK_PM0_RMIN63N_RMIN63n_MASK)
462         statistic->rxMinPacket            = base->PM0_RMIN63N;
463 #endif
464     }
465     else if (macType == kNETC_PreemptableMAC)
466     {
467         statistic->totalOctet             = base->PM1_REOCTN;
468         statistic->validOctet             = base->PM1_ROCTN;
469         statistic->pauseFrame             = base->PM1_RXPFN;
470         statistic->validFrame             = base->PM1_RFRMN;
471         statistic->vlanFrame              = base->PM1_RVLANN;
472         statistic->unicastFrame           = base->PM1_RUCAN;
473         statistic->multicastFrame         = base->PM1_RMCAN;
474         statistic->boradcastFrame         = base->PM1_RBCAN;
475         statistic->totalPacket            = base->PM1_RPKTN;
476         statistic->total64BPacket         = base->PM1_R64N;
477         statistic->total65To127BPacket    = base->PM1_R127N;
478         statistic->total128To255BPacket   = base->PM1_R255N;
479         statistic->total256To511BPacket   = base->PM1_R511N;
480         statistic->total511To1023BPacket  = base->PM1_R1023N;
481         statistic->total1024To1522BPacket = base->PM1_R1522N;
482         statistic->total1523ToMaxBPacket  = base->PM1_R1523XN;
483         statistic->controlPacket          = base->PM1_RCNPN;
484 #if defined(NETC_ETH_LINK_PM1_RMIN63N_RMIN63n_MASK)
485         statistic->rxMinPacket            = base->PM1_RMIN63N;
486 #endif
487     }
488     else
489     {
490         ; /* Intentional empty */
491     }
492 
493 #if (defined(FSL_FEATURE_NETC_HAS_ERRATA_050679) && FSL_FEATURE_NETC_HAS_ERRATA_050679)
494     EnableGlobalIRQ(primask);
495 #endif
496 }
497 
NETC_PortGetPhyMacDiscardStatistic(NETC_ETH_LINK_Type * base,netc_port_phy_mac_type_t macType,netc_port_phy_mac_discard_statistic_t * statistic)498 void NETC_PortGetPhyMacDiscardStatistic(NETC_ETH_LINK_Type *base,
499                                         netc_port_phy_mac_type_t macType,
500                                         netc_port_phy_mac_discard_statistic_t *statistic)
501 {
502 #if (defined(FSL_FEATURE_NETC_HAS_ERRATA_050679) && FSL_FEATURE_NETC_HAS_ERRATA_050679)
503     uint32_t primask;
504 
505     primask = DisableGlobalIRQ();
506 #endif
507     if (macType == kNETC_ExpressMAC)
508     {
509         statistic->rxError              = base->PM0_RERRN;
510         statistic->rxUndersized         = base->PM0_RUNDN;
511         statistic->rxOversized          = base->PM0_ROVRN;
512         statistic->rxErrorFCS           = base->PM0_RFCSN;
513         statistic->rxFragment           = base->PM0_RFRGN;
514         statistic->rxJabber             = base->PM0_RJBRN;
515         statistic->rxDiscard            = base->PM0_RDRPN;
516         statistic->rxDiscardNoTruncated = base->PM0_RDRNTPN;
517         statistic->txErrorFCS           = base->PM0_TERRN;
518         statistic->txUndersized         = base->PM0_TUNDN;
519     }
520     else if (macType == kNETC_PreemptableMAC)
521     {
522         statistic->rxError              = base->PM1_RERRN;
523         statistic->rxUndersized         = base->PM1_RUNDN;
524         statistic->rxOversized          = base->PM1_ROVRN;
525         statistic->rxErrorFCS           = base->PM1_RFCSN;
526         statistic->rxFragment           = base->PM1_RFRGN;
527         statistic->rxJabber             = base->PM1_RJBRN;
528         statistic->rxDiscard            = base->PM1_RDRPN;
529         statistic->rxDiscardNoTruncated = base->PM1_RDRNTPN;
530         statistic->txErrorFCS           = base->PM1_TERRN;
531         statistic->txUndersized         = base->PM1_TUNDN;
532     }
533     else
534     {
535         ; /* Intentional empty */
536     }
537 #if (defined(FSL_FEATURE_NETC_HAS_ERRATA_050679) && FSL_FEATURE_NETC_HAS_ERRATA_050679)
538     EnableGlobalIRQ(primask);
539 #endif
540 }
541 
NETC_PortGetPhyMacPreemptionStatistic(NETC_ETH_LINK_Type * base,netc_port_phy_mac_preemption_statistic_t * statistic)542 void NETC_PortGetPhyMacPreemptionStatistic(NETC_ETH_LINK_Type *base,
543                                            netc_port_phy_mac_preemption_statistic_t *statistic)
544 {
545     statistic->rxReassembledFrame = base->MAC_MERGE_MMFAOCR;
546 #if defined(FSL_FEATURE_NETC_HAS_ERRATA_051707) && FSL_FEATURE_NETC_HAS_ERRATA_051707
547     /* ERRATA051707: The host that is reading MAC_MERGE_MMFAECR register should check status of PM1_RFCS. If the PM1_RFCS indicates no
548        error then MAC_MERGE_MMFAECR is valid and can be used if on other hand there is an error reported in PM1_RFCS register
549        then MAC_MERGE_MMFAECR might be incorrect and should be treated accordingly. */
550     statistic->rxReassembledError = (base->PM1_RFCSN == 0U) ? base->MAC_MERGE_MMFAECR : 0U;
551 #else
552     statistic->rxReassembledError = base->MAC_MERGE_MMFAECR;
553 #endif
554     statistic->rxMPacket          = base->MAC_MERGE_MMFCRXR;
555     statistic->rxSMDError         = base->MAC_MERGE_MMFSECR;
556     statistic->txPreemptionReq    = base->MAC_MERGE_MMHCR;
557     statistic->txMPacket          = base->MAC_MERGE_MMFCTXR;
558 }
559 
560 #if !(defined(FSL_FEATURE_NETC_HAS_NO_SWITCH) && FSL_FEATURE_NETC_HAS_NO_SWITCH)
NETC_PortGetPseudoMacTrafficStatistic(NETC_PSEUDO_LINK_Type * base,bool getTx,netc_port_pseudo_mac_traffic_statistic_t * statistic)561 void NETC_PortGetPseudoMacTrafficStatistic(NETC_PSEUDO_LINK_Type *base,
562                                            bool getTx,
563                                            netc_port_pseudo_mac_traffic_statistic_t *statistic)
564 {
565 #if (defined(FSL_FEATURE_NETC_HAS_ERRATA_050679) && FSL_FEATURE_NETC_HAS_ERRATA_050679)
566     uint32_t primask;
567 
568     primask = DisableGlobalIRQ();
569 #endif
570     if (getTx)
571     {
572         statistic->totalOctet     = ((uint64_t)base->PPMTOCR[1] << 32U) | base->PPMTOCR[0];
573         statistic->unicastFrame   = ((uint64_t)base->PPMTUFCR[1] << 32U) | base->PPMTUFCR[0];
574         statistic->multicastFrame = ((uint64_t)base->PPMTMFCR[1] << 32U) | base->PPMTMFCR[0];
575         statistic->boradcastFrame = ((uint64_t)base->PPMTBFCR[1] << 32U) | base->PPMTBFCR[0];
576     }
577     else
578     {
579         statistic->totalOctet     = ((uint64_t)base->PPMROCR[1] << 32U) | base->PPMROCR[0];
580         statistic->unicastFrame   = ((uint64_t)base->PPMRUFCR[1] << 32U) | base->PPMRUFCR[0];
581         statistic->multicastFrame = ((uint64_t)base->PPMRMFCR[1] << 32U) | base->PPMRMFCR[0];
582         statistic->boradcastFrame = ((uint64_t)base->PPMRBFCR[1] << 32U) | base->PPMRBFCR[0];
583     }
584 #if (defined(FSL_FEATURE_NETC_HAS_ERRATA_050679) && FSL_FEATURE_NETC_HAS_ERRATA_050679)
585     EnableGlobalIRQ(primask);
586 #endif
587 }
588 #endif
589 
NETC_PortConfigTcCBS(NETC_PORT_Type * base,netc_hw_tc_idx_t tcIdx,const netc_port_tc_cbs_config_t * config)590 status_t NETC_PortConfigTcCBS(NETC_PORT_Type *base, netc_hw_tc_idx_t tcIdx, const netc_port_tc_cbs_config_t *config)
591 {
592     status_t result = kStatus_Success;
593     uint8_t usedBw  = 0U;
594     uint8_t index;
595 
596     for (index = (uint8_t)kNETC_TxTC0; index <= (uint8_t)kNETC_TxTC7; index++)
597     {
598         if (index == (uint8_t)tcIdx)
599         {
600             continue;
601         }
602 
603         if (0U != (base->TCT_NUM[index].PTCCBSR0 & NETC_PORT_PTCCBSR0_CBSE_MASK))
604         {
605             usedBw += (uint8_t)(base->TCT_NUM[index].PTCCBSR0 & NETC_PORT_PTCCBSR0_BW_MASK);
606         }
607     }
608 
609     if ((usedBw + config->bwWeight) <= 100U)
610     {
611         base->TCT_NUM[tcIdx].PTCCBSR0 = NETC_PORT_PTCCBSR0_BW(config->bwWeight) | NETC_PORT_PTCCBSR0_CBSE_MASK;
612         base->TCT_NUM[tcIdx].PTCCBSR1 = NETC_PORT_PTCCBSR1_HI_CREDIT(config->hiCredit);
613     }
614     else
615     {
616         /* The sum of all traffic class credit-based shaper's bandwidth cannot execeed 100 */
617         result = kStatus_Fail;
618     }
619 
620     return result;
621 }
622 
NETC_PortEthMacGracefulStop(NETC_PORT_Type * base)623 void NETC_PortEthMacGracefulStop(NETC_PORT_Type *base)
624 {
625     NETC_ETH_LINK_Type *eth = (NETC_ETH_LINK_Type *)((uintptr_t)base + 0x1000U);
626     bool hasPM1             = 0U != (eth->MAC_MERGE_MMCSR & NETC_ETH_LINK_MAC_MERGE_MMCSR_ME_MASK);
627 
628     /* In order to stop receive */
629     eth->PM0_COMMAND_CONFIG &= ~NETC_ETH_LINK_PM0_COMMAND_CONFIG_RX_EN_MASK;
630     while (0U == (eth->PM0_IEVENT & NETC_ETH_LINK_PM0_IEVENT_RX_EMPTY_MASK))
631     {
632     }
633     if (hasPM1)
634     {
635         eth->PM1_COMMAND_CONFIG &= ~NETC_ETH_LINK_PM1_COMMAND_CONFIG_RX_EN_MASK;
636         while (0U == (eth->PM1_IEVENT & NETC_ETH_LINK_PM1_IEVENT_RX_EMPTY_MASK))
637         {
638         }
639     }
640     while (0U != (base->PSR & NETC_PORT_PSR_RX_BUSY_MASK))
641     {
642     }
643     base->POR |= NETC_PORT_POR_RXDIS_MASK;
644 
645     /* In order to stop transmit */
646     base->POR |= NETC_PORT_POR_TXDIS_MASK;
647     while (0U == (eth->PM0_IEVENT & NETC_ETH_LINK_PM0_IEVENT_TX_EMPTY_MASK))
648     {
649     }
650     if (hasPM1)
651     {
652         while (0U == (eth->PM1_IEVENT & NETC_ETH_LINK_PM1_IEVENT_TX_EMPTY_MASK))
653         {
654         }
655     }
656     /* Wait 64 byte time for Tx packet transmission to complete.  */
657     SDK_DelayAtLeastUs(512, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
658     eth->PM0_COMMAND_CONFIG &= ~NETC_ETH_LINK_PM0_COMMAND_CONFIG_TX_EN_MASK;
659     if (hasPM1)
660     {
661         eth->PM1_COMMAND_CONFIG &= ~NETC_ETH_LINK_PM1_COMMAND_CONFIG_TX_EN_MASK;
662     }
663 }
664