]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_A53_64-bit_UltraScale_MPSoC/RTOSDemo_A53_bsp/psu_cortexa53_0/libsrc/usbpsu_v1_4/src/xusbpsu_controltransfers.c
Update Zynq, MPSoc Cortex-A53 and MPSoc Cortex-R5 demo projects to build with the...
[freertos] / FreeRTOS / Demo / CORTEX_A53_64-bit_UltraScale_MPSoC / RTOSDemo_A53_bsp / psu_cortexa53_0 / libsrc / usbpsu_v1_4 / src / xusbpsu_controltransfers.c
1 /******************************************************************************
2 *
3 * Copyright (C) 2016 Xilinx, Inc.  All rights reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * Use of the Software is limited solely to applications:
16 * (a) running on a Xilinx device, or
17 * (b) that interact with a Xilinx device through a bus or interconnect.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * XILINX  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
24 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * SOFTWARE.
26 *
27 * Except as contained in this notice, the name of the Xilinx shall not be used
28 * in advertising or otherwise to promote the sale, use or other dealings in
29 * this Software without prior written authorization from Xilinx.
30 *
31 ******************************************************************************/
32 /****************************************************************************/
33 /**
34 *
35 * @file xusbpsu_controltransfers.c
36 * @addtogroup usbpsu_v1_0
37 * @{
38 *
39 * <pre>
40 * MODIFICATION HISTORY:
41 *
42 * Ver   Who  Date     Changes
43 * ----- ---- -------- -------------------------------------------------------
44 * 1.0   sg  06/06/16 First release
45 * 1.3   vak 04/03/17 Added CCI support for USB
46 * 1.4   bk  12/01/18 Modify USBPSU driver code to fit USB common example code
47 *                    for all USB IPs.
48 *
49 * </pre>
50 *
51 *****************************************************************************/
52
53 /***************************** Include Files *********************************/
54 #include "xusbpsu_endpoint.h"
55 #include "sleep.h"
56 #include "xusb_wrapper.h"
57
58 /************************** Constant Definitions *****************************/
59
60 /**************************** Type Definitions *******************************/
61
62 /***************** Macros (Inline Functions) Definitions *********************/
63
64 /************************** Function Prototypes ******************************/
65
66 /************************** Variable Definitions *****************************/
67
68 /****************************************************************************/
69 /**
70 * Initiates DMA on Control Endpoint 0 to receive Setup packet.
71 *
72 * @param        InstancePtr is a pointer to the XUsbPsu instance.
73 *
74 * @return       XST_SUCCESS else XST_FAILURE.
75 *
76 * @note         None.
77 *
78 *****************************************************************************/
79 s32 XUsbPsu_RecvSetup(struct XUsbPsu *InstancePtr)
80 {
81         struct XUsbPsu_EpParams *Params;
82         struct XUsbPsu_Trb      *TrbPtr;
83         struct XUsbPsu_Ep       *Ept;
84         s32     Ret;
85
86         Xil_AssertNonvoid(InstancePtr != NULL);
87
88         Params = XUsbPsu_GetEpParams(InstancePtr);
89         Xil_AssertNonvoid(Params != NULL);
90
91         /* Setup packet always on EP0 */
92         Ept = &InstancePtr->eps[0];
93         if ((Ept->EpStatus & XUSBPSU_EP_BUSY) != 0U) {
94                 return (s32)XST_FAILURE;
95         }
96
97         TrbPtr = &InstancePtr->Ep0_Trb;
98
99         TrbPtr->BufferPtrLow = (UINTPTR)&InstancePtr->SetupData;
100         TrbPtr->BufferPtrHigh = ((UINTPTR)&InstancePtr->SetupData >> 16) >> 16;
101         TrbPtr->Size = 8U;
102         TrbPtr->Ctrl = XUSBPSU_TRBCTL_CONTROL_SETUP;
103
104         TrbPtr->Ctrl |= (XUSBPSU_TRB_CTRL_HWO
105                         | XUSBPSU_TRB_CTRL_LST
106                         | XUSBPSU_TRB_CTRL_IOC
107                         | XUSBPSU_TRB_CTRL_ISP_IMI);
108
109         if (InstancePtr->ConfigPtr->IsCacheCoherent == 0) {
110                 Xil_DCacheFlushRange((INTPTR)TrbPtr, sizeof(struct XUsbPsu_Trb));
111                 Xil_DCacheFlushRange((UINTPTR)&InstancePtr->SetupData, sizeof(SetupPacket));
112         }
113
114         Params->Param0 = 0U;
115         Params->Param1 = (UINTPTR)TrbPtr;
116
117         InstancePtr->Ep0State = XUSBPSU_EP0_SETUP_PHASE;
118
119         Ret = XUsbPsu_SendEpCmd(InstancePtr, 0U, XUSBPSU_EP_DIR_OUT,
120                                 XUSBPSU_DEPCMD_STARTTRANSFER, Params);
121         if (Ret != XST_SUCCESS) {
122                 return (s32)XST_FAILURE;
123         }
124
125         Ept->EpStatus |= XUSBPSU_EP_BUSY;
126         Ept->ResourceIndex = (u8)XUsbPsu_EpGetTransferIndex(InstancePtr,
127                                                 Ept->UsbEpNum, Ept->Direction);
128
129         return XST_SUCCESS;
130 }
131
132 /****************************************************************************/
133 /**
134 * Stalls Control Endpoint and restarts to receive Setup packet.
135 *
136 * @param        InstancePtr is a pointer to the XUsbPsu instance.
137 *
138 * @return       None
139 *
140 * @note         None.
141 *
142 *****************************************************************************/
143 void XUsbPsu_Ep0StallRestart(struct XUsbPsu *InstancePtr)
144 {
145         struct XUsbPsu_Ep               *Ept;
146
147         Xil_AssertVoid(InstancePtr != NULL);
148
149         /* reinitialize physical ep1 */
150         Ept = &InstancePtr->eps[1];
151         Ept->EpStatus = XUSBPSU_EP_ENABLED;
152
153         /* stall is always issued on EP0 */
154         XUsbPsu_EpSetStall(InstancePtr, 0U, XUSBPSU_EP_DIR_OUT);
155
156         Ept = &InstancePtr->eps[0];
157         Ept->EpStatus = XUSBPSU_EP_ENABLED;
158         InstancePtr->Ep0State = XUSBPSU_EP0_SETUP_PHASE;
159         (void)XUsbPsu_RecvSetup(InstancePtr);
160 }
161
162 /****************************************************************************/
163 /**
164 * Checks the Data Phase and calls user Endpoint handler.
165 *
166 * @param        InstancePtr is a pointer to the XUsbPsu instance.
167 * @param        Event is a pointer to the Endpoint event occured in core.
168 *
169 * @return       None.
170 *
171 * @note         None.
172 *
173 *****************************************************************************/
174 void XUsbPsu_Ep0DataDone(struct XUsbPsu *InstancePtr,
175                                                  const struct XUsbPsu_Event_Epevt *Event)
176 {
177         struct XUsbPsu_Ep       *Ept;
178         struct XUsbPsu_Trb      *TrbPtr;
179         u32     Status;
180         u32     Length;
181         u32     Epnum;
182         u8      Dir;
183
184         Xil_AssertVoid(InstancePtr != NULL);
185         Xil_AssertVoid(Event != NULL);
186
187         Epnum = Event->Epnumber;
188         Dir = (u8)(!!Epnum);
189         Ept = &InstancePtr->eps[Epnum];
190         TrbPtr = &InstancePtr->Ep0_Trb;
191
192         if (InstancePtr->ConfigPtr->IsCacheCoherent == 0)
193                 Xil_DCacheInvalidateRange((INTPTR)TrbPtr, sizeof(struct XUsbPsu_Trb));
194
195         Status = XUSBPSU_TRB_SIZE_TRBSTS(TrbPtr->Size);
196         if (Status == XUSBPSU_TRBSTS_SETUP_PENDING) {
197                 return;
198         }
199
200         Length = TrbPtr->Size & XUSBPSU_TRB_SIZE_MASK;
201
202         if (Length == 0U) {
203                 Ept->BytesTxed = Ept->RequestedBytes;
204         } else {
205                 if (Dir == XUSBPSU_EP_DIR_IN) {
206                         Ept->BytesTxed = Ept->RequestedBytes - Length;
207                 } else {
208                         if ((Dir == XUSBPSU_EP_DIR_OUT) && (Ept->UnalignedTx == 1U)) {
209                                         Ept->BytesTxed = Ept->RequestedBytes;
210                                         Ept->UnalignedTx = 0U;
211                         }
212                 }
213         }
214
215         if (Dir == XUSBPSU_EP_DIR_OUT) {
216                 /* Invalidate Cache */
217                 if (InstancePtr->ConfigPtr->IsCacheCoherent == 0)
218                         Xil_DCacheInvalidateRange((INTPTR)Ept->BufferPtr, Ept->BytesTxed);
219         }
220
221         if (Ept->Handler != NULL) {
222                 Ept->Handler(InstancePtr->AppData, Ept->RequestedBytes, Ept->BytesTxed);
223         }
224 }
225
226 /****************************************************************************/
227 /**
228 * Checks the Status Phase and starts next Control transfer.
229 *
230 * @param        InstancePtr is a pointer to the XUsbPsu instance.
231 * @param        Event is a pointer to the Endpoint event occured in core.
232 *
233 * @return       None.
234 *
235 * @note         None.
236 *
237 *****************************************************************************/
238 void XUsbPsu_Ep0StatusDone(struct XUsbPsu *InstancePtr,
239                 const struct XUsbPsu_Event_Epevt *Event)
240 {
241         struct XUsbPsu_Trb      *TrbPtr;
242
243         Xil_AssertVoid(InstancePtr != NULL);
244         Xil_AssertVoid(Event != NULL);
245
246         TrbPtr = &InstancePtr->Ep0_Trb;
247
248         if (InstancePtr->IsInTestMode != 0U) {
249                 s32 Ret;
250
251                 Ret = XUsbPsu_SetTestMode(InstancePtr,
252                                         InstancePtr->TestMode);
253                 if (Ret < 0) {
254                         XUsbPsu_Ep0StallRestart(InstancePtr);
255                         return;
256                 }
257         }
258         if (InstancePtr->ConfigPtr->IsCacheCoherent == 0)
259                 Xil_DCacheInvalidateRange((INTPTR)TrbPtr, sizeof(struct XUsbPsu_Trb));
260
261         (void)XUsbPsu_RecvSetup(InstancePtr);
262 }
263
264 /****************************************************************************/
265 /**
266 * Handles Transfer complete event of Control Endpoints EP0 OUT and EP0 IN.
267 *
268 * @param        InstancePtr is a pointer to the XUsbPsu instance.
269 * @param        Event is a pointer to the Endpoint event occured in core.
270 *
271 * @return       None.
272 *
273 * @note         None.
274 *
275 *****************************************************************************/
276 void XUsbPsu_Ep0XferComplete(struct XUsbPsu *InstancePtr,
277                                                          const struct XUsbPsu_Event_Epevt *Event)
278 {
279         struct XUsbPsu_Ep *Ept;
280         SetupPacket *Ctrl;
281         u16 Length;
282
283         Xil_AssertVoid(InstancePtr != NULL);
284         Xil_AssertVoid(Event != NULL);
285
286         Ept = &InstancePtr->eps[Event->Epnumber];
287         Ctrl = &InstancePtr->SetupData;
288
289         Ept->EpStatus &= ~XUSBPSU_EP_BUSY;
290         Ept->ResourceIndex = 0U;
291
292         switch (InstancePtr->Ep0State) {
293         case XUSBPSU_EP0_SETUP_PHASE:
294                 if (InstancePtr->ConfigPtr->IsCacheCoherent == 0) {
295                         Xil_DCacheInvalidateRange((INTPTR)&InstancePtr->SetupData,
296                                         sizeof(InstancePtr->SetupData));
297                 }
298                 Length = Ctrl->wLength;
299                 if (Length == 0U) {
300                         InstancePtr->IsThreeStage = 0U;
301                         InstancePtr->ControlDir = XUSBPSU_EP_DIR_OUT;
302                 } else {
303                         InstancePtr->IsThreeStage = 1U;
304                         InstancePtr->ControlDir = !!(Ctrl->bRequestType &
305                                                         USB_DIR_IN);
306                 }
307
308                 Xil_AssertVoid(InstancePtr->Chapter9 != NULL);
309
310                 InstancePtr->Chapter9(InstancePtr->AppData,
311                                                                         &InstancePtr->SetupData);
312                 break;
313
314         case XUSBPSU_EP0_DATA_PHASE:
315                 XUsbPsu_Ep0DataDone(InstancePtr, Event);
316                 break;
317
318         case XUSBPSU_EP0_STATUS_PHASE:
319                 XUsbPsu_Ep0StatusDone(InstancePtr, Event);
320                 break;
321
322         default:
323                 /* Default case is a required MISRA-C guideline. */
324                 break;
325         }
326 }
327
328 /****************************************************************************/
329 /**
330 * Starts Status Phase of Control Transfer
331 *
332 * @param        InstancePtr is a pointer to the XUsbPsu instance.
333 * @param        Event is a pointer to the Endpoint event occured in core.
334 *
335 * @return       XST_SUCCESS else XST_FAILURE
336 *
337 * @note         None.
338 *
339 *****************************************************************************/
340 s32 XUsbPsu_Ep0StartStatus(struct XUsbPsu *InstancePtr,
341                                 const struct XUsbPsu_Event_Epevt *Event)
342 {
343         struct XUsbPsu_Ep  *Ept;
344         struct XUsbPsu_EpParams *Params;
345         struct XUsbPsu_Trb *TrbPtr;
346         u32 Type;
347         s32 Ret;
348         u8 Dir;
349
350         Xil_AssertNonvoid(InstancePtr != NULL);
351         Xil_AssertNonvoid(Event != NULL);
352
353         Ept = &InstancePtr->eps[Event->Epnumber];
354         Params = XUsbPsu_GetEpParams(InstancePtr);
355         Xil_AssertNonvoid(Params != NULL);
356         if ((Ept->EpStatus & XUSBPSU_EP_BUSY) != 0U) {
357                 return (s32)XST_FAILURE;
358         }
359
360         Type = (InstancePtr->IsThreeStage != 0U) ? XUSBPSU_TRBCTL_CONTROL_STATUS3
361                                         : XUSBPSU_TRBCTL_CONTROL_STATUS2;
362         TrbPtr = &InstancePtr->Ep0_Trb;
363         /* we use same TrbPtr for setup packet */
364         TrbPtr->BufferPtrLow = (UINTPTR)&InstancePtr->SetupData;
365         TrbPtr->BufferPtrHigh = ((UINTPTR)&InstancePtr->SetupData >> 16) >> 16;
366         TrbPtr->Size = 0U;
367         TrbPtr->Ctrl = Type;
368
369         TrbPtr->Ctrl |= (XUSBPSU_TRB_CTRL_HWO
370                         | XUSBPSU_TRB_CTRL_LST
371                         | XUSBPSU_TRB_CTRL_IOC
372                         | XUSBPSU_TRB_CTRL_ISP_IMI);
373
374         if (InstancePtr->ConfigPtr->IsCacheCoherent == 0) {
375                 Xil_DCacheFlushRange((INTPTR)TrbPtr, sizeof(struct XUsbPsu_Trb));
376         }
377
378         Params->Param0 = 0U;
379         Params->Param1 = (UINTPTR)TrbPtr;
380
381         InstancePtr->Ep0State = XUSBPSU_EP0_STATUS_PHASE;
382
383         /*
384          * Control OUT transfer - Status stage happens on EP0 IN - EP1
385          * Control IN transfer - Status stage happens on EP0 OUT - EP0
386          */
387         Dir = !InstancePtr->ControlDir;
388
389         Ret = XUsbPsu_SendEpCmd(InstancePtr, 0U, Dir,
390                                                         XUSBPSU_DEPCMD_STARTTRANSFER, Params);
391         if (Ret != XST_SUCCESS) {
392                 return (s32)XST_FAILURE;
393         }
394
395         Ept->EpStatus |= XUSBPSU_EP_BUSY;
396         Ept->ResourceIndex = (u8)XUsbPsu_EpGetTransferIndex(InstancePtr,
397                                                         Ept->UsbEpNum, Ept->Direction);
398
399         return XST_SUCCESS;
400 }
401
402 /****************************************************************************/
403 /**
404 * Ends Data Phase - used incase of error.
405 *
406 * @param        InstancePtr is a pointer to the XUsbPsu instance.
407 * @param        Dep is a pointer to the Endpoint structure.
408 *
409 * @return       None
410 *
411 * @note         None.
412 *
413 *****************************************************************************/
414 void XUsbPsu_Ep0_EndControlData(struct XUsbPsu *InstancePtr,
415                                                                 struct XUsbPsu_Ep *Ept)
416 {
417         struct XUsbPsu_EpParams *Params;
418         u32     Cmd;
419
420         Xil_AssertVoid(InstancePtr != NULL);
421         Xil_AssertVoid(Ept != NULL);
422
423         if (Ept->ResourceIndex == 0U) {
424                 return;
425         }
426
427         Params = XUsbPsu_GetEpParams(InstancePtr);
428         Xil_AssertVoid(Params != NULL);
429
430         Cmd = XUSBPSU_DEPCMD_ENDTRANSFER;
431         Cmd |= XUSBPSU_DEPCMD_PARAM(Ept->ResourceIndex);
432         (void)XUsbPsu_SendEpCmd(InstancePtr, Ept->UsbEpNum, Ept->Direction,
433                                                 Cmd, Params);
434         Ept->ResourceIndex = 0U;
435         XUsbSleep(200U);
436 }
437
438 /****************************************************************************/
439 /**
440 * Handles Transfer Not Ready event of Control Endpoints EP0 OUT and EP0 IN.
441 *
442 * @param        InstancePtr is a pointer to the XUsbPsu instance.
443 * @param        Event is a pointer to the Endpoint event occured in core.
444 *
445 * @return       None.
446 *
447 * @note         None.
448 *
449 *****************************************************************************/
450 void XUsbPsu_Ep0XferNotReady(struct XUsbPsu *InstancePtr,
451                                                          const struct XUsbPsu_Event_Epevt *Event)
452 {
453         struct XUsbPsu_Ep *Ept;
454
455         Xil_AssertVoid(InstancePtr != NULL);
456         Xil_AssertVoid(Event != NULL);
457
458         Ept = &InstancePtr->eps[Event->Epnumber];
459
460         switch (Event->Status) {
461         case DEPEVT_STATUS_CONTROL_DATA:
462                 /*
463                  * We already have a DATA transfer in the controller's cache,
464                  * if we receive a XferNotReady(DATA) we will ignore it, unless
465                  * it's for the wrong direction.
466                  *
467                  * In that case, we must issue END_TRANSFER command to the Data
468                  * Phase we already have started and issue SetStall on the
469                  * control endpoint.
470                  */
471                 if (Event->Epnumber != InstancePtr->ControlDir) {
472                         XUsbPsu_Ep0_EndControlData(InstancePtr, Ept);
473                         XUsbPsu_Ep0StallRestart(InstancePtr);
474                 }
475                 break;
476
477         case DEPEVT_STATUS_CONTROL_STATUS:
478                 (void)XUsbPsu_Ep0StartStatus(InstancePtr, Event);
479                 break;
480
481         default:
482                 /* Default case is a required MIRSA-C guideline. */
483                 break;
484         }
485 }
486
487 /****************************************************************************/
488 /**
489 * Handles Interrupts of Control Endpoints EP0 OUT and EP0 IN.
490 *
491 * @param        InstancePtr is a pointer to the XUsbPsu instance.
492 * @param        Event is a pointer to the Endpoint event occured in core.
493 *
494 * @return       None.
495 *
496 * @note         None.
497 *
498 *****************************************************************************/
499 void XUsbPsu_Ep0Intr(struct XUsbPsu *InstancePtr,
500                 const struct XUsbPsu_Event_Epevt *Event)
501 {
502
503         Xil_AssertVoid(InstancePtr != NULL);
504         Xil_AssertVoid(Event != NULL);
505
506         switch (Event->Endpoint_Event) {
507         case XUSBPSU_DEPEVT_XFERCOMPLETE:
508                 XUsbPsu_Ep0XferComplete(InstancePtr, Event);
509                 break;
510
511         case XUSBPSU_DEPEVT_XFERNOTREADY:
512                 XUsbPsu_Ep0XferNotReady(InstancePtr, Event);
513                 break;
514
515         case XUSBPSU_DEPEVT_XFERINPROGRESS:
516         case XUSBPSU_DEPEVT_STREAMEVT:
517         case XUSBPSU_DEPEVT_EPCMDCMPLT:
518                 break;
519
520         default:
521                 /* Default case is a required MIRSA-C guideline. */
522                 break;
523         }
524 }
525
526 /****************************************************************************/
527 /**
528 * Initiates DMA to send data on Control Endpoint EP0 IN to Host.
529 *
530 * @param        InstancePtr is a pointer to the XUsbPsu instance.
531 * @param        BufferPtr is pointer to data.
532 * @param        BufferLen is Length of data buffer.
533 *
534 * @return       XST_SUCCESS else XST_FAILURE
535 *
536 * @note         None.
537 *
538 *****************************************************************************/
539 s32 XUsbPsu_Ep0Send(struct XUsbPsu *InstancePtr, u8 *BufferPtr, u32 BufferLen)
540 {
541         /* Control IN - EP1 */
542         struct XUsbPsu_EpParams *Params;
543         struct XUsbPsu_Ep       *Ept;
544         struct XUsbPsu_Trb      *TrbPtr;
545         s32 Ret;
546
547         Xil_AssertNonvoid(InstancePtr != NULL);
548         Xil_AssertNonvoid(BufferPtr != NULL);
549
550         Ept = &InstancePtr->eps[1];
551         Params = XUsbPsu_GetEpParams(InstancePtr);
552         Xil_AssertNonvoid(Params != NULL);
553
554         if ((Ept->EpStatus & XUSBPSU_EP_BUSY) != 0U) {
555                 return (s32)XST_FAILURE;
556         }
557
558         Ept->RequestedBytes = BufferLen;
559         Ept->BytesTxed = 0U;
560         Ept->BufferPtr = BufferPtr;
561
562         TrbPtr = &InstancePtr->Ep0_Trb;
563
564         TrbPtr->BufferPtrLow  = (UINTPTR)BufferPtr;
565         TrbPtr->BufferPtrHigh  = ((UINTPTR)BufferPtr >> 16) >> 16;
566         TrbPtr->Size = BufferLen;
567         TrbPtr->Ctrl = XUSBPSU_TRBCTL_CONTROL_DATA;
568
569         TrbPtr->Ctrl |= (XUSBPSU_TRB_CTRL_HWO
570                         | XUSBPSU_TRB_CTRL_LST
571                         | XUSBPSU_TRB_CTRL_IOC
572                         | XUSBPSU_TRB_CTRL_ISP_IMI);
573
574         Params->Param0 = 0U;
575         Params->Param1 = (UINTPTR)TrbPtr;
576
577         if (InstancePtr->ConfigPtr->IsCacheCoherent == 0) {
578                 Xil_DCacheFlushRange((INTPTR)TrbPtr, sizeof(struct XUsbPsu_Trb));
579                 Xil_DCacheFlushRange((INTPTR)BufferPtr, BufferLen);
580         }
581
582         InstancePtr->Ep0State = XUSBPSU_EP0_DATA_PHASE;
583
584         Ret = XUsbPsu_SendEpCmd(InstancePtr, 0U, XUSBPSU_EP_DIR_IN,
585                                                         XUSBPSU_DEPCMD_STARTTRANSFER, Params);
586         if (Ret != XST_SUCCESS) {
587                 return (s32)XST_FAILURE;
588         }
589
590         Ept->EpStatus |= XUSBPSU_EP_BUSY;
591         Ept->ResourceIndex = (u8)XUsbPsu_EpGetTransferIndex(InstancePtr,
592                                                 Ept->UsbEpNum, Ept->Direction);
593
594         return XST_SUCCESS;
595 }
596
597 /****************************************************************************/
598 /**
599 * Initiates DMA to receive data on Control Endpoint EP0 OUT from Host.
600 *
601 * @param        InstancePtr is a pointer to the XUsbPsu instance.
602 * @param        BufferPtr is pointer to data.
603 * @param        Length is Length of data to be received.
604 *
605 * @return       XST_SUCCESS else XST_FAILURE
606 *
607 * @note         None.
608 *
609 *****************************************************************************/
610 s32 XUsbPsu_Ep0Recv(struct XUsbPsu *InstancePtr, u8 *BufferPtr, u32 Length)
611 {
612         struct XUsbPsu_EpParams *Params;
613         struct XUsbPsu_Ep       *Ept;
614         struct XUsbPsu_Trb      *TrbPtr;
615         u32 Size;
616         s32 Ret;
617
618         Xil_AssertNonvoid(InstancePtr != NULL);
619         Xil_AssertNonvoid(BufferPtr != NULL);
620
621         Ept = &InstancePtr->eps[0];
622         Params = XUsbPsu_GetEpParams(InstancePtr);
623         Xil_AssertNonvoid(Params != NULL);
624
625         if ((Ept->EpStatus & XUSBPSU_EP_BUSY) != 0U) {
626                 return (s32)XST_FAILURE;
627         }
628
629         Ept->RequestedBytes = Length;
630         Size = Length;
631         Ept->BytesTxed = 0U;
632         Ept->BufferPtr = BufferPtr;
633
634         /*
635          * 8.2.5 - An OUT transfer size (Total TRB buffer allocation)
636          * must be a multiple of MaxPacketSize even if software is expecting a
637          * fixed non-multiple of MaxPacketSize transfer from the Host.
638          */
639         if (!IS_ALIGNED(Length, Ept->MaxSize)) {
640                 Size = (u32)roundup(Length, Ept->MaxSize);
641                 Ept->UnalignedTx = 1U;
642         }
643
644         TrbPtr = &InstancePtr->Ep0_Trb;
645
646         TrbPtr->BufferPtrLow = (UINTPTR)BufferPtr;
647         TrbPtr->BufferPtrHigh = ((UINTPTR)BufferPtr >> 16) >> 16;
648         TrbPtr->Size = Size;
649         TrbPtr->Ctrl = XUSBPSU_TRBCTL_CONTROL_DATA;
650
651         TrbPtr->Ctrl |= (XUSBPSU_TRB_CTRL_HWO
652                         | XUSBPSU_TRB_CTRL_LST
653                         | XUSBPSU_TRB_CTRL_IOC
654                         | XUSBPSU_TRB_CTRL_ISP_IMI);
655
656         if (InstancePtr->ConfigPtr->IsCacheCoherent == 0) {
657                 Xil_DCacheFlushRange((INTPTR)TrbPtr, sizeof(struct XUsbPsu_Trb));
658                 Xil_DCacheInvalidateRange((INTPTR)BufferPtr, Length);
659         }
660
661         Params->Param0 = 0U;
662         Params->Param1 = (UINTPTR)TrbPtr;
663
664         InstancePtr->Ep0State = XUSBPSU_EP0_DATA_PHASE;
665
666         Ret = XUsbPsu_SendEpCmd(InstancePtr, 0U, XUSBPSU_EP_DIR_OUT,
667                                 XUSBPSU_DEPCMD_STARTTRANSFER, Params);
668         if (Ret != XST_SUCCESS) {
669                 return (s32)XST_FAILURE;
670         }
671
672         Ept->EpStatus |= XUSBPSU_EP_BUSY;
673         Ept->ResourceIndex = (u8)XUsbPsu_EpGetTransferIndex(InstancePtr,
674                                                         Ept->UsbEpNum, Ept->Direction);
675
676         return XST_SUCCESS;
677 }
678
679 /*****************************************************************************/
680 /**
681 *
682 * API for Sleep routine.
683 *
684 * @param        USeconds is time in MicroSeconds.
685 *
686 * @return       None.
687 *
688 * @note         None.
689 *
690 ******************************************************************************/
691 void XUsbSleep(u32 USeconds) {
692         (void)usleep(USeconds);
693 }
694 /** @} */