]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_R5_UltraScale_MPSoC/RTOSDemo_R5_bsp/psu_cortexr5_0/libsrc/usbpsu_v1_1/src/xusbpsu_endpoint.c
Update BSP source files for UltraScale Cortex-A53 and Cortex-R5 and Microblaze to...
[freertos] / FreeRTOS / Demo / CORTEX_R5_UltraScale_MPSoC / RTOSDemo_R5_bsp / psu_cortexr5_0 / libsrc / usbpsu_v1_1 / src / xusbpsu_endpoint.c
1 /******************************************************************************
2 *
3 * Copyright (C) 2016 Xilinx, Inc.  All rights reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * Use of the Software is limited solely to applications:
16 * (a) running on a Xilinx device, or
17 * (b) that interact with a Xilinx device through a bus or interconnect.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * XILINX  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
24 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * SOFTWARE.
26 *
27 * Except as contained in this notice, the name of the Xilinx shall not be used
28 * in advertising or otherwise to promote the sale, use or other dealings in
29 * this Software without prior written authorization from Xilinx.
30 *
31 *****************************************************************************/
32 /****************************************************************************/
33 /**
34 *
35 * @file xusbpsu_endpoint.c
36 * @addtogroup usbpsu_v1_0
37 * @{
38 *
39 *
40 * <pre>
41 * MODIFICATION HISTORY:
42 *
43 * Ver   Who  Date     Changes
44 * ----- ---- -------- -------------------------------------------------------
45 * 1.0   sg  06/06/16 First release
46 *
47 * </pre>
48 *
49 *****************************************************************************/
50
51 /***************************** Include Files *********************************/
52
53 #include "xusbpsu.h"
54 #include "xusbpsu_endpoint.h"
55 /************************** Constant Definitions *****************************/
56
57
58 /**************************** Type Definitions *******************************/
59
60 /* return Physical EP number as dwc3 mapping */
61 #define PhysicalEp(epnum, direction)    (((epnum) << 1 ) | (direction))
62
63 /***************** Macros (Inline Functions) Definitions *********************/
64
65
66 /************************** Function Prototypes ******************************/
67
68
69 /************************** Variable Definitions *****************************/
70
71
72 /****************************************************************************/
73 /**
74 * Returns zeroed parameters to be used by Endpoint commands
75 *
76 * @param        InstancePtr is a pointer to the XUsbPsu instance.
77 *
78 * @return       Zeroed Params structure pointer.
79 *
80 * @note         None.
81 *
82 *****************************************************************************/
83 struct XUsbPsu_EpParams *XUsbPsu_GetEpParams(struct XUsbPsu *InstancePtr)
84 {
85         if (InstancePtr == NULL) {
86                 return NULL;
87         }
88
89         InstancePtr->EpParams.Param0 = 0x00U;
90         InstancePtr->EpParams.Param1 = 0x00U;
91         InstancePtr->EpParams.Param2 = 0x00U;
92
93         return &InstancePtr->EpParams;
94 }
95
96 /****************************************************************************/
97 /**
98 * Returns Transfer Index assigned by Core for an Endpoint transfer.
99 *
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
103 *
104 * @return       Transfer Resource Index.
105 *
106 * @note         None.
107 *
108 *****************************************************************************/
109 u32 XUsbPsu_EpGetTransferIndex(struct XUsbPsu *InstancePtr, u8 UsbEpNum,
110                                                                 u8 Dir)
111 {
112         u8 PhyEpNum;
113         u32 ResourceIndex;
114
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));
119
120         PhyEpNum = (u8)PhysicalEp(UsbEpNum, Dir);
121         ResourceIndex = XUsbPsu_ReadReg(InstancePtr, XUSBPSU_DEPCMD(PhyEpNum));
122
123         return (u32)XUSBPSU_DEPCMD_GET_RSC_IDX(ResourceIndex);
124 }
125
126 /****************************************************************************/
127 /**
128 * Sends Endpoint command to Endpoint.
129 *
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.
136 *
137 * @return       XST_SUCCESS else XST_FAILURE.
138 *
139 * @note         None.
140 *
141 *****************************************************************************/
142 s32 XUsbPsu_SendEpCmd(struct XUsbPsu *InstancePtr, u8 UsbEpNum, u8 Dir,
143                                           u32 Cmd, struct XUsbPsu_EpParams *Params)
144 {
145         u32     PhyEpNum;
146
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));
151
152         PhyEpNum = PhysicalEp(UsbEpNum, Dir);
153
154         XUsbPsu_WriteReg(InstancePtr, XUSBPSU_DEPCMDPAR0(PhyEpNum),
155                                          Params->Param0);
156         XUsbPsu_WriteReg(InstancePtr, XUSBPSU_DEPCMDPAR1(PhyEpNum),
157                                          Params->Param1);
158         XUsbPsu_WriteReg(InstancePtr, XUSBPSU_DEPCMDPAR2(PhyEpNum),
159                                          Params->Param2);
160
161         XUsbPsu_WriteReg(InstancePtr, XUSBPSU_DEPCMD(PhyEpNum),
162                         Cmd | XUSBPSU_DEPCMD_CMDACT);
163
164         if (XUsbPsu_Wait_Clear_Timeout(InstancePtr, XUSBPSU_DEPCMD(PhyEpNum),
165                         XUSBPSU_DEPCMD_CMDACT, 500U) == (s32)XST_FAILURE) {
166                 return XST_FAILURE;
167         }
168
169         return XST_SUCCESS;
170 }
171
172 /****************************************************************************/
173 /**
174 * Sends Start New Configuration command to Endpoint.
175 *
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.
180 *
181 * @return       XST_SUCCESS else XST_FAILURE.
182 *
183 * @note
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).
192 *
193 *****************************************************************************/
194 s32 XUsbPsu_StartEpConfig(struct XUsbPsu *InstancePtr, u32 UsbEpNum, u8 Dir)
195 {
196         struct XUsbPsu_EpParams *Params;
197         u32     Cmd;
198         u8 PhyEpNum;
199
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));
204
205         PhyEpNum = (u8)PhysicalEp(UsbEpNum, (u32)Dir);
206         Params =  XUsbPsu_GetEpParams(InstancePtr);
207         Xil_AssertNonvoid(Params != NULL);
208
209         if (PhyEpNum != 1U) {
210                 Cmd = XUSBPSU_DEPCMD_DEPSTARTCFG;
211                 /* XferRscIdx == 0 for EP0 and 2 for the remaining */
212                 if (PhyEpNum > 1U) {
213                         if (InstancePtr->IsConfigDone != 0U) {
214                                 return XST_SUCCESS;
215                         }
216                         InstancePtr->IsConfigDone = 1U;
217                         Cmd |= XUSBPSU_DEPCMD_PARAM(2);
218                 }
219
220                 return XUsbPsu_SendEpCmd(InstancePtr, 0U, XUSBPSU_EP_DIR_OUT,
221                                                                  Cmd, Params);
222         }
223
224         return XST_SUCCESS;
225 }
226
227 /****************************************************************************/
228 /**
229 * Sends Set Endpoint Configuration command to Endpoint.
230 *
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.
236 *
237 * @return       XST_SUCCESS else XST_FAILURE.
238 *
239 * @note         None.
240 *
241 *****************************************************************************/
242 s32 XUsbPsu_SetEpConfig(struct XUsbPsu *InstancePtr, u8 UsbEpNum, u8 Dir,
243                                                 u16 Size, u8 Type)
244 {
245         struct XUsbPsu_EpParams *Params;
246         u8 PhyEpNum;
247
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));
253
254         Params = XUsbPsu_GetEpParams(InstancePtr);
255         Xil_AssertNonvoid(Params != NULL);
256
257         PhyEpNum = PhysicalEp(UsbEpNum , Dir);
258
259         Params->Param0 = XUSBPSU_DEPCFG_EP_TYPE(Type)
260                 | XUSBPSU_DEPCFG_MAX_PACKET_SIZE(Size);
261
262         /*
263          * Set burst size to 1 as recommended
264          */
265         Params->Param0 |= XUSBPSU_DEPCFG_BURST_SIZE(1);
266
267         Params->Param1 = XUSBPSU_DEPCFG_XFER_COMPLETE_EN
268                 | XUSBPSU_DEPCFG_XFER_NOT_READY_EN;
269
270         /*
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.
275          */
276         Params->Param1 |= XUSBPSU_DEPCFG_EP_NUMBER(PhyEpNum);
277
278         if (Dir != XUSBPSU_EP_DIR_OUT) {
279                  Params->Param0 |= XUSBPSU_DEPCFG_FIFO_NUMBER((u32)PhyEpNum >> 1);
280         }
281
282         return XUsbPsu_SendEpCmd(InstancePtr, UsbEpNum, Dir,
283                                                          XUSBPSU_DEPCMD_SETEPCONFIG, Params);
284 }
285
286 /****************************************************************************/
287 /**
288 * Sends Set Transfer Resource command to Endpoint.
289 *
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.
294 *
295 * @return       XST_SUCCESS else XST_FAILURE.
296 *
297 * @note         None.
298 *
299 *****************************************************************************/
300 s32 XUsbPsu_SetXferResource(struct XUsbPsu *InstancePtr, u8 UsbEpNum, u8 Dir)
301 {
302         struct XUsbPsu_EpParams *Params;
303
304
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));
309
310         Params = XUsbPsu_GetEpParams(InstancePtr);
311         Xil_AssertNonvoid(Params != NULL);
312
313         Params->Param0 = XUSBPSU_DEPXFERCFG_NUM_XFER_RES(1);
314
315         return XUsbPsu_SendEpCmd(InstancePtr, UsbEpNum, Dir,
316                                                          XUSBPSU_DEPCMD_SETTRANSFRESOURCE, Params);
317 }
318
319 /****************************************************************************/
320 /**
321 * Enables Endpoint for sending/receiving data.
322 *
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.
328 *
329 * @return       XST_SUCCESS else XST_FAILURE.
330 *
331 * @note         None.
332 *
333 ****************************************************************************/
334 s32 XUsbPsu_EpEnable(struct XUsbPsu *InstancePtr, u8 UsbEpNum, u8 Dir,
335                         u16 Maxsize, u8 Type)
336 {
337         struct XUsbPsu_Ep *Ept;
338         u32 RegVal;
339         s32 Ret = (s32)XST_FAILURE;
340         u32 PhyEpNum;
341
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));
347
348         PhyEpNum = PhysicalEp(UsbEpNum , Dir);
349         Ept = &InstancePtr->eps[PhyEpNum];
350
351         Ept->UsbEpNum   = UsbEpNum;
352         Ept->Direction  = Dir;
353         Ept->Type       = Type;
354         Ept->MaxSize    = Maxsize;
355         Ept->PhyEpNum   = (u8)PhyEpNum;
356
357         if ((Ept->EpStatus & XUSBPSU_EP_ENABLED) == 0U) {
358                 Ret = XUsbPsu_StartEpConfig(InstancePtr, UsbEpNum, Dir);
359                 if (Ret != 0) {
360                         return Ret;
361                 }
362         }
363
364         Ret = XUsbPsu_SetEpConfig(InstancePtr, UsbEpNum, Dir, Maxsize, Type);
365         if (Ret != 0) {
366                 return Ret;
367         }
368
369         if ((Ept->EpStatus & XUSBPSU_EP_ENABLED) == 0U) {
370                 Ret = XUsbPsu_SetXferResource(InstancePtr, UsbEpNum, Dir);
371                 if (Ret != 0) {
372                         return Ret;
373                 }
374
375                 Ept->EpStatus |= XUSBPSU_EP_ENABLED;
376
377                 RegVal = XUsbPsu_ReadReg(InstancePtr, XUSBPSU_DALEPENA);
378                 RegVal |= XUSBPSU_DALEPENA_EP(Ept->PhyEpNum);
379                 XUsbPsu_WriteReg(InstancePtr, XUSBPSU_DALEPENA, RegVal);
380         }
381
382         return XST_SUCCESS;
383 }
384
385 /****************************************************************************/
386 /**
387 * Disables Endpoint.
388 *
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.
393 *
394 * @return       XST_SUCCESS else XST_FAILURE.
395 *
396 * @note         None.
397 *
398 ****************************************************************************/
399 s32 XUsbPsu_EpDisable(struct XUsbPsu *InstancePtr, u8 UsbEpNum, u8 Dir)
400 {
401         u32     RegVal;
402         u8      PhyEpNum;
403         struct XUsbPsu_Ep *Ept;
404
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));
409
410         PhyEpNum = PhysicalEp(UsbEpNum , Dir);
411         Ept = &InstancePtr->eps[PhyEpNum];
412
413         RegVal = XUsbPsu_ReadReg(InstancePtr, XUSBPSU_DALEPENA);
414         RegVal &= ~XUSBPSU_DALEPENA_EP(PhyEpNum);
415         XUsbPsu_WriteReg(InstancePtr, XUSBPSU_DALEPENA, RegVal);
416
417         Ept->Type = 0U;
418         Ept->EpStatus = 0U;
419         Ept->MaxSize = 0U;
420
421         return XST_SUCCESS;
422 }
423
424 /****************************************************************************/
425 /**
426 * Enables USB Control Endpoint i.e., EP0OUT and EP0IN of Core.
427 *
428 * @param        InstancePtr is a pointer to the XUsbPsu instance.
429 * @param        Size is control endpoint size.
430 *
431 * @return       XST_SUCCESS else XST_FAILURE.
432 *
433 * @note         None.
434 *
435 ****************************************************************************/
436 s32 XUsbPsu_EnableControlEp(struct XUsbPsu *InstancePtr, u16 Size)
437 {
438         s32 RetVal;
439
440         Xil_AssertNonvoid(InstancePtr != NULL);
441         Xil_AssertNonvoid((Size >= 64U) && (Size <= 512U));
442
443         RetVal = XUsbPsu_EpEnable(InstancePtr, 0U, XUSBPSU_EP_DIR_OUT, Size,
444                                 XUSBPSU_ENDPOINT_XFER_CONTROL);
445         if (RetVal != 0) {
446                 return XST_FAILURE;
447         }
448
449         RetVal = XUsbPsu_EpEnable(InstancePtr, 0U, XUSBPSU_EP_DIR_IN, Size,
450                                 XUSBPSU_ENDPOINT_XFER_CONTROL);
451         if (RetVal != 0) {
452                 return XST_FAILURE;
453         }
454
455         return XST_SUCCESS;
456 }
457
458 /****************************************************************************/
459 /**
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
462 * Control IN.
463 *
464 * @param        InstancePtr is a pointer to the XUsbPsu instance.
465 *
466 * @return       None.
467 *
468 * @note         None.
469 *
470 ****************************************************************************/
471 void XUsbPsu_InitializeEps(struct XUsbPsu *InstancePtr)
472 {
473         u8  i;
474         u8 Epnum;
475
476         Xil_AssertVoid(InstancePtr != NULL);
477
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;
482         }
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;
487         }
488 }
489
490 /****************************************************************************/
491 /**
492 * Stops transfer on Endpoint.
493 *
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.
497 *
498 * @return       None.
499 *
500 * @note         None.
501 *
502 ****************************************************************************/
503 void XUsbPsu_StopTransfer(struct XUsbPsu *InstancePtr, u8 UsbEpNum, u8 Dir)
504 {
505         struct XUsbPsu_Ep *Ept;
506         struct XUsbPsu_EpParams *Params;
507         u8 PhyEpNum;
508         u32 Cmd;
509
510         Xil_AssertVoid(InstancePtr != NULL);
511         Xil_AssertVoid(UsbEpNum <= (u8)16U);
512         Xil_AssertVoid((Dir == XUSBPSU_EP_DIR_IN) || (Dir == XUSBPSU_EP_DIR_OUT));
513
514         PhyEpNum = PhysicalEp(UsbEpNum, Dir);
515         Params = XUsbPsu_GetEpParams(InstancePtr);
516         Xil_AssertVoid(Params != NULL);
517
518         Ept = &InstancePtr->eps[PhyEpNum];
519
520         if (Ept->ResourceIndex == 0U) {
521                 return;
522         }
523
524         /*
525          * - Issue EndTransfer WITH CMDIOC bit set
526          * - Wait 100us
527          */
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,
532                                                         Cmd, Params);
533         Ept->ResourceIndex = 0U;
534         Ept->EpStatus &= ~XUSBPSU_EP_BUSY;
535         XUsbSleep(100U);
536 }
537
538 /****************************************************************************/
539 /**
540 * Clears Stall on all endpoints.
541 *
542 * @param        InstancePtr is a pointer to the XUsbPsu instance.
543 *
544 * @return       None.
545 *
546 * @note         None.
547 *
548 ****************************************************************************/
549 void XUsbPsu_ClearStalls(struct XUsbPsu *InstancePtr)
550 {
551         struct XUsbPsu_EpParams *Params;
552         u32 Epnum;
553         struct XUsbPsu_Ep *Ept;
554
555         Xil_AssertVoid(InstancePtr != NULL);
556
557         Params = XUsbPsu_GetEpParams(InstancePtr);
558         Xil_AssertVoid(Params != NULL);
559
560         for (Epnum = 1U; Epnum < XUSBPSU_ENDPOINTS_NUM; Epnum++) {
561
562                 Ept = &InstancePtr->eps[Epnum];
563                 if (Ept == NULL) {
564                         continue;
565                 }
566
567                 if ((Ept->EpStatus & XUSBPSU_EP_STALL) == 0U) {
568                         continue;
569                 }
570
571                 Ept->EpStatus &= ~XUSBPSU_EP_STALL;
572
573                 (void)XUsbPsu_SendEpCmd(InstancePtr, Ept->PhyEpNum,
574                                                   Ept->Direction, XUSBPSU_DEPCMD_CLEARSTALL,
575                                                   Params);
576         }
577 }
578
579 /****************************************************************************/
580 /**
581 * Initiates DMA to send data on endpoint to Host.
582 *
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.
587 *
588 * @return       XST_SUCCESS else XST_FAILURE
589 *
590 * @note         None.
591 *
592 *****************************************************************************/
593 s32 XUsbPsu_EpBufferSend(struct XUsbPsu *InstancePtr, u8 UsbEp,
594                                                  u8 *BufferPtr, u32 BufferLen)
595 {
596         u8      PhyEpNum;
597         s32     RetVal;
598         struct XUsbPsu_Trb      *TrbPtr;
599         struct XUsbPsu_Ep *Ept;
600         struct XUsbPsu_EpParams *Params;
601
602         Xil_AssertNonvoid(InstancePtr != NULL);
603         Xil_AssertNonvoid(UsbEp <= (u8)16U);
604         Xil_AssertNonvoid(BufferPtr != NULL);
605
606         PhyEpNum = PhysicalEp(UsbEp, XUSBPSU_EP_DIR_IN);
607         if (PhyEpNum == 1U) {
608                 RetVal = XUsbPsu_Ep0Send(InstancePtr, BufferPtr, BufferLen);
609                 return RetVal;
610         }
611
612         Ept = &InstancePtr->eps[PhyEpNum];
613
614         if (Ept->Direction != XUSBPSU_EP_DIR_IN) {
615                 return XST_FAILURE;
616         }
617
618         Ept->RequestedBytes = BufferLen;
619         Ept->BytesTxed = 0U;
620         Ept->BufferPtr = BufferPtr;
621
622         TrbPtr = &Ept->EpTrb;
623         Xil_AssertNonvoid(TrbPtr != NULL);
624
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;
629
630         TrbPtr->Ctrl |= (XUSBPSU_TRB_CTRL_HWO
631                                         | XUSBPSU_TRB_CTRL_LST
632                                         | XUSBPSU_TRB_CTRL_IOC
633                                         | XUSBPSU_TRB_CTRL_ISP_IMI);
634
635         Xil_DCacheFlushRange((INTPTR)TrbPtr, sizeof(struct XUsbPsu_Trb));
636         Xil_DCacheFlushRange((INTPTR)BufferPtr, BufferLen);
637
638         Params = XUsbPsu_GetEpParams(InstancePtr);
639         Xil_AssertNonvoid(Params != NULL);
640         Params->Param0 = 0U;
641         Params->Param1 = (UINTPTR)TrbPtr;
642
643         RetVal = XUsbPsu_SendEpCmd(InstancePtr, UsbEp, Ept->Direction,
644                                                                 XUSBPSU_DEPCMD_STARTTRANSFER, Params);
645         if (RetVal != XST_SUCCESS) {
646                 return XST_FAILURE;
647         }
648         Ept->ResourceIndex = (u8)XUsbPsu_EpGetTransferIndex(InstancePtr,
649                                                                                                         Ept->UsbEpNum,
650                                                                                                         Ept->Direction);
651         return XST_SUCCESS;
652 }
653
654 /****************************************************************************/
655 /**
656 * Initiates DMA to receive data on Endpoint from Host.
657 *
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.
662 *
663 * @return       XST_SUCCESS else XST_FAILURE
664 *
665 * @note         None.
666 *
667 *****************************************************************************/
668 s32 XUsbPsu_EpBufferRecv(struct XUsbPsu *InstancePtr, u8 UsbEp,
669                                                  u8 *BufferPtr, u32 Length)
670 {
671         u8      PhyEpNum;
672         u32 Size;
673         s32     RetVal;
674         struct XUsbPsu_Trb      *TrbPtr;
675         struct XUsbPsu_Ep *Ept;
676         struct XUsbPsu_EpParams *Params;
677
678         Xil_AssertNonvoid(InstancePtr != NULL);
679         Xil_AssertNonvoid(UsbEp <= (u8)16U);
680         Xil_AssertNonvoid(BufferPtr != NULL);
681
682         PhyEpNum = PhysicalEp(UsbEp, XUSBPSU_EP_DIR_OUT);
683         if (PhyEpNum == 0U) {
684                 RetVal = XUsbPsu_Ep0Recv(InstancePtr, BufferPtr, Length);
685                 return RetVal;
686         }
687
688         Ept = &InstancePtr->eps[PhyEpNum];
689
690         if (Ept->Direction != XUSBPSU_EP_DIR_OUT) {
691                 return XST_FAILURE;
692         }
693
694         Ept->RequestedBytes = Length;
695         Size = Length;
696         Ept->BytesTxed = 0U;
697         Ept->BufferPtr = BufferPtr;
698
699         /*
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.
703          */
704         if (!IS_ALIGNED(Length, Ept->MaxSize)) {
705                 Size = (u32)roundup(Length, Ept->MaxSize);
706                 Ept->UnalignedTx = 1U;
707         }
708
709         TrbPtr = &Ept->EpTrb;
710         Xil_AssertNonvoid(TrbPtr != NULL);
711
712         TrbPtr->BufferPtrLow  = (UINTPTR)BufferPtr;
713         TrbPtr->BufferPtrHigh = ((UINTPTR)BufferPtr >> 16) >> 16;
714         TrbPtr->Size = Size;
715         TrbPtr->Ctrl = XUSBPSU_TRBCTL_NORMAL;
716
717         TrbPtr->Ctrl |= (XUSBPSU_TRB_CTRL_HWO
718                                         | XUSBPSU_TRB_CTRL_LST
719                                         | XUSBPSU_TRB_CTRL_IOC
720                                         | XUSBPSU_TRB_CTRL_ISP_IMI);
721
722
723         Xil_DCacheFlushRange((INTPTR)TrbPtr, sizeof(struct XUsbPsu_Trb));
724         Xil_DCacheInvalidateRange((INTPTR)BufferPtr, Length);
725
726         Params = XUsbPsu_GetEpParams(InstancePtr);
727         Xil_AssertNonvoid(Params != NULL);
728         Params->Param0 = 0U;
729         Params->Param1 = (UINTPTR)TrbPtr;
730
731         RetVal = XUsbPsu_SendEpCmd(InstancePtr, UsbEp, Ept->Direction,
732                                                                 XUSBPSU_DEPCMD_STARTTRANSFER, Params);
733         if (RetVal != XST_SUCCESS) {
734                 return XST_FAILURE;
735         }
736         Ept->ResourceIndex = (u8)XUsbPsu_EpGetTransferIndex(InstancePtr,
737                                                                                                         Ept->UsbEpNum,
738                                                                                                         Ept->Direction);
739         return XST_SUCCESS;
740 }
741
742 /****************************************************************************/
743 /**
744 * Stalls an Endpoint.
745 *
746 * @param        InstancePtr is a pointer to the XUsbPsu instance.
747 * @param        EpNum is USB endpoint number.
748 * @param        Dir     is direction.
749 *
750 * @return       None.
751 *
752 * @note         None.
753 *
754 *****************************************************************************/
755 void XUsbPsu_EpSetStall(struct XUsbPsu *InstancePtr, u8 Epnum, u8 Dir)
756 {
757         u8      PhyEpNum;
758         struct XUsbPsu_Ep *Ept = NULL;
759         struct XUsbPsu_EpParams *Params;
760
761         Xil_AssertVoid(InstancePtr != NULL);
762         Xil_AssertVoid(Epnum <= (u8)16U);
763         Xil_AssertVoid((Dir == XUSBPSU_EP_DIR_IN) || (Dir == XUSBPSU_EP_DIR_OUT));
764
765         PhyEpNum = PhysicalEp(Epnum, Dir);
766         Ept = &InstancePtr->eps[PhyEpNum];
767
768         Params = XUsbPsu_GetEpParams(InstancePtr);
769         Xil_AssertVoid(Params != NULL);
770
771         (void)XUsbPsu_SendEpCmd(InstancePtr, Ept->PhyEpNum, Ept->Direction,
772                                                         XUSBPSU_DEPCMD_SETSTALL, Params);
773
774         Ept->EpStatus |= XUSBPSU_EP_STALL;
775 }
776
777 /****************************************************************************/
778 /**
779 * Clears Stall on an Endpoint.
780 *
781 * @param        InstancePtr is a pointer to the XUsbPsu instance.
782 * @param        EpNum is USB endpoint number.
783 * @param        Dir     is direction.
784 *
785 * @return       None.
786 *
787 * @note         None.
788 *
789 *****************************************************************************/
790 void XUsbPsu_EpClearStall(struct XUsbPsu *InstancePtr, u8 Epnum, u8 Dir)
791 {
792         u8      PhyEpNum;
793         struct XUsbPsu_Ep *Ept = NULL;
794         struct XUsbPsu_EpParams *Params;
795
796         Xil_AssertVoid(InstancePtr != NULL);
797         Xil_AssertVoid(Epnum <= (u8)16U);
798         Xil_AssertVoid((Dir == XUSBPSU_EP_DIR_IN) || (Dir == XUSBPSU_EP_DIR_OUT));
799
800         PhyEpNum = PhysicalEp(Epnum, Dir);
801         Ept = &InstancePtr->eps[PhyEpNum];
802
803         Params = XUsbPsu_GetEpParams(InstancePtr);
804         Xil_AssertVoid(Params != NULL);
805
806         (void)XUsbPsu_SendEpCmd(InstancePtr, Ept->PhyEpNum, Ept->Direction,
807                                                         XUSBPSU_DEPCMD_CLEARSTALL, Params);
808
809         Ept->EpStatus &= ~XUSBPSU_EP_STALL;
810 }
811
812 /****************************************************************************/
813 /**
814 * Sets an user handler to be called after data is sent/received by an Endpoint
815 *
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.
820 *
821 * @return       None.
822 *
823 * @note         None.
824 *
825 *****************************************************************************/
826 void XUsbPsu_SetEpHandler(struct XUsbPsu *InstancePtr, u8 Epnum,
827                         u8 Dir, void (*Handler)(void *, u32, u32))
828 {
829         u8 PhyEpNum;
830         struct XUsbPsu_Ep *Ept;
831
832         Xil_AssertVoid(InstancePtr != NULL);
833         Xil_AssertVoid(Epnum <= (u8)16U);
834         Xil_AssertVoid((Dir == XUSBPSU_EP_DIR_IN) || (Dir == XUSBPSU_EP_DIR_OUT));
835
836         PhyEpNum = PhysicalEp(Epnum, Dir);
837         Ept = &InstancePtr->eps[PhyEpNum];
838         Ept->Handler = Handler;
839 }
840
841 /****************************************************************************/
842 /**
843 * Returns status of endpoint - Stalled or not
844 *
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.
848 *
849 * @return
850 *                       1 - if stalled
851 *                       0 - if not stalled
852 *
853 * @note         None.
854 *
855 *****************************************************************************/
856 s32 XUsbPsu_IsEpStalled(struct XUsbPsu *InstancePtr, u8 Epnum, u8 Dir)
857 {
858         u8 PhyEpNum;
859         struct XUsbPsu_Ep *Ept;
860
861         Xil_AssertNonvoid(InstancePtr != NULL);
862         Xil_AssertNonvoid(Epnum <= (u8)16U);
863         Xil_AssertNonvoid((Dir == XUSBPSU_EP_DIR_IN) || (Dir == XUSBPSU_EP_DIR_OUT));
864
865         PhyEpNum = PhysicalEp(Epnum, Dir);
866         Ept = &InstancePtr->eps[PhyEpNum];
867
868         return (s32)(!!(Ept->EpStatus & XUSBPSU_EP_STALL));
869 }
870
871 /****************************************************************************/
872 /**
873 * Checks the Data Phase and calls user Endpoint handler.
874 *
875 * @param        InstancePtr is a pointer to the XUsbPsu instance.
876 * @param        Event is a pointer to the Endpoint event occured in core.
877 *
878 * @return       None.
879 *
880 * @note         None.
881 *
882 *****************************************************************************/
883 void XUsbPsu_EpXferComplete(struct XUsbPsu *InstancePtr,
884                                                         const struct XUsbPsu_Event_Epevt *Event)
885 {
886         struct XUsbPsu_Ep       *Ept;
887         struct XUsbPsu_Trb      *TrbPtr;
888         u32     Length;
889         u32     Epnum;
890         u8      Dir;
891
892         Xil_AssertVoid(InstancePtr != NULL);
893         Xil_AssertVoid(Event != NULL);
894
895         Epnum = Event->Epnumber;
896         Ept = &InstancePtr->eps[Epnum];
897         Dir = Ept->Direction;
898         TrbPtr = &Ept->EpTrb;
899         Xil_AssertVoid(TrbPtr != NULL);
900
901         Xil_DCacheInvalidateRange((INTPTR)TrbPtr, sizeof(struct XUsbPsu_Trb));
902
903         Length = TrbPtr->Size & XUSBPSU_TRB_SIZE_MASK;
904
905         if (Length == 0U) {
906                 Ept->BytesTxed = Ept->RequestedBytes;
907         } else {
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;
914                         }
915                 }
916         }
917
918         if (Dir == XUSBPSU_EP_DIR_OUT) {
919                 /* Invalidate Cache */
920                 Xil_DCacheInvalidateRange((INTPTR)Ept->BufferPtr, Ept->BytesTxed);
921         }
922
923         if (Ept->Handler != NULL) {
924                 Ept->Handler(InstancePtr, Ept->RequestedBytes, Ept->BytesTxed);
925         }
926 }
927 /** @} */