1 /******************************************************************************
3 * Copyright (C) 2015 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
39 * MODIFICATION HISTORY:
41 * Ver Who Date Changes
42 * ----- ---- -------- -------------------------------------------------------
43 * 1.00a bss 01/22/15 First release
44 * 1.00a bss 03/18/15 Added XUsbPsu_EpXferComplete function to handle Non
45 * control endpoint interrupt.
49 *****************************************************************************/
51 /***************************** Include Files *********************************/
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 Xil_AssertNonvoid(InstancePtr != NULL);
87 InstancePtr->EpParams.Param0 = 0x00;
88 InstancePtr->EpParams.Param1 = 0x00;
89 InstancePtr->EpParams.Param2 = 0x00;
91 return &InstancePtr->EpParams;
94 /****************************************************************************/
96 * Returns Transfer Index assigned by Core for an Endpoint transfer.
98 * @param InstancePtr is a pointer to the XUsbPsu instance.
99 * @param UsbEpNum is USB endpoint number.
100 * @param Dir is direction of endpoint - XUSBPSU_EP_DIR_IN/XUSBPSU_EP_DIR_OUT
102 * @return Transfer Resource Index.
106 *****************************************************************************/
107 u32 XUsbPsu_EpGetTransferIndex(struct XUsbPsu *InstancePtr, u8 UsbEpNum,
113 Xil_AssertNonvoid(InstancePtr != NULL);
114 Xil_AssertNonvoid(UsbEpNum >= 0 && UsbEpNum <= 16);
115 Xil_AssertNonvoid((Dir == XUSBPSU_EP_DIR_IN) ||
116 (Dir == XUSBPSU_EP_DIR_OUT));
118 PhyEpNum = PhysicalEp(UsbEpNum, Dir);
119 ResourceIndex = XUsbPsu_ReadReg(InstancePtr, XUSBPSU_DEPCMD(PhyEpNum));
121 return XUSBPSU_DEPCMD_GET_RSC_IDX(ResourceIndex);
124 /****************************************************************************/
126 * Sends Endpoint command to Endpoint.
128 * @param InstancePtr is a pointer to the XUsbPsu instance.
129 * @param UsbEpNum is USB endpoint number.
130 * @param Dir is direction of endpoint
131 * - XUSBPSU_EP_DIR_IN/ XUSBPSU_EP_DIR_OUT.
132 * @param Cmd is Endpoint command.
133 * @param Params is Endpoint command parameters.
135 * @return XST_SUCCESS else XST_FAILURE.
139 *****************************************************************************/
140 int XUsbPsu_SendEpCmd(struct XUsbPsu *InstancePtr, u8 UsbEpNum, u8 Dir,
141 u32 Cmd, struct XUsbPsu_EpParams *Params)
146 Xil_AssertNonvoid(InstancePtr != NULL);
147 Xil_AssertNonvoid(UsbEpNum >= 0 && UsbEpNum <= 16);
148 Xil_AssertNonvoid((Dir == XUSBPSU_EP_DIR_IN) ||
149 (Dir == XUSBPSU_EP_DIR_OUT));
151 PhyEpnum = PhysicalEp(UsbEpNum, Dir);
153 XUsbPsu_WriteReg(InstancePtr, XUSBPSU_DEPCMDPAR0(PhyEpnum),
155 XUsbPsu_WriteReg(InstancePtr, XUSBPSU_DEPCMDPAR1(PhyEpnum),
157 XUsbPsu_WriteReg(InstancePtr, XUSBPSU_DEPCMDPAR2(PhyEpnum),
160 XUsbPsu_WriteReg(InstancePtr, XUSBPSU_DEPCMD(PhyEpnum),
161 Cmd | XUSBPSU_DEPCMD_CMDACT);
163 if (XUsbPsu_Wait_Clear_Timeout(InstancePtr, XUSBPSU_DEPCMD(PhyEpnum),
164 XUSBPSU_DEPCMD_CMDACT, 500) == XST_FAILURE) {
171 /****************************************************************************/
173 * Sends Start New Configuration command to Endpoint.
175 * @param InstancePtr is a pointer to the XUsbPsu instance.
176 * @param UsbEpNum is USB endpoint number.
177 * @param Dir is direction of endpoint
178 * - XUSBPSU_EP_DIR_IN/ XUSBPSU_EP_DIR_OUT.
180 * @return XST_SUCCESS else XST_FAILURE.
183 * As per data book this command should be issued by software
184 * under these conditions:
185 * 1. After power-on-reset with XferRscIdx=0 before starting
186 * to configure Physical Endpoints 0 and 1.
187 * 2. With XferRscIdx=2 before starting to configure
188 * Physical Endpoints > 1
189 * 3. This command should always be issued to
190 * Endpoint 0 (DEPCMD0).
192 *****************************************************************************/
193 int XUsbPsu_StartEpConfig(struct XUsbPsu *InstancePtr, u32 UsbEpNum, u8 Dir)
195 struct XUsbPsu_EpParams *Params;
199 Xil_AssertNonvoid(InstancePtr != NULL);
200 Xil_AssertNonvoid(UsbEpNum >= 0 && UsbEpNum <= 16);
201 Xil_AssertNonvoid((Dir == XUSBPSU_EP_DIR_IN) ||
202 (Dir == XUSBPSU_EP_DIR_OUT));
204 PhyEpNum = PhysicalEp(UsbEpNum, Dir);
205 Params = XUsbPsu_GetEpParams(InstancePtr);
208 Cmd = XUSBPSU_DEPCMD_DEPSTARTCFG;
209 /* XferRscIdx == 0 for EP0 and 2 for the remaining */
211 if (InstancePtr->IsConfigDone)
213 InstancePtr->IsConfigDone = 1;
214 Cmd |= XUSBPSU_DEPCMD_PARAM(2);
216 InstancePtr->eps[0].Cmd = XUSBPSU_DEPCMD_DEPSTARTCFG;
217 return XUsbPsu_SendEpCmd(InstancePtr, 0, XUSBPSU_EP_DIR_OUT,
224 /****************************************************************************/
226 * Sends Set Endpoint Configuration command to Endpoint.
228 * @param InstancePtr is a pointer to the XUsbPsu instance.
229 * @param UsbEpNum is USB endpoint number.
230 * @param Dir is direction of endpoint - XUSBPSU_EP_DIR_IN/XUSBPSU_EP_DIR_OUT.
231 * @param Size is size of Endpoint size.
232 * @param Type is Endpoint type Control/Bulk/Interrupt/Isoc.
234 * @return XST_SUCCESS else XST_FAILURE.
238 *****************************************************************************/
239 int XUsbPsu_SetEpConfig(struct XUsbPsu *InstancePtr, u8 UsbEpNum, u8 Dir,
242 struct XUsbPsu_EpParams *Params;
245 Xil_AssertNonvoid(InstancePtr != NULL);
246 Xil_AssertNonvoid(UsbEpNum >= 0 && UsbEpNum <= 16);
247 Xil_AssertNonvoid((Dir == XUSBPSU_EP_DIR_IN) ||
248 (Dir == XUSBPSU_EP_DIR_OUT));
249 Xil_AssertNonvoid(Size >= 64 && Size <= 1024);
251 Params = XUsbPsu_GetEpParams(InstancePtr);
252 PhyEpnum = PhysicalEp(UsbEpNum , Dir);
254 Params->Param0 = XUSBPSU_DEPCFG_EP_TYPE(Type)
255 | XUSBPSU_DEPCFG_MAX_PACKET_SIZE(Size);
257 Params->Param1 = XUSBPSU_DEPCFG_XFER_COMPLETE_EN
258 | XUSBPSU_DEPCFG_XFER_NOT_READY_EN;
261 * We are doing 1:1 mapping for endpoints, meaning
262 * Physical Endpoints 2 maps to Logical Endpoint 2 and
263 * so on. We consider the direction bit as part of the physical
264 * endpoint number. So USB endpoint 0x81 is 0x03.
266 Params->Param1 |= XUSBPSU_DEPCFG_EP_NUMBER(PhyEpnum);
269 Params->Param0 |= XUSBPSU_DEPCFG_FIFO_NUMBER(PhyEpnum >> 1);
271 InstancePtr->eps[PhyEpnum].Cmd = XUSBPSU_DEPCMD_SETEPCONFIG;
273 return XUsbPsu_SendEpCmd(InstancePtr, UsbEpNum, Dir,
274 XUSBPSU_DEPCMD_SETEPCONFIG, Params);
277 /****************************************************************************/
279 * Sends Set Transfer Resource command to Endpoint.
281 * @param InstancePtr is a pointer to the XUsbPsu instance.
282 * @param UsbEpNum is USB endpoint number.
283 * @param Dir is direction of endpoint - XUSBPSU_EP_DIR_IN/
284 * XUSBPSU_EP_DIR_OUT.
286 * @return XST_SUCCESS else XST_FAILURE.
290 *****************************************************************************/
291 int XUsbPsu_SetXferResource(struct XUsbPsu *InstancePtr, u8 UsbEpNum, u8 Dir)
293 struct XUsbPsu_EpParams *Params;
296 Xil_AssertNonvoid(InstancePtr != NULL);
297 Xil_AssertNonvoid(UsbEpNum >= 0 && UsbEpNum <= 16);
298 Xil_AssertNonvoid((Dir == XUSBPSU_EP_DIR_IN) ||
299 (Dir == XUSBPSU_EP_DIR_OUT));
301 PhyEpnum = PhysicalEp(UsbEpNum , Dir);
302 Params = XUsbPsu_GetEpParams(InstancePtr);
304 Params->Param0 = XUSBPSU_DEPXFERCFG_NUM_XFER_RES(1);
306 InstancePtr->eps[PhyEpnum].Cmd = XUSBPSU_DEPCMD_SETTRANSFRESOURCE;
308 return XUsbPsu_SendEpCmd(InstancePtr, UsbEpNum, Dir,
309 XUSBPSU_DEPCMD_SETTRANSFRESOURCE, Params);
312 /****************************************************************************/
314 * Enables Endpoint for sending/receiving data.
316 * @param InstancePtr is a pointer to the XUsbPsu instance.
317 * @param UsbEpNum is USB endpoint number.
318 * @param Dir is direction of endpoint - XUSBPSU_EP_DIR_IN/XUSBPSU_EP_DIR_OUT.
319 * @param Maxsize is size of Endpoint size.
320 * @param Type is Endpoint type Control/Bulk/Interrupt/Isoc.
322 * @return XST_SUCCESS else XST_FAILURE.
326 ****************************************************************************/
327 int XUsbPsu_EpEnable(struct XUsbPsu *InstancePtr, u8 UsbEpNum, u8 Dir,
328 u16 Maxsize, u8 Type)
330 struct XUsbPsu_Ep *Ept;
332 int Ret = XST_FAILURE;
335 Xil_AssertNonvoid(InstancePtr != NULL);
336 Xil_AssertNonvoid(UsbEpNum >= 0 && UsbEpNum <= 16);
337 Xil_AssertNonvoid((Dir == XUSBPSU_EP_DIR_IN) ||
338 (Dir == XUSBPSU_EP_DIR_OUT));
339 Xil_AssertNonvoid(Maxsize >= 64 && Maxsize <= 1024);
341 PhyEpnum = PhysicalEp(UsbEpNum , Dir);
342 Ept = &InstancePtr->eps[PhyEpnum];
344 Ept->UsbEpNum = UsbEpNum;
345 Ept->Direction = Dir;
347 Ept->MaxSize = Maxsize;
348 Ept->PhyEpNum = PhyEpnum;
350 if (!(Ept->EpStatus & XUSBPSU_EP_ENABLED)) {
351 Ret = XUsbPsu_StartEpConfig(InstancePtr, UsbEpNum, Dir);
356 Ret = XUsbPsu_SetEpConfig(InstancePtr, UsbEpNum, Dir, Maxsize, Type);
360 if (!(Ept->EpStatus & XUSBPSU_EP_ENABLED)) {
361 Ret = XUsbPsu_SetXferResource(InstancePtr, UsbEpNum, Dir);
365 Ept->EpStatus |= XUSBPSU_EP_ENABLED;
367 RegVal = XUsbPsu_ReadReg(InstancePtr, XUSBPSU_DALEPENA);
368 RegVal |= XUSBPSU_DALEPENA_EP(Ept->PhyEpNum);
369 XUsbPsu_WriteReg(InstancePtr, XUSBPSU_DALEPENA, RegVal);
375 /****************************************************************************/
379 * @param InstancePtr is a pointer to the XUsbPsu instance.
380 * @param UsbEpNum is USB endpoint number.
381 * @param Dir is direction of endpoint
382 * - XUSBPSU_EP_DIR_IN/XUSBPSU_EP_DIR_OUT.
384 * @return XST_SUCCESS else XST_FAILURE.
388 ****************************************************************************/
389 int XUsbPsu_EpDisable(struct XUsbPsu *InstancePtr, u8 UsbEpNum, u8 Dir)
393 struct XUsbPsu_Ep *Ept;
395 Xil_AssertNonvoid(InstancePtr != NULL);
396 Xil_AssertNonvoid(UsbEpNum >= 0 && UsbEpNum <= 16);
397 Xil_AssertNonvoid((Dir == XUSBPSU_EP_DIR_IN) ||
398 (Dir == XUSBPSU_EP_DIR_OUT));
400 PhyEpNum = PhysicalEp(UsbEpNum , Dir);
401 Ept = &InstancePtr->eps[PhyEpNum];
403 RegVal = XUsbPsu_ReadReg(InstancePtr, XUSBPSU_DALEPENA);
404 RegVal &= ~XUSBPSU_DALEPENA_EP(PhyEpNum);
405 XUsbPsu_WriteReg(InstancePtr, XUSBPSU_DALEPENA, RegVal);
414 /****************************************************************************/
416 * Enables USB Control Endpoint i.e., EP0OUT and EP0IN of Core.
418 * @param InstancePtr is a pointer to the XUsbPsu instance.
419 * @param Size is control endpoint size.
421 * @return XST_SUCCESS else XST_FAILURE.
425 ****************************************************************************/
426 int XUsbPsu_EnableControlEp(struct XUsbPsu *InstancePtr, u16 Size)
430 Xil_AssertNonvoid(InstancePtr != NULL);
431 Xil_AssertNonvoid(Size >= 64 && Size <= 512);
433 RetVal = XUsbPsu_EpEnable(InstancePtr, 0, XUSBPSU_EP_DIR_OUT, Size,
434 USB_ENDPOINT_XFER_CONTROL);
439 RetVal = XUsbPsu_EpEnable(InstancePtr, 0, XUSBPSU_EP_DIR_IN, Size,
440 USB_ENDPOINT_XFER_CONTROL);
448 /****************************************************************************/
450 * Initializes Endpoints. All OUT endpoints are even numbered and all IN
451 * endpoints are odd numbered. EP0 is for Control OUT and EP1 is for
454 * @param InstancePtr is a pointer to the XUsbPsu instance.
460 ****************************************************************************/
461 void XUsbPsu_InitializeEps(struct XUsbPsu *InstancePtr)
463 struct XUsbPsu_Ep *Ept;
467 Xil_AssertVoid(InstancePtr != NULL);
469 for (i = 0; i < InstancePtr->NumOutEps; i++) {
470 epnum = (i << 1) | XUSBPSU_EP_DIR_OUT;
471 InstancePtr->eps[epnum].PhyEpNum = epnum;
472 InstancePtr->eps[epnum].Direction = XUSBPSU_EP_DIR_OUT;
474 for (i = 0; i < InstancePtr->NumInEps; i++) {
475 epnum = (i << 1) | XUSBPSU_EP_DIR_IN;
476 InstancePtr->eps[epnum].PhyEpNum = epnum;
477 InstancePtr->eps[epnum].Direction = XUSBPSU_EP_DIR_IN;
481 /****************************************************************************/
483 * Stops transfer on Endpoint.
485 * @param InstancePtr is a pointer to the XUsbPsu instance.
486 * @param UsbEpNum is USB endpoint number.
487 * @param Dir is direction of endpoint - XUSBPSU_EP_DIR_IN/XUSBPSU_EP_DIR_OUT.
493 ****************************************************************************/
494 void XUsbPsu_StopTransfer(struct XUsbPsu *InstancePtr, u8 UsbEpNum, u8 Dir)
496 struct XUsbPsu_Ep *Ept;
497 struct XUsbPsu_EpParams *Params;
502 Xil_AssertVoid(InstancePtr != NULL);
503 Xil_AssertVoid(UsbEpNum >= 0 && UsbEpNum <= 16);
504 Xil_AssertVoid((Dir == XUSBPSU_EP_DIR_IN) || (Dir == XUSBPSU_EP_DIR_OUT));
506 PhyEpNum = PhysicalEp(UsbEpNum, Dir);
507 Params = XUsbPsu_GetEpParams(InstancePtr);
508 Ept = &InstancePtr->eps[PhyEpNum];
510 if (!Ept->ResourceIndex)
514 * - Issue EndTransfer WITH CMDIOC bit set
517 Cmd = XUSBPSU_DEPCMD_ENDTRANSFER;
518 Cmd |= XUSBPSU_DEPCMD_CMDIOC;
519 Cmd |= XUSBPSU_DEPCMD_PARAM(Ept->ResourceIndex);
520 Ept->Cmd = XUSBPSU_DEPCMD_ENDTRANSFER;
521 Ret = XUsbPsu_SendEpCmd(InstancePtr, Ept->PhyEpNum, Ept->Direction,
523 Ept->ResourceIndex = 0;
524 Ept->EpStatus &= ~XUSBPSU_EP_BUSY;
528 /****************************************************************************/
530 * Clears Stall on all endpoints.
532 * @param InstancePtr is a pointer to the XUsbPsu instance.
538 ****************************************************************************/
539 void XUsbPsu_ClearStalls(struct XUsbPsu *InstancePtr)
541 struct XUsbPsu_EpParams *Params;
543 struct XUsbPsu_Ep *Ept;
545 Xil_AssertVoid(InstancePtr != NULL);
547 Params = XUsbPsu_GetEpParams(InstancePtr);
548 for (epnum = 1; epnum < XUSBPSU_ENDPOINTS_NUM; epnum++) {
550 Ept = &InstancePtr->eps[epnum];
554 if (!(Ept->EpStatus & XUSBPSU_EP_STALL))
557 Ept->EpStatus &= ~XUSBPSU_EP_STALL;
559 Ept->Cmd = XUSBPSU_DEPCMD_CLEARSTALL;
560 XUsbPsu_SendEpCmd(InstancePtr, Ept->PhyEpNum,
561 Ept->Direction, XUSBPSU_DEPCMD_CLEARSTALL,
566 /****************************************************************************/
568 * Initiates DMA to send data on endpoint to Host.
570 * @param InstancePtr is a pointer to the XUsbPsu instance.
571 * @param UsbEp is USB endpoint number.
572 * @param BufferPtr is pointer to data.
573 * @param BufferLen is length of data buffer.
575 * @return XST_SUCCESS else XST_FAILURE
579 *****************************************************************************/
580 int XUsbPsu_EpBufferSend(struct XUsbPsu *InstancePtr, u8 UsbEp,
581 u8 *BufferPtr, u32 BufferLen)
585 struct XUsbPsu_Trb *TrbPtr;
586 struct XUsbPsu_Ep *Ept;
587 struct XUsbPsu_EpParams *Params;
589 Xil_AssertNonvoid(InstancePtr != NULL);
590 Xil_AssertNonvoid(UsbEp >= 0 && UsbEp <= 16);
591 Xil_AssertNonvoid(BufferPtr != NULL);
593 PhyEpNum = PhysicalEp(UsbEp, XUSBPSU_EP_DIR_IN);
596 RetVal = XUsbPsu_Ep0Send(InstancePtr, BufferPtr, BufferLen);
600 Ept = &InstancePtr->eps[PhyEpNum];
602 if (Ept->Direction != XUSBPSU_EP_DIR_IN) {
606 Ept->RequestedBytes = BufferLen;
608 Ept->BufferPtr = BufferPtr;
610 TrbPtr = &Ept->EpTrb;
612 TrbPtr->BufferPtrLow = (UINTPTR)BufferPtr;
613 TrbPtr->BufferPtrHigh = ((UINTPTR)BufferPtr >> 16) >> 16;
614 TrbPtr->Size = BufferLen & XUSBPSU_TRB_SIZE_MASK;
615 TrbPtr->Ctrl = XUSBPSU_TRBCTL_NORMAL;
617 TrbPtr->Ctrl |= (XUSBPSU_TRB_CTRL_HWO
618 | XUSBPSU_TRB_CTRL_LST
619 | XUSBPSU_TRB_CTRL_IOC
620 | XUSBPSU_TRB_CTRL_ISP_IMI);
622 Xil_DCacheFlushRange(TrbPtr, sizeof(struct XUsbPsu_Trb));
623 Xil_DCacheFlushRange(BufferPtr, BufferLen);
625 Params = XUsbPsu_GetEpParams(InstancePtr);
627 Params->Param1 = (UINTPTR)TrbPtr;
629 Ept->Cmd = XUSBPSU_DEPCMD_STARTTRANSFER;
630 RetVal = XUsbPsu_SendEpCmd(InstancePtr, UsbEp, Ept->Direction,
631 XUSBPSU_DEPCMD_STARTTRANSFER, Params);
632 if (RetVal != XST_SUCCESS) {
635 Ept->ResourceIndex = XUsbPsu_EpGetTransferIndex(InstancePtr,
641 /****************************************************************************/
643 * Initiates DMA to receive data on Endpoint from Host.
645 * @param InstancePtr is a pointer to the XUsbPsu instance.
646 * @param EpNum is USB endpoint number.
647 * @param BufferPtr is pointer to data.
648 * @param Length is length of data to be received.
650 * @return XST_SUCCESS else XST_FAILURE
654 *****************************************************************************/
655 int XUsbPsu_EpBufferRecv(struct XUsbPsu *InstancePtr, u8 UsbEp,
656 u8 *BufferPtr, u32 Length)
661 struct XUsbPsu_Trb *TrbPtr;
662 struct XUsbPsu_Ep *Ept;
663 struct XUsbPsu_EpParams *Params;
665 Xil_AssertNonvoid(InstancePtr != NULL);
666 Xil_AssertNonvoid(UsbEp >= 0 && UsbEp <= 16);
667 Xil_AssertNonvoid(BufferPtr != NULL);
669 PhyEpNum = PhysicalEp(UsbEp, XUSBPSU_EP_DIR_OUT);
672 RetVal = XUsbPsu_Ep0Recv(InstancePtr, BufferPtr, Length);
676 Ept = &InstancePtr->eps[PhyEpNum];
678 if (Ept->Direction != XUSBPSU_EP_DIR_OUT) {
682 Params = XUsbPsu_GetEpParams(InstancePtr);
684 Size = Ept->RequestedBytes = Length;
686 Ept->BufferPtr = BufferPtr;
689 * 8.2.5 - An OUT transfer size (Total TRB buffer allocation)
690 * must be a multiple of MaxPacketSize even if software is expecting a
691 * fixed non-multiple of MaxPacketSize transfer from the Host.
693 if (!IS_ALIGNED(Length, Ept->MaxSize)) {
694 Size = roundup(Length, Ept->MaxSize);
695 Ept->UnalignedTx = 1;
698 TrbPtr = &Ept->EpTrb;
700 TrbPtr->BufferPtrLow = (UINTPTR)BufferPtr;
701 TrbPtr->BufferPtrHigh = ((UINTPTR)BufferPtr >> 16) >> 16;
703 TrbPtr->Ctrl = XUSBPSU_TRBCTL_NORMAL;
705 TrbPtr->Ctrl |= (XUSBPSU_TRB_CTRL_HWO
706 | XUSBPSU_TRB_CTRL_LST
707 | XUSBPSU_TRB_CTRL_IOC
708 | XUSBPSU_TRB_CTRL_ISP_IMI);
711 Params->Param1 = (UINTPTR)TrbPtr;
713 Xil_DCacheFlushRange(TrbPtr, sizeof(struct XUsbPsu_Trb));
715 Params = XUsbPsu_GetEpParams(InstancePtr);
717 Params->Param1 = (UINTPTR)TrbPtr;
719 Ept->Cmd = XUSBPSU_DEPCMD_STARTTRANSFER;
721 RetVal = XUsbPsu_SendEpCmd(InstancePtr, UsbEp, Ept->Direction,
722 XUSBPSU_DEPCMD_STARTTRANSFER, Params);
723 if (RetVal != XST_SUCCESS) {
726 Ept->ResourceIndex = XUsbPsu_EpGetTransferIndex(InstancePtr,
732 /****************************************************************************/
734 * Stalls an Endpoint.
736 * @param InstancePtr is a pointer to the XUsbPsu instance.
737 * @param EpNum is USB endpoint number.
738 * @param Dir is direction.
744 *****************************************************************************/
745 void XUsbPsu_EpSetStall(struct XUsbPsu *InstancePtr, u8 Epnum, u8 Dir)
748 struct XUsbPsu_Ep *Ept;
749 struct XUsbPsu_EpParams *Params;
751 Xil_AssertVoid(InstancePtr != NULL);
752 Xil_AssertVoid(Epnum >= 0 && Epnum <= 16);
753 Xil_AssertVoid((Dir == XUSBPSU_EP_DIR_IN) || (Dir == XUSBPSU_EP_DIR_OUT));
755 PhyEpNum = PhysicalEp(Epnum, Dir);
756 Params = XUsbPsu_GetEpParams(InstancePtr);
758 if ((PhyEpNum == 0) || (PhyEpNum == 1)) {
759 /* Control Endpoint stall is issued on EP0 */
760 Ept = &InstancePtr->eps[0];
763 Ept->Cmd = XUSBPSU_DEPCMD_SETSTALL;
764 XUsbPsu_SendEpCmd(InstancePtr, Ept->PhyEpNum, Ept->Direction,
765 XUSBPSU_DEPCMD_SETSTALL, Params);
767 Ept->EpStatus |= XUSBPSU_EP_STALL;
770 /****************************************************************************/
772 * Clears Stall on an Endpoint.
774 * @param InstancePtr is a pointer to the XUsbPsu instance.
775 * @param EpNum is USB endpoint number.
776 * @param Dir is direction.
782 *****************************************************************************/
783 void XUsbPsu_EpClearStall(struct XUsbPsu *InstancePtr, u8 Epnum, u8 Dir)
786 struct XUsbPsu_Ep *Ept;
787 struct XUsbPsu_EpParams *Params;
789 Xil_AssertVoid(InstancePtr != NULL);
790 Xil_AssertVoid(Epnum >= 0 && Epnum <= 16);
791 Xil_AssertVoid((Dir == XUSBPSU_EP_DIR_IN) || (Dir == XUSBPSU_EP_DIR_OUT));
793 PhyEpNum = PhysicalEp(Epnum, Dir);
794 Params = XUsbPsu_GetEpParams(InstancePtr);
796 if ((PhyEpNum == 0) || (PhyEpNum == 1)) {
797 /* Control Endpoint stall is issued on EP0 */
798 Ept = &InstancePtr->eps[0];
801 Ept->Cmd = XUSBPSU_DEPCMD_CLEARSTALL;
802 XUsbPsu_SendEpCmd(InstancePtr, Ept->PhyEpNum, Ept->Direction,
803 XUSBPSU_DEPCMD_CLEARSTALL, Params);
805 Ept->EpStatus &= ~XUSBPSU_EP_STALL;
808 /****************************************************************************/
810 * Sets an user handler to be called after data is sent/received by an Endpoint
812 * @param InstancePtr is a pointer to the XUsbPsu instance.
813 * @param EpNum is USB endpoint number.
814 * @param Dir is direction of endpoint - XUSBPSU_EP_DIR_IN/XUSBPSU_EP_DIR_OUT.
815 * @param Handler is user handler to be called.
821 *****************************************************************************/
822 void XUsbPsu_SetEpHandler(struct XUsbPsu *InstancePtr, u8 Epnum,
823 u8 Dir, void (*Handler)(void *, u32, u32))
826 struct XUsbPsu_Ep *Ept;
828 Xil_AssertVoid(InstancePtr != NULL);
829 Xil_AssertVoid(Epnum >= 0 && Epnum <= 16);
830 Xil_AssertVoid((Dir == XUSBPSU_EP_DIR_IN) || (Dir == XUSBPSU_EP_DIR_OUT));
832 PhyEpNum = PhysicalEp(Epnum, Dir);
833 Ept = &InstancePtr->eps[PhyEpNum];
834 Ept->Handler = Handler;
837 /****************************************************************************/
839 * Returns status of endpoint - Stalled or not
841 * @param InstancePtr is a pointer to the XUsbPsu instance.
842 * @param EpNum is USB endpoint number.
843 * @param Dir is direction of endpoint - XUSBPSU_EP_DIR_IN/XUSBPSU_EP_DIR_OUT.
851 *****************************************************************************/
852 int XUsbPsu_IsEpStalled(struct XUsbPsu *InstancePtr, u8 Epnum, u8 Dir)
855 struct XUsbPsu_Ep *Ept;
857 Xil_AssertVoid(InstancePtr != NULL);
858 Xil_AssertVoid(Epnum >= 0 && Epnum <= 16);
859 Xil_AssertVoid((Dir == XUSBPSU_EP_DIR_IN) || (Dir == XUSBPSU_EP_DIR_OUT));
861 PhyEpNum = PhysicalEp(Epnum, Dir);
862 Ept = &InstancePtr->eps[PhyEpNum];
864 return !!(Ept->EpStatus & XUSBPSU_EP_STALL);
867 /****************************************************************************/
869 * Checks the Data Phase and calls user Endpoint handler.
871 * @param InstancePtr is a pointer to the XUsbPsu instance.
872 * @param Event is a pointer to the Endpoint event occured in core.
878 *****************************************************************************/
879 void XUsbPsu_EpXferComplete(struct XUsbPsu *InstancePtr,
880 const struct XUsbPsu_Event_Epevt *Event)
882 struct XUsbPsu_Ep *Ept;
883 struct XUsbPsu_Trb *TrbPtr;
889 Xil_AssertVoid(InstancePtr != NULL);
890 Xil_AssertVoid(Event != NULL);
892 EpNum = Event->Epnumber;
893 Ept = &InstancePtr->eps[EpNum];
894 Dir = Ept->Direction;
895 TrbPtr = &Ept->EpTrb;
897 Xil_DCacheInvalidateRange(TrbPtr, sizeof(struct XUsbPsu_Trb));
899 Status = XUSBPSU_TRB_SIZE_TRBSTS(TrbPtr->Size);
900 Length = TrbPtr->Size & XUSBPSU_TRB_SIZE_MASK;
902 if (Length && Dir) { /* IN */
903 Ept->BytesTxed = Ept->RequestedBytes - Length;
907 Ept->BytesTxed = Ept->RequestedBytes;
910 if (Length && !Dir) { /* OUT */
911 if (Ept->UnalignedTx == 1) {
912 Ept->BytesTxed = Ept->RequestedBytes;
913 Ept->UnalignedTx = 0;
918 /* Invalidate Cache */
919 Xil_DCacheInvalidateRange(Ept->BufferPtr, Ept->BytesTxed);
923 Ept->Handler(InstancePtr, Ept->RequestedBytes, Ept->BytesTxed);