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