1 /******************************************************************************
3 * Copyright (C) 2016 Xilinx, Inc. All rights reserved.
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:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
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.
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
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.
31 *****************************************************************************/
32 /****************************************************************************/
35 * @file xusbpsu_endpoint.c
36 * @addtogroup usbpsu_v1_0
41 * MODIFICATION HISTORY:
43 * Ver Who Date Changes
44 * ----- ---- -------- -------------------------------------------------------
45 * 1.0 sg 06/06/16 First release
49 *****************************************************************************/
51 /***************************** Include Files *********************************/
54 #include "xusbpsu_endpoint.h"
55 /************************** Constant Definitions *****************************/
58 /**************************** Type Definitions *******************************/
60 /* return Physical EP number as dwc3 mapping */
61 #define PhysicalEp(epnum, direction) (((epnum) << 1 ) | (direction))
63 /***************** Macros (Inline Functions) Definitions *********************/
66 /************************** Function Prototypes ******************************/
69 /************************** Variable Definitions *****************************/
72 /****************************************************************************/
74 * Returns zeroed parameters to be used by Endpoint commands
76 * @param InstancePtr is a pointer to the XUsbPsu instance.
78 * @return Zeroed Params structure pointer.
82 *****************************************************************************/
83 struct XUsbPsu_EpParams *XUsbPsu_GetEpParams(struct XUsbPsu *InstancePtr)
85 if (InstancePtr == NULL) {
89 InstancePtr->EpParams.Param0 = 0x00U;
90 InstancePtr->EpParams.Param1 = 0x00U;
91 InstancePtr->EpParams.Param2 = 0x00U;
93 return &InstancePtr->EpParams;
96 /****************************************************************************/
98 * Returns Transfer Index assigned by Core for an Endpoint transfer.
100 * @param InstancePtr is a pointer to the XUsbPsu instance.
101 * @param UsbEpNum is USB endpoint number.
102 * @param Dir is direction of endpoint - XUSBPSU_EP_DIR_IN/XUSBPSU_EP_DIR_OUT
104 * @return Transfer Resource Index.
108 *****************************************************************************/
109 u32 XUsbPsu_EpGetTransferIndex(struct XUsbPsu *InstancePtr, u8 UsbEpNum,
115 Xil_AssertNonvoid(InstancePtr != NULL);
116 Xil_AssertNonvoid(UsbEpNum <= (u8)16U);
117 Xil_AssertNonvoid((Dir == XUSBPSU_EP_DIR_IN) ||
118 (Dir == XUSBPSU_EP_DIR_OUT));
120 PhyEpNum = (u8)PhysicalEp(UsbEpNum, Dir);
121 ResourceIndex = XUsbPsu_ReadReg(InstancePtr, XUSBPSU_DEPCMD(PhyEpNum));
123 return (u32)XUSBPSU_DEPCMD_GET_RSC_IDX(ResourceIndex);
126 /****************************************************************************/
128 * Sends Endpoint command to Endpoint.
130 * @param InstancePtr is a pointer to the XUsbPsu instance.
131 * @param UsbEpNum is USB endpoint number.
132 * @param Dir is direction of endpoint
133 * - XUSBPSU_EP_DIR_IN/ XUSBPSU_EP_DIR_OUT.
134 * @param Cmd is Endpoint command.
135 * @param Params is Endpoint command parameters.
137 * @return XST_SUCCESS else XST_FAILURE.
141 *****************************************************************************/
142 s32 XUsbPsu_SendEpCmd(struct XUsbPsu *InstancePtr, u8 UsbEpNum, u8 Dir,
143 u32 Cmd, struct XUsbPsu_EpParams *Params)
147 Xil_AssertNonvoid(InstancePtr != NULL);
148 Xil_AssertNonvoid(UsbEpNum <= (u8)16U);
149 Xil_AssertNonvoid((Dir == XUSBPSU_EP_DIR_IN) ||
150 (Dir == XUSBPSU_EP_DIR_OUT));
152 PhyEpNum = PhysicalEp(UsbEpNum, Dir);
154 XUsbPsu_WriteReg(InstancePtr, XUSBPSU_DEPCMDPAR0(PhyEpNum),
156 XUsbPsu_WriteReg(InstancePtr, XUSBPSU_DEPCMDPAR1(PhyEpNum),
158 XUsbPsu_WriteReg(InstancePtr, XUSBPSU_DEPCMDPAR2(PhyEpNum),
161 XUsbPsu_WriteReg(InstancePtr, XUSBPSU_DEPCMD(PhyEpNum),
162 Cmd | XUSBPSU_DEPCMD_CMDACT);
164 if (XUsbPsu_Wait_Clear_Timeout(InstancePtr, XUSBPSU_DEPCMD(PhyEpNum),
165 XUSBPSU_DEPCMD_CMDACT, 500U) == (s32)XST_FAILURE) {
172 /****************************************************************************/
174 * Sends Start New Configuration command to Endpoint.
176 * @param InstancePtr is a pointer to the XUsbPsu instance.
177 * @param UsbEpNum is USB endpoint number.
178 * @param Dir is direction of endpoint
179 * - XUSBPSU_EP_DIR_IN/ XUSBPSU_EP_DIR_OUT.
181 * @return XST_SUCCESS else XST_FAILURE.
184 * As per data book this command should be issued by software
185 * under these conditions:
186 * 1. After power-on-reset with XferRscIdx=0 before starting
187 * to configure Physical Endpoints 0 and 1.
188 * 2. With XferRscIdx=2 before starting to configure
189 * Physical Endpoints > 1
190 * 3. This command should always be issued to
191 * Endpoint 0 (DEPCMD0).
193 *****************************************************************************/
194 s32 XUsbPsu_StartEpConfig(struct XUsbPsu *InstancePtr, u32 UsbEpNum, u8 Dir)
196 struct XUsbPsu_EpParams *Params;
200 Xil_AssertNonvoid(InstancePtr != NULL);
201 Xil_AssertNonvoid(UsbEpNum <= (u32)16U);
202 Xil_AssertNonvoid((Dir == XUSBPSU_EP_DIR_IN) ||
203 (Dir == XUSBPSU_EP_DIR_OUT));
205 PhyEpNum = (u8)PhysicalEp(UsbEpNum, (u32)Dir);
206 Params = XUsbPsu_GetEpParams(InstancePtr);
207 Xil_AssertNonvoid(Params != NULL);
209 if (PhyEpNum != 1U) {
210 Cmd = XUSBPSU_DEPCMD_DEPSTARTCFG;
211 /* XferRscIdx == 0 for EP0 and 2 for the remaining */
213 if (InstancePtr->IsConfigDone != 0U) {
216 InstancePtr->IsConfigDone = 1U;
217 Cmd |= XUSBPSU_DEPCMD_PARAM(2);
220 return XUsbPsu_SendEpCmd(InstancePtr, 0U, XUSBPSU_EP_DIR_OUT,
227 /****************************************************************************/
229 * Sends Set Endpoint Configuration command to Endpoint.
231 * @param InstancePtr is a pointer to the XUsbPsu instance.
232 * @param UsbEpNum is USB endpoint number.
233 * @param Dir is direction of endpoint - XUSBPSU_EP_DIR_IN/XUSBPSU_EP_DIR_OUT.
234 * @param Size is size of Endpoint size.
235 * @param Type is Endpoint type Control/Bulk/Interrupt/Isoc.
237 * @return XST_SUCCESS else XST_FAILURE.
241 *****************************************************************************/
242 s32 XUsbPsu_SetEpConfig(struct XUsbPsu *InstancePtr, u8 UsbEpNum, u8 Dir,
245 struct XUsbPsu_EpParams *Params;
248 Xil_AssertNonvoid(InstancePtr != NULL);
249 Xil_AssertNonvoid(UsbEpNum <= (u8)16U);
250 Xil_AssertNonvoid((Dir == XUSBPSU_EP_DIR_IN) ||
251 (Dir == XUSBPSU_EP_DIR_OUT));
252 Xil_AssertNonvoid((Size >= 64U) && (Size <= 1024U));
254 Params = XUsbPsu_GetEpParams(InstancePtr);
255 Xil_AssertNonvoid(Params != NULL);
257 PhyEpNum = PhysicalEp(UsbEpNum , Dir);
259 Params->Param0 = XUSBPSU_DEPCFG_EP_TYPE(Type)
260 | XUSBPSU_DEPCFG_MAX_PACKET_SIZE(Size);
263 * Set burst size to 1 as recommended
265 Params->Param0 |= XUSBPSU_DEPCFG_BURST_SIZE(1);
267 Params->Param1 = XUSBPSU_DEPCFG_XFER_COMPLETE_EN
268 | XUSBPSU_DEPCFG_XFER_NOT_READY_EN;
271 * We are doing 1:1 mapping for endpoints, meaning
272 * Physical Endpoints 2 maps to Logical Endpoint 2 and
273 * so on. We consider the direction bit as part of the physical
274 * endpoint number. So USB endpoint 0x81 is 0x03.
276 Params->Param1 |= XUSBPSU_DEPCFG_EP_NUMBER(PhyEpNum);
278 if (Dir != XUSBPSU_EP_DIR_OUT) {
279 Params->Param0 |= XUSBPSU_DEPCFG_FIFO_NUMBER((u32)PhyEpNum >> 1);
282 return XUsbPsu_SendEpCmd(InstancePtr, UsbEpNum, Dir,
283 XUSBPSU_DEPCMD_SETEPCONFIG, Params);
286 /****************************************************************************/
288 * Sends Set Transfer Resource command to Endpoint.
290 * @param InstancePtr is a pointer to the XUsbPsu instance.
291 * @param UsbEpNum is USB endpoint number.
292 * @param Dir is direction of endpoint - XUSBPSU_EP_DIR_IN/
293 * XUSBPSU_EP_DIR_OUT.
295 * @return XST_SUCCESS else XST_FAILURE.
299 *****************************************************************************/
300 s32 XUsbPsu_SetXferResource(struct XUsbPsu *InstancePtr, u8 UsbEpNum, u8 Dir)
302 struct XUsbPsu_EpParams *Params;
305 Xil_AssertNonvoid(InstancePtr != NULL);
306 Xil_AssertNonvoid(UsbEpNum <= (u8)16U);
307 Xil_AssertNonvoid((Dir == XUSBPSU_EP_DIR_IN) ||
308 (Dir == XUSBPSU_EP_DIR_OUT));
310 Params = XUsbPsu_GetEpParams(InstancePtr);
311 Xil_AssertNonvoid(Params != NULL);
313 Params->Param0 = XUSBPSU_DEPXFERCFG_NUM_XFER_RES(1);
315 return XUsbPsu_SendEpCmd(InstancePtr, UsbEpNum, Dir,
316 XUSBPSU_DEPCMD_SETTRANSFRESOURCE, Params);
319 /****************************************************************************/
321 * Enables Endpoint for sending/receiving data.
323 * @param InstancePtr is a pointer to the XUsbPsu instance.
324 * @param UsbEpNum is USB endpoint number.
325 * @param Dir is direction of endpoint - XUSBPSU_EP_DIR_IN/XUSBPSU_EP_DIR_OUT.
326 * @param Maxsize is size of Endpoint size.
327 * @param Type is Endpoint type Control/Bulk/Interrupt/Isoc.
329 * @return XST_SUCCESS else XST_FAILURE.
333 ****************************************************************************/
334 s32 XUsbPsu_EpEnable(struct XUsbPsu *InstancePtr, u8 UsbEpNum, u8 Dir,
335 u16 Maxsize, u8 Type)
337 struct XUsbPsu_Ep *Ept;
339 s32 Ret = (s32)XST_FAILURE;
342 Xil_AssertNonvoid(InstancePtr != NULL);
343 Xil_AssertNonvoid(UsbEpNum <= (u8)16U);
344 Xil_AssertNonvoid((Dir == XUSBPSU_EP_DIR_IN) ||
345 (Dir == XUSBPSU_EP_DIR_OUT));
346 Xil_AssertNonvoid((Maxsize >= 64U) && (Maxsize <= 1024U));
348 PhyEpNum = PhysicalEp(UsbEpNum , Dir);
349 Ept = &InstancePtr->eps[PhyEpNum];
351 Ept->UsbEpNum = UsbEpNum;
352 Ept->Direction = Dir;
354 Ept->MaxSize = Maxsize;
355 Ept->PhyEpNum = (u8)PhyEpNum;
357 if ((Ept->EpStatus & XUSBPSU_EP_ENABLED) == 0U) {
358 Ret = XUsbPsu_StartEpConfig(InstancePtr, UsbEpNum, Dir);
364 Ret = XUsbPsu_SetEpConfig(InstancePtr, UsbEpNum, Dir, Maxsize, Type);
369 if ((Ept->EpStatus & XUSBPSU_EP_ENABLED) == 0U) {
370 Ret = XUsbPsu_SetXferResource(InstancePtr, UsbEpNum, Dir);
375 Ept->EpStatus |= XUSBPSU_EP_ENABLED;
377 RegVal = XUsbPsu_ReadReg(InstancePtr, XUSBPSU_DALEPENA);
378 RegVal |= XUSBPSU_DALEPENA_EP(Ept->PhyEpNum);
379 XUsbPsu_WriteReg(InstancePtr, XUSBPSU_DALEPENA, RegVal);
385 /****************************************************************************/
389 * @param InstancePtr is a pointer to the XUsbPsu instance.
390 * @param UsbEpNum is USB endpoint number.
391 * @param Dir is direction of endpoint
392 * - XUSBPSU_EP_DIR_IN/XUSBPSU_EP_DIR_OUT.
394 * @return XST_SUCCESS else XST_FAILURE.
398 ****************************************************************************/
399 s32 XUsbPsu_EpDisable(struct XUsbPsu *InstancePtr, u8 UsbEpNum, u8 Dir)
403 struct XUsbPsu_Ep *Ept;
405 Xil_AssertNonvoid(InstancePtr != NULL);
406 Xil_AssertNonvoid(UsbEpNum <= (u8)16U);
407 Xil_AssertNonvoid((Dir == XUSBPSU_EP_DIR_IN) ||
408 (Dir == XUSBPSU_EP_DIR_OUT));
410 PhyEpNum = PhysicalEp(UsbEpNum , Dir);
411 Ept = &InstancePtr->eps[PhyEpNum];
413 RegVal = XUsbPsu_ReadReg(InstancePtr, XUSBPSU_DALEPENA);
414 RegVal &= ~XUSBPSU_DALEPENA_EP(PhyEpNum);
415 XUsbPsu_WriteReg(InstancePtr, XUSBPSU_DALEPENA, RegVal);
424 /****************************************************************************/
426 * Enables USB Control Endpoint i.e., EP0OUT and EP0IN of Core.
428 * @param InstancePtr is a pointer to the XUsbPsu instance.
429 * @param Size is control endpoint size.
431 * @return XST_SUCCESS else XST_FAILURE.
435 ****************************************************************************/
436 s32 XUsbPsu_EnableControlEp(struct XUsbPsu *InstancePtr, u16 Size)
440 Xil_AssertNonvoid(InstancePtr != NULL);
441 Xil_AssertNonvoid((Size >= 64U) && (Size <= 512U));
443 RetVal = XUsbPsu_EpEnable(InstancePtr, 0U, XUSBPSU_EP_DIR_OUT, Size,
444 XUSBPSU_ENDPOINT_XFER_CONTROL);
449 RetVal = XUsbPsu_EpEnable(InstancePtr, 0U, XUSBPSU_EP_DIR_IN, Size,
450 XUSBPSU_ENDPOINT_XFER_CONTROL);
458 /****************************************************************************/
460 * Initializes Endpoints. All OUT endpoints are even numbered and all IN
461 * endpoints are odd numbered. EP0 is for Control OUT and EP1 is for
464 * @param InstancePtr is a pointer to the XUsbPsu instance.
470 ****************************************************************************/
471 void XUsbPsu_InitializeEps(struct XUsbPsu *InstancePtr)
476 Xil_AssertVoid(InstancePtr != NULL);
478 for (i = 0U; i < InstancePtr->NumOutEps; i++) {
479 Epnum = (i << 1U) | XUSBPSU_EP_DIR_OUT;
480 InstancePtr->eps[Epnum].PhyEpNum = Epnum;
481 InstancePtr->eps[Epnum].Direction = XUSBPSU_EP_DIR_OUT;
483 for (i = 0U; i < InstancePtr->NumInEps; i++) {
484 Epnum = (i << 1U) | XUSBPSU_EP_DIR_IN;
485 InstancePtr->eps[Epnum].PhyEpNum = Epnum;
486 InstancePtr->eps[Epnum].Direction = XUSBPSU_EP_DIR_IN;
490 /****************************************************************************/
492 * Stops transfer on Endpoint.
494 * @param InstancePtr is a pointer to the XUsbPsu instance.
495 * @param UsbEpNum is USB endpoint number.
496 * @param Dir is direction of endpoint - XUSBPSU_EP_DIR_IN/XUSBPSU_EP_DIR_OUT.
502 ****************************************************************************/
503 void XUsbPsu_StopTransfer(struct XUsbPsu *InstancePtr, u8 UsbEpNum, u8 Dir)
505 struct XUsbPsu_Ep *Ept;
506 struct XUsbPsu_EpParams *Params;
510 Xil_AssertVoid(InstancePtr != NULL);
511 Xil_AssertVoid(UsbEpNum <= (u8)16U);
512 Xil_AssertVoid((Dir == XUSBPSU_EP_DIR_IN) || (Dir == XUSBPSU_EP_DIR_OUT));
514 PhyEpNum = PhysicalEp(UsbEpNum, Dir);
515 Params = XUsbPsu_GetEpParams(InstancePtr);
516 Xil_AssertVoid(Params != NULL);
518 Ept = &InstancePtr->eps[PhyEpNum];
520 if (Ept->ResourceIndex == 0U) {
525 * - Issue EndTransfer WITH CMDIOC bit set
528 Cmd = XUSBPSU_DEPCMD_ENDTRANSFER;
529 Cmd |= XUSBPSU_DEPCMD_CMDIOC;
530 Cmd |= XUSBPSU_DEPCMD_PARAM(Ept->ResourceIndex);
531 (void)XUsbPsu_SendEpCmd(InstancePtr, Ept->PhyEpNum, Ept->Direction,
533 Ept->ResourceIndex = 0U;
534 Ept->EpStatus &= ~XUSBPSU_EP_BUSY;
538 /****************************************************************************/
540 * Clears Stall on all endpoints.
542 * @param InstancePtr is a pointer to the XUsbPsu instance.
548 ****************************************************************************/
549 void XUsbPsu_ClearStalls(struct XUsbPsu *InstancePtr)
551 struct XUsbPsu_EpParams *Params;
553 struct XUsbPsu_Ep *Ept;
555 Xil_AssertVoid(InstancePtr != NULL);
557 Params = XUsbPsu_GetEpParams(InstancePtr);
558 Xil_AssertVoid(Params != NULL);
560 for (Epnum = 1U; Epnum < XUSBPSU_ENDPOINTS_NUM; Epnum++) {
562 Ept = &InstancePtr->eps[Epnum];
567 if ((Ept->EpStatus & XUSBPSU_EP_STALL) == 0U) {
571 Ept->EpStatus &= ~XUSBPSU_EP_STALL;
573 (void)XUsbPsu_SendEpCmd(InstancePtr, Ept->PhyEpNum,
574 Ept->Direction, XUSBPSU_DEPCMD_CLEARSTALL,
579 /****************************************************************************/
581 * Initiates DMA to send data on endpoint to Host.
583 * @param InstancePtr is a pointer to the XUsbPsu instance.
584 * @param UsbEp is USB endpoint number.
585 * @param BufferPtr is pointer to data.
586 * @param BufferLen is length of data buffer.
588 * @return XST_SUCCESS else XST_FAILURE
592 *****************************************************************************/
593 s32 XUsbPsu_EpBufferSend(struct XUsbPsu *InstancePtr, u8 UsbEp,
594 u8 *BufferPtr, u32 BufferLen)
598 struct XUsbPsu_Trb *TrbPtr;
599 struct XUsbPsu_Ep *Ept;
600 struct XUsbPsu_EpParams *Params;
602 Xil_AssertNonvoid(InstancePtr != NULL);
603 Xil_AssertNonvoid(UsbEp <= (u8)16U);
604 Xil_AssertNonvoid(BufferPtr != NULL);
606 PhyEpNum = PhysicalEp(UsbEp, XUSBPSU_EP_DIR_IN);
607 if (PhyEpNum == 1U) {
608 RetVal = XUsbPsu_Ep0Send(InstancePtr, BufferPtr, BufferLen);
612 Ept = &InstancePtr->eps[PhyEpNum];
614 if (Ept->Direction != XUSBPSU_EP_DIR_IN) {
618 Ept->RequestedBytes = BufferLen;
620 Ept->BufferPtr = BufferPtr;
622 TrbPtr = &Ept->EpTrb;
623 Xil_AssertNonvoid(TrbPtr != NULL);
625 TrbPtr->BufferPtrLow = (UINTPTR)BufferPtr;
626 TrbPtr->BufferPtrHigh = ((UINTPTR)BufferPtr >> 16) >> 16;
627 TrbPtr->Size = BufferLen & XUSBPSU_TRB_SIZE_MASK;
628 TrbPtr->Ctrl = XUSBPSU_TRBCTL_NORMAL;
630 TrbPtr->Ctrl |= (XUSBPSU_TRB_CTRL_HWO
631 | XUSBPSU_TRB_CTRL_LST
632 | XUSBPSU_TRB_CTRL_IOC
633 | XUSBPSU_TRB_CTRL_ISP_IMI);
635 Xil_DCacheFlushRange((INTPTR)TrbPtr, sizeof(struct XUsbPsu_Trb));
636 Xil_DCacheFlushRange((INTPTR)BufferPtr, BufferLen);
638 Params = XUsbPsu_GetEpParams(InstancePtr);
639 Xil_AssertNonvoid(Params != NULL);
641 Params->Param1 = (UINTPTR)TrbPtr;
643 RetVal = XUsbPsu_SendEpCmd(InstancePtr, UsbEp, Ept->Direction,
644 XUSBPSU_DEPCMD_STARTTRANSFER, Params);
645 if (RetVal != XST_SUCCESS) {
648 Ept->ResourceIndex = (u8)XUsbPsu_EpGetTransferIndex(InstancePtr,
654 /****************************************************************************/
656 * Initiates DMA to receive data on Endpoint from Host.
658 * @param InstancePtr is a pointer to the XUsbPsu instance.
659 * @param EpNum is USB endpoint number.
660 * @param BufferPtr is pointer to data.
661 * @param Length is length of data to be received.
663 * @return XST_SUCCESS else XST_FAILURE
667 *****************************************************************************/
668 s32 XUsbPsu_EpBufferRecv(struct XUsbPsu *InstancePtr, u8 UsbEp,
669 u8 *BufferPtr, u32 Length)
674 struct XUsbPsu_Trb *TrbPtr;
675 struct XUsbPsu_Ep *Ept;
676 struct XUsbPsu_EpParams *Params;
678 Xil_AssertNonvoid(InstancePtr != NULL);
679 Xil_AssertNonvoid(UsbEp <= (u8)16U);
680 Xil_AssertNonvoid(BufferPtr != NULL);
682 PhyEpNum = PhysicalEp(UsbEp, XUSBPSU_EP_DIR_OUT);
683 if (PhyEpNum == 0U) {
684 RetVal = XUsbPsu_Ep0Recv(InstancePtr, BufferPtr, Length);
688 Ept = &InstancePtr->eps[PhyEpNum];
690 if (Ept->Direction != XUSBPSU_EP_DIR_OUT) {
694 Ept->RequestedBytes = Length;
697 Ept->BufferPtr = BufferPtr;
700 * 8.2.5 - An OUT transfer size (Total TRB buffer allocation)
701 * must be a multiple of MaxPacketSize even if software is expecting a
702 * fixed non-multiple of MaxPacketSize transfer from the Host.
704 if (!IS_ALIGNED(Length, Ept->MaxSize)) {
705 Size = (u32)roundup(Length, Ept->MaxSize);
706 Ept->UnalignedTx = 1U;
709 TrbPtr = &Ept->EpTrb;
710 Xil_AssertNonvoid(TrbPtr != NULL);
712 TrbPtr->BufferPtrLow = (UINTPTR)BufferPtr;
713 TrbPtr->BufferPtrHigh = ((UINTPTR)BufferPtr >> 16) >> 16;
715 TrbPtr->Ctrl = XUSBPSU_TRBCTL_NORMAL;
717 TrbPtr->Ctrl |= (XUSBPSU_TRB_CTRL_HWO
718 | XUSBPSU_TRB_CTRL_LST
719 | XUSBPSU_TRB_CTRL_IOC
720 | XUSBPSU_TRB_CTRL_ISP_IMI);
723 Xil_DCacheFlushRange((INTPTR)TrbPtr, sizeof(struct XUsbPsu_Trb));
724 Xil_DCacheInvalidateRange((INTPTR)BufferPtr, Length);
726 Params = XUsbPsu_GetEpParams(InstancePtr);
727 Xil_AssertNonvoid(Params != NULL);
729 Params->Param1 = (UINTPTR)TrbPtr;
731 RetVal = XUsbPsu_SendEpCmd(InstancePtr, UsbEp, Ept->Direction,
732 XUSBPSU_DEPCMD_STARTTRANSFER, Params);
733 if (RetVal != XST_SUCCESS) {
736 Ept->ResourceIndex = (u8)XUsbPsu_EpGetTransferIndex(InstancePtr,
742 /****************************************************************************/
744 * Stalls an Endpoint.
746 * @param InstancePtr is a pointer to the XUsbPsu instance.
747 * @param EpNum is USB endpoint number.
748 * @param Dir is direction.
754 *****************************************************************************/
755 void XUsbPsu_EpSetStall(struct XUsbPsu *InstancePtr, u8 Epnum, u8 Dir)
758 struct XUsbPsu_Ep *Ept = NULL;
759 struct XUsbPsu_EpParams *Params;
761 Xil_AssertVoid(InstancePtr != NULL);
762 Xil_AssertVoid(Epnum <= (u8)16U);
763 Xil_AssertVoid((Dir == XUSBPSU_EP_DIR_IN) || (Dir == XUSBPSU_EP_DIR_OUT));
765 PhyEpNum = PhysicalEp(Epnum, Dir);
766 Ept = &InstancePtr->eps[PhyEpNum];
768 Params = XUsbPsu_GetEpParams(InstancePtr);
769 Xil_AssertVoid(Params != NULL);
771 (void)XUsbPsu_SendEpCmd(InstancePtr, Ept->PhyEpNum, Ept->Direction,
772 XUSBPSU_DEPCMD_SETSTALL, Params);
774 Ept->EpStatus |= XUSBPSU_EP_STALL;
777 /****************************************************************************/
779 * Clears Stall on an Endpoint.
781 * @param InstancePtr is a pointer to the XUsbPsu instance.
782 * @param EpNum is USB endpoint number.
783 * @param Dir is direction.
789 *****************************************************************************/
790 void XUsbPsu_EpClearStall(struct XUsbPsu *InstancePtr, u8 Epnum, u8 Dir)
793 struct XUsbPsu_Ep *Ept = NULL;
794 struct XUsbPsu_EpParams *Params;
796 Xil_AssertVoid(InstancePtr != NULL);
797 Xil_AssertVoid(Epnum <= (u8)16U);
798 Xil_AssertVoid((Dir == XUSBPSU_EP_DIR_IN) || (Dir == XUSBPSU_EP_DIR_OUT));
800 PhyEpNum = PhysicalEp(Epnum, Dir);
801 Ept = &InstancePtr->eps[PhyEpNum];
803 Params = XUsbPsu_GetEpParams(InstancePtr);
804 Xil_AssertVoid(Params != NULL);
806 (void)XUsbPsu_SendEpCmd(InstancePtr, Ept->PhyEpNum, Ept->Direction,
807 XUSBPSU_DEPCMD_CLEARSTALL, Params);
809 Ept->EpStatus &= ~XUSBPSU_EP_STALL;
812 /****************************************************************************/
814 * Sets an user handler to be called after data is sent/received by an Endpoint
816 * @param InstancePtr is a pointer to the XUsbPsu instance.
817 * @param EpNum is USB endpoint number.
818 * @param Dir is direction of endpoint - XUSBPSU_EP_DIR_IN/XUSBPSU_EP_DIR_OUT.
819 * @param Handler is user handler to be called.
825 *****************************************************************************/
826 void XUsbPsu_SetEpHandler(struct XUsbPsu *InstancePtr, u8 Epnum,
827 u8 Dir, void (*Handler)(void *, u32, u32))
830 struct XUsbPsu_Ep *Ept;
832 Xil_AssertVoid(InstancePtr != NULL);
833 Xil_AssertVoid(Epnum <= (u8)16U);
834 Xil_AssertVoid((Dir == XUSBPSU_EP_DIR_IN) || (Dir == XUSBPSU_EP_DIR_OUT));
836 PhyEpNum = PhysicalEp(Epnum, Dir);
837 Ept = &InstancePtr->eps[PhyEpNum];
838 Ept->Handler = Handler;
841 /****************************************************************************/
843 * Returns status of endpoint - Stalled or not
845 * @param InstancePtr is a pointer to the XUsbPsu instance.
846 * @param EpNum is USB endpoint number.
847 * @param Dir is direction of endpoint - XUSBPSU_EP_DIR_IN/XUSBPSU_EP_DIR_OUT.
855 *****************************************************************************/
856 s32 XUsbPsu_IsEpStalled(struct XUsbPsu *InstancePtr, u8 Epnum, u8 Dir)
859 struct XUsbPsu_Ep *Ept;
861 Xil_AssertNonvoid(InstancePtr != NULL);
862 Xil_AssertNonvoid(Epnum <= (u8)16U);
863 Xil_AssertNonvoid((Dir == XUSBPSU_EP_DIR_IN) || (Dir == XUSBPSU_EP_DIR_OUT));
865 PhyEpNum = PhysicalEp(Epnum, Dir);
866 Ept = &InstancePtr->eps[PhyEpNum];
868 return (s32)(!!(Ept->EpStatus & XUSBPSU_EP_STALL));
871 /****************************************************************************/
873 * Checks the Data Phase and calls user Endpoint handler.
875 * @param InstancePtr is a pointer to the XUsbPsu instance.
876 * @param Event is a pointer to the Endpoint event occured in core.
882 *****************************************************************************/
883 void XUsbPsu_EpXferComplete(struct XUsbPsu *InstancePtr,
884 const struct XUsbPsu_Event_Epevt *Event)
886 struct XUsbPsu_Ep *Ept;
887 struct XUsbPsu_Trb *TrbPtr;
892 Xil_AssertVoid(InstancePtr != NULL);
893 Xil_AssertVoid(Event != NULL);
895 Epnum = Event->Epnumber;
896 Ept = &InstancePtr->eps[Epnum];
897 Dir = Ept->Direction;
898 TrbPtr = &Ept->EpTrb;
899 Xil_AssertVoid(TrbPtr != NULL);
901 Xil_DCacheInvalidateRange((INTPTR)TrbPtr, sizeof(struct XUsbPsu_Trb));
903 Length = TrbPtr->Size & XUSBPSU_TRB_SIZE_MASK;
906 Ept->BytesTxed = Ept->RequestedBytes;
908 if (Dir == XUSBPSU_EP_DIR_IN) {
909 Ept->BytesTxed = Ept->RequestedBytes - Length;
910 } else if (Dir == XUSBPSU_EP_DIR_OUT) {
911 if (Ept->UnalignedTx == 1U) {
912 Ept->BytesTxed = Ept->RequestedBytes;
913 Ept->UnalignedTx = 0U;
918 if (Dir == XUSBPSU_EP_DIR_OUT) {
919 /* Invalidate Cache */
920 Xil_DCacheInvalidateRange((INTPTR)Ept->BufferPtr, Ept->BytesTxed);
923 if (Ept->Handler != NULL) {
924 Ept->Handler(InstancePtr, Ept->RequestedBytes, Ept->BytesTxed);