1 /*
2  * Copyright 2021-2022, 2024 NXP
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include "fsl_netc_hw_si.h"
8 
NETC_SIConfigTxBDR(ENETC_SI_Type * base,uint8_t ring,const netc_tx_bdr_config_t * bdrConfig)9 status_t NETC_SIConfigTxBDR(ENETC_SI_Type *base, uint8_t ring, const netc_tx_bdr_config_t *bdrConfig)
10 {
11     uint64_t address;
12 
13     /* Set the MSIX entry index triggered when interrupt occurs. */
14     base->SIMSITRVR[ring] = bdrConfig->msixEntryIdx;
15 
16     /* Map function only supports 32-bit now, so here limit 32-bit first */
17     address = (uintptr_t)bdrConfig->bdArray;
18 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
19     address = (uint64_t)MEMORY_ConvertMemoryMapAddress((uintptr_t)address, kMEMORY_Local2DMA);
20 #endif
21 
22     /* Set the tx descriptor start/tail pointer, shall be word aligned. */
23     base->BDR[ring].TBBAR0 = NETC_ADDR_LOW_32BIT(address);
24     base->BDR[ring].TBBAR1 = NETC_ADDR_HIGH_32BIT(address);
25     base->BDR[ring].TBPIR  = 0;
26     base->BDR[ring].TBCIR  = 0;
27     base->BDR[ring].TBLENR = ENETC_SI_TBLENR_LENGTH((uint32_t)bdrConfig->len / 8U);
28     base->BDR[ring].TBIER  = ENETC_SI_TBIER_TXFIE(bdrConfig->enIntr) | ENETC_SI_TBIER_TXTIE(bdrConfig->enThresIntr);
29     base->BDR[ring].TBMR   = ENETC_SI_TBMR_EN_MASK | ENETC_SI_TBMR_WRR(bdrConfig->wrrWeight) |
30                            ENETC_SI_TBMR_PRIO(bdrConfig->priority) | ENETC_SI_TBMR_VIH(bdrConfig->isVlanInsert);
31 
32     return kStatus_Success;
33 }
34 
NETC_SIConfigRxBDR(ENETC_SI_Type * base,uint8_t ring,const netc_rx_bdr_config_t * bdrConfig)35 status_t NETC_SIConfigRxBDR(ENETC_SI_Type *base, uint8_t ring, const netc_rx_bdr_config_t *bdrConfig)
36 {
37     uint64_t address;
38 
39     /* The BD ring length should be multiple of 8/16 according to whether extended descriptor is enabled. */
40     /* Maximun BD number is 64K. */
41     if ((bdrConfig->extendDescEn && (((bdrConfig->len & 0xFU) != 0U) || ((bdrConfig->len / 2U) > 65536U))) ||
42         ((!bdrConfig->extendDescEn) && (((bdrConfig->len & 0x7U) != 0U) || (bdrConfig->len > 65536U))))
43     {
44         return kStatus_InvalidArgument;
45     }
46 
47     /* Minimum buffer size is 128 bytes. */
48     if (bdrConfig->buffSize < 128U)
49     {
50         return kStatus_InvalidArgument;
51     }
52 
53     /* Set the MSIX entry index triggered when interrupt occurs. */
54     base->SIMSIRRVR[ring] = bdrConfig->msixEntryIdx;
55 
56     /* Map function only supports 32-bit now, so here limit 32-bit first */
57     address = (uintptr_t)bdrConfig->bdArray;
58 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
59     address = (uint64_t)MEMORY_ConvertMemoryMapAddress((uintptr_t)address, kMEMORY_Local2DMA);
60 #endif
61 
62     /* Set the Rx descriptor address, shall be word aligned. */
63     base->BDR[ring].RBBAR0 = NETC_ADDR_LOW_32BIT(address);
64     base->BDR[ring].RBBAR1 = NETC_ADDR_HIGH_32BIT(address);
65     base->BDR[ring].RBBSR  = bdrConfig->buffSize;
66     base->BDR[ring].RBPIR  = 0;
67     base->BDR[ring].RBCIR  = 0;
68     base->BDR[ring].RBLENR = bdrConfig->extendDescEn ? (bdrConfig->len / 2U) : bdrConfig->len;
69     base->BDR[ring].RBIER  = ENETC_SI_RBIER_RXTIE(bdrConfig->enThresIntr);
70     base->BDR[ring].RBICR0 =
71         ENETC_SI_RBICR0_ICEN(bdrConfig->enCoalIntr) | ENETC_SI_RBICR0_ICPT(bdrConfig->intrThreshold);
72     base->BDR[ring].RBICR1 = ENETC_SI_RBICR1_ICTT(bdrConfig->intrTimerThres);
73     base->BDR[ring].RBMR   = ENETC_SI_RBMR_CRC(bdrConfig->isKeepCRC) | ENETC_SI_RBMR_BDS(bdrConfig->extendDescEn) |
74                            ENETC_SI_RBMR_CM(bdrConfig->congestionMode) | ENETC_SI_RBMR_AL(bdrConfig->enHeaderAlign) |
75                            ENETC_SI_RBMR_VTPD(bdrConfig->disVlanPresent) | ENETC_SI_RBMR_VTE(bdrConfig->enVlanExtract);
76 
77     return kStatus_Success;
78 }
79 
NETC_SIPsiEnableInterrupt(ENETC_SI_Type * base,uint32_t mask,bool enable)80 void NETC_SIPsiEnableInterrupt(ENETC_SI_Type *base, uint32_t mask, bool enable)
81 {
82     if (enable)
83     {
84         base->PSI.PSIIER |= mask;
85     }
86     else
87     {
88         base->PSI.PSIIER &= ~mask;
89     }
90 }
91 
NETC_SIPsiSendMsg(ENETC_SI_Type * base,uint16_t msg,netc_vsi_number_t vsi)92 status_t NETC_SIPsiSendMsg(ENETC_SI_Type *base, uint16_t msg, netc_vsi_number_t vsi)
93 {
94     status_t result;
95 
96     if (NETC_SIPsiCheckTxBusy(base, vsi))
97     {
98         result = kStatus_Busy;
99     }
100     else
101     {
102         base->PSI_A.PSIMSGSR = ENETC_SI_PSIMSGSR_MC(msg) | (uint32_t)vsi;
103         result               = kStatus_Success;
104     }
105     return result;
106 }
107 
NETC_SIPsiSetRxBuffer(ENETC_SI_Type * base,netc_vsi_number_t vsi,uint64_t buffAddr)108 status_t NETC_SIPsiSetRxBuffer(ENETC_SI_Type *base, netc_vsi_number_t vsi, uint64_t buffAddr)
109 {
110     status_t result  = kStatus_InvalidArgument;
111     uint16_t vsiIdx  = NETC_SIGetVsiIndex(vsi);
112     uint64_t address = buffAddr;
113     bool addrAlign;
114 
115 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
116     address = (uint64_t)MEMORY_ConvertMemoryMapAddress((uintptr_t)address, kMEMORY_Local2DMA);
117 #endif
118     addrAlign = (address & 0x3FU) == 0U;
119     if (addrAlign)
120     {
121         base->PSI_A.VSI_NUM[vsiIdx].PSIVMSGRCVAR0 = (uint32_t)address & ENETC_SI_PSIVMSGRCVAR0_ADDRL_MASK;
122         base->PSI_A.VSI_NUM[vsiIdx].PSIVMSGRCVAR1 = (uint32_t)(address >> 32U);
123         result                                    = kStatus_Success;
124     }
125     return result;
126 }
127 
NETC_SIPsiGetRxMsg(ENETC_SI_Type * base,netc_vsi_number_t vsi,netc_psi_rx_msg_t * msgInfo)128 status_t NETC_SIPsiGetRxMsg(ENETC_SI_Type *base, netc_vsi_number_t vsi, netc_psi_rx_msg_t *msgInfo)
129 {
130     assert(msgInfo != NULL);
131 
132     status_t result   = kStatus_Fail;
133     uint16_t siBitMap = (uint16_t)base->PSI_A.PSIMSGRR;
134     uint16_t vsiIdx   = NETC_SIGetVsiIndex(vsi);
135     uint64_t address;
136     uint8_t msgSize;
137     uint32_t addrH;
138     uint32_t addrL;
139 
140     if ((siBitMap & (uint16_t)vsi) != 0U)
141     {
142         addrH   = base->PSI_A.VSI_NUM[vsiIdx].PSIVMSGRCVAR1;
143         addrL   = base->PSI_A.VSI_NUM[vsiIdx].PSIVMSGRCVAR0 & ENETC_SI_PSIVMSGRCVAR0_ADDRL_MASK;
144         address = ((uint64_t)addrH << 32U) + addrL;
145 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
146         address = (uint64_t)MEMORY_ConvertMemoryMapAddress((uintptr_t)address, kMEMORY_DMA2Local);
147 #endif
148         msgInfo->msgBuff = (uint8_t *)(uintptr_t)address;
149         msgSize          = (uint8_t)(base->PSI_A.VSI_NUM[vsiIdx].PSIVMSGRCVAR0 & ENETC_SI_PSIVMSGRCVAR0_MSIZE_MASK);
150         msgInfo->msgLen  = (msgSize == 0U) ? 1024U : (32U * (uint32_t)msgSize);
151 
152         /* Clear specified VSI status, VSI-side Tx busy status will be cleared together. */
153         base->PSI_A.PSIMSGRR = (uint16_t)vsi;
154 
155         result = kStatus_Success;
156     }
157     return result;
158 }
159 
NETC_SIVsiEnableInterrupt(ENETC_SI_Type * base,uint32_t mask,bool enable)160 void NETC_SIVsiEnableInterrupt(ENETC_SI_Type *base, uint32_t mask, bool enable)
161 {
162     if (enable)
163     {
164         base->VSI.VSIIER |= (mask << 8U);
165     }
166     else
167     {
168         base->VSI.VSIIER &= ~(mask << 8U);
169     }
170 }
171 
NETC_SIVsiSendMsg(ENETC_SI_Type * base,uint64_t msgAddr,uint32_t msgLen)172 status_t NETC_SIVsiSendMsg(ENETC_SI_Type *base, uint64_t msgAddr, uint32_t msgLen)
173 {
174     status_t result  = kStatus_InvalidArgument;
175     uint64_t address = msgAddr;
176     uint8_t msgSize;
177     bool addrAlign;
178     bool lenAlign;
179 
180     if ((base->VSI_A.VSIMSGSR & ENETC_SI_VSIMSGSR_MB_MASK) != 0U)
181     {
182         result = kStatus_Busy;
183     }
184     else
185     {
186 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
187         address = (uint64_t)MEMORY_ConvertMemoryMapAddress((uintptr_t)address, kMEMORY_Local2DMA);
188 #endif
189         addrAlign = (address & 0x3FU) == 0U;
190         lenAlign  = (msgLen & 0x1FU) == 0U;
191         if ((msgLen <= 1024U) && addrAlign && lenAlign)
192         {
193             msgSize                  = (uint8_t)((msgLen == 1024U) ? 0U : (msgLen / 32U));
194             base->VSI_A.VSIMSGSNDAR1 = (uint32_t)(address >> 32U);
195             base->VSI_A.VSIMSGSNDAR0 =
196                 ((uint32_t)address & ENETC_SI_VSIMSGSNDAR0_ADDRL_MASK) | ENETC_SI_VSIMSGSNDAR0_MSIZE(msgSize);
197             result = kStatus_Success;
198         }
199     }
200     return result;
201 }
202 
NETC_SIVsiCheckTxStatus(ENETC_SI_Type * base,netc_vsi_msg_tx_status_t * status)203 void NETC_SIVsiCheckTxStatus(ENETC_SI_Type *base, netc_vsi_msg_tx_status_t *status)
204 {
205     assert(status != NULL);
206 
207     uint32_t txStatus = base->VSI_A.VSIMSGSR;
208 
209     status->txBusy  = ((txStatus & ENETC_SI_VSIMSGSR_MB_MASK) != 0U);
210     status->isTxErr = ((txStatus & ENETC_SI_VSIMSGSR_MS_MASK) != 0U);
211     status->msgCode = (uint16_t)((txStatus & ENETC_SI_VSIMSGSR_MC_MASK) >> ENETC_SI_VSIMSGSR_MC_SHIFT);
212 }
213 
NETC_SIVsiReceiveMsg(ENETC_SI_Type * base,uint16_t * msg)214 status_t NETC_SIVsiReceiveMsg(ENETC_SI_Type *base, uint16_t *msg)
215 {
216     status_t result = kStatus_NoData;
217     uint32_t msgData;
218 
219     msgData = base->VSI_A.VSIMSGRR;
220     if ((msgData & ENETC_SI_VSIMSGRR_MR_MASK) != 0U)
221     {
222         *msg   = (uint16_t)((msgData & ENETC_SI_VSIMSGRR_MC_MASK) >> ENETC_SI_VSIMSGRR_MC_SHIFT);
223         result = kStatus_Success;
224     }
225     return result;
226 }
227 
NETC_SIGetDiscardStatistic(ENETC_SI_Type * base,netc_si_discard_statistic_t * statistic)228 void NETC_SIGetDiscardStatistic(ENETC_SI_Type *base, netc_si_discard_statistic_t *statistic)
229 {
230     uint8_t rxRingNum =
231         (uint8_t)((base->SICAPR0 & ENETC_SI_SICAPR0_NUM_RX_BDR_MASK) >> ENETC_SI_SICAPR0_NUM_RX_BDR_SHIFT);
232     assert(rxRingNum <= ARRAY_SIZE(base->BDR));
233 
234     statistic->programError = base->SIUPECTR;
235     statistic->busError     = base->SIUNSBECTR;
236     for (uint32_t i = 0; i < ARRAY_SIZE(statistic->lackBD); i++)
237     {
238         if (i < rxRingNum)
239         {
240             statistic->lackBD[i] = base->BDR[i].RBDCR;
241         }
242         else
243         {
244             statistic->lackBD[i] = 0U;
245         }
246     }
247 }
248 
NETC_SIGetTrafficStatistic(ENETC_SI_Type * base,netc_si_traffic_statistic_t * statistic)249 void NETC_SIGetTrafficStatistic(ENETC_SI_Type *base, netc_si_traffic_statistic_t *statistic)
250 {
251     statistic->rxOctet          = ((uint64_t)base->SIROCT1 << 32U) | base->SIROCT0;
252     statistic->rxFrame          = ((uint64_t)base->SIRFRM1 << 32U) | base->SIRFRM0;
253     statistic->rxFrameUnicast   = ((uint64_t)base->SIRUCA1 << 32U) | base->SIRUCA0;
254     statistic->rxFrameMulticast = ((uint64_t)base->SIRMCA1 << 32U) | base->SIRMCA0;
255     statistic->txOctet          = ((uint64_t)base->SITOCT1 << 32U) | base->SITOCT0;
256     statistic->txFrame          = ((uint64_t)base->SITFRM1 << 32U) | base->SITFRM0;
257     statistic->txFrameUnicast   = ((uint64_t)base->SITUCA1 << 32U) | base->SITUCA0;
258     statistic->txFrameMulticast = ((uint64_t)base->SITMCA1 << 32U) | base->SITMCA0;
259 }
260