]> git.sur5r.net Git - freertos/blob
8e7d4c5cd3d1601c3fa45a592e8d8671a5cf515a
[freertos] /
1 /******************************************************************************
2 *
3 * Copyright (C) 2015 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 *
37 *
38 * <pre>
39 * MODIFICATION HISTORY:
40 *
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.
46 *
47 * </pre>
48 *
49 *****************************************************************************/
50
51 /***************************** Include Files *********************************/
52
53 #include "xusbpsu.h"
54
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         Xil_AssertNonvoid(InstancePtr != NULL);
86
87         InstancePtr->EpParams.Param0 = 0x00;
88         InstancePtr->EpParams.Param1 = 0x00;
89         InstancePtr->EpParams.Param2 = 0x00;
90
91         return &InstancePtr->EpParams;
92 }
93
94 /****************************************************************************/
95 /**
96 * Returns Transfer Index assigned by Core for an Endpoint transfer.
97 *
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
101 *
102 * @return       Transfer Resource Index.
103 *
104 * @note         None.
105 *
106 *****************************************************************************/
107 u32 XUsbPsu_EpGetTransferIndex(struct XUsbPsu *InstancePtr, u8 UsbEpNum,
108                                                                 u8 Dir)
109 {
110         u8 PhyEpNum;
111         u32 ResourceIndex;
112
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));
117
118         PhyEpNum = PhysicalEp(UsbEpNum, Dir);
119         ResourceIndex = XUsbPsu_ReadReg(InstancePtr, XUSBPSU_DEPCMD(PhyEpNum));
120
121         return XUSBPSU_DEPCMD_GET_RSC_IDX(ResourceIndex);
122 }
123
124 /****************************************************************************/
125 /**
126 * Sends Endpoint command to Endpoint.
127 *
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.
134 *
135 * @return       XST_SUCCESS else XST_FAILURE.
136 *
137 * @note         None.
138 *
139 *****************************************************************************/
140 int XUsbPsu_SendEpCmd(struct XUsbPsu *InstancePtr, u8 UsbEpNum, u8 Dir,
141                                           u32 Cmd, struct XUsbPsu_EpParams *Params)
142 {
143         u32     RegVal;
144         u32     PhyEpnum;
145
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));
150
151         PhyEpnum = PhysicalEp(UsbEpNum, Dir);
152
153         XUsbPsu_WriteReg(InstancePtr, XUSBPSU_DEPCMDPAR0(PhyEpnum),
154                                          Params->Param0);
155         XUsbPsu_WriteReg(InstancePtr, XUSBPSU_DEPCMDPAR1(PhyEpnum),
156                                          Params->Param1);
157         XUsbPsu_WriteReg(InstancePtr, XUSBPSU_DEPCMDPAR2(PhyEpnum),
158                                          Params->Param2);
159
160         XUsbPsu_WriteReg(InstancePtr, XUSBPSU_DEPCMD(PhyEpnum),
161                         Cmd | XUSBPSU_DEPCMD_CMDACT);
162
163         if (XUsbPsu_Wait_Clear_Timeout(InstancePtr, XUSBPSU_DEPCMD(PhyEpnum),
164                         XUSBPSU_DEPCMD_CMDACT, 500) == XST_FAILURE) {
165                 return XST_FAILURE;
166         }
167
168         return XST_SUCCESS;
169 }
170
171 /****************************************************************************/
172 /**
173 * Sends Start New Configuration command to Endpoint.
174 *
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.
179 *
180 * @return       XST_SUCCESS else XST_FAILURE.
181 *
182 * @note
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).
191 *
192 *****************************************************************************/
193 int XUsbPsu_StartEpConfig(struct XUsbPsu *InstancePtr, u32 UsbEpNum, u8 Dir)
194 {
195         struct XUsbPsu_EpParams *Params;
196         u32     Cmd;
197         u8 PhyEpNum;
198
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));
203
204         PhyEpNum = PhysicalEp(UsbEpNum, Dir);
205         Params =  XUsbPsu_GetEpParams(InstancePtr);
206
207         if (PhyEpNum != 1) {
208                 Cmd = XUSBPSU_DEPCMD_DEPSTARTCFG;
209                 /* XferRscIdx == 0 for EP0 and 2 for the remaining */
210                 if (PhyEpNum > 1) {
211                         if (InstancePtr->IsConfigDone)
212                                 return XST_SUCCESS;
213                         InstancePtr->IsConfigDone = 1;
214                         Cmd |= XUSBPSU_DEPCMD_PARAM(2);
215                 }
216                 InstancePtr->eps[0].Cmd = XUSBPSU_DEPCMD_DEPSTARTCFG;
217                 return XUsbPsu_SendEpCmd(InstancePtr, 0, XUSBPSU_EP_DIR_OUT,
218                                                                  Cmd, Params);
219         }
220
221         return XST_SUCCESS;
222 }
223
224 /****************************************************************************/
225 /**
226 * Sends Set Endpoint Configuration command to Endpoint.
227 *
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.
233 *
234 * @return       XST_SUCCESS else XST_FAILURE.
235 *
236 * @note         None.
237 *
238 *****************************************************************************/
239 int XUsbPsu_SetEpConfig(struct XUsbPsu *InstancePtr, u8 UsbEpNum, u8 Dir,
240                                                 u16 Size, u8 Type)
241 {
242         struct XUsbPsu_EpParams *Params;
243         u8 PhyEpnum;
244
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);
250
251         Params = XUsbPsu_GetEpParams(InstancePtr);
252         PhyEpnum = PhysicalEp(UsbEpNum , Dir);
253
254         Params->Param0 = XUSBPSU_DEPCFG_EP_TYPE(Type)
255                 | XUSBPSU_DEPCFG_MAX_PACKET_SIZE(Size);
256
257         Params->Param1 = XUSBPSU_DEPCFG_XFER_COMPLETE_EN
258                 | XUSBPSU_DEPCFG_XFER_NOT_READY_EN;
259
260         /*
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.
265          */
266         Params->Param1 |= XUSBPSU_DEPCFG_EP_NUMBER(PhyEpnum);
267
268         if (Dir)
269                  Params->Param0 |= XUSBPSU_DEPCFG_FIFO_NUMBER(PhyEpnum >> 1);
270
271         InstancePtr->eps[PhyEpnum].Cmd = XUSBPSU_DEPCMD_SETEPCONFIG;
272
273         return XUsbPsu_SendEpCmd(InstancePtr, UsbEpNum, Dir,
274                                                          XUSBPSU_DEPCMD_SETEPCONFIG, Params);
275 }
276
277 /****************************************************************************/
278 /**
279 * Sends Set Transfer Resource command to Endpoint.
280 *
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.
285 *
286 * @return       XST_SUCCESS else XST_FAILURE.
287 *
288 * @note         None.
289 *
290 *****************************************************************************/
291 int XUsbPsu_SetXferResource(struct XUsbPsu *InstancePtr, u8 UsbEpNum, u8 Dir)
292 {
293         struct XUsbPsu_EpParams *Params;
294         u8 PhyEpnum;
295
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));
300
301         PhyEpnum = PhysicalEp(UsbEpNum , Dir);
302         Params = XUsbPsu_GetEpParams(InstancePtr);
303
304         Params->Param0 = XUSBPSU_DEPXFERCFG_NUM_XFER_RES(1);
305
306         InstancePtr->eps[PhyEpnum].Cmd = XUSBPSU_DEPCMD_SETTRANSFRESOURCE;
307
308         return XUsbPsu_SendEpCmd(InstancePtr, UsbEpNum, Dir,
309                                                          XUSBPSU_DEPCMD_SETTRANSFRESOURCE, Params);
310 }
311
312 /****************************************************************************/
313 /**
314 * Enables Endpoint for sending/receiving data.
315 *
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.
321 *
322 * @return       XST_SUCCESS else XST_FAILURE.
323 *
324 * @note         None.
325 *
326 ****************************************************************************/
327 int XUsbPsu_EpEnable(struct XUsbPsu *InstancePtr, u8 UsbEpNum, u8 Dir,
328                         u16 Maxsize, u8 Type)
329 {
330         struct XUsbPsu_Ep *Ept;
331         u32 RegVal;
332         int Ret = XST_FAILURE;
333         u32 PhyEpnum;
334
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);
340
341         PhyEpnum = PhysicalEp(UsbEpNum , Dir);
342         Ept = &InstancePtr->eps[PhyEpnum];
343
344         Ept->UsbEpNum   = UsbEpNum;
345         Ept->Direction  = Dir;
346         Ept->Type       = Type;
347         Ept->MaxSize    = Maxsize;
348         Ept->PhyEpNum   = PhyEpnum;
349
350         if (!(Ept->EpStatus & XUSBPSU_EP_ENABLED)) {
351                 Ret = XUsbPsu_StartEpConfig(InstancePtr, UsbEpNum, Dir);
352                 if (Ret)
353                         return Ret;
354         }
355
356         Ret = XUsbPsu_SetEpConfig(InstancePtr, UsbEpNum, Dir, Maxsize, Type);
357         if (Ret)
358                 return Ret;
359
360         if (!(Ept->EpStatus & XUSBPSU_EP_ENABLED)) {
361                 Ret = XUsbPsu_SetXferResource(InstancePtr, UsbEpNum, Dir);
362                 if (Ret)
363                         return Ret;
364
365                 Ept->EpStatus |= XUSBPSU_EP_ENABLED;
366
367                 RegVal = XUsbPsu_ReadReg(InstancePtr, XUSBPSU_DALEPENA);
368                 RegVal |= XUSBPSU_DALEPENA_EP(Ept->PhyEpNum);
369                 XUsbPsu_WriteReg(InstancePtr, XUSBPSU_DALEPENA, RegVal);
370         }
371
372         return XST_SUCCESS;
373 }
374
375 /****************************************************************************/
376 /**
377 * Disables Endpoint.
378 *
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.
383 *
384 * @return       XST_SUCCESS else XST_FAILURE.
385 *
386 * @note         None.
387 *
388 ****************************************************************************/
389 int XUsbPsu_EpDisable(struct XUsbPsu *InstancePtr, u8 UsbEpNum, u8 Dir)
390 {
391         u32     RegVal;
392         u8      PhyEpNum;
393         struct XUsbPsu_Ep *Ept;
394
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));
399
400         PhyEpNum = PhysicalEp(UsbEpNum , Dir);
401         Ept = &InstancePtr->eps[PhyEpNum];
402
403         RegVal = XUsbPsu_ReadReg(InstancePtr, XUSBPSU_DALEPENA);
404         RegVal &= ~XUSBPSU_DALEPENA_EP(PhyEpNum);
405         XUsbPsu_WriteReg(InstancePtr, XUSBPSU_DALEPENA, RegVal);
406
407         Ept->Type = 0;
408         Ept->EpStatus = 0;
409         Ept->MaxSize = 0;
410
411         return XST_SUCCESS;
412 }
413
414 /****************************************************************************/
415 /**
416 * Enables USB Control Endpoint i.e., EP0OUT and EP0IN of Core.
417 *
418 * @param        InstancePtr is a pointer to the XUsbPsu instance.
419 * @param        Size is control endpoint size.
420 *
421 * @return       XST_SUCCESS else XST_FAILURE.
422 *
423 * @note         None.
424 *
425 ****************************************************************************/
426 int XUsbPsu_EnableControlEp(struct XUsbPsu *InstancePtr, u16 Size)
427 {
428         int RetVal;
429
430         Xil_AssertNonvoid(InstancePtr != NULL);
431         Xil_AssertNonvoid(Size >= 64 && Size <= 512);
432
433         RetVal = XUsbPsu_EpEnable(InstancePtr, 0, XUSBPSU_EP_DIR_OUT, Size,
434                                 USB_ENDPOINT_XFER_CONTROL);
435         if (RetVal) {
436                 return XST_FAILURE;
437         }
438
439         RetVal = XUsbPsu_EpEnable(InstancePtr, 0, XUSBPSU_EP_DIR_IN, Size,
440                                 USB_ENDPOINT_XFER_CONTROL);
441         if (RetVal) {
442                 return XST_FAILURE;
443         }
444
445         return XST_SUCCESS;
446 }
447
448 /****************************************************************************/
449 /**
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
452 * Control IN.
453 *
454 * @param        InstancePtr is a pointer to the XUsbPsu instance.
455 *
456 * @return       None.
457 *
458 * @note         None.
459 *
460 ****************************************************************************/
461 void XUsbPsu_InitializeEps(struct XUsbPsu *InstancePtr)
462 {
463         struct XUsbPsu_Ep       *Ept;
464         u8  i;
465         u8 epnum;
466
467         Xil_AssertVoid(InstancePtr != NULL);
468
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;
473         }
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;
478         }
479 }
480
481 /****************************************************************************/
482 /**
483 * Stops transfer on Endpoint.
484 *
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.
488 *
489 * @return       None.
490 *
491 * @note         None.
492 *
493 ****************************************************************************/
494 void XUsbPsu_StopTransfer(struct XUsbPsu *InstancePtr, u8 UsbEpNum, u8 Dir)
495 {
496         struct XUsbPsu_Ep *Ept;
497         struct XUsbPsu_EpParams *Params;
498         u8 PhyEpNum;
499         u32 Cmd;
500         int Ret;
501
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));
505
506         PhyEpNum = PhysicalEp(UsbEpNum, Dir);
507         Params = XUsbPsu_GetEpParams(InstancePtr);
508         Ept = &InstancePtr->eps[PhyEpNum];
509
510         if (!Ept->ResourceIndex)
511                 return;
512
513         /*
514          * - Issue EndTransfer WITH CMDIOC bit set
515          * - Wait 100us
516          */
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,
522                                                         Cmd, Params);
523         Ept->ResourceIndex = 0;
524         Ept->EpStatus &= ~XUSBPSU_EP_BUSY;
525         usleep(100);
526 }
527
528 /****************************************************************************/
529 /**
530 * Clears Stall on all endpoints.
531 *
532 * @param        InstancePtr is a pointer to the XUsbPsu instance.
533 *
534 * @return       None.
535 *
536 * @note         None.
537 *
538 ****************************************************************************/
539 void XUsbPsu_ClearStalls(struct XUsbPsu *InstancePtr)
540 {
541         struct XUsbPsu_EpParams *Params;
542         u32 epnum;
543         struct XUsbPsu_Ep *Ept;
544
545         Xil_AssertVoid(InstancePtr != NULL);
546
547         Params = XUsbPsu_GetEpParams(InstancePtr);
548         for (epnum = 1; epnum < XUSBPSU_ENDPOINTS_NUM; epnum++) {
549
550                 Ept = &InstancePtr->eps[epnum];
551                 if (!Ept)
552                         continue;
553
554                 if (!(Ept->EpStatus & XUSBPSU_EP_STALL))
555                         continue;
556
557                 Ept->EpStatus &= ~XUSBPSU_EP_STALL;
558
559                 Ept->Cmd = XUSBPSU_DEPCMD_CLEARSTALL;
560                 XUsbPsu_SendEpCmd(InstancePtr, Ept->PhyEpNum,
561                                                   Ept->Direction, XUSBPSU_DEPCMD_CLEARSTALL,
562                                                   Params);
563         }
564 }
565
566 /****************************************************************************/
567 /**
568 * Initiates DMA to send data on endpoint to Host.
569 *
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.
574 *
575 * @return       XST_SUCCESS else XST_FAILURE
576 *
577 * @note         None.
578 *
579 *****************************************************************************/
580 int XUsbPsu_EpBufferSend(struct XUsbPsu *InstancePtr, u8 UsbEp,
581                                                  u8 *BufferPtr, u32 BufferLen)
582 {
583         u8      PhyEpNum;
584         int     RetVal;
585         struct XUsbPsu_Trb      *TrbPtr;
586         struct XUsbPsu_Ep *Ept;
587         struct XUsbPsu_EpParams *Params;
588
589         Xil_AssertNonvoid(InstancePtr != NULL);
590         Xil_AssertNonvoid(UsbEp >= 0 && UsbEp <= 16);
591         Xil_AssertNonvoid(BufferPtr != NULL);
592
593         PhyEpNum = PhysicalEp(UsbEp, XUSBPSU_EP_DIR_IN);
594         if (PhyEpNum == 1)
595         {
596                 RetVal = XUsbPsu_Ep0Send(InstancePtr, BufferPtr, BufferLen);
597                 return RetVal;
598         }
599
600         Ept = &InstancePtr->eps[PhyEpNum];
601
602         if (Ept->Direction != XUSBPSU_EP_DIR_IN) {
603                 return XST_FAILURE;
604         }
605
606         Ept->RequestedBytes = BufferLen;
607         Ept->BytesTxed = 0;
608         Ept->BufferPtr = BufferPtr;
609
610         TrbPtr = &Ept->EpTrb;
611
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;
616
617         TrbPtr->Ctrl |= (XUSBPSU_TRB_CTRL_HWO
618                                         | XUSBPSU_TRB_CTRL_LST
619                                         | XUSBPSU_TRB_CTRL_IOC
620                                         | XUSBPSU_TRB_CTRL_ISP_IMI);
621
622         Xil_DCacheFlushRange(TrbPtr, sizeof(struct XUsbPsu_Trb));
623         Xil_DCacheFlushRange(BufferPtr, BufferLen);
624
625         Params = XUsbPsu_GetEpParams(InstancePtr);
626         Params->Param0 = 0;
627         Params->Param1 = (UINTPTR)TrbPtr;
628
629         Ept->Cmd = XUSBPSU_DEPCMD_STARTTRANSFER;
630         RetVal = XUsbPsu_SendEpCmd(InstancePtr, UsbEp, Ept->Direction,
631                                                                 XUSBPSU_DEPCMD_STARTTRANSFER, Params);
632         if (RetVal != XST_SUCCESS) {
633                 return XST_FAILURE;
634         }
635         Ept->ResourceIndex = XUsbPsu_EpGetTransferIndex(InstancePtr,
636                                                                                                         Ept->UsbEpNum,
637                                                                                                         Ept->Direction);
638         return XST_SUCCESS;
639 }
640
641 /****************************************************************************/
642 /**
643 * Initiates DMA to receive data on Endpoint from Host.
644 *
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.
649 *
650 * @return       XST_SUCCESS else XST_FAILURE
651 *
652 * @note         None.
653 *
654 *****************************************************************************/
655 int XUsbPsu_EpBufferRecv(struct XUsbPsu *InstancePtr, u8 UsbEp,
656                                                  u8 *BufferPtr, u32 Length)
657 {
658         u8      PhyEpNum;
659         u32 Size;
660         int     RetVal;
661         struct XUsbPsu_Trb      *TrbPtr;
662         struct XUsbPsu_Ep *Ept;
663         struct XUsbPsu_EpParams *Params;
664
665         Xil_AssertNonvoid(InstancePtr != NULL);
666         Xil_AssertNonvoid(UsbEp >= 0 && UsbEp <= 16);
667         Xil_AssertNonvoid(BufferPtr != NULL);
668
669         PhyEpNum = PhysicalEp(UsbEp, XUSBPSU_EP_DIR_OUT);
670         if (PhyEpNum == 0)
671         {
672                 RetVal = XUsbPsu_Ep0Recv(InstancePtr, BufferPtr, Length);
673                 return RetVal;
674         }
675
676         Ept = &InstancePtr->eps[PhyEpNum];
677
678         if (Ept->Direction != XUSBPSU_EP_DIR_OUT) {
679                 return XST_FAILURE;
680         }
681
682         Params = XUsbPsu_GetEpParams(InstancePtr);
683
684         Size = Ept->RequestedBytes = Length;
685         Ept->BytesTxed = 0;
686         Ept->BufferPtr = BufferPtr;
687
688         /*
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.
692          */
693         if (!IS_ALIGNED(Length, Ept->MaxSize)) {
694                 Size = roundup(Length, Ept->MaxSize);
695                 Ept->UnalignedTx = 1;
696         }
697
698         TrbPtr = &Ept->EpTrb;
699
700         TrbPtr->BufferPtrLow  = (UINTPTR)BufferPtr;
701         TrbPtr->BufferPtrHigh = ((UINTPTR)BufferPtr >> 16) >> 16;
702         TrbPtr->Size = Size;
703         TrbPtr->Ctrl = XUSBPSU_TRBCTL_NORMAL;
704
705         TrbPtr->Ctrl |= (XUSBPSU_TRB_CTRL_HWO
706                                         | XUSBPSU_TRB_CTRL_LST
707                                         | XUSBPSU_TRB_CTRL_IOC
708                                         | XUSBPSU_TRB_CTRL_ISP_IMI);
709
710         Params->Param0 = 0;
711         Params->Param1 = (UINTPTR)TrbPtr;
712
713         Xil_DCacheFlushRange(TrbPtr, sizeof(struct XUsbPsu_Trb));
714
715         Params = XUsbPsu_GetEpParams(InstancePtr);
716         Params->Param0 = 0;
717         Params->Param1 = (UINTPTR)TrbPtr;
718
719         Ept->Cmd = XUSBPSU_DEPCMD_STARTTRANSFER;
720
721         RetVal = XUsbPsu_SendEpCmd(InstancePtr, UsbEp, Ept->Direction,
722                                                                 XUSBPSU_DEPCMD_STARTTRANSFER, Params);
723         if (RetVal != XST_SUCCESS) {
724                 return XST_FAILURE;
725         }
726         Ept->ResourceIndex = XUsbPsu_EpGetTransferIndex(InstancePtr,
727                                                                                                         Ept->UsbEpNum,
728                                                                                                         Ept->Direction);
729         return XST_SUCCESS;
730 }
731
732 /****************************************************************************/
733 /**
734 * Stalls an Endpoint.
735 *
736 * @param        InstancePtr is a pointer to the XUsbPsu instance.
737 * @param        EpNum is USB endpoint number.
738 * @param        Dir     is direction.
739 *
740 * @return       None.
741 *
742 * @note         None.
743 *
744 *****************************************************************************/
745 void XUsbPsu_EpSetStall(struct XUsbPsu *InstancePtr, u8 Epnum, u8 Dir)
746 {
747         u8      PhyEpNum;
748         struct XUsbPsu_Ep *Ept;
749         struct XUsbPsu_EpParams *Params;
750
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));
754
755         PhyEpNum = PhysicalEp(Epnum, Dir);
756         Params = XUsbPsu_GetEpParams(InstancePtr);
757
758         if ((PhyEpNum == 0) || (PhyEpNum == 1)) {
759                 /* Control Endpoint stall is issued on EP0 */
760                 Ept = &InstancePtr->eps[0];
761         }
762
763         Ept->Cmd = XUSBPSU_DEPCMD_SETSTALL;
764         XUsbPsu_SendEpCmd(InstancePtr, Ept->PhyEpNum, Ept->Direction,
765                                                         XUSBPSU_DEPCMD_SETSTALL, Params);
766
767         Ept->EpStatus |= XUSBPSU_EP_STALL;
768 }
769
770 /****************************************************************************/
771 /**
772 * Clears Stall on an Endpoint.
773 *
774 * @param        InstancePtr is a pointer to the XUsbPsu instance.
775 * @param        EpNum is USB endpoint number.
776 * @param        Dir     is direction.
777 *
778 * @return       None.
779 *
780 * @note         None.
781 *
782 *****************************************************************************/
783 void XUsbPsu_EpClearStall(struct XUsbPsu *InstancePtr, u8 Epnum, u8 Dir)
784 {
785         u8      PhyEpNum;
786         struct XUsbPsu_Ep *Ept;
787         struct XUsbPsu_EpParams *Params;
788
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));
792
793         PhyEpNum = PhysicalEp(Epnum, Dir);
794         Params = XUsbPsu_GetEpParams(InstancePtr);
795
796         if ((PhyEpNum == 0) || (PhyEpNum == 1)) {
797                 /* Control Endpoint stall is issued on EP0 */
798                 Ept = &InstancePtr->eps[0];
799         }
800
801         Ept->Cmd = XUSBPSU_DEPCMD_CLEARSTALL;
802         XUsbPsu_SendEpCmd(InstancePtr, Ept->PhyEpNum, Ept->Direction,
803                                                         XUSBPSU_DEPCMD_CLEARSTALL, Params);
804
805         Ept->EpStatus &= ~XUSBPSU_EP_STALL;
806 }
807
808 /****************************************************************************/
809 /**
810 * Sets an user handler to be called after data is sent/received by an Endpoint
811 *
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.
816 *
817 * @return       None.
818 *
819 * @note         None.
820 *
821 *****************************************************************************/
822 void XUsbPsu_SetEpHandler(struct XUsbPsu *InstancePtr, u8 Epnum,
823                         u8 Dir, void (*Handler)(void *, u32, u32))
824 {
825         u8 PhyEpNum;
826         struct XUsbPsu_Ep *Ept;
827
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));
831
832         PhyEpNum = PhysicalEp(Epnum, Dir);
833         Ept = &InstancePtr->eps[PhyEpNum];
834         Ept->Handler = Handler;
835 }
836
837 /****************************************************************************/
838 /**
839 * Returns status of endpoint - Stalled or not
840 *
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.
844 *
845 * @return
846 *                       1 - if stalled
847 *                       0 - if not stalled
848 *
849 * @note         None.
850 *
851 *****************************************************************************/
852 int XUsbPsu_IsEpStalled(struct XUsbPsu *InstancePtr, u8 Epnum, u8 Dir)
853 {
854         u8 PhyEpNum;
855         struct XUsbPsu_Ep *Ept;
856
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));
860
861         PhyEpNum = PhysicalEp(Epnum, Dir);
862         Ept = &InstancePtr->eps[PhyEpNum];
863
864         return !!(Ept->EpStatus & XUSBPSU_EP_STALL);
865 }
866
867 /****************************************************************************/
868 /**
869 * Checks the Data Phase and calls user Endpoint handler.
870 *
871 * @param        InstancePtr is a pointer to the XUsbPsu instance.
872 * @param        Event is a pointer to the Endpoint event occured in core.
873 *
874 * @return       None.
875 *
876 * @note         None.
877 *
878 *****************************************************************************/
879 void XUsbPsu_EpXferComplete(struct XUsbPsu *InstancePtr,
880                                                         const struct XUsbPsu_Event_Epevt *Event)
881 {
882         struct XUsbPsu_Ep       *Ept;
883         struct XUsbPsu_Trb      *TrbPtr;
884         u32     Status;
885         u32     Length;
886         u32     EpNum;
887         u8      Dir;
888
889         Xil_AssertVoid(InstancePtr != NULL);
890         Xil_AssertVoid(Event != NULL);
891
892         EpNum = Event->Epnumber;
893         Ept = &InstancePtr->eps[EpNum];
894         Dir = Ept->Direction;
895         TrbPtr = &Ept->EpTrb;
896
897         Xil_DCacheInvalidateRange(TrbPtr, sizeof(struct XUsbPsu_Trb));
898
899         Status = XUSBPSU_TRB_SIZE_TRBSTS(TrbPtr->Size);
900         Length = TrbPtr->Size & XUSBPSU_TRB_SIZE_MASK;
901
902         if (Length && Dir) { /* IN */
903                 Ept->BytesTxed = Ept->RequestedBytes - Length;
904         }
905
906         if (!Length) {
907                 Ept->BytesTxed = Ept->RequestedBytes;
908         }
909
910         if (Length && !Dir) { /* OUT */
911                 if (Ept->UnalignedTx == 1) {
912                         Ept->BytesTxed = Ept->RequestedBytes;
913                         Ept->UnalignedTx = 0;
914                 }
915         }
916
917         if (!Dir) {
918                 /* Invalidate Cache */
919                 Xil_DCacheInvalidateRange(Ept->BufferPtr, Ept->BytesTxed);
920         }
921
922         if (Ept->Handler) {
923                 Ept->Handler(InstancePtr, Ept->RequestedBytes, Ept->BytesTxed);
924         }
925 }