--- /dev/null
+/******************************************************************************
+*
+* 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_endpoint.c
+* @addtogroup usbpsu_v1_3
+* @{
+*
+*
+* <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
+* myk 12/01/18 Added hibernation support for device mode
+* </pre>
+*
+*****************************************************************************/
+
+/***************************** Include Files *********************************/
+#include "xusbpsu_endpoint.h"
+
+/************************** Constant Definitions *****************************/
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/************************** Function Prototypes ******************************/
+
+/************************** Variable Definitions *****************************/
+
+/****************************************************************************/
+/**
+* Returns zeroed parameters to be used by Endpoint commands
+*
+* @param InstancePtr is a pointer to the XUsbPsu instance.
+*
+* @return Zeroed Params structure pointer.
+*
+* @note None.
+*
+*****************************************************************************/
+struct XUsbPsu_EpParams *XUsbPsu_GetEpParams(struct XUsbPsu *InstancePtr)
+{
+ if (InstancePtr == NULL) {
+ return NULL;
+ }
+
+ InstancePtr->EpParams.Param0 = 0x00U;
+ InstancePtr->EpParams.Param1 = 0x00U;
+ InstancePtr->EpParams.Param2 = 0x00U;
+
+ return &InstancePtr->EpParams;
+}
+
+/****************************************************************************/
+/**
+* Returns Transfer Index assigned by Core for an Endpoint transfer.
+*
+* @param InstancePtr is a pointer to the XUsbPsu instance.
+* @param UsbEpNum is USB endpoint number.
+* @param Dir is direction of endpoint - XUSBPSU_EP_DIR_IN/XUSBPSU_EP_DIR_OUT
+*
+* @return Transfer Resource Index.
+*
+* @note None.
+*
+*****************************************************************************/
+u32 XUsbPsu_EpGetTransferIndex(struct XUsbPsu *InstancePtr, u8 UsbEpNum,
+ u8 Dir)
+{
+ u8 PhyEpNum;
+ u32 ResourceIndex;
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(UsbEpNum <= (u8)16U);
+ Xil_AssertNonvoid((Dir == XUSBPSU_EP_DIR_IN) ||
+ (Dir == XUSBPSU_EP_DIR_OUT));
+
+ PhyEpNum = (u8)PhysicalEp(UsbEpNum, Dir);
+ ResourceIndex = XUsbPsu_ReadReg(InstancePtr, XUSBPSU_DEPCMD(PhyEpNum));
+
+ return (u32)XUSBPSU_DEPCMD_GET_RSC_IDX(ResourceIndex);
+}
+
+/****************************************************************************/
+/**
+* Sends Endpoint command to Endpoint.
+*
+* @param InstancePtr is a pointer to the XUsbPsu instance.
+* @param UsbEpNum is USB endpoint number.
+* @param Dir is direction of endpoint
+* - XUSBPSU_EP_DIR_IN/ XUSBPSU_EP_DIR_OUT.
+* @param Cmd is Endpoint command.
+* @param Params is Endpoint command parameters.
+*
+* @return XST_SUCCESS else XST_FAILURE.
+*
+* @note None.
+*
+*****************************************************************************/
+s32 XUsbPsu_SendEpCmd(struct XUsbPsu *InstancePtr, u8 UsbEpNum, u8 Dir,
+ u32 Cmd, struct XUsbPsu_EpParams *Params)
+{
+ u32 PhyEpNum;
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(UsbEpNum <= (u8)16U);
+ Xil_AssertNonvoid((Dir == XUSBPSU_EP_DIR_IN) ||
+ (Dir == XUSBPSU_EP_DIR_OUT));
+
+ PhyEpNum = PhysicalEp(UsbEpNum, Dir);
+
+ XUsbPsu_WriteReg(InstancePtr, XUSBPSU_DEPCMDPAR0(PhyEpNum),
+ Params->Param0);
+ XUsbPsu_WriteReg(InstancePtr, XUSBPSU_DEPCMDPAR1(PhyEpNum),
+ Params->Param1);
+ XUsbPsu_WriteReg(InstancePtr, XUSBPSU_DEPCMDPAR2(PhyEpNum),
+ Params->Param2);
+
+ XUsbPsu_WriteReg(InstancePtr, XUSBPSU_DEPCMD(PhyEpNum),
+ Cmd | XUSBPSU_DEPCMD_CMDACT);
+
+ if (XUsbPsu_Wait_Clear_Timeout(InstancePtr, XUSBPSU_DEPCMD(PhyEpNum),
+ XUSBPSU_DEPCMD_CMDACT, 500U) == (s32)XST_FAILURE) {
+ return XST_FAILURE;
+ }
+
+ return XST_SUCCESS;
+}
+
+/****************************************************************************/
+/**
+* Sends Start New Configuration command to Endpoint.
+*
+* @param InstancePtr is a pointer to the XUsbPsu instance.
+* @param UsbEpNum is USB endpoint number.
+* @param Dir is direction of endpoint
+* - XUSBPSU_EP_DIR_IN/ XUSBPSU_EP_DIR_OUT.
+*
+* @return XST_SUCCESS else XST_FAILURE.
+*
+* @note
+* As per data book this command should be issued by software
+* under these conditions:
+* 1. After power-on-reset with XferRscIdx=0 before starting
+* to configure Physical Endpoints 0 and 1.
+* 2. With XferRscIdx=2 before starting to configure
+* Physical Endpoints > 1
+* 3. This command should always be issued to
+* Endpoint 0 (DEPCMD0).
+*
+*****************************************************************************/
+s32 XUsbPsu_StartEpConfig(struct XUsbPsu *InstancePtr, u32 UsbEpNum, u8 Dir)
+{
+ struct XUsbPsu_EpParams *Params;
+ u32 Cmd;
+ u8 PhyEpNum;
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(UsbEpNum <= (u32)16U);
+ Xil_AssertNonvoid((Dir == XUSBPSU_EP_DIR_IN) ||
+ (Dir == XUSBPSU_EP_DIR_OUT));
+
+ PhyEpNum = (u8)PhysicalEp(UsbEpNum, (u32)Dir);
+ Params = XUsbPsu_GetEpParams(InstancePtr);
+ Xil_AssertNonvoid(Params != NULL);
+
+ if (PhyEpNum != 1U) {
+ Cmd = XUSBPSU_DEPCMD_DEPSTARTCFG;
+ /* XferRscIdx == 0 for EP0 and 2 for the remaining */
+ if (PhyEpNum > 1U) {
+ if (InstancePtr->IsConfigDone != 0U) {
+ return XST_SUCCESS;
+ }
+ InstancePtr->IsConfigDone = 1U;
+ Cmd |= XUSBPSU_DEPCMD_PARAM(2);
+ }
+
+ return XUsbPsu_SendEpCmd(InstancePtr, 0U, XUSBPSU_EP_DIR_OUT,
+ Cmd, Params);
+ }
+
+ return XST_SUCCESS;
+}
+
+/****************************************************************************/
+/**
+* Sends Set Endpoint Configuration command to Endpoint.
+*
+* @param InstancePtr is a pointer to the XUsbPsu instance.
+* @param UsbEpNum is USB endpoint number.
+* @param Dir is direction of endpoint - XUSBPSU_EP_DIR_IN/XUSBPSU_EP_DIR_OUT.
+* @param Size is size of Endpoint size.
+* @param Type is Endpoint type Control/Bulk/Interrupt/Isoc.
+* @param Restore should be true if saved state should be restored;
+* typically this would be false
+*
+* @return XST_SUCCESS else XST_FAILURE.
+*
+* @note None.
+*
+*****************************************************************************/
+s32 XUsbPsu_SetEpConfig(struct XUsbPsu *InstancePtr, u8 UsbEpNum, u8 Dir,
+ u16 Size, u8 Type, u8 Restore)
+{
+ struct XUsbPsu_Ep *Ept;
+ struct XUsbPsu_EpParams *Params;
+ u8 PhyEpNum;
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(UsbEpNum <= (u8)16U);
+ Xil_AssertNonvoid((Dir == XUSBPSU_EP_DIR_IN) ||
+ (Dir == XUSBPSU_EP_DIR_OUT));
+ Xil_AssertNonvoid((Size >= 64U) && (Size <= 1024U));
+
+ Params = XUsbPsu_GetEpParams(InstancePtr);
+ Xil_AssertNonvoid(Params != NULL);
+
+ PhyEpNum = PhysicalEp(UsbEpNum , Dir);
+ Ept = &InstancePtr->eps[PhyEpNum];
+
+ Params->Param0 = XUSBPSU_DEPCFG_EP_TYPE(Type)
+ | XUSBPSU_DEPCFG_MAX_PACKET_SIZE(Size);
+
+ /*
+ * Set burst size to 1 as recommended
+ */
+ if (InstancePtr->AppData->Speed == XUSBPSU_SPEED_SUPER) {
+ Params->Param0 |= XUSBPSU_DEPCFG_BURST_SIZE(1);
+ }
+
+ Params->Param1 = XUSBPSU_DEPCFG_XFER_COMPLETE_EN
+ | XUSBPSU_DEPCFG_XFER_NOT_READY_EN;
+
+ if (Restore) {
+ Params->Param0 |= XUSBPSU_DEPCFG_ACTION_RESTORE;
+ Params->Param2 = Ept->EpSavedState;
+ }
+
+ /*
+ * We are doing 1:1 mapping for endpoints, meaning
+ * Physical Endpoints 2 maps to Logical Endpoint 2 and
+ * so on. We consider the direction bit as part of the physical
+ * endpoint number. So USB endpoint 0x81 is 0x03.
+ */
+ Params->Param1 |= XUSBPSU_DEPCFG_EP_NUMBER(PhyEpNum);
+
+ if (Dir != XUSBPSU_EP_DIR_OUT) {
+ Params->Param0 |= XUSBPSU_DEPCFG_FIFO_NUMBER((u32)PhyEpNum >> 1);
+ }
+
+ if (Ept->Type == XUSBPSU_ENDPOINT_XFER_ISOC) {
+ Params->Param1 |= XUSBPSU_DEPCFG_BINTERVAL_M1(Ept->Interval - 1);
+ Params->Param1 |= XUSBPSU_DEPCFG_XFER_IN_PROGRESS_EN;
+ }
+
+ return XUsbPsu_SendEpCmd(InstancePtr, UsbEpNum, Dir,
+ XUSBPSU_DEPCMD_SETEPCONFIG, Params);
+}
+
+/****************************************************************************/
+/**
+* Sends Set Transfer Resource command to Endpoint.
+*
+* @param InstancePtr is a pointer to the XUsbPsu instance.
+* @param UsbEpNum is USB endpoint number.
+* @param Dir is direction of endpoint - XUSBPSU_EP_DIR_IN/
+* XUSBPSU_EP_DIR_OUT.
+*
+* @return XST_SUCCESS else XST_FAILURE.
+*
+* @note None.
+*
+*****************************************************************************/
+s32 XUsbPsu_SetXferResource(struct XUsbPsu *InstancePtr, u8 UsbEpNum, u8 Dir)
+{
+ struct XUsbPsu_EpParams *Params;
+
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(UsbEpNum <= (u8)16U);
+ Xil_AssertNonvoid((Dir == XUSBPSU_EP_DIR_IN) ||
+ (Dir == XUSBPSU_EP_DIR_OUT));
+
+ Params = XUsbPsu_GetEpParams(InstancePtr);
+ Xil_AssertNonvoid(Params != NULL);
+
+ Params->Param0 = XUSBPSU_DEPXFERCFG_NUM_XFER_RES(1);
+
+ return XUsbPsu_SendEpCmd(InstancePtr, UsbEpNum, Dir,
+ XUSBPSU_DEPCMD_SETTRANSFRESOURCE, Params);
+}
+
+/****************************************************************************/
+/**
+* Enables Endpoint for sending/receiving data.
+*
+* @param InstancePtr is a pointer to the XUsbPsu instance.
+* @param UsbEpNum is USB endpoint number.
+* @param Dir is direction of endpoint - XUSBPSU_EP_DIR_IN/XUSBPSU_EP_DIR_OUT.
+* @param Maxsize is size of Endpoint size.
+* @param Type is Endpoint type Control/Bulk/Interrupt/Isoc.
+* @param Restore should be true if saved state should be restored;
+* typically this would be false
+*
+* @return XST_SUCCESS else XST_FAILURE.
+*
+* @note None.
+*
+****************************************************************************/
+s32 XUsbPsu_EpEnable(struct XUsbPsu *InstancePtr, u8 UsbEpNum, u8 Dir,
+ u16 Maxsize, u8 Type, u8 Restore)
+{
+ struct XUsbPsu_Ep *Ept;
+ struct XUsbPsu_Trb *TrbStHw, *TrbLink;
+ u32 RegVal;
+ s32 Ret = (s32)XST_FAILURE;
+ u32 PhyEpNum;
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(UsbEpNum <= (u8)16U);
+ Xil_AssertNonvoid((Dir == XUSBPSU_EP_DIR_IN) ||
+ (Dir == XUSBPSU_EP_DIR_OUT));
+ Xil_AssertNonvoid((Maxsize >= 64U) && (Maxsize <= 1024U));
+
+ PhyEpNum = PhysicalEp(UsbEpNum , Dir);
+ Ept = &InstancePtr->eps[PhyEpNum];
+
+ Ept->UsbEpNum = UsbEpNum;
+ Ept->Direction = Dir;
+ Ept->Type = Type;
+ Ept->MaxSize = Maxsize;
+ Ept->PhyEpNum = (u8)PhyEpNum;
+ Ept->CurUf = 0;
+ if (!InstancePtr->IsHibernated) {
+ Ept->TrbEnqueue = 0;
+ Ept->TrbDequeue = 0;
+ }
+
+ if (((Ept->EpStatus & XUSBPSU_EP_ENABLED) == 0U)
+ || (InstancePtr->IsHibernated)) {
+ Ret = XUsbPsu_StartEpConfig(InstancePtr, UsbEpNum, Dir);
+ if (Ret != 0) {
+ return Ret;
+ }
+ }
+
+ Ret = XUsbPsu_SetEpConfig(InstancePtr, UsbEpNum, Dir, Maxsize,
+ Type, Restore);
+ if (Ret != 0) {
+ return Ret;
+ }
+
+ if (((Ept->EpStatus & XUSBPSU_EP_ENABLED) == 0U)
+ || (InstancePtr->IsHibernated)) {
+ Ret = XUsbPsu_SetXferResource(InstancePtr, UsbEpNum, Dir);
+ if (Ret != 0) {
+ return Ret;
+ }
+
+ Ept->EpStatus |= XUSBPSU_EP_ENABLED;
+
+ RegVal = XUsbPsu_ReadReg(InstancePtr, XUSBPSU_DALEPENA);
+ RegVal |= XUSBPSU_DALEPENA_EP(Ept->PhyEpNum);
+ XUsbPsu_WriteReg(InstancePtr, XUSBPSU_DALEPENA, RegVal);
+
+ /* Following code is only applicable for ISO XFER */
+ TrbStHw = &Ept->EpTrb[0];
+
+ /* Link TRB. The HWO bit is never reset */
+ TrbLink = &Ept->EpTrb[NO_OF_TRB_PER_EP];
+ memset(TrbLink, 0x00, sizeof(struct XUsbPsu_Trb));
+
+ TrbLink->BufferPtrLow = (UINTPTR)TrbStHw;
+ TrbLink->BufferPtrHigh = ((UINTPTR)TrbStHw >> 16) >> 16;
+ TrbLink->Ctrl |= XUSBPSU_TRBCTL_LINK_TRB;
+ TrbLink->Ctrl |= XUSBPSU_TRB_CTRL_HWO;
+ }
+
+ return XST_SUCCESS;
+}
+
+/****************************************************************************/
+/**
+* Disables Endpoint.
+*
+* @param InstancePtr is a pointer to the XUsbPsu instance.
+* @param UsbEpNum is USB endpoint number.
+* @param Dir is direction of endpoint
+* - XUSBPSU_EP_DIR_IN/XUSBPSU_EP_DIR_OUT.
+*
+* @return XST_SUCCESS else XST_FAILURE.
+*
+* @note None.
+*
+****************************************************************************/
+s32 XUsbPsu_EpDisable(struct XUsbPsu *InstancePtr, u8 UsbEpNum, u8 Dir)
+{
+ u32 RegVal;
+ u8 PhyEpNum;
+ struct XUsbPsu_Ep *Ept;
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(UsbEpNum <= (u8)16U);
+ Xil_AssertNonvoid((Dir == XUSBPSU_EP_DIR_IN) ||
+ (Dir == XUSBPSU_EP_DIR_OUT));
+
+ PhyEpNum = PhysicalEp(UsbEpNum , Dir);
+ Ept = &InstancePtr->eps[PhyEpNum];
+
+ /* make sure HW endpoint isn't stalled */
+ if (Ept->EpStatus & XUSBPSU_EP_STALL)
+ XUsbPsu_EpClearStall(InstancePtr, Ept->UsbEpNum, Ept->Direction);
+
+ RegVal = XUsbPsu_ReadReg(InstancePtr, XUSBPSU_DALEPENA);
+ RegVal &= ~XUSBPSU_DALEPENA_EP(PhyEpNum);
+ XUsbPsu_WriteReg(InstancePtr, XUSBPSU_DALEPENA, RegVal);
+
+ Ept->Type = 0U;
+ Ept->EpStatus = 0U;
+ Ept->MaxSize = 0U;
+ Ept->TrbEnqueue = 0U;
+ Ept->TrbDequeue = 0U;
+
+ return XST_SUCCESS;
+}
+
+/****************************************************************************/
+/**
+* Enables USB Control Endpoint i.e., EP0OUT and EP0IN of Core.
+*
+* @param InstancePtr is a pointer to the XUsbPsu instance.
+* @param Size is control endpoint size.
+*
+* @return XST_SUCCESS else XST_FAILURE.
+*
+* @note None.
+*
+****************************************************************************/
+s32 XUsbPsu_EnableControlEp(struct XUsbPsu *InstancePtr, u16 Size)
+{
+ s32 RetVal;
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid((Size >= 64U) && (Size <= 512U));
+
+ RetVal = XUsbPsu_EpEnable(InstancePtr, 0U, XUSBPSU_EP_DIR_OUT, Size,
+ XUSBPSU_ENDPOINT_XFER_CONTROL, FALSE);
+ if (RetVal != 0) {
+ return XST_FAILURE;
+ }
+
+ RetVal = XUsbPsu_EpEnable(InstancePtr, 0U, XUSBPSU_EP_DIR_IN, Size,
+ XUSBPSU_ENDPOINT_XFER_CONTROL, FALSE);
+ if (RetVal != 0) {
+ return XST_FAILURE;
+ }
+
+ return XST_SUCCESS;
+}
+
+/****************************************************************************/
+/**
+* Initializes Endpoints. All OUT endpoints are even numbered and all IN
+* endpoints are odd numbered. EP0 is for Control OUT and EP1 is for
+* Control IN.
+*
+* @param InstancePtr is a pointer to the XUsbPsu instance.
+*
+* @return None.
+*
+* @note None.
+*
+****************************************************************************/
+void XUsbPsu_InitializeEps(struct XUsbPsu *InstancePtr)
+{
+ u8 i;
+ u8 Epnum;
+
+ Xil_AssertVoid(InstancePtr != NULL);
+
+ for (i = 0U; i < InstancePtr->NumOutEps; i++) {
+ Epnum = (i << 1U) | XUSBPSU_EP_DIR_OUT;
+ InstancePtr->eps[Epnum].PhyEpNum = Epnum;
+ InstancePtr->eps[Epnum].Direction = XUSBPSU_EP_DIR_OUT;
+ InstancePtr->eps[Epnum].ResourceIndex = 0;
+ }
+ for (i = 0U; i < InstancePtr->NumInEps; i++) {
+ Epnum = (i << 1U) | XUSBPSU_EP_DIR_IN;
+ InstancePtr->eps[Epnum].PhyEpNum = Epnum;
+ InstancePtr->eps[Epnum].Direction = XUSBPSU_EP_DIR_IN;
+ InstancePtr->eps[Epnum].ResourceIndex = 0;
+ }
+}
+
+/****************************************************************************/
+/**
+* Stops transfer on Endpoint.
+*
+* @param InstancePtr is a pointer to the XUsbPsu instance.
+* @param UsbEpNum is USB endpoint number.
+* @param Dir is direction of endpoint - XUSBPSU_EP_DIR_IN/XUSBPSU_EP_DIR_OUT.
+* @Force Force flag to stop/pause transfer.
+*
+* @return None.
+*
+* @note None.
+*
+****************************************************************************/
+void XUsbPsu_StopTransfer(struct XUsbPsu *InstancePtr, u8 UsbEpNum,
+ u8 Dir, u8 Force)
+{
+ struct XUsbPsu_Ep *Ept;
+ struct XUsbPsu_EpParams *Params;
+ u8 PhyEpNum;
+ u32 Cmd;
+
+ Xil_AssertVoid(InstancePtr != NULL);
+ Xil_AssertVoid(UsbEpNum <= (u8)16U);
+ Xil_AssertVoid((Dir == XUSBPSU_EP_DIR_IN) || (Dir == XUSBPSU_EP_DIR_OUT));
+
+ PhyEpNum = PhysicalEp(UsbEpNum, Dir);
+ Params = XUsbPsu_GetEpParams(InstancePtr);
+ Xil_AssertVoid(Params != NULL);
+
+ Ept = &InstancePtr->eps[PhyEpNum];
+
+ if (Ept->ResourceIndex == 0U) {
+ return;
+ }
+
+ /*
+ * - Issue EndTransfer WITH CMDIOC bit set
+ * - Wait 100us
+ */
+ Cmd = XUSBPSU_DEPCMD_ENDTRANSFER;
+ Cmd |= Force ? XUSBPSU_DEPCMD_HIPRI_FORCERM : 0;
+ Cmd |= XUSBPSU_DEPCMD_CMDIOC;
+ Cmd |= XUSBPSU_DEPCMD_PARAM(Ept->ResourceIndex);
+ (void)XUsbPsu_SendEpCmd(InstancePtr, Ept->UsbEpNum, Ept->Direction,
+ Cmd, Params);
+ if (Force)
+ Ept->ResourceIndex = 0U;
+ Ept->EpStatus &= ~XUSBPSU_EP_BUSY;
+ XUsbSleep(100U);
+}
+
+/****************************************************************************/
+/**
+* Query endpoint state and save it in EpSavedState
+*
+* @param InstancePtr is a pointer to the XUsbPsu instance.
+* @param Ept is a pointer to the XUsbPsu pointer structure.
+*
+* @return None.
+*
+* @note None.
+*
+****************************************************************************/
+void XUsbPsu_SaveEndpointState(struct XUsbPsu *InstancePtr, struct XUsbPsu_Ep *Ept)
+{
+ struct XUsbPsu_EpParams *Params = XUsbPsu_GetEpParams(InstancePtr);
+ XUsbPsu_SendEpCmd(InstancePtr, Ept->UsbEpNum, Ept->Direction,
+ XUSBPSU_DEPCMD_GETEPSTATE, Params);
+ Ept->EpSavedState = XUsbPsu_ReadReg(InstancePtr, XUSBPSU_DEPCMDPAR2(Ept->PhyEpNum));
+}
+
+/****************************************************************************/
+/**
+* Clears Stall on all endpoints.
+*
+* @param InstancePtr is a pointer to the XUsbPsu instance.
+*
+* @return None.
+*
+* @note None.
+*
+****************************************************************************/
+void XUsbPsu_ClearStalls(struct XUsbPsu *InstancePtr)
+{
+ struct XUsbPsu_EpParams *Params;
+ u32 Epnum;
+ struct XUsbPsu_Ep *Ept;
+
+ Xil_AssertVoid(InstancePtr != NULL);
+
+ Params = XUsbPsu_GetEpParams(InstancePtr);
+ Xil_AssertVoid(Params != NULL);
+
+ for (Epnum = 1U; Epnum < XUSBPSU_ENDPOINTS_NUM; Epnum++) {
+
+ Ept = &InstancePtr->eps[Epnum];
+ if (Ept == NULL) {
+ continue;
+ }
+
+ if ((Ept->EpStatus & XUSBPSU_EP_STALL) == 0U) {
+ continue;
+ }
+
+ Ept->EpStatus &= ~XUSBPSU_EP_STALL;
+
+ (void)XUsbPsu_SendEpCmd(InstancePtr, Ept->UsbEpNum,
+ Ept->Direction, XUSBPSU_DEPCMD_CLEARSTALL,
+ Params);
+ }
+}
+
+/****************************************************************************/
+/**
+* Initiates DMA to send data on endpoint to Host.
+*
+* @param InstancePtr is a pointer to the XUsbPsu instance.
+* @param UsbEp is USB endpoint number.
+* @param BufferPtr is pointer to data.
+* @param BufferLen is length of data buffer.
+*
+* @return XST_SUCCESS else XST_FAILURE
+*
+* @note None.
+*
+*****************************************************************************/
+s32 XUsbPsu_EpBufferSend(struct XUsbPsu *InstancePtr, u8 UsbEp,
+ u8 *BufferPtr, u32 BufferLen)
+{
+ u8 PhyEpNum;
+ u32 cmd;
+ s32 RetVal;
+ struct XUsbPsu_Trb *TrbPtr;
+ struct XUsbPsu_Ep *Ept;
+ struct XUsbPsu_EpParams *Params;
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(UsbEp <= (u8)16U);
+ Xil_AssertNonvoid(BufferPtr != NULL);
+
+ PhyEpNum = PhysicalEp(UsbEp, XUSBPSU_EP_DIR_IN);
+ if (PhyEpNum == 1U) {
+ RetVal = XUsbPsu_Ep0Send(InstancePtr, BufferPtr, BufferLen);
+ return RetVal;
+ }
+
+ Ept = &InstancePtr->eps[PhyEpNum];
+
+ if (Ept->Direction != XUSBPSU_EP_DIR_IN) {
+ return XST_FAILURE;
+ }
+
+ Ept->RequestedBytes = BufferLen;
+ Ept->BytesTxed = 0U;
+ Ept->BufferPtr = BufferPtr;
+
+ TrbPtr = &Ept->EpTrb[Ept->TrbEnqueue];
+ Xil_AssertNonvoid(TrbPtr != NULL);
+
+ Ept->TrbEnqueue++;
+ if (Ept->TrbEnqueue == NO_OF_TRB_PER_EP)
+ Ept->TrbEnqueue = 0;
+ TrbPtr->BufferPtrLow = (UINTPTR)BufferPtr;
+ TrbPtr->BufferPtrHigh = ((UINTPTR)BufferPtr >> 16) >> 16;
+ TrbPtr->Size = BufferLen & XUSBPSU_TRB_SIZE_MASK;
+
+ switch (Ept->Type) {
+ case XUSBPSU_ENDPOINT_XFER_ISOC:
+ /*
+ * According to DWC3 datasheet, XUSBPSU_TRBCTL_ISOCHRONOUS and
+ * XUSBPSU_TRBCTL_CHN fields are only set when request has
+ * scattered list so these fields are not set over here.
+ */
+ TrbPtr->Ctrl = (XUSBPSU_TRBCTL_ISOCHRONOUS_FIRST
+ | XUSBPSU_TRB_CTRL_CSP);
+
+ break;
+ case XUSBPSU_ENDPOINT_XFER_INT:
+ case XUSBPSU_ENDPOINT_XFER_BULK:
+ TrbPtr->Ctrl = (XUSBPSU_TRBCTL_NORMAL
+ | XUSBPSU_TRB_CTRL_LST);
+
+ break;
+ }
+
+ TrbPtr->Ctrl |= (XUSBPSU_TRB_CTRL_HWO
+ | XUSBPSU_TRB_CTRL_IOC
+ | XUSBPSU_TRB_CTRL_ISP_IMI);
+
+ if (InstancePtr->ConfigPtr->IsCacheCoherent == 0) {
+ Xil_DCacheFlushRange((INTPTR)TrbPtr, sizeof(struct XUsbPsu_Trb));
+ Xil_DCacheFlushRange((INTPTR)BufferPtr, BufferLen);
+ }
+
+ Params = XUsbPsu_GetEpParams(InstancePtr);
+ Xil_AssertNonvoid(Params != NULL);
+ Params->Param0 = 0U;
+ Params->Param1 = (UINTPTR)TrbPtr;
+
+ if (Ept->EpStatus & XUSBPSU_EP_BUSY) {
+ cmd = XUSBPSU_DEPCMD_UPDATETRANSFER;
+ cmd |= XUSBPSU_DEPCMD_PARAM(Ept->ResourceIndex);
+ } else {
+ if (Ept->Type == XUSBPSU_ENDPOINT_XFER_ISOC) {
+ BufferPtr += BufferLen;
+ struct XUsbPsu_Trb *TrbTempNext;
+ TrbTempNext = &Ept->EpTrb[Ept->TrbEnqueue];
+ Xil_AssertNonvoid(TrbTempNext != NULL);
+
+ Ept->TrbEnqueue++;
+ if (Ept->TrbEnqueue == NO_OF_TRB_PER_EP)
+ Ept->TrbEnqueue = 0;
+ TrbTempNext->BufferPtrLow = (UINTPTR)BufferPtr;
+ TrbTempNext->BufferPtrHigh = ((UINTPTR)BufferPtr >> 16) >> 16;
+ TrbTempNext->Size = BufferLen & XUSBPSU_TRB_SIZE_MASK;
+
+ TrbTempNext->Ctrl = (XUSBPSU_TRBCTL_ISOCHRONOUS_FIRST
+ | XUSBPSU_TRB_CTRL_CSP
+ | XUSBPSU_TRB_CTRL_HWO
+ | XUSBPSU_TRB_CTRL_IOC
+ | XUSBPSU_TRB_CTRL_ISP_IMI);
+
+ if (InstancePtr->ConfigPtr->IsCacheCoherent == 0) {
+ Xil_DCacheFlushRange((INTPTR)TrbTempNext,
+ sizeof(struct XUsbPsu_Trb));
+ Xil_DCacheFlushRange((INTPTR)BufferPtr, BufferLen);
+ }
+
+ }
+
+ cmd = XUSBPSU_DEPCMD_STARTTRANSFER;
+ cmd |= XUSBPSU_DEPCMD_PARAM(Ept->CurUf);
+ }
+
+ RetVal = XUsbPsu_SendEpCmd(InstancePtr, UsbEp, Ept->Direction,
+ cmd, Params);
+ if (RetVal != XST_SUCCESS) {
+ return XST_FAILURE;
+ }
+
+ if (!(Ept->EpStatus & XUSBPSU_EP_BUSY)) {
+ Ept->ResourceIndex = (u8)XUsbPsu_EpGetTransferIndex(InstancePtr,
+ Ept->UsbEpNum,
+ Ept->Direction);
+
+ Ept->EpStatus |= XUSBPSU_EP_BUSY;
+ }
+
+ return XST_SUCCESS;
+}
+
+/****************************************************************************/
+/**
+* Initiates DMA to receive data on Endpoint from Host.
+*
+* @param InstancePtr is a pointer to the XUsbPsu instance.
+* @param UsbEp is USB endpoint number.
+* @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_EpBufferRecv(struct XUsbPsu *InstancePtr, u8 UsbEp,
+ u8 *BufferPtr, u32 Length)
+{
+ u8 PhyEpNum;
+ u32 cmd;
+ u32 Size;
+ s32 RetVal;
+ struct XUsbPsu_Trb *TrbPtr;
+ struct XUsbPsu_Ep *Ept;
+ struct XUsbPsu_EpParams *Params;
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(UsbEp <= (u8)16U);
+ Xil_AssertNonvoid(BufferPtr != NULL);
+
+ PhyEpNum = PhysicalEp(UsbEp, XUSBPSU_EP_DIR_OUT);
+ if (PhyEpNum == 0U) {
+ RetVal = XUsbPsu_Ep0Recv(InstancePtr, BufferPtr, Length);
+ return RetVal;
+ }
+
+ Ept = &InstancePtr->eps[PhyEpNum];
+
+ if (Ept->Direction != XUSBPSU_EP_DIR_OUT) {
+ return 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 = &Ept->EpTrb[Ept->TrbEnqueue];
+ Xil_AssertNonvoid(TrbPtr != NULL);
+
+ Ept->TrbEnqueue++;
+ if (Ept->TrbEnqueue == NO_OF_TRB_PER_EP)
+ Ept->TrbEnqueue = 0;
+
+ TrbPtr->BufferPtrLow = (UINTPTR)BufferPtr;
+ TrbPtr->BufferPtrHigh = ((UINTPTR)BufferPtr >> 16) >> 16;
+ TrbPtr->Size = Size;
+
+ switch (Ept->Type) {
+ case XUSBPSU_ENDPOINT_XFER_ISOC:
+ /*
+ * According to Linux driver, XUSBPSU_TRBCTL_ISOCHRONOUS and
+ * XUSBPSU_TRBCTL_CHN fields are only set when request has
+ * scattered list so these fields are not set over here.
+ */
+ TrbPtr->Ctrl = (XUSBPSU_TRBCTL_ISOCHRONOUS_FIRST
+ | XUSBPSU_TRB_CTRL_CSP);
+
+ break;
+ case XUSBPSU_ENDPOINT_XFER_INT:
+ case XUSBPSU_ENDPOINT_XFER_BULK:
+ TrbPtr->Ctrl = (XUSBPSU_TRBCTL_NORMAL
+ | XUSBPSU_TRB_CTRL_LST);
+
+ break;
+ }
+
+ TrbPtr->Ctrl |= (XUSBPSU_TRB_CTRL_HWO
+ | 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 = XUsbPsu_GetEpParams(InstancePtr);
+ Xil_AssertNonvoid(Params != NULL);
+ Params->Param0 = 0U;
+ Params->Param1 = (UINTPTR)TrbPtr;
+
+ if (Ept->EpStatus & XUSBPSU_EP_BUSY) {
+ cmd = XUSBPSU_DEPCMD_UPDATETRANSFER;
+ cmd |= XUSBPSU_DEPCMD_PARAM(Ept->ResourceIndex);
+ } else {
+ if (Ept->Type == XUSBPSU_ENDPOINT_XFER_ISOC) {
+ BufferPtr += Length;
+ struct XUsbPsu_Trb *TrbTempNext;
+ TrbTempNext = &Ept->EpTrb[Ept->TrbEnqueue];
+ Xil_AssertNonvoid(TrbTempNext != NULL);
+
+ Ept->TrbEnqueue++;
+ if (Ept->TrbEnqueue == NO_OF_TRB_PER_EP)
+ Ept->TrbEnqueue = 0;
+ TrbTempNext->BufferPtrLow = (UINTPTR)BufferPtr;
+ TrbTempNext->BufferPtrHigh = ((UINTPTR)BufferPtr >> 16) >> 16;
+ TrbTempNext->Size = Length & XUSBPSU_TRB_SIZE_MASK;
+
+ TrbTempNext->Ctrl = (XUSBPSU_TRBCTL_ISOCHRONOUS_FIRST
+ | XUSBPSU_TRB_CTRL_CSP
+ | XUSBPSU_TRB_CTRL_HWO
+ | XUSBPSU_TRB_CTRL_IOC
+ | XUSBPSU_TRB_CTRL_ISP_IMI);
+
+ if (InstancePtr->ConfigPtr->IsCacheCoherent == 0) {
+ Xil_DCacheFlushRange((INTPTR)TrbTempNext,
+ sizeof(struct XUsbPsu_Trb));
+ Xil_DCacheFlushRange((INTPTR)BufferPtr, Length);
+ }
+
+ }
+
+ cmd = XUSBPSU_DEPCMD_STARTTRANSFER;
+ cmd |= XUSBPSU_DEPCMD_PARAM(Ept->CurUf);
+ }
+
+ RetVal = XUsbPsu_SendEpCmd(InstancePtr, UsbEp, Ept->Direction,
+ cmd, Params);
+ if (RetVal != XST_SUCCESS) {
+ return XST_FAILURE;
+ }
+
+ if (!(Ept->EpStatus & XUSBPSU_EP_BUSY)) {
+ Ept->ResourceIndex = (u8)XUsbPsu_EpGetTransferIndex(InstancePtr,
+ Ept->UsbEpNum,
+ Ept->Direction);
+
+ Ept->EpStatus |= XUSBPSU_EP_BUSY;
+ }
+
+ return XST_SUCCESS;
+}
+
+/****************************************************************************/
+/**
+* Stalls an Endpoint.
+*
+* @param InstancePtr is a pointer to the XUsbPsu instance.
+* @param Epnum is USB endpoint number.
+* @param Dir is direction.
+*
+* @return None.
+*
+* @note None.
+*
+*****************************************************************************/
+void XUsbPsu_EpSetStall(struct XUsbPsu *InstancePtr, u8 Epnum, u8 Dir)
+{
+ u8 PhyEpNum;
+ struct XUsbPsu_Ep *Ept = NULL;
+ struct XUsbPsu_EpParams *Params;
+
+ Xil_AssertVoid(InstancePtr != NULL);
+ Xil_AssertVoid(Epnum <= (u8)16U);
+ Xil_AssertVoid((Dir == XUSBPSU_EP_DIR_IN) || (Dir == XUSBPSU_EP_DIR_OUT));
+
+ PhyEpNum = PhysicalEp(Epnum, Dir);
+ Ept = &InstancePtr->eps[PhyEpNum];
+
+ Params = XUsbPsu_GetEpParams(InstancePtr);
+ Xil_AssertVoid(Params != NULL);
+
+ (void)XUsbPsu_SendEpCmd(InstancePtr, Ept->UsbEpNum, Ept->Direction,
+ XUSBPSU_DEPCMD_SETSTALL, Params);
+
+ Ept->EpStatus |= XUSBPSU_EP_STALL;
+}
+
+/****************************************************************************/
+/**
+* Clears Stall on an Endpoint.
+*
+* @param InstancePtr is a pointer to the XUsbPsu instance.
+* @param EpNum is USB endpoint number.
+* @param Dir is direction.
+*
+* @return None.
+*
+* @note None.
+*
+*****************************************************************************/
+void XUsbPsu_EpClearStall(struct XUsbPsu *InstancePtr, u8 Epnum, u8 Dir)
+{
+ u8 PhyEpNum;
+ struct XUsbPsu_Ep *Ept = NULL;
+ struct XUsbPsu_EpParams *Params;
+
+ Xil_AssertVoid(InstancePtr != NULL);
+ Xil_AssertVoid(Epnum <= (u8)16U);
+ Xil_AssertVoid((Dir == XUSBPSU_EP_DIR_IN) || (Dir == XUSBPSU_EP_DIR_OUT));
+
+ PhyEpNum = PhysicalEp(Epnum, Dir);
+ Ept = &InstancePtr->eps[PhyEpNum];
+
+ Params = XUsbPsu_GetEpParams(InstancePtr);
+ Xil_AssertVoid(Params != NULL);
+
+ (void)XUsbPsu_SendEpCmd(InstancePtr, Ept->UsbEpNum, Ept->Direction,
+ XUSBPSU_DEPCMD_CLEARSTALL, Params);
+
+ Ept->EpStatus &= ~XUSBPSU_EP_STALL;
+}
+
+/****************************************************************************/
+/**
+* Sets an user handler to be called after data is sent/received by an Endpoint
+*
+* @param InstancePtr is a pointer to the XUsbPsu instance.
+* @param EpNum is USB endpoint number.
+* @param Dir is direction of endpoint - XUSBPSU_EP_DIR_IN/XUSBPSU_EP_DIR_OUT.
+* @param Handler is user handler to be called.
+*
+* @return None.
+*
+* @note None.
+*
+*****************************************************************************/
+void XUsbPsu_SetEpHandler(struct XUsbPsu *InstancePtr, u8 Epnum,
+ u8 Dir, void (*Handler)(void *, u32, u32))
+{
+ u8 PhyEpNum;
+ struct XUsbPsu_Ep *Ept;
+
+ Xil_AssertVoid(InstancePtr != NULL);
+ Xil_AssertVoid(Epnum <= (u8)16U);
+ Xil_AssertVoid((Dir == XUSBPSU_EP_DIR_IN) || (Dir == XUSBPSU_EP_DIR_OUT));
+
+ PhyEpNum = PhysicalEp(Epnum, Dir);
+ Ept = &InstancePtr->eps[PhyEpNum];
+ Ept->Handler = Handler;
+}
+
+/****************************************************************************/
+/**
+* Returns status of endpoint - Stalled or not
+*
+* @param InstancePtr is a pointer to the XUsbPsu instance.
+* @param EpNum is USB endpoint number.
+* @param Dir is direction of endpoint - XUSBPSU_EP_DIR_IN/XUSBPSU_EP_DIR_OUT.
+*
+* @return
+* 1 - if stalled
+* 0 - if not stalled
+*
+* @note None.
+*
+*****************************************************************************/
+s32 XUsbPsu_IsEpStalled(struct XUsbPsu *InstancePtr, u8 Epnum, u8 Dir)
+{
+ u8 PhyEpNum;
+ struct XUsbPsu_Ep *Ept;
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(Epnum <= (u8)16U);
+ Xil_AssertNonvoid((Dir == XUSBPSU_EP_DIR_IN) || (Dir == XUSBPSU_EP_DIR_OUT));
+
+ PhyEpNum = PhysicalEp(Epnum, Dir);
+ Ept = &InstancePtr->eps[PhyEpNum];
+
+ return (s32)(!!(Ept->EpStatus & XUSBPSU_EP_STALL));
+}
+
+/****************************************************************************/
+/**
+* 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_EpXferComplete(struct XUsbPsu *InstancePtr,
+ const struct XUsbPsu_Event_Epevt *Event)
+{
+ struct XUsbPsu_Ep *Ept;
+ struct XUsbPsu_Trb *TrbPtr;
+ u32 Length;
+ u32 Epnum;
+ u8 Dir;
+
+ Xil_AssertVoid(InstancePtr != NULL);
+ Xil_AssertVoid(Event != NULL);
+
+ Epnum = Event->Epnumber;
+ Ept = &InstancePtr->eps[Epnum];
+ Dir = Ept->Direction;
+ TrbPtr = &Ept->EpTrb[Ept->TrbDequeue];
+ Xil_AssertVoid(TrbPtr != NULL);
+
+ Ept->TrbDequeue++;
+ if (Ept->TrbDequeue == NO_OF_TRB_PER_EP)
+ Ept->TrbDequeue = 0;
+
+ if (InstancePtr->ConfigPtr->IsCacheCoherent == 0)
+ Xil_DCacheInvalidateRange((INTPTR)TrbPtr, sizeof(struct XUsbPsu_Trb));
+
+ if (Event->Endpoint_Event == XUSBPSU_DEPEVT_XFERCOMPLETE) {
+ Ept->EpStatus &= ~(XUSBPSU_EP_BUSY);
+ Ept->ResourceIndex = 0;
+ }
+
+ 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) {
+ if (Ept->UnalignedTx == 1U) {
+ Ept->BytesTxed = (u32)roundup(Ept->RequestedBytes,
+ Ept->MaxSize);
+ Ept->BytesTxed -= Length;
+ Ept->UnalignedTx = 0U;
+ } else {
+ /*
+ * Get the actual number of bytes transmitted
+ * by host
+ */
+ Ept->BytesTxed = Ept->RequestedBytes - Length;
+ }
+ }
+ }
+
+ 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);
+ }
+}
+
+/****************************************************************************/
+/**
+* For Isochronous transfer, get the microframe time and calls respective Endpoint
+* handler.
+*
+* @param InstancePtr is a pointer to the XUsbPsu instance.
+* @param Event is a pointer to the Endpoint event occurred in core.
+*
+* @return None.
+*
+* @note None.
+*
+*****************************************************************************/
+void XUsbPsu_EpXferNotReady(struct XUsbPsu *InstancePtr,
+ const struct XUsbPsu_Event_Epevt *Event)
+{
+ struct XUsbPsu_Ep *Ept;
+ u32 Epnum;
+ u32 CurUf, Mask;
+
+ Xil_AssertVoid(InstancePtr != NULL);
+ Xil_AssertVoid(Event != NULL);
+
+ Epnum = Event->Epnumber;
+ Ept = &InstancePtr->eps[Epnum];
+
+ if (Ept->Type == XUSBPSU_ENDPOINT_XFER_ISOC) {
+ Mask = ~(1 << (Ept->Interval - 1));
+ CurUf = Event->Parameters & Mask;
+ Ept->CurUf = CurUf + (Ept->Interval * 4);
+ if (Ept->Handler != NULL) {
+ Ept->Handler(InstancePtr->AppData, 0, 0);
+ }
+ }
+}
+/** @} */