]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Demo/CORTEX_R5_UltraScale_MPSoC/RTOSDemo_R5_bsp/psu_cortexr5_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_R5_UltraScale_MPSoC / RTOSDemo_R5_bsp / psu_cortexr5_0 / libsrc / usbpsu_v1_4 / src / xusbpsu_controltransfers.c
diff --git a/FreeRTOS/Demo/CORTEX_R5_UltraScale_MPSoC/RTOSDemo_R5_bsp/psu_cortexr5_0/libsrc/usbpsu_v1_4/src/xusbpsu_controltransfers.c b/FreeRTOS/Demo/CORTEX_R5_UltraScale_MPSoC/RTOSDemo_R5_bsp/psu_cortexr5_0/libsrc/usbpsu_v1_4/src/xusbpsu_controltransfers.c
new file mode 100644 (file)
index 0000000..19be417
--- /dev/null
@@ -0,0 +1,694 @@
+/******************************************************************************
+*
+* Copyright (C) 2016 Xilinx, Inc.  All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* Use of the Software is limited solely to applications:
+* (a) running on a Xilinx device, or
+* (b) that interact with a Xilinx device through a bus or interconnect.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* XILINX  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* Except as contained in this notice, the name of the Xilinx shall not be used
+* in advertising or otherwise to promote the sale, use or other dealings in
+* this Software without prior written authorization from Xilinx.
+*
+******************************************************************************/
+/****************************************************************************/
+/**
+*
+* @file xusbpsu_controltransfers.c
+* @addtogroup usbpsu_v1_0
+* @{
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.0   sg  06/06/16 First release
+* 1.3  vak 04/03/17 Added CCI support for USB
+* 1.4  bk  12/01/18 Modify USBPSU driver code to fit USB common example code
+*                   for all USB IPs.
+*
+* </pre>
+*
+*****************************************************************************/
+
+/***************************** Include Files *********************************/
+#include "xusbpsu_endpoint.h"
+#include "sleep.h"
+#include "xusb_wrapper.h"
+
+/************************** Constant Definitions *****************************/
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/************************** Function Prototypes ******************************/
+
+/************************** Variable Definitions *****************************/
+
+/****************************************************************************/
+/**
+* Initiates DMA on Control Endpoint 0 to receive Setup packet.
+*
+* @param       InstancePtr is a pointer to the XUsbPsu instance.
+*
+* @return      XST_SUCCESS else XST_FAILURE.
+*
+* @note                None.
+*
+*****************************************************************************/
+s32 XUsbPsu_RecvSetup(struct XUsbPsu *InstancePtr)
+{
+       struct XUsbPsu_EpParams *Params;
+       struct XUsbPsu_Trb      *TrbPtr;
+       struct XUsbPsu_Ep       *Ept;
+       s32     Ret;
+
+       Xil_AssertNonvoid(InstancePtr != NULL);
+
+       Params = XUsbPsu_GetEpParams(InstancePtr);
+       Xil_AssertNonvoid(Params != NULL);
+
+       /* Setup packet always on EP0 */
+       Ept = &InstancePtr->eps[0];
+       if ((Ept->EpStatus & XUSBPSU_EP_BUSY) != 0U) {
+               return (s32)XST_FAILURE;
+       }
+
+       TrbPtr = &InstancePtr->Ep0_Trb;
+
+       TrbPtr->BufferPtrLow = (UINTPTR)&InstancePtr->SetupData;
+       TrbPtr->BufferPtrHigh = ((UINTPTR)&InstancePtr->SetupData >> 16) >> 16;
+       TrbPtr->Size = 8U;
+       TrbPtr->Ctrl = XUSBPSU_TRBCTL_CONTROL_SETUP;
+
+       TrbPtr->Ctrl |= (XUSBPSU_TRB_CTRL_HWO
+                       | XUSBPSU_TRB_CTRL_LST
+                       | XUSBPSU_TRB_CTRL_IOC
+                       | XUSBPSU_TRB_CTRL_ISP_IMI);
+
+       if (InstancePtr->ConfigPtr->IsCacheCoherent == 0) {
+               Xil_DCacheFlushRange((INTPTR)TrbPtr, sizeof(struct XUsbPsu_Trb));
+               Xil_DCacheFlushRange((UINTPTR)&InstancePtr->SetupData, sizeof(SetupPacket));
+       }
+
+       Params->Param0 = 0U;
+       Params->Param1 = (UINTPTR)TrbPtr;
+
+       InstancePtr->Ep0State = XUSBPSU_EP0_SETUP_PHASE;
+
+       Ret = XUsbPsu_SendEpCmd(InstancePtr, 0U, XUSBPSU_EP_DIR_OUT,
+                               XUSBPSU_DEPCMD_STARTTRANSFER, Params);
+       if (Ret != XST_SUCCESS) {
+               return (s32)XST_FAILURE;
+       }
+
+       Ept->EpStatus |= XUSBPSU_EP_BUSY;
+       Ept->ResourceIndex = (u8)XUsbPsu_EpGetTransferIndex(InstancePtr,
+                                               Ept->UsbEpNum, Ept->Direction);
+
+       return XST_SUCCESS;
+}
+
+/****************************************************************************/
+/**
+* Stalls Control Endpoint and restarts to receive Setup packet.
+*
+* @param       InstancePtr is a pointer to the XUsbPsu instance.
+*
+* @return      None
+*
+* @note                None.
+*
+*****************************************************************************/
+void XUsbPsu_Ep0StallRestart(struct XUsbPsu *InstancePtr)
+{
+       struct XUsbPsu_Ep               *Ept;
+
+       Xil_AssertVoid(InstancePtr != NULL);
+
+       /* reinitialize physical ep1 */
+       Ept = &InstancePtr->eps[1];
+       Ept->EpStatus = XUSBPSU_EP_ENABLED;
+
+       /* stall is always issued on EP0 */
+       XUsbPsu_EpSetStall(InstancePtr, 0U, XUSBPSU_EP_DIR_OUT);
+
+       Ept = &InstancePtr->eps[0];
+       Ept->EpStatus = XUSBPSU_EP_ENABLED;
+       InstancePtr->Ep0State = XUSBPSU_EP0_SETUP_PHASE;
+       (void)XUsbPsu_RecvSetup(InstancePtr);
+}
+
+/****************************************************************************/
+/**
+* Checks the Data Phase and calls user Endpoint handler.
+*
+* @param       InstancePtr is a pointer to the XUsbPsu instance.
+* @param       Event is a pointer to the Endpoint event occured in core.
+*
+* @return      None.
+*
+* @note                None.
+*
+*****************************************************************************/
+void XUsbPsu_Ep0DataDone(struct XUsbPsu *InstancePtr,
+                                                const struct XUsbPsu_Event_Epevt *Event)
+{
+       struct XUsbPsu_Ep       *Ept;
+       struct XUsbPsu_Trb      *TrbPtr;
+       u32     Status;
+       u32     Length;
+       u32     Epnum;
+       u8      Dir;
+
+       Xil_AssertVoid(InstancePtr != NULL);
+       Xil_AssertVoid(Event != NULL);
+
+       Epnum = Event->Epnumber;
+       Dir = (u8)(!!Epnum);
+       Ept = &InstancePtr->eps[Epnum];
+       TrbPtr = &InstancePtr->Ep0_Trb;
+
+       if (InstancePtr->ConfigPtr->IsCacheCoherent == 0)
+               Xil_DCacheInvalidateRange((INTPTR)TrbPtr, sizeof(struct XUsbPsu_Trb));
+
+       Status = XUSBPSU_TRB_SIZE_TRBSTS(TrbPtr->Size);
+       if (Status == XUSBPSU_TRBSTS_SETUP_PENDING) {
+               return;
+       }
+
+       Length = TrbPtr->Size & XUSBPSU_TRB_SIZE_MASK;
+
+       if (Length == 0U) {
+               Ept->BytesTxed = Ept->RequestedBytes;
+       } else {
+               if (Dir == XUSBPSU_EP_DIR_IN) {
+                       Ept->BytesTxed = Ept->RequestedBytes - Length;
+               } else {
+                       if ((Dir == XUSBPSU_EP_DIR_OUT) && (Ept->UnalignedTx == 1U)) {
+                                       Ept->BytesTxed = Ept->RequestedBytes;
+                                       Ept->UnalignedTx = 0U;
+                       }
+               }
+       }
+
+       if (Dir == XUSBPSU_EP_DIR_OUT) {
+               /* Invalidate Cache */
+               if (InstancePtr->ConfigPtr->IsCacheCoherent == 0)
+                       Xil_DCacheInvalidateRange((INTPTR)Ept->BufferPtr, Ept->BytesTxed);
+       }
+
+       if (Ept->Handler != NULL) {
+               Ept->Handler(InstancePtr->AppData, Ept->RequestedBytes, Ept->BytesTxed);
+       }
+}
+
+/****************************************************************************/
+/**
+* Checks the Status Phase and starts next Control transfer.
+*
+* @param       InstancePtr is a pointer to the XUsbPsu instance.
+* @param       Event is a pointer to the Endpoint event occured in core.
+*
+* @return      None.
+*
+* @note                None.
+*
+*****************************************************************************/
+void XUsbPsu_Ep0StatusDone(struct XUsbPsu *InstancePtr,
+               const struct XUsbPsu_Event_Epevt *Event)
+{
+       struct XUsbPsu_Trb      *TrbPtr;
+
+       Xil_AssertVoid(InstancePtr != NULL);
+       Xil_AssertVoid(Event != NULL);
+
+       TrbPtr = &InstancePtr->Ep0_Trb;
+
+       if (InstancePtr->IsInTestMode != 0U) {
+               s32 Ret;
+
+               Ret = XUsbPsu_SetTestMode(InstancePtr,
+                                       InstancePtr->TestMode);
+               if (Ret < 0) {
+                       XUsbPsu_Ep0StallRestart(InstancePtr);
+                       return;
+               }
+       }
+       if (InstancePtr->ConfigPtr->IsCacheCoherent == 0)
+               Xil_DCacheInvalidateRange((INTPTR)TrbPtr, sizeof(struct XUsbPsu_Trb));
+
+       (void)XUsbPsu_RecvSetup(InstancePtr);
+}
+
+/****************************************************************************/
+/**
+* Handles Transfer complete event of Control Endpoints EP0 OUT and EP0 IN.
+*
+* @param       InstancePtr is a pointer to the XUsbPsu instance.
+* @param       Event is a pointer to the Endpoint event occured in core.
+*
+* @return      None.
+*
+* @note                None.
+*
+*****************************************************************************/
+void XUsbPsu_Ep0XferComplete(struct XUsbPsu *InstancePtr,
+                                                        const struct XUsbPsu_Event_Epevt *Event)
+{
+       struct XUsbPsu_Ep *Ept;
+       SetupPacket *Ctrl;
+       u16 Length;
+
+       Xil_AssertVoid(InstancePtr != NULL);
+       Xil_AssertVoid(Event != NULL);
+
+       Ept = &InstancePtr->eps[Event->Epnumber];
+       Ctrl = &InstancePtr->SetupData;
+
+       Ept->EpStatus &= ~XUSBPSU_EP_BUSY;
+       Ept->ResourceIndex = 0U;
+
+       switch (InstancePtr->Ep0State) {
+       case XUSBPSU_EP0_SETUP_PHASE:
+               if (InstancePtr->ConfigPtr->IsCacheCoherent == 0) {
+                       Xil_DCacheInvalidateRange((INTPTR)&InstancePtr->SetupData,
+                                       sizeof(InstancePtr->SetupData));
+               }
+               Length = Ctrl->wLength;
+               if (Length == 0U) {
+                       InstancePtr->IsThreeStage = 0U;
+                       InstancePtr->ControlDir = XUSBPSU_EP_DIR_OUT;
+               } else {
+                       InstancePtr->IsThreeStage = 1U;
+                       InstancePtr->ControlDir = !!(Ctrl->bRequestType &
+                                                       USB_DIR_IN);
+               }
+
+               Xil_AssertVoid(InstancePtr->Chapter9 != NULL);
+
+               InstancePtr->Chapter9(InstancePtr->AppData,
+                                                                       &InstancePtr->SetupData);
+               break;
+
+       case XUSBPSU_EP0_DATA_PHASE:
+               XUsbPsu_Ep0DataDone(InstancePtr, Event);
+               break;
+
+       case XUSBPSU_EP0_STATUS_PHASE:
+               XUsbPsu_Ep0StatusDone(InstancePtr, Event);
+               break;
+
+       default:
+               /* Default case is a required MISRA-C guideline. */
+               break;
+       }
+}
+
+/****************************************************************************/
+/**
+* Starts Status Phase of Control Transfer
+*
+* @param       InstancePtr is a pointer to the XUsbPsu instance.
+* @param       Event is a pointer to the Endpoint event occured in core.
+*
+* @return      XST_SUCCESS else XST_FAILURE
+*
+* @note                None.
+*
+*****************************************************************************/
+s32 XUsbPsu_Ep0StartStatus(struct XUsbPsu *InstancePtr,
+                               const struct XUsbPsu_Event_Epevt *Event)
+{
+       struct XUsbPsu_Ep  *Ept;
+       struct XUsbPsu_EpParams *Params;
+       struct XUsbPsu_Trb *TrbPtr;
+       u32 Type;
+       s32 Ret;
+       u8 Dir;
+
+       Xil_AssertNonvoid(InstancePtr != NULL);
+       Xil_AssertNonvoid(Event != NULL);
+
+       Ept = &InstancePtr->eps[Event->Epnumber];
+       Params = XUsbPsu_GetEpParams(InstancePtr);
+       Xil_AssertNonvoid(Params != NULL);
+       if ((Ept->EpStatus & XUSBPSU_EP_BUSY) != 0U) {
+               return (s32)XST_FAILURE;
+       }
+
+       Type = (InstancePtr->IsThreeStage != 0U) ? XUSBPSU_TRBCTL_CONTROL_STATUS3
+                                       : XUSBPSU_TRBCTL_CONTROL_STATUS2;
+       TrbPtr = &InstancePtr->Ep0_Trb;
+       /* we use same TrbPtr for setup packet */
+       TrbPtr->BufferPtrLow = (UINTPTR)&InstancePtr->SetupData;
+       TrbPtr->BufferPtrHigh = ((UINTPTR)&InstancePtr->SetupData >> 16) >> 16;
+       TrbPtr->Size = 0U;
+       TrbPtr->Ctrl = Type;
+
+       TrbPtr->Ctrl |= (XUSBPSU_TRB_CTRL_HWO
+                       | XUSBPSU_TRB_CTRL_LST
+                       | XUSBPSU_TRB_CTRL_IOC
+                       | XUSBPSU_TRB_CTRL_ISP_IMI);
+
+       if (InstancePtr->ConfigPtr->IsCacheCoherent == 0) {
+               Xil_DCacheFlushRange((INTPTR)TrbPtr, sizeof(struct XUsbPsu_Trb));
+       }
+
+       Params->Param0 = 0U;
+       Params->Param1 = (UINTPTR)TrbPtr;
+
+       InstancePtr->Ep0State = XUSBPSU_EP0_STATUS_PHASE;
+
+       /*
+        * Control OUT transfer - Status stage happens on EP0 IN - EP1
+        * Control IN transfer - Status stage happens on EP0 OUT - EP0
+        */
+       Dir = !InstancePtr->ControlDir;
+
+       Ret = XUsbPsu_SendEpCmd(InstancePtr, 0U, Dir,
+                                                       XUSBPSU_DEPCMD_STARTTRANSFER, Params);
+       if (Ret != XST_SUCCESS) {
+               return (s32)XST_FAILURE;
+       }
+
+       Ept->EpStatus |= XUSBPSU_EP_BUSY;
+       Ept->ResourceIndex = (u8)XUsbPsu_EpGetTransferIndex(InstancePtr,
+                                                       Ept->UsbEpNum, Ept->Direction);
+
+       return XST_SUCCESS;
+}
+
+/****************************************************************************/
+/**
+* Ends Data Phase - used incase of error.
+*
+* @param       InstancePtr is a pointer to the XUsbPsu instance.
+* @param       Dep is a pointer to the Endpoint structure.
+*
+* @return      None
+*
+* @note                None.
+*
+*****************************************************************************/
+void XUsbPsu_Ep0_EndControlData(struct XUsbPsu *InstancePtr,
+                                                               struct XUsbPsu_Ep *Ept)
+{
+       struct XUsbPsu_EpParams *Params;
+       u32     Cmd;
+
+       Xil_AssertVoid(InstancePtr != NULL);
+       Xil_AssertVoid(Ept != NULL);
+
+       if (Ept->ResourceIndex == 0U) {
+               return;
+       }
+
+       Params = XUsbPsu_GetEpParams(InstancePtr);
+       Xil_AssertVoid(Params != NULL);
+
+       Cmd = XUSBPSU_DEPCMD_ENDTRANSFER;
+       Cmd |= XUSBPSU_DEPCMD_PARAM(Ept->ResourceIndex);
+       (void)XUsbPsu_SendEpCmd(InstancePtr, Ept->UsbEpNum, Ept->Direction,
+                                               Cmd, Params);
+       Ept->ResourceIndex = 0U;
+       XUsbSleep(200U);
+}
+
+/****************************************************************************/
+/**
+* Handles Transfer Not Ready event of Control Endpoints EP0 OUT and EP0 IN.
+*
+* @param       InstancePtr is a pointer to the XUsbPsu instance.
+* @param       Event is a pointer to the Endpoint event occured in core.
+*
+* @return      None.
+*
+* @note                None.
+*
+*****************************************************************************/
+void XUsbPsu_Ep0XferNotReady(struct XUsbPsu *InstancePtr,
+                                                        const struct XUsbPsu_Event_Epevt *Event)
+{
+       struct XUsbPsu_Ep *Ept;
+
+       Xil_AssertVoid(InstancePtr != NULL);
+       Xil_AssertVoid(Event != NULL);
+
+       Ept = &InstancePtr->eps[Event->Epnumber];
+
+       switch (Event->Status) {
+       case DEPEVT_STATUS_CONTROL_DATA:
+               /*
+                * We already have a DATA transfer in the controller's cache,
+                * if we receive a XferNotReady(DATA) we will ignore it, unless
+                * it's for the wrong direction.
+                *
+                * In that case, we must issue END_TRANSFER command to the Data
+                * Phase we already have started and issue SetStall on the
+                * control endpoint.
+                */
+               if (Event->Epnumber != InstancePtr->ControlDir) {
+                       XUsbPsu_Ep0_EndControlData(InstancePtr, Ept);
+                       XUsbPsu_Ep0StallRestart(InstancePtr);
+               }
+               break;
+
+       case DEPEVT_STATUS_CONTROL_STATUS:
+               (void)XUsbPsu_Ep0StartStatus(InstancePtr, Event);
+               break;
+
+       default:
+               /* Default case is a required MIRSA-C guideline. */
+               break;
+       }
+}
+
+/****************************************************************************/
+/**
+* Handles Interrupts of Control Endpoints EP0 OUT and EP0 IN.
+*
+* @param       InstancePtr is a pointer to the XUsbPsu instance.
+* @param       Event is a pointer to the Endpoint event occured in core.
+*
+* @return      None.
+*
+* @note                None.
+*
+*****************************************************************************/
+void XUsbPsu_Ep0Intr(struct XUsbPsu *InstancePtr,
+               const struct XUsbPsu_Event_Epevt *Event)
+{
+
+       Xil_AssertVoid(InstancePtr != NULL);
+       Xil_AssertVoid(Event != NULL);
+
+       switch (Event->Endpoint_Event) {
+       case XUSBPSU_DEPEVT_XFERCOMPLETE:
+               XUsbPsu_Ep0XferComplete(InstancePtr, Event);
+               break;
+
+       case XUSBPSU_DEPEVT_XFERNOTREADY:
+               XUsbPsu_Ep0XferNotReady(InstancePtr, Event);
+               break;
+
+       case XUSBPSU_DEPEVT_XFERINPROGRESS:
+       case XUSBPSU_DEPEVT_STREAMEVT:
+       case XUSBPSU_DEPEVT_EPCMDCMPLT:
+               break;
+
+       default:
+               /* Default case is a required MIRSA-C guideline. */
+               break;
+       }
+}
+
+/****************************************************************************/
+/**
+* Initiates DMA to send data on Control Endpoint EP0 IN to Host.
+*
+* @param       InstancePtr is a pointer to the XUsbPsu instance.
+* @param       BufferPtr is pointer to data.
+* @param       BufferLen is Length of data buffer.
+*
+* @return      XST_SUCCESS else XST_FAILURE
+*
+* @note                None.
+*
+*****************************************************************************/
+s32 XUsbPsu_Ep0Send(struct XUsbPsu *InstancePtr, u8 *BufferPtr, u32 BufferLen)
+{
+       /* Control IN - EP1 */
+       struct XUsbPsu_EpParams *Params;
+       struct XUsbPsu_Ep       *Ept;
+       struct XUsbPsu_Trb      *TrbPtr;
+       s32 Ret;
+
+       Xil_AssertNonvoid(InstancePtr != NULL);
+       Xil_AssertNonvoid(BufferPtr != NULL);
+
+       Ept = &InstancePtr->eps[1];
+       Params = XUsbPsu_GetEpParams(InstancePtr);
+       Xil_AssertNonvoid(Params != NULL);
+
+       if ((Ept->EpStatus & XUSBPSU_EP_BUSY) != 0U) {
+               return (s32)XST_FAILURE;
+       }
+
+       Ept->RequestedBytes = BufferLen;
+       Ept->BytesTxed = 0U;
+       Ept->BufferPtr = BufferPtr;
+
+       TrbPtr = &InstancePtr->Ep0_Trb;
+
+       TrbPtr->BufferPtrLow  = (UINTPTR)BufferPtr;
+       TrbPtr->BufferPtrHigh  = ((UINTPTR)BufferPtr >> 16) >> 16;
+       TrbPtr->Size = BufferLen;
+       TrbPtr->Ctrl = XUSBPSU_TRBCTL_CONTROL_DATA;
+
+       TrbPtr->Ctrl |= (XUSBPSU_TRB_CTRL_HWO
+                       | XUSBPSU_TRB_CTRL_LST
+                       | XUSBPSU_TRB_CTRL_IOC
+                       | XUSBPSU_TRB_CTRL_ISP_IMI);
+
+       Params->Param0 = 0U;
+       Params->Param1 = (UINTPTR)TrbPtr;
+
+       if (InstancePtr->ConfigPtr->IsCacheCoherent == 0) {
+               Xil_DCacheFlushRange((INTPTR)TrbPtr, sizeof(struct XUsbPsu_Trb));
+               Xil_DCacheFlushRange((INTPTR)BufferPtr, BufferLen);
+       }
+
+       InstancePtr->Ep0State = XUSBPSU_EP0_DATA_PHASE;
+
+       Ret = XUsbPsu_SendEpCmd(InstancePtr, 0U, XUSBPSU_EP_DIR_IN,
+                                                       XUSBPSU_DEPCMD_STARTTRANSFER, Params);
+       if (Ret != XST_SUCCESS) {
+               return (s32)XST_FAILURE;
+       }
+
+       Ept->EpStatus |= XUSBPSU_EP_BUSY;
+       Ept->ResourceIndex = (u8)XUsbPsu_EpGetTransferIndex(InstancePtr,
+                                               Ept->UsbEpNum, Ept->Direction);
+
+       return XST_SUCCESS;
+}
+
+/****************************************************************************/
+/**
+* Initiates DMA to receive data on Control Endpoint EP0 OUT from Host.
+*
+* @param       InstancePtr is a pointer to the XUsbPsu instance.
+* @param       BufferPtr is pointer to data.
+* @param       Length is Length of data to be received.
+*
+* @return      XST_SUCCESS else XST_FAILURE
+*
+* @note                None.
+*
+*****************************************************************************/
+s32 XUsbPsu_Ep0Recv(struct XUsbPsu *InstancePtr, u8 *BufferPtr, u32 Length)
+{
+       struct XUsbPsu_EpParams *Params;
+       struct XUsbPsu_Ep       *Ept;
+       struct XUsbPsu_Trb      *TrbPtr;
+       u32 Size;
+       s32 Ret;
+
+       Xil_AssertNonvoid(InstancePtr != NULL);
+       Xil_AssertNonvoid(BufferPtr != NULL);
+
+       Ept = &InstancePtr->eps[0];
+       Params = XUsbPsu_GetEpParams(InstancePtr);
+       Xil_AssertNonvoid(Params != NULL);
+
+       if ((Ept->EpStatus & XUSBPSU_EP_BUSY) != 0U) {
+               return (s32)XST_FAILURE;
+       }
+
+       Ept->RequestedBytes = Length;
+       Size = Length;
+       Ept->BytesTxed = 0U;
+       Ept->BufferPtr = BufferPtr;
+
+       /*
+        * 8.2.5 - An OUT transfer size (Total TRB buffer allocation)
+        * must be a multiple of MaxPacketSize even if software is expecting a
+        * fixed non-multiple of MaxPacketSize transfer from the Host.
+        */
+       if (!IS_ALIGNED(Length, Ept->MaxSize)) {
+               Size = (u32)roundup(Length, Ept->MaxSize);
+               Ept->UnalignedTx = 1U;
+       }
+
+       TrbPtr = &InstancePtr->Ep0_Trb;
+
+       TrbPtr->BufferPtrLow = (UINTPTR)BufferPtr;
+       TrbPtr->BufferPtrHigh = ((UINTPTR)BufferPtr >> 16) >> 16;
+       TrbPtr->Size = Size;
+       TrbPtr->Ctrl = XUSBPSU_TRBCTL_CONTROL_DATA;
+
+       TrbPtr->Ctrl |= (XUSBPSU_TRB_CTRL_HWO
+                       | XUSBPSU_TRB_CTRL_LST
+                       | XUSBPSU_TRB_CTRL_IOC
+                       | XUSBPSU_TRB_CTRL_ISP_IMI);
+
+       if (InstancePtr->ConfigPtr->IsCacheCoherent == 0) {
+               Xil_DCacheFlushRange((INTPTR)TrbPtr, sizeof(struct XUsbPsu_Trb));
+               Xil_DCacheInvalidateRange((INTPTR)BufferPtr, Length);
+       }
+
+       Params->Param0 = 0U;
+       Params->Param1 = (UINTPTR)TrbPtr;
+
+       InstancePtr->Ep0State = XUSBPSU_EP0_DATA_PHASE;
+
+       Ret = XUsbPsu_SendEpCmd(InstancePtr, 0U, XUSBPSU_EP_DIR_OUT,
+                               XUSBPSU_DEPCMD_STARTTRANSFER, Params);
+       if (Ret != XST_SUCCESS) {
+               return (s32)XST_FAILURE;
+       }
+
+       Ept->EpStatus |= XUSBPSU_EP_BUSY;
+       Ept->ResourceIndex = (u8)XUsbPsu_EpGetTransferIndex(InstancePtr,
+                                                       Ept->UsbEpNum, Ept->Direction);
+
+       return XST_SUCCESS;
+}
+
+/*****************************************************************************/
+/**
+*
+* API for Sleep routine.
+*
+* @param       USeconds is time in MicroSeconds.
+*
+* @return      None.
+*
+* @note                None.
+*
+******************************************************************************/
+void XUsbSleep(u32 USeconds) {
+       (void)usleep(USeconds);
+}
+/** @} */