1 /******************************************************************************\r
2 * Copyright (c) 2019 Texas Instruments Incorporated - http://www.ti.com\r
3 *\r
4 * Redistribution and use in source and binary forms, with or without\r
5 * modification, are permitted provided that the following conditions\r
6 * are met:\r
7 *\r
8 * Redistributions of source code must retain the above copyright\r
9 * notice, this list of conditions and the following disclaimer.\r
10 *\r
11 * Redistributions in binary form must reproduce the above copyright\r
12 * notice, this list of conditions and the following disclaimer in the\r
13 * documentation and/or other materials provided with the\r
14 * distribution.\r
15 *\r
16 * Neither the name of Texas Instruments Incorporated nor the names of\r
17 * its contributors may be used to endorse or promote products derived\r
18 * from this software without specific prior written permission.\r
19 *\r
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\r
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\r
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\r
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
31 *\r
32 *****************************************************************************/\r
33 /**\r
34 * \file cpsw_test.c\r
35 *\r
36 * \brief CPSW9G ethernet diagnostic test file\r
37 *\r
38 * Targeted Functionality: Verification of basic functionality of\r
39 * CPSW9G Ethernet interface.\r
40 *\r
41 * Operation: This is the Loopback test code for the Ethernet Interface.\r
42 * The test code showcases usage of the CPSW Driver exported API for\r
43 * sending/receiving Ethernet packets.\r
44 *\r
45 * Supported SoCs: J721E.\r
46 *\r
47 * Supported Platforms:j721e_evm.\r
48 *\r
49 */\r
50 \r
51 /* Test application local header file */\r
52 #include "cpsw_eth_test.h"\r
53 \r
54 static volatile bool txSem = false;\r
55 static volatile bool rxSem = false;\r
56 \r
57 /* Broadcast address */\r
58 static uint8_t bcastAddr[ETH_MAC_ADDR_LEN] =\r
59 { 0xffU, 0xffU, 0xffU, 0xffU, 0xffU, 0xffU };\r
60 \r
61 /* CPSW configuration */\r
62 static CpswDma_OpenTxChPrms cpswTxChCfg;\r
63 \r
64 static CpswDma_OpenRxFlowPrms cpswRxFlowCfg;\r
65 \r
66 static cpsw_Obj gCpswLpbkObj = {\r
67 .cpswType = CPSW_9G,\r
68 };\r
69 \r
70 /**\r
71 * \brief CPSW receive ISR function\r
72 *\r
73 * \param hUdmaEvt [IN] UDMA event handle\r
74 * \param eventType [IN] Event type\r
75 * \param appData [IN] Pointer to application data\r
76 *\r
77 */\r
78 static void BoardDiag_cpswRxIsrFxn(void *appData)\r
79 {\r
80 rxSem = true;\r
81 }\r
82 \r
83 /**\r
84 * \brief CPSW transmit ISR function\r
85 *\r
86 * \param hUdmaEvt [IN] UDMA event handle\r
87 * \param eventType [IN] Event type\r
88 * \param appData [IN] Pointer to application data\r
89 *\r
90 */\r
91 static void BoardDiag_cpswTxIsrFxn(void *appData)\r
92 {\r
93 txSem = true;\r
94 }\r
95 \r
96 /**\r
97 * \brief This function is used to queue the received packets to rx ready queue\r
98 *\r
99 * \return uint32_t - Receive ready queue count\r
100 *\r
101 */\r
102 static uint32_t BoardDiag_cpswReceivePkts(void)\r
103 {\r
104 CpswDma_PktInfoQ rxReadyQ;\r
105 CpswDma_PktInfo *pktInfo;\r
106 int32_t status;\r
107 uint32_t rxReadyCnt = 0U;\r
108 \r
109 CpswUtils_initQ(&rxReadyQ);\r
110 \r
111 /* Retrieve any CPSW packets which are ready */\r
112 status = CpswDma_retrieveRxPackets(gCpswLpbkObj.hRxFlow, &rxReadyQ);\r
113 if (status == CPSW_SOK)\r
114 {\r
115 rxReadyCnt = CpswUtils_getQCount(&rxReadyQ);\r
116 /* Queue the received packet to rxReadyQ and pass new ones from rxFreeQ\r
117 **/\r
118 pktInfo = (CpswDma_PktInfo *) CpswUtils_deQ(&rxReadyQ);\r
119 while (pktInfo != NULL)\r
120 {\r
121 CpswUtils_checkPktState(&pktInfo->pktState,\r
122 CPSW_PKTSTATE_MODULE_APP,\r
123 CPSW_PKTSTATE_APP_WITH_DRIVER,\r
124 CPSW_PKTSTATE_APP_WITH_READYQ);\r
125 \r
126 CpswUtils_enQ(&gCpswLpbkObj.rxReadyQ, &pktInfo->node);\r
127 pktInfo = (CpswDma_PktInfo *) CpswUtils_deQ(&rxReadyQ);\r
128 }\r
129 }\r
130 else\r
131 {\r
132 UART_printf("receivePkts() failed to retrieve pkts: %d\n",\r
133 status);\r
134 }\r
135 \r
136 return rxReadyCnt;\r
137 }\r
138 \r
139 /**\r
140 * \brief This function is used to retrieve's any CPSW packets that may be free now\r
141 *\r
142 * \return uint32_t - Transmit free queue count\r
143 *\r
144 */\r
145 static uint32_t BoardDiag_cpswRetrieveFreeTxPkts(void)\r
146 {\r
147 CpswDma_PktInfoQ txFreeQ;\r
148 CpswDma_PktInfo *pktInfo;\r
149 int32_t status;\r
150 uint32_t txFreeQCnt = 0U;\r
151 \r
152 CpswUtils_initQ(&txFreeQ);\r
153 \r
154 /* Retrieve any CPSW packets that may be free now */\r
155 status = CpswDma_retrieveTxDonePackets(gCpswLpbkObj.hTxCh, &txFreeQ);\r
156 if (status == CPSW_SOK)\r
157 {\r
158 txFreeQCnt = CpswUtils_getQCount(&txFreeQ);\r
159 \r
160 pktInfo = (CpswDma_PktInfo *) CpswUtils_deQ(&txFreeQ);\r
161 while (pktInfo != NULL)\r
162 {\r
163 CpswUtils_checkPktState(&pktInfo->pktState,\r
164 CPSW_PKTSTATE_MODULE_APP,\r
165 CPSW_PKTSTATE_APP_WITH_DRIVER,\r
166 CPSW_PKTSTATE_APP_WITH_FREEQ);\r
167 \r
168 CpswUtils_enQ(&gCpswLpbkObj.txFreePktInfoQ, &pktInfo->node);\r
169 pktInfo = (CpswDma_PktInfo *) CpswUtils_deQ(&txFreeQ);\r
170 }\r
171 }\r
172 else\r
173 {\r
174 UART_printf("retrieveFreeTxPkts() failed to retrieve pkts: %d\n",\r
175 status);\r
176 }\r
177 \r
178 return txFreeQCnt;\r
179 }\r
180 \r
181 /**\r
182 * \brief CPSW delay function\r
183 *\r
184 * \param waitTime [IN] Wait time\r
185 *\r
186 */\r
187 static void BoardDiag_cpswWait(uint32_t waitTime)\r
188 {\r
189 volatile uint32_t index;\r
190 \r
191 /* we multiply waitTime by 10000 as 400MHz R5 takes 2.5ns for single cycle\r
192 * and we assume for loop takes 4 cycles */\r
193 for (index = 0; index < (waitTime*10000); index++);\r
194 }\r
195 \r
196 /**\r
197 * \brief This function is used to initialize the receive ready packet queue\r
198 *\r
199 * \return int8_t\r
200 * 0 - in case of success\r
201 * -1 - in case of failure.\r
202 *\r
203 */\r
204 static int8_t boarDiag_cpswInitRxReadyPktQ(void)\r
205 {\r
206 CpswDma_PktInfoQ rxReadyQ;\r
207 int32_t status;\r
208 uint32_t index;\r
209 CpswDma_PktInfo *pPktInfo;\r
210 \r
211 CpswUtils_initQ(&gCpswLpbkObj.rxFreeQ);\r
212 CpswUtils_initQ(&gCpswLpbkObj.rxReadyQ);\r
213 CpswUtils_initQ(&rxReadyQ);\r
214 \r
215 for (index = 0U; index < CPSW_APPMEMUTILS_NUM_RX_PKTS; index++)\r
216 {\r
217 pPktInfo = CpswAppMemUtils_allocEthPktFxn(&gCpswLpbkObj,\r
218 CPSW_APPMEMUTILS_LARGE_POOL_PKT_SIZE,\r
219 UDMA_CACHELINE_ALIGNMENT);\r
220 if(pPktInfo == NULL)\r
221 {\r
222 UART_printf("\n"); \r
223 }\r
224 CPSW_UTILS_SET_PKT_APP_STATE(&pPktInfo->pktState,\r
225 CPSW_PKTSTATE_APP_WITH_FREEQ);\r
226 CpswUtils_enQ(&gCpswLpbkObj.rxFreeQ,\r
227 &pPktInfo->node);\r
228 }\r
229 \r
230 /* Retrieve any CPSW packets which are ready */\r
231 status = CpswDma_retrieveRxPackets(gCpswLpbkObj.hRxFlow,\r
232 &rxReadyQ);\r
233 if( status != CPSW_SOK )\r
234 {\r
235 UART_printf("Failed to retrive the CPSW RX packets\n");\r
236 return -1;\r
237 }\r
238 \r
239 /* There should not be any packet with DMA during init */\r
240 if(CpswUtils_getQCount(&rxReadyQ) != 0U )\r
241 {\r
242 UART_printf("rxReadyQ is not zero,...Exiting\n");\r
243 return -1; \r
244 }\r
245 \r
246 CpswAppUtils_validatePacketState(&gCpswLpbkObj.rxFreeQ,\r
247 CPSW_PKTSTATE_APP_WITH_FREEQ,\r
248 CPSW_PKTSTATE_APP_WITH_DRIVER);\r
249 \r
250 CpswAppUtils_submitRxPackets(gCpswLpbkObj.hRxFlow,\r
251 &gCpswLpbkObj.rxFreeQ);\r
252 /* Assert here as during init no. of DMA descriptors should be equal to\r
253 * no. of free Ethernet buffers available with app */\r
254 \r
255 if(CpswUtils_getQCount(&gCpswLpbkObj.rxFreeQ) != 0)\r
256 {\r
257 UART_printf("rxFreeQ is not '0',...Exiting\n");\r
258 return -1;\r
259 }\r
260 \r
261 return 0;\r
262 }\r
263 \r
264 /**\r
265 * \brief This function is used to initialize the free packet\r
266 * info queue with the Ethernet packets to be transmitted.\r
267 *\r
268 * \return int8_t\r
269 * 0 - in case of success\r
270 * -1 - in case of failure.\r
271 *\r
272 */\r
273 static int8_t BoardDiag_cpswInitTxFreePktQ(void)\r
274 {\r
275 CpswDma_PktInfo *pktInfo;\r
276 uint32_t index;\r
277 \r
278 /* Initialize all queues */\r
279 CpswUtils_initQ(&gCpswLpbkObj.txFreePktInfoQ);\r
280 \r
281 /* Initialize TX EthPkts and queue them to txFreePktInfoQ */\r
282 for(index = 0U; index < CPSWAPPUTILS_ARRAY_SIZE(gCpswLpbkObj.txFreePktInfo); index++)\r
283 {\r
284 pktInfo = &gCpswLpbkObj.txFreePktInfo[index];\r
285 if(pktInfo == NULL)\r
286 {\r
287 return -1;\r
288 }\r
289 \r
290 CpswDma_pktInfoInit(pktInfo);\r
291 \r
292 memset (&pktInfo->node, 0U, sizeof(pktInfo->node));\r
293 pktInfo->bufPtr = (uint8_t *)&gCpswLpbkObj.txBufMem[index][0U];\r
294 pktInfo->orgBufLen = ETH_MAX_FRAME_LEN;\r
295 pktInfo->userBufLen = ETH_MAX_FRAME_LEN;\r
296 pktInfo->appPriv = NULL;\r
297 \r
298 CPSW_UTILS_SET_PKT_APP_STATE(&pktInfo->pktState,\r
299 CPSW_PKTSTATE_APP_WITH_FREEQ);\r
300 \r
301 CpswUtils_enQ(&gCpswLpbkObj.txFreePktInfoQ,\r
302 &pktInfo->node);\r
303 }\r
304 \r
305 UART_printf("initQs() txFreePktInfoQ initialized with %d pkts\n",\r
306 CpswUtils_getQCount(&gCpswLpbkObj.txFreePktInfoQ));\r
307 return 0;\r
308 }\r
309 \r
310 /**\r
311 * \brief This function is used to set the ALE port state to forward.\r
312 *\r
313 * \param macAddr [IN] host MAC address\r
314 *\r
315 * \return int32_t\r
316 * 0 - in case of success\r
317 * -1 - in case of failure.\r
318 *\r
319 */\r
320 static int32_t BoardDiag_cpswChangeHostAleEntry(uint8_t macAddr[])\r
321 {\r
322 int32_t status;\r
323 Cpsw_IoctlPrms prms;\r
324 CpswAle_AddEntryOutArgs setUcastOutArgs;\r
325 CpswAle_SetUcastEntryInArgs setUcastInArgs;\r
326 \r
327 memcpy(&setUcastInArgs.addr.addr[0U],\r
328 macAddr,\r
329 sizeof(setUcastInArgs.addr.addr));\r
330 \r
331 setUcastInArgs.addr.vlanId = 0U;\r
332 setUcastInArgs.info.portNum = 0U;\r
333 setUcastInArgs.info.blocked = false;\r
334 setUcastInArgs.info.secure = false;\r
335 setUcastInArgs.info.super = 0U;\r
336 setUcastInArgs.info.ageable = false;\r
337 \r
338 \r
339 CPSW_IOCTL_SET_INOUT_ARGS(&prms,\r
340 &setUcastInArgs,\r
341 &setUcastOutArgs);\r
342 \r
343 status = Cpsw_ioctl(gCpswLpbkObj.hCpsw,\r
344 gCpswLpbkObj.coreId,\r
345 CPSW_ALE_IOCTL_ADD_UNICAST,\r
346 &prms);\r
347 if (status != CPSW_SOK)\r
348 {\r
349 UART_printf("Setting the ALE port state to forward failed with error status - %d\n\r", status);\r
350 return status;\r
351 }\r
352 \r
353 return status;\r
354 }\r
355 \r
356 /**\r
357 * \brief This function is used for converting the virtual address\r
358 * to physical address\r
359 *\r
360 * \param virtAddr [IN/OUT] Pointer to virtual address\r
361 * \param appData [IN] Pointer to application data\r
362 *\r
363 * \return uint64_t - CPSW physical address\r
364 *\r
365 */\r
366 static uint64_t BoardDiag_cpswvirtToPhyFx(const void *virtAddr,\r
367 void *appData)\r
368 {\r
369 return ((uint64_t)virtAddr);\r
370 }\r
371 \r
372 /**\r
373 * \brief This function is used for converting the physical address\r
374 * to virtual address\r
375 *\r
376 * \param phyAddr [IN] Pointer to physical address\r
377 * \param appData [IN] Pointer to application data\r
378 *\r
379 * \return void - Pointer to virtual address\r
380 *\r
381 */\r
382 static void *BoardDiag_cpswPhyToVirtFxn(uint64_t phyAddr,\r
383 void *appData)\r
384 {\r
385 #if defined (__aarch64__)\r
386 uint64_t temp = phyAddr;\r
387 #else\r
388 /* R5 is 32-bit machine, need to truncate to avoid void * typecast error */\r
389 uint32_t temp = (uint32_t)phyAddr;\r
390 #endif\r
391 return ((void *) temp);\r
392 }\r
393 \r
394 /**\r
395 * \brief This function is used for initialize the ALE submodule.\r
396 *\r
397 * \param aleConfig [IN] Pointer to ALE configuration structure\r
398 *\r
399 */\r
400 static void BoardDiag_cpswInitAleConfig(CpswAle_Config *aleConfig)\r
401 {\r
402 aleConfig->modeFlags =\r
403 (CPSW_ALE_CONFIG_MASK_ALE_MODULE_ENABLE);\r
404 aleConfig->agingConfig.enableAutoAging = TRUE;\r
405 aleConfig->agingConfig.agingPeriodInMs = 1000;\r
406 aleConfig->nwSecCfg.enableVid0Mode = TRUE;\r
407 aleConfig->vlanConfig.aleVlanAwareMode = FALSE;\r
408 aleConfig->vlanConfig.cpswVlanAwareMode = FALSE;\r
409 aleConfig->vlanConfig.unknownUnregMcastFloodMask = CPSW_ALE_ALL_PORTS_MASK;\r
410 aleConfig->vlanConfig.unknownRegMcastFloodMask = CPSW_ALE_ALL_PORTS_MASK;\r
411 aleConfig->vlanConfig.unknownVlanMemberListMask = CPSW_ALE_ALL_PORTS_MASK;\r
412 }\r
413 \r
414 /**\r
415 * \brief This function is used for de-initialize the CPSW module.\r
416 *\r
417 */\r
418 void BoardDiag_cpswClose(void)\r
419 {\r
420 int32_t status;\r
421 Cpsw_IoctlPrms prms;\r
422 \r
423 Cpsw_GenericPortLinkInArgs args0 = {\r
424 .portNum = gCpswLpbkObj.portNum0,\r
425 };\r
426 \r
427 \r
428 Cpsw_GenericPortLinkInArgs args1 = {\r
429 .portNum = gCpswLpbkObj.portNum1,\r
430 };\r
431 \r
432 CPSW_IOCTL_SET_IN_ARGS(&prms,\r
433 &gCpswLpbkObj.coreKey);\r
434 \r
435 status = Cpsw_ioctl(gCpswLpbkObj.hCpsw,\r
436 gCpswLpbkObj.coreId,\r
437 CPSW_IOCTL_DETACH_CORE,\r
438 &prms);\r
439 if (status != CPSW_SOK)\r
440 {\r
441 UART_printf("close() failed to close MAC port: %d\n", status);\r
442 }\r
443 \r
444 CPSW_IOCTL_SET_IN_ARGS(&prms, &args0);\r
445 status = Cpsw_ioctl(gCpswLpbkObj.hCpsw,\r
446 gCpswLpbkObj.coreId,\r
447 CPSW_IOCTL_CLOSE_PORT_LINK,\r
448 &prms);\r
449 if (status != CPSW_SOK)\r
450 {\r
451 UART_printf("close() failed to close MAC port0: %d\n", status);\r
452 }\r
453 \r
454 CPSW_IOCTL_SET_IN_ARGS(&prms, &args1);\r
455 status = Cpsw_ioctl(gCpswLpbkObj.hCpsw,\r
456 gCpswLpbkObj.coreId,\r
457 CPSW_IOCTL_CLOSE_PORT_LINK,\r
458 &prms);\r
459 if (status != CPSW_SOK)\r
460 {\r
461 UART_printf("close() failed to close MAC port1: %d\n", status);\r
462 }\r
463 \r
464 Cpsw_close(gCpswLpbkObj.hCpsw);\r
465 \r
466 Cpsw_deinit(gCpswLpbkObj.cpswType);\r
467 }\r
468 \r
469 \r
470 /**\r
471 * \brief This function is used for de-initialize the CPSW DMA driver.\r
472 *\r
473 */\r
474 void BoardDiag_cpswCloseDma(void)\r
475 {\r
476 CpswDma_PktInfoQ fqPktInfoQ;\r
477 CpswDma_PktInfoQ cqPktInfoQ;\r
478 \r
479 CpswUtils_initQ(&fqPktInfoQ);\r
480 CpswUtils_initQ(&cqPktInfoQ);\r
481 \r
482 /* Close RX Flow */\r
483 CpswAppUtils_closeRxFlow(gCpswLpbkObj.hCpsw,\r
484 gCpswLpbkObj.coreKey,\r
485 gCpswLpbkObj.coreId,\r
486 true,\r
487 &fqPktInfoQ,\r
488 &cqPktInfoQ,\r
489 gCpswLpbkObj.rxStartFlowIdx,\r
490 gCpswLpbkObj.rxFlowIdx,\r
491 gCpswLpbkObj.hostMacAddr,\r
492 gCpswLpbkObj.hRxFlow);\r
493 \r
494 CpswAppUtils_freePktInfoQ(&fqPktInfoQ);\r
495 CpswAppUtils_freePktInfoQ(&cqPktInfoQ);\r
496 \r
497 /* Close TX channel */\r
498 CpswUtils_initQ(&fqPktInfoQ);\r
499 CpswUtils_initQ(&cqPktInfoQ);\r
500 \r
501 CpswAppUtils_closeTxCh(gCpswLpbkObj.hCpsw,\r
502 gCpswLpbkObj.coreKey,\r
503 gCpswLpbkObj.coreId,\r
504 &fqPktInfoQ,\r
505 &cqPktInfoQ,\r
506 gCpswLpbkObj.hTxCh,\r
507 gCpswLpbkObj.txChNum);\r
508 \r
509 CpswAppUtils_freePktInfoQ(&fqPktInfoQ);\r
510 CpswAppUtils_freePktInfoQ(&cqPktInfoQ);\r
511 \r
512 CpswAppUtils_freePktInfoQ(&gCpswLpbkObj.rxFreeQ);\r
513 CpswAppUtils_freePktInfoQ(&gCpswLpbkObj.txFreePktInfoQ);\r
514 \r
515 CpswAppMemUtils_deInit();\r
516 }\r
517 \r
518 /**\r
519 * \brief This function is used to display Mac and Host port statistics\r
520 *\r
521 */\r
522 static void BoardDiag_cpswShowStats(void)\r
523 {\r
524 Cpsw_IoctlPrms prms;\r
525 CpswStats_GenericMacPortInArgs inArgs;\r
526 CpswStats_PortStats portStats;\r
527 int32_t status = CPSW_SOK;\r
528 \r
529 CPSW_IOCTL_SET_OUT_ARGS(&prms,\r
530 &portStats);\r
531 status = Cpsw_ioctl(gCpswLpbkObj.hCpsw,\r
532 gCpswLpbkObj.coreId,\r
533 CPSW_STATS_IOCTL_GET_HOSTPORT_STATS,\r
534 &prms); \r
535 if (status != CPSW_SOK)\r
536 {\r
537 UART_printf("CpswApp_showStats() failed to get host stats: %d\n",\r
538 status);\r
539 }\r
540 \r
541 if (status == CPSW_SOK)\r
542 {\r
543 inArgs.portNum = CPSW_MAC_PORT_0;\r
544 CPSW_IOCTL_SET_INOUT_ARGS(&prms,\r
545 &inArgs,\r
546 &portStats);\r
547 \r
548 status = Cpsw_ioctl(gCpswLpbkObj.hCpsw,\r
549 gCpswLpbkObj.coreId,\r
550 CPSW_STATS_IOCTL_GET_MACPORT_STATS,\r
551 &prms);\r
552 if (status != CPSW_SOK)\r
553 {\r
554 UART_printf("CpswApp_showStats() failed to get MAC stats: %d\n",\r
555 status);\r
556 }\r
557 }\r
558 }\r
559 \r
560 /**\r
561 * \brief This function is used for CPSW packet transmission\r
562 * and reception\r
563 *\r
564 * \return int32_t\r
565 * 0 - in case of success\r
566 * -1 - in case of failure.\r
567 *\r
568 */\r
569 int32_t BoardDiag_cpswPktRxTx(void)\r
570 {\r
571 CpswDma_PktInfoQ txSubmitQ;\r
572 CpswDma_PktInfo *pktInfo;\r
573 EthFrame *frame;\r
574 uint32_t txRetrievePktCnt;\r
575 uint32_t loopTxPktCnt;\r
576 uint32_t totalTxCnt;\r
577 uint32_t rxReadyCnt;\r
578 uint32_t loopCnt;\r
579 uint32_t pktCnt;\r
580 uint32_t loopRxPktCnt;\r
581 int32_t status = CPSW_SOK;\r
582 \r
583 totalTxCnt = 0U;\r
584 for (loopCnt = 0U; loopCnt < TEST_NUM_LOOP; loopCnt++)\r
585 {\r
586 pktCnt = 0U;\r
587 while (pktCnt < TEST_PTK_NUM)\r
588 {\r
589 loopRxPktCnt = loopTxPktCnt = 0U;\r
590 /* Transmit a single packet */\r
591 CpswUtils_initQ(&txSubmitQ);\r
592 \r
593 /* Dequeue one free TX Eth packet */\r
594 pktInfo = (CpswDma_PktInfo *)CpswUtils_deQ(&gCpswLpbkObj.txFreePktInfoQ);\r
595 \r
596 while ( NULL != pktInfo )\r
597 {\r
598 pktCnt++;\r
599 /* Fill the TX Eth frame with test content */\r
600 frame = (EthFrame *)pktInfo->bufPtr;\r
601 \r
602 memcpy(frame->hdr.dstMac,\r
603 bcastAddr,\r
604 ETH_MAC_ADDR_LEN);\r
605 \r
606 memcpy(frame->hdr.srcMac,\r
607 &gCpswLpbkObj.hostMacAddr[0U],\r
608 ETH_MAC_ADDR_LEN);\r
609 \r
610 frame->hdr.etherType = htons(ETHERTYPE_EXPERIMENTAL1);\r
611 memset(&frame->payload[0U],\r
612 (uint8_t)(0xA5 + pktCnt),\r
613 TEST_LEN);\r
614 pktInfo->userBufLen = TEST_LEN + sizeof (EthFrameHeader);\r
615 pktInfo->appPriv = &gCpswLpbkObj;\r
616 CpswUtils_checkPktState(&pktInfo->pktState,\r
617 CPSW_PKTSTATE_MODULE_APP,\r
618 CPSW_PKTSTATE_APP_WITH_FREEQ,\r
619 CPSW_PKTSTATE_APP_WITH_DRIVER);\r
620 \r
621 /* Enqueue the packet for later transmission */\r
622 CpswUtils_enQ(&txSubmitQ,\r
623 &pktInfo->node);\r
624 \r
625 if (pktCnt >= TEST_PTK_NUM)\r
626 {\r
627 break;\r
628 }\r
629 /* Dequeue one free TX Eth packet */\r
630 pktInfo = (CpswDma_PktInfo *)CpswUtils_deQ(&gCpswLpbkObj.txFreePktInfoQ);\r
631 }\r
632 \r
633 loopTxPktCnt = CpswUtils_getQCount(&txSubmitQ);\r
634 while (0U != CpswUtils_getQCount(&txSubmitQ))\r
635 {\r
636 uint32_t txCnt = CpswUtils_getQCount(&txSubmitQ);\r
637 status = CpswAppUtils_submitTxPackets(gCpswLpbkObj.hTxCh,\r
638 &txSubmitQ);\r
639 while (txSem != true);\r
640 txSem = false;\r
641 \r
642 /* Retrieve TX free packets */\r
643 if (status == CPSW_SOK)\r
644 {\r
645 txCnt = txCnt - CpswUtils_getQCount(&txSubmitQ);\r
646 txRetrievePktCnt = 0U;\r
647 while (txRetrievePktCnt != txCnt)\r
648 {\r
649 BOARD_delay(1);\r
650 txRetrievePktCnt |= BoardDiag_cpswRetrieveFreeTxPkts();\r
651 }\r
652 }\r
653 else\r
654 {\r
655 break;\r
656 }\r
657 }\r
658 \r
659 /* Wait for packet reception */\r
660 do\r
661 {\r
662 while (rxSem != true);\r
663 rxSem = false;\r
664 \r
665 /* Get the packets received so far */\r
666 rxReadyCnt = BoardDiag_cpswReceivePkts();\r
667 if (rxReadyCnt > 0U)\r
668 {\r
669 /* Consume the received packets and release them */\r
670 pktInfo = (CpswDma_PktInfo *)CpswUtils_deQ(&gCpswLpbkObj.rxReadyQ);\r
671 while (pktInfo != NULL)\r
672 {\r
673 CpswUtils_checkPktState(&pktInfo->pktState,\r
674 CPSW_PKTSTATE_MODULE_APP,\r
675 CPSW_PKTSTATE_APP_WITH_READYQ,\r
676 CPSW_PKTSTATE_APP_WITH_FREEQ);\r
677 \r
678 /* Consume the packet by just printing its content */\r
679 frame = (EthFrame *)pktInfo->bufPtr;\r
680 if (gCpswLpbkObj.printFrame)\r
681 {\r
682 CpswAppUtils_printFrame(frame,\r
683 (pktInfo->userBufLen - sizeof (EthFrameHeader)));\r
684 }\r
685 \r
686 /* Release the received packet */\r
687 CpswUtils_enQ(&gCpswLpbkObj.rxFreeQ,\r
688 &pktInfo->node);\r
689 pktInfo = (CpswDma_PktInfo *)CpswUtils_deQ(&gCpswLpbkObj.rxReadyQ);\r
690 }\r
691 \r
692 /*Submit now processed buffers */\r
693 if (status == CPSW_SOK)\r
694 {\r
695 CpswAppUtils_validatePacketState(&gCpswLpbkObj.rxFreeQ,\r
696 CPSW_PKTSTATE_APP_WITH_FREEQ,\r
697 CPSW_PKTSTATE_APP_WITH_DRIVER);\r
698 \r
699 CpswAppUtils_submitRxPackets(gCpswLpbkObj.hRxFlow,\r
700 &gCpswLpbkObj.rxFreeQ);\r
701 }\r
702 }\r
703 loopRxPktCnt |= rxReadyCnt;\r
704 }\r
705 while (loopRxPktCnt < loopTxPktCnt);\r
706 \r
707 totalTxCnt |= loopTxPktCnt;\r
708 }\r
709 }\r
710 \r
711 if (status == CPSW_SOK)\r
712 {\r
713 UART_printf("Transmitted & Received %d packets\n", totalTxCnt);\r
714 }\r
715 else\r
716 {\r
717 UART_printf("Failed to transmit/receive packets: %d, transmitted: %d \n", TEST_PTK_NUM, totalTxCnt);\r
718 }\r
719 \r
720 return status;\r
721 }\r
722 \r
723 /**\r
724 * \brief This function is used to open the CPSW DMA module\r
725 *\r
726 * \return int32_t\r
727 * 0 - in case of success\r
728 * -1 - in case of failure.\r
729 *\r
730 */\r
731 int32_t BoardDiag_cpswOpenDma(void)\r
732 {\r
733 int32_t status = CPSW_SOK;\r
734 \r
735 /* Open the CPSW TX channel */\r
736 CpswDma_initTxChParams(&cpswTxChCfg);\r
737 \r
738 cpswTxChCfg.hUdmaDrv = gCpswLpbkObj.hUdmaDrv;\r
739 cpswTxChCfg.hCbArg = &gCpswLpbkObj;\r
740 cpswTxChCfg.notifyCb = BoardDiag_cpswTxIsrFxn;\r
741 \r
742 CpswAppUtils_setCommonTxChPrms(&cpswTxChCfg);\r
743 \r
744 CpswAppUtils_openTxCh(gCpswLpbkObj.hCpsw,\r
745 gCpswLpbkObj.coreKey,\r
746 gCpswLpbkObj.coreId,\r
747 &gCpswLpbkObj.txChNum,\r
748 &gCpswLpbkObj.hTxCh,\r
749 &cpswTxChCfg);\r
750 \r
751 BoardDiag_cpswInitTxFreePktQ();\r
752 \r
753 if (NULL != gCpswLpbkObj.hTxCh)\r
754 {\r
755 status = CpswDma_enableTxEvent(gCpswLpbkObj.hTxCh);\r
756 if (CPSW_SOK != status)\r
757 {\r
758 /* Free the Ch Num if enable event failed */\r
759 CpswAppUtils_freeTxCh(gCpswLpbkObj.hCpsw,\r
760 gCpswLpbkObj.coreKey,\r
761 gCpswLpbkObj.coreId,\r
762 gCpswLpbkObj.txChNum);\r
763 UART_printf("CpswDma_startTxCh() failed: %d\n", status);\r
764 status = CPSW_EFAIL;\r
765 }\r
766 }\r
767 else\r
768 {\r
769 /* Free the Ch Num if open Tx Ch failed */\r
770 CpswAppUtils_freeTxCh(gCpswLpbkObj.hCpsw,\r
771 gCpswLpbkObj.coreKey,\r
772 gCpswLpbkObj.coreId,\r
773 gCpswLpbkObj.txChNum);\r
774 UART_printf("CpswDma_openTxCh() failed to open: %d\n",\r
775 status);\r
776 status = CPSW_EFAIL;\r
777 }\r
778 \r
779 /* Open the CPSW RX flow */\r
780 if (status == CPSW_SOK)\r
781 {\r
782 CpswDma_initRxFlowParams(&cpswRxFlowCfg);\r
783 cpswRxFlowCfg.notifyCb = BoardDiag_cpswRxIsrFxn;\r
784 cpswRxFlowCfg.hUdmaDrv = gCpswLpbkObj.hUdmaDrv;\r
785 cpswRxFlowCfg.hCbArg = &gCpswLpbkObj;\r
786 \r
787 CpswAppUtils_setCommonRxFlowPrms(&cpswRxFlowCfg);\r
788 \r
789 CpswAppUtils_openRxFlow(gCpswLpbkObj.hCpsw,\r
790 gCpswLpbkObj.coreKey,\r
791 gCpswLpbkObj.coreId,\r
792 true,\r
793 &gCpswLpbkObj.rxStartFlowIdx,\r
794 &gCpswLpbkObj.rxFlowIdx,\r
795 &gCpswLpbkObj.hostMacAddr[0U],\r
796 &gCpswLpbkObj.hRxFlow,\r
797 &cpswRxFlowCfg);\r
798 \r
799 if (NULL == gCpswLpbkObj.hRxFlow)\r
800 {\r
801 CpswAppUtils_freeRxFlow(gCpswLpbkObj.hCpsw,\r
802 gCpswLpbkObj.coreKey,\r
803 gCpswLpbkObj.coreId,\r
804 gCpswLpbkObj.rxFlowIdx);\r
805 UART_printf("CpswDma_openRxFlow() failed to open: %d\n",\r
806 status);\r
807 if(gCpswLpbkObj.hRxFlow == NULL)\r
808 {\r
809 return -1;\r
810 }\r
811 }\r
812 else\r
813 {\r
814 CpswAppUtils_print("Host MAC address: ");\r
815 CpswAppUtils_printMacAddr(gCpswLpbkObj.hostMacAddr);\r
816 /* For MAC loopback disable secure flag for the host port entry */\r
817 BoardDiag_cpswChangeHostAleEntry(&gCpswLpbkObj.hostMacAddr[0U]);\r
818 \r
819 /* Submit all ready RX buffers to DMA.*/\r
820 boarDiag_cpswInitRxReadyPktQ();\r
821 }\r
822 }\r
823 \r
824 return status;\r
825 }\r
826 \r
827 /**\r
828 * \brief This function is used to open the CPSW driver\r
829 *\r
830 * \return int32_t\r
831 * 0 - in case of success\r
832 * -1 - in case of failure.\r
833 *\r
834 */\r
835 static int32_t BoardDiag_cpswOpen(void)\r
836 {\r
837 Cpsw_Config cpswCfg;\r
838 CpswOsal_Prms osalPrms;\r
839 CpswUtils_Prms utilsPrms;\r
840 int32_t status = CPSW_SOK;\r
841 Cpsw_IoctlPrms prms;\r
842 Cpsw_AttachCoreOutArgs attachCoreOutArgs;\r
843 \r
844 /* Set configuration parameters */\r
845 Cpsw_initParams(&cpswCfg);\r
846 cpswCfg.vlanConfig.vlanAware = false;\r
847 cpswCfg.hostPortConfig.removeCrc = true;\r
848 cpswCfg.hostPortConfig.padShortPacket = true;\r
849 cpswCfg.hostPortConfig.passCrcErrors = true;\r
850 CpswAppUtils_initResourceConfig(gCpswLpbkObj.cpswType,\r
851 gCpswLpbkObj.coreId,\r
852 &cpswCfg.resourceConfig);\r
853 BoardDiag_cpswInitAleConfig(&cpswCfg.aleConfig);\r
854 \r
855 UART_printf("CPSW_9G Test on MAIN NAVSS\n");\r
856 \r
857 cpswCfg.dmaConfig.rxChInitPrms.dmaPriority = UDMA_DEFAULT_RX_CH_DMA_PRIORITY;\r
858 \r
859 \r
860 \r
861 \r
862 /* App should open UDMA first as UDMA handle is needed to initialize\r
863 * CPSW RX channel */\r
864 gCpswLpbkObj.hUdmaDrv = CpswAppUtils_udmaOpen(gCpswLpbkObj.cpswType, NULL);\r
865 if(gCpswLpbkObj.hUdmaDrv != NULL)\r
866 {\r
867 cpswCfg.dmaConfig.hUdmaDrv = gCpswLpbkObj.hUdmaDrv;\r
868 }\r
869 else\r
870 {\r
871 UART_printf("Failed to get the UDMA handle\n");\r
872 return -1;\r
873 }\r
874 \r
875 /* Initialize CPSW driver with default OSAL, utils */\r
876 utilsPrms.printFxn = UART_printf;\r
877 utilsPrms.traceFxn = UART_printf;\r
878 utilsPrms.phyToVirtFxn = &BoardDiag_cpswPhyToVirtFxn;\r
879 utilsPrms.virtToPhyFxn = &BoardDiag_cpswvirtToPhyFx;\r
880 \r
881 Cpsw_initOsalPrms(&osalPrms);\r
882 \r
883 Cpsw_init(gCpswLpbkObj.cpswType,\r
884 &osalPrms,\r
885 &utilsPrms);\r
886 \r
887 /* Open the CPSW driver */\r
888 gCpswLpbkObj.hCpsw = Cpsw_open(gCpswLpbkObj.cpswType,\r
889 &cpswCfg);\r
890 if(gCpswLpbkObj.hCpsw == NULL)\r
891 {\r
892 UART_printf("BoardDiag_cpswOpen() failed to open: %d\n", status);\r
893 status = CPSW_EFAIL;\r
894 }\r
895 \r
896 if(status == CPSW_SOK)\r
897 {\r
898 /* Attach the core with RM */\r
899 CPSW_IOCTL_SET_INOUT_ARGS(&prms,\r
900 &gCpswLpbkObj.coreId,\r
901 &attachCoreOutArgs);\r
902 \r
903 status = Cpsw_ioctl(gCpswLpbkObj.hCpsw,\r
904 gCpswLpbkObj.coreId,\r
905 CPSW_IOCTL_ATTACH_CORE,\r
906 &prms);\r
907 if(status != CPSW_SOK)\r
908 {\r
909 UART_printf("CpswApp_loopbackTest failed CPSW_IOCTL_ATTACH_CORE: %d\n",\r
910 status);\r
911 }\r
912 else\r
913 {\r
914 gCpswLpbkObj.coreKey = attachCoreOutArgs.coreKey;\r
915 }\r
916 }\r
917 \r
918 if (status == CPSW_SOK)\r
919 {\r
920 status = CpswAppUtils_allocMac(gCpswLpbkObj.hCpsw,\r
921 gCpswLpbkObj.coreKey,\r
922 gCpswLpbkObj.coreId,\r
923 gCpswLpbkObj.hostMacAddr);\r
924 if(status != CPSW_SOK)\r
925 {\r
926 UART_printf("CpswApp_loopbackTest failed CpswAppUtils_allocMac: %d\n",\r
927 status);\r
928 }\r
929 else\r
930 {\r
931 CpswAppUtils_addHostPortEntry(gCpswLpbkObj.hCpsw,\r
932 gCpswLpbkObj.coreId,\r
933 gCpswLpbkObj.hostMacAddr);\r
934 }\r
935 }\r
936 \r
937 if(status == CPSW_SOK)\r
938 {\r
939 /* memutils open should happen after Cpsw is opened as it uses CpswUtils_Q\r
940 * functions */\r
941 status = CpswAppMemUtils_init();\r
942 if(status != CPSW_SOK)\r
943 {\r
944 UART_printf("cpsw memutils open function failed\n");\r
945 }\r
946 }\r
947 \r
948 if(status == CPSW_SOK)\r
949 {\r
950 Cpsw_OpenPortLinkInArgs linkArgs0 = {\r
951 .portNum = gCpswLpbkObj.portNum0,\r
952 };\r
953 CpswMacPort_Config *macConfig = &linkArgs0.macConfig;\r
954 CpswMacPort_LinkConfig *linkConfig = &linkArgs0.linkConfig;\r
955 CpswPhy_Config *phyConfig = &linkArgs0.phyConfig;\r
956 CpswMacPort_Interface *interface = &linkArgs0.interface;\r
957 \r
958 Cpsw_initMacPortParams(macConfig);\r
959 \r
960 BoardDiag_cpswChangeHostAleEntry(&gCpswLpbkObj.hostMacAddr[0U]);\r
961 \r
962 CpswAppBoardUtils_setPhyConfig(gCpswLpbkObj.cpswType,\r
963 linkArgs0.portNum,\r
964 interface,\r
965 phyConfig);\r
966 \r
967 macConfig->enableLoopback = false;\r
968 linkConfig->speed = CPSW_SPEED_AUTO;\r
969 linkConfig->duplexity = CPSW_DUPLEX_AUTO;\r
970 \r
971 Cpsw_OpenPortLinkInArgs linkArgs1 = {\r
972 .portNum = gCpswLpbkObj.portNum1,\r
973 };\r
974 \r
975 macConfig = &linkArgs1.macConfig;\r
976 linkConfig = &linkArgs1.linkConfig;\r
977 phyConfig = &linkArgs1.phyConfig;\r
978 interface = &linkArgs1.interface;\r
979 \r
980 Cpsw_initMacPortParams(macConfig);\r
981 \r
982 BoardDiag_cpswChangeHostAleEntry(&gCpswLpbkObj.hostMacAddr[0U]);\r
983 \r
984 CpswAppBoardUtils_setPhyConfig(gCpswLpbkObj.cpswType,\r
985 linkArgs1.portNum,\r
986 interface,\r
987 phyConfig);\r
988 if(status == CPSW_PHY_INVALID_PHYADDR)\r
989 {\r
990 UART_printf("PHY configuration failed\n\r");\r
991 return -1;\r
992 }\r
993 \r
994 macConfig->enableLoopback = false;\r
995 linkConfig->speed = CPSW_SPEED_AUTO;\r
996 linkConfig->duplexity = CPSW_DUPLEX_AUTO;\r
997 \r
998 CPSW_IOCTL_SET_IN_ARGS(&prms, &linkArgs0);\r
999 \r
1000 status = Cpsw_ioctl(gCpswLpbkObj.hCpsw,\r
1001 gCpswLpbkObj.coreId,\r
1002 CPSW_IOCTL_OPEN_PORT_LINK,\r
1003 &prms);\r
1004 if (status != CPSW_SOK)\r
1005 {\r
1006 UART_printf("CpswApp_openCpsw() failed to open MAC port: %d\n",\r
1007 status);\r
1008 }\r
1009 \r
1010 CPSW_IOCTL_SET_IN_ARGS(&prms, &linkArgs1);\r
1011 status = Cpsw_ioctl(gCpswLpbkObj.hCpsw,\r
1012 gCpswLpbkObj.coreId,\r
1013 CPSW_IOCTL_OPEN_PORT_LINK,\r
1014 &prms);\r
1015 if(status != CPSW_SOK)\r
1016 {\r
1017 UART_printf("CpswApp_openCpsw() failed to open MAC port: %d\n",\r
1018 status);\r
1019 }\r
1020 \r
1021 }\r
1022 \r
1023 return status;\r
1024 }\r
1025 \r
1026 /**\r
1027 * \brief This function is used to perform the CPSW9G\r
1028 * Ethernet port to port external loopback test \r
1029 *\r
1030 * \return int32_t\r
1031 * 0 - in case of success\r
1032 * -1 - in case of failure.\r
1033 *\r
1034 */\r
1035 int32_t BoardDiag_cpswLoopbackTest(void)\r
1036 {\r
1037 int32_t status;\r
1038 bool alive;\r
1039 uint8_t index;\r
1040 \r
1041 Cpsw_IoctlPrms prms;\r
1042 CpswAle_SetPortStateInArgs setPortStateInArgs;\r
1043 \r
1044 CpswAppBoardUtils_init();\r
1045 CpswAppUtils_enableClocks(gCpswLpbkObj.cpswType,\r
1046 MAC_CONN_TYPE_RGMII_FORCE_1000_FULL);\r
1047 \r
1048 gCpswLpbkObj.coreId = CpswAppSoc_getCoreId();\r
1049 \r
1050 /* Open the CPSW */\r
1051 status = BoardDiag_cpswOpen();\r
1052 if (status != CPSW_SOK)\r
1053 {\r
1054 UART_printf("Failed to open CPSW: %d\n", status);\r
1055 }\r
1056 \r
1057 /* Open CPSW DMA driver */\r
1058 if (status == CPSW_SOK)\r
1059 {\r
1060 status = BoardDiag_cpswOpenDma();\r
1061 if (status != CPSW_SOK)\r
1062 {\r
1063 UART_printf("Failed to open CPSW DMA: %d\n", status);\r
1064 }\r
1065 }\r
1066 \r
1067 /* Enable host port */\r
1068 if (status == CPSW_SOK)\r
1069 {\r
1070 setPortStateInArgs.portNum = CPSW_ALE_HOST_PORT_NUM;\r
1071 setPortStateInArgs.portState = CPSW_ALE_PORTSTATE_FORWARD;\r
1072 \r
1073 CPSW_IOCTL_SET_IN_ARGS(&prms,\r
1074 &setPortStateInArgs);\r
1075 prms.outArgs = NULL;\r
1076 \r
1077 status = Cpsw_ioctl(gCpswLpbkObj.hCpsw,\r
1078 gCpswLpbkObj.coreId,\r
1079 CPSW_ALE_IOCTL_SET_PORT_STATE,\r
1080 &prms);\r
1081 if (status != CPSW_SOK)\r
1082 {\r
1083 UART_printf("CpswApp_openCpsw() failed CPSW_ALE_IOCTL_SET_PORT_STATE: %d\n", status);\r
1084 }\r
1085 \r
1086 if (status == CPSW_SOK)\r
1087 {\r
1088 status = Cpsw_ioctl(gCpswLpbkObj.hCpsw,\r
1089 gCpswLpbkObj.coreId,\r
1090 CPSW_HOSTPORT_IOCTL_ENABLE,\r
1091 NULL);\r
1092 if (status != CPSW_SOK)\r
1093 {\r
1094 UART_printf("Failed to enable host port: %d\n", status);\r
1095 }\r
1096 }\r
1097 }\r
1098 \r
1099 /* Show alive PHYs */\r
1100 if (status == CPSW_SOK)\r
1101 {\r
1102 for (index = CPSW_PHY_START_ADDRESS; index < CPSW_PHY_END_ADDRESS; index++)\r
1103 {\r
1104 CPSW_IOCTL_SET_INOUT_ARGS(&prms, &index, &alive);\r
1105 \r
1106 status = Cpsw_ioctl(gCpswLpbkObj.hCpsw,\r
1107 gCpswLpbkObj.coreId,\r
1108 CPSW_MDIO_IOCTL_GET_ALIVE_STATUS,\r
1109 &prms);\r
1110 if (status == CPSW_SOK)\r
1111 {\r
1112 if (alive == true)\r
1113 {\r
1114 UART_printf("PHY %d is alive\n", index);\r
1115 }\r
1116 }\r
1117 else\r
1118 {\r
1119 UART_printf("Failed to get PHY %d alive status: %d\n", index,\r
1120 status);\r
1121 }\r
1122 }\r
1123 }\r
1124 \r
1125 UART_printf("Waiting for link to up for portNum-%d and portNum-%d...\n\r",\r
1126 gCpswLpbkObj.portNum0,\r
1127 gCpswLpbkObj.portNum1);\r
1128 \r
1129 if (status == CPSW_SOK)\r
1130 {\r
1131 \r
1132 while (!CpswAppUtils_isPortLinkUp(gCpswLpbkObj.hCpsw,\r
1133 gCpswLpbkObj.coreId,\r
1134 gCpswLpbkObj.portNum0))\r
1135 {\r
1136 Cpsw_periodicTick(gCpswLpbkObj.hCpsw);\r
1137 BoardDiag_cpswWait(1000);\r
1138 }\r
1139 \r
1140 while (!CpswAppUtils_isPortLinkUp(gCpswLpbkObj.hCpsw,\r
1141 gCpswLpbkObj.coreId,\r
1142 gCpswLpbkObj.portNum1))\r
1143 {\r
1144 Cpsw_periodicTick(gCpswLpbkObj.hCpsw);\r
1145 BoardDiag_cpswWait(1000);\r
1146 }\r
1147 \r
1148 UART_printf("Link up for portNum-%d and portNum-%d\n\r",\r
1149 gCpswLpbkObj.portNum0,\r
1150 gCpswLpbkObj.portNum1);\r
1151 \r
1152 BoardDiag_cpswWait(20000);\r
1153 UART_printf("Started with the packet rx tx test\n\r");\r
1154 status = BoardDiag_cpswPktRxTx();\r
1155 if (status != CPSW_SOK)\r
1156 {\r
1157 UART_printf("Failed to enable host port: %d\n", status);\r
1158 return -1;\r
1159 }\r
1160 }\r
1161 \r
1162 /* Print CPSW statistics of all ports */\r
1163 BoardDiag_cpswShowStats();\r
1164 \r
1165 /* Disable host port */\r
1166 status = Cpsw_ioctl(gCpswLpbkObj.hCpsw,\r
1167 gCpswLpbkObj.coreId,\r
1168 CPSW_HOSTPORT_IOCTL_DISABLE,\r
1169 NULL);\r
1170 if (status != CPSW_SOK)\r
1171 {\r
1172 UART_printf("Failed to disable host port: %d\n", status);\r
1173 return -1;\r
1174 }\r
1175 \r
1176 /* Close CPSW DMA driver */\r
1177 BoardDiag_cpswCloseDma();\r
1178 /* Close CPSW */\r
1179 BoardDiag_cpswClose();\r
1180 /* Close UDMA driver */\r
1181 CpswAppUtils_udmaclose(gCpswLpbkObj.hUdmaDrv);\r
1182 \r
1183 CpswAppUtils_disableClocks(gCpswLpbkObj.cpswType);\r
1184 CpswAppBoardUtils_deInit();\r
1185 \r
1186 return 0;\r
1187 }\r
1188 \r
1189 /**\r
1190 * \brief This function runs CPSW9G ethernet test\r
1191 *\r
1192 * \return int8_t\r
1193 * 0 - in case of success\r
1194 * -1 - in case of failure.\r
1195 *\r
1196 */\r
1197 int8_t BoardDiag_CpswEthRunTest(void)\r
1198 {\r
1199 int8_t ret;\r
1200 uint8_t userInput;\r
1201 \r
1202 UART_printf ("************************************************\n");\r
1203 UART_printf ("* CPSW Ethernet Test *\n");\r
1204 UART_printf ("************************************************\n");\r
1205 \r
1206 /* This should not be removed, as this is fix for linker issue in release mode.\r
1207 * If removed linker will complain "undefined reference to `_sbrk'".\r
1208 * This arises whenever library invokes printf() but the app doesn't.\r
1209 */\r
1210 #ifndef UART_ENABLED\r
1211 printf( "CPSW Bare metal Loopback App \n");\r
1212 #endif\r
1213 \r
1214 UART_printf("Loopback test for Port 0\n\r");\r
1215 \r
1216 UART_printf("Select any one option from below\n\r");\r
1217 UART_printf("1 - PRG0 ports verification\n\r");\r
1218 UART_printf("2 - PRG1 ports verification\n\r");\r
1219 \r
1220 UART_scanFmt("%d", &userInput);\r
1221 \r
1222 while((userInput != PRG0_PORT_VERIFICATION) &&\r
1223 (userInput != PRG1_PORT_VERIFICATION))\r
1224 {\r
1225 UART_printf("Invalid userInput, Please try again\n\r");\r
1226 UART_scanFmt("%d", &userInput);\r
1227 }\r
1228 \r
1229 if(userInput == PRG0_PORT_VERIFICATION)\r
1230 {\r
1231 gCpswLpbkObj.portNum0 = CPSW_MAC_PORT_2;\r
1232 gCpswLpbkObj.portNum1 = CPSW_MAC_PORT_3;\r
1233 }\r
1234 else\r
1235 {\r
1236 gCpswLpbkObj.portNum0 = CPSW_MAC_PORT_0;\r
1237 gCpswLpbkObj.portNum1 = CPSW_MAC_PORT_1; \r
1238 }\r
1239 \r
1240 /* Run the loopback test */\r
1241 ret = BoardDiag_cpswLoopbackTest();\r
1242 if(ret == -1)\r
1243 {\r
1244 UART_printf("CPSW Loopback Test failed\n\r");\r
1245 return -1;\r
1246 }\r
1247 \r
1248 return ret;\r
1249 }\r
1250 \r
1251 /**\r
1252 * \brief CPSW diagnostic test main function\r
1253 *\r
1254 * This function performs board initializations and calls cpsw9g ethernet test\r
1255 *\r
1256 * \return int\r
1257 * 0 - in case of success\r
1258 * -1 - in case of failure\r
1259 *\r
1260 */\r
1261 int main(void)\r
1262 {\r
1263 Board_initCfg boardCfg;\r
1264 Board_STATUS status;\r
1265 int8_t ret = 0;\r
1266 \r
1267 Board_PinmuxConfig_t gesiIcssgPinmux;\r
1268 \r
1269 Board_pinmuxGetCfg(&gesiIcssgPinmux);\r
1270 gesiIcssgPinmux.autoCfg = BOARD_PINMUX_CUSTOM;\r
1271 gesiIcssgPinmux.gesiExp = BOARD_PINMUX_GESI_CPSW9G;\r
1272 Board_pinmuxSetCfg(&gesiIcssgPinmux);\r
1273 \r
1274 #ifdef PDK_RAW_BOOT\r
1275 boardCfg = BOARD_INIT_MODULE_CLOCK |\r
1276 BOARD_INIT_PINMUX_CONFIG |\r
1277 BOARD_INIT_UART_STDIO |\r
1278 BOARD_INIT_ETH_PHY;\r
1279 #else\r
1280 boardCfg = BOARD_INIT_UART_STDIO;\r
1281 #endif\r
1282 \r
1283 status = Board_init(boardCfg);\r
1284 if(status != BOARD_SOK)\r
1285 {\r
1286 return -1;\r
1287 }\r
1288 \r
1289 /* Enable CPSW9G MDIO mux */\r
1290 status = Board_control(BOARD_CTRL_CMD_SET_CPSW9G_MDIO_MUX,\r
1291 NULL);\r
1292 if(status != BOARD_SOK)\r
1293 {\r
1294 return -1;\r
1295 }\r
1296 \r
1297 boardCfg = BOARD_INIT_CPSW9G_ETH_PHY;\r
1298 status = Board_init(boardCfg);\r
1299 if(status != BOARD_SOK)\r
1300 {\r
1301 return -1;\r
1302 }\r
1303 \r
1304 \r
1305 ret = BoardDiag_CpswEthRunTest();\r
1306 if(ret == 0)\r
1307 {\r
1308 UART_printf("CPSW loopback test completed successfully\n");\r
1309 }\r
1310 \r
1311 return ret;\r
1312 \r
1313 }\r