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_controltransfers.c
38 * MODIFICATION HISTORY:
40 * Ver Who Date Changes
41 * ----- ---- -------- -------------------------------------------------------
42 * 1.00a bss 01/22/15 First release
43 * 1.00a bss 03/18/15 Modified u32 pointer casts to UINTPTR.
47 *****************************************************************************/
49 /***************************** Include Files *********************************/
53 /************************** Constant Definitions *****************************/
55 #define USB_DIR_OUT 0 /* to device */
56 #define USB_DIR_IN 0x80 /* to host */
58 /**************************** Type Definitions *******************************/
60 /***************** Macros (Inline Functions) Definitions *********************/
62 /************************** Function Prototypes ******************************/
65 /************************** Variable Definitions *****************************/
68 /****************************************************************************/
70 * Initiates DMA on Control Endpoint 0 to receive Setup packet.
72 * @param InstancePtr is a pointer to the XUsbPsu instance.
74 * @return XST_SUCCESS else XST_FAILURE.
78 *****************************************************************************/
79 int XUsbPsu_RecvSetup(struct XUsbPsu *InstancePtr)
81 struct XUsbPsu_EpParams *Params;
82 struct XUsbPsu_Trb *TrbPtr;
83 struct XUsbPsu_Ep *Ept;
86 Xil_AssertNonvoid(InstancePtr != NULL);
88 Params = XUsbPsu_GetEpParams(InstancePtr);
89 /* Setup packet always on EP0 */
90 Ept = &InstancePtr->eps[0];
91 if (Ept->EpStatus & XUSBPSU_EP_BUSY) {
95 TrbPtr = &InstancePtr->Ep0_Trb;
97 TrbPtr->BufferPtrLow = (UINTPTR)&InstancePtr->SetupData;
98 TrbPtr->BufferPtrHigh = ((UINTPTR)&InstancePtr->SetupData >> 16) >> 16;
100 TrbPtr->Ctrl = XUSBPSU_TRBCTL_CONTROL_SETUP;
102 TrbPtr->Ctrl |= (XUSBPSU_TRB_CTRL_HWO
103 | XUSBPSU_TRB_CTRL_LST
104 | XUSBPSU_TRB_CTRL_IOC
105 | XUSBPSU_TRB_CTRL_ISP_IMI);
107 Xil_DCacheFlushRange(TrbPtr, sizeof(struct XUsbPsu_Trb));
110 Params->Param1 = (UINTPTR)TrbPtr;
112 InstancePtr->Ep0State = XUSBPSU_EP0_SETUP_PHASE;
114 Ept->Cmd = XUSBPSU_DEPCMD_STARTTRANSFER;
115 Ret = XUsbPsu_SendEpCmd(InstancePtr, 0, XUSBPSU_EP_DIR_OUT,
116 XUSBPSU_DEPCMD_STARTTRANSFER, Params);
121 Ept->EpStatus |= XUSBPSU_EP_BUSY;
122 Ept->ResourceIndex = XUsbPsu_EpGetTransferIndex(InstancePtr,
123 Ept->UsbEpNum, Ept->Direction);
128 /****************************************************************************/
130 * Stalls Control Endpoint and restarts to receive Setup packet.
132 * @param InstancePtr is a pointer to the XUsbPsu instance.
138 *****************************************************************************/
139 void XUsbPsu_Ep0StallRestart(struct XUsbPsu *InstancePtr)
141 struct XUsbPsu_Ep *Ept;
143 Xil_AssertVoid(InstancePtr != NULL);
145 /* reinitialize physical ep1 */
146 Ept = &InstancePtr->eps[1];
147 Ept->EpStatus = XUSBPSU_EP_ENABLED;
149 /* stall is always issued on EP0 */
150 XUsbPsu_EpSetStall(InstancePtr, 0, XUSBPSU_EP_DIR_OUT);
152 Ept = &InstancePtr->eps[0];
153 Ept->EpStatus = XUSBPSU_EP_ENABLED;
154 InstancePtr->Ep0State = XUSBPSU_EP0_SETUP_PHASE;
155 XUsbPsu_RecvSetup(InstancePtr);
158 /****************************************************************************/
160 * Changes State of Core to USB configured State.
162 * @param InstancePtr is a pointer to the XUsbPsu instance.
163 * @param Ctrl is a pointer to the Setup packet data.
165 * @return XST_SUCCESS else XST_FAILURE
169 *****************************************************************************/
170 int XUsbPsu_SetConfiguration(struct XUsbPsu *InstancePtr, SetupPacket *Ctrl)
176 Xil_AssertNonvoid(InstancePtr != NULL);
177 Xil_AssertNonvoid(Ctrl != NULL);
179 State = InstancePtr->State;
180 InstancePtr->IsConfigDone = 0;
183 case XUSBPSU_STATE_DEFAULT:
187 case XUSBPSU_STATE_ADDRESS:
188 InstancePtr->State = XUSBPSU_STATE_CONFIGURED;
191 case XUSBPSU_STATE_CONFIGURED:
202 /****************************************************************************/
204 * Checks the Data Phase and calls user Endpoint handler.
206 * @param InstancePtr is a pointer to the XUsbPsu instance.
207 * @param Event is a pointer to the Endpoint event occured in core.
213 *****************************************************************************/
214 void XUsbPsu_Ep0DataDone(struct XUsbPsu *InstancePtr,
215 const struct XUsbPsu_Event_Epevt *Event)
217 struct XUsbPsu_Ep *Ept;
218 struct XUsbPsu_Trb *TrbPtr;
224 Xil_AssertVoid(InstancePtr != NULL);
225 Xil_AssertVoid(Event != NULL);
227 EpNum = Event->Epnumber;
229 Ept = &InstancePtr->eps[EpNum];
230 TrbPtr = &InstancePtr->Ep0_Trb;
232 Xil_DCacheInvalidateRange(TrbPtr, sizeof(struct XUsbPsu_Trb));
234 Status = XUSBPSU_TRB_SIZE_TRBSTS(TrbPtr->Size);
235 if (Status == XUSBPSU_TRBSTS_SETUP_PENDING) {
239 Length = TrbPtr->Size & XUSBPSU_TRB_SIZE_MASK;
241 if (Length && Dir) { /* IN */
242 Ept->BytesTxed = Ept->RequestedBytes - Length;
246 Ept->BytesTxed = Ept->RequestedBytes;
249 if (Length && !Dir) { /* OUT */
250 /* may be wLength < Maxpacketsize */
251 if (InstancePtr->UnalignedTx) {
252 Ept->BytesTxed = Ept->RequestedBytes;
253 InstancePtr->UnalignedTx = 0;
258 /* Invalidate Cache */
259 Xil_DCacheInvalidateRange(Ept->BufferPtr, Ept->BytesTxed);
263 Ept->Handler(InstancePtr, Ept->RequestedBytes, Ept->BytesTxed);
267 /****************************************************************************/
269 * Checks the Status Phase and starts next Control transfer.
271 * @param InstancePtr is a pointer to the XUsbPsu instance.
272 * @param Event is a pointer to the Endpoint event occured in core.
278 *****************************************************************************/
279 void XUsbPsu_Ep0StatusDone(struct XUsbPsu *InstancePtr,
280 const struct XUsbPsu_Event_Epevt *Event)
282 struct XUsbPsu_Trb *TrbPtr;
285 Xil_AssertVoid(InstancePtr != NULL);
286 Xil_AssertVoid(Event != NULL);
288 TrbPtr = &InstancePtr->Ep0_Trb;
290 if (InstancePtr->IsInTestMode) {
293 Ret = XUsbPsu_SetTestMode(InstancePtr,
294 InstancePtr->TestMode);
296 XUsbPsu_Ep0StallRestart(InstancePtr);
300 Xil_DCacheInvalidateRange(TrbPtr, sizeof(struct XUsbPsu_Trb));
301 Status = XUSBPSU_TRB_SIZE_TRBSTS(TrbPtr->Size);
302 /* There is nothing driver can do for Setup Pending received */
304 XUsbPsu_RecvSetup(InstancePtr);
307 /****************************************************************************/
309 * Handles Transfer complete event of Control Endpoints EP0 OUT and EP0 IN.
311 * @param InstancePtr is a pointer to the XUsbPsu instance.
312 * @param Event is a pointer to the Endpoint event occured in core.
318 *****************************************************************************/
319 void XUsbPsu_Ep0XferComplete(struct XUsbPsu *InstancePtr,
320 const struct XUsbPsu_Event_Epevt *Event)
322 struct XUsbPsu_Ep *Ept;
326 Xil_AssertVoid(InstancePtr != NULL);
327 Xil_AssertVoid(Event != NULL);
329 Ept = &InstancePtr->eps[Event->Epnumber];
330 Ctrl = &InstancePtr->SetupData;
332 Ept->EpStatus &= ~XUSBPSU_EP_BUSY;
333 Ept->ResourceIndex = 0;
335 switch (InstancePtr->Ep0State) {
336 case XUSBPSU_EP0_SETUP_PHASE:
337 Xil_DCacheInvalidateRange(&InstancePtr->SetupData,
338 sizeof(InstancePtr->SetupData));
339 Length = Ctrl->wLength;
341 InstancePtr->IsThreeStage = 0;
342 InstancePtr->ControlDir = XUSBPSU_EP_DIR_OUT;
344 InstancePtr->IsThreeStage = 1;
345 InstancePtr->ControlDir = !!(Ctrl->bRequestType &
349 if (InstancePtr->Chapter9 == NULL) {
352 InstancePtr->Chapter9(InstancePtr,
353 &InstancePtr->SetupData);
357 case XUSBPSU_EP0_DATA_PHASE:
358 XUsbPsu_Ep0DataDone(InstancePtr, Event);
361 case XUSBPSU_EP0_STATUS_PHASE:
362 XUsbPsu_Ep0StatusDone(InstancePtr, Event);
370 /****************************************************************************/
372 * Starts Status Phase of Control Transfer
374 * @param InstancePtr is a pointer to the XUsbPsu instance.
375 * @param Event is a pointer to the Endpoint event occured in core.
377 * @return XST_SUCCESS else XST_FAILURE
381 *****************************************************************************/
382 int XUsbPsu_Ep0StartStatus(struct XUsbPsu *InstancePtr,
383 const struct XUsbPsu_Event_Epevt *Event)
385 struct XUsbPsu_Ep *Ept;
386 struct XUsbPsu_EpParams *Params;
387 struct XUsbPsu_Trb *TrbPtr;
392 Xil_AssertNonvoid(InstancePtr != NULL);
393 Xil_AssertNonvoid(Event != NULL);
395 Ept = &InstancePtr->eps[Event->Epnumber];
396 Params = XUsbPsu_GetEpParams(InstancePtr);
397 if (Ept->EpStatus & XUSBPSU_EP_BUSY) {
401 Type = InstancePtr->IsThreeStage ? XUSBPSU_TRBCTL_CONTROL_STATUS3
402 : XUSBPSU_TRBCTL_CONTROL_STATUS2;
403 TrbPtr = &InstancePtr->Ep0_Trb;
404 /* we use same TrbPtr for setup packet */
405 TrbPtr->BufferPtrLow = (UINTPTR)&InstancePtr->SetupData;
406 TrbPtr->BufferPtrHigh = ((UINTPTR)&InstancePtr->SetupData >> 16) >> 16;
410 TrbPtr->Ctrl |= (XUSBPSU_TRB_CTRL_HWO
411 | XUSBPSU_TRB_CTRL_LST
412 | XUSBPSU_TRB_CTRL_IOC
413 | XUSBPSU_TRB_CTRL_ISP_IMI);
415 Xil_DCacheFlushRange(TrbPtr, sizeof(struct XUsbPsu_Trb));
418 Params->Param1 = (UINTPTR)TrbPtr;
420 InstancePtr->Ep0State = XUSBPSU_EP0_STATUS_PHASE;
423 * Control OUT transfer - Status stage happens on EP0 IN - EP1
424 * Control IN transfer - Status stage happens on EP0 OUT - EP0
426 Dir = !InstancePtr->ControlDir;
427 Ept->Cmd = XUSBPSU_DEPCMD_STARTTRANSFER;
428 Ret = XUsbPsu_SendEpCmd(InstancePtr, 0, Dir,
429 XUSBPSU_DEPCMD_STARTTRANSFER, Params);
430 if (Ret != XST_SUCCESS) {
434 Ept->EpStatus |= XUSBPSU_EP_BUSY;
435 Ept->ResourceIndex = XUsbPsu_EpGetTransferIndex(InstancePtr,
436 Ept->UsbEpNum, Ept->Direction);
441 /****************************************************************************/
443 * Ends Data Phase - used incase of error.
445 * @param InstancePtr is a pointer to the XUsbPsu instance.
446 * @param Dep is a pointer to the Endpoint structure.
452 *****************************************************************************/
453 void XUsbPsu_Ep0_EndControlData(struct XUsbPsu *InstancePtr,
454 struct XUsbPsu_Ep *Ept)
456 struct XUsbPsu_EpParams *Params;
459 Xil_AssertVoid(InstancePtr != NULL);
460 Xil_AssertVoid(Ept != NULL);
462 if (!Ept->ResourceIndex)
465 Params = XUsbPsu_GetEpParams(InstancePtr);
466 Cmd = XUSBPSU_DEPCMD_ENDTRANSFER;
467 Cmd |= XUSBPSU_DEPCMD_PARAM(Ept->ResourceIndex);
468 Ept->Cmd = XUSBPSU_DEPCMD_ENDTRANSFER;
469 XUsbPsu_SendEpCmd(InstancePtr, Ept->UsbEpNum, Ept->Direction,
471 Ept->ResourceIndex = 0;
475 /****************************************************************************/
477 * Handles Transfer Not Ready event of Control Endpoints EP0 OUT and EP0 IN.
479 * @param InstancePtr is a pointer to the XUsbPsu instance.
480 * @param Event is a pointer to the Endpoint event occured in core.
486 *****************************************************************************/
487 void XUsbPsu_Ep0XferNotReady(struct XUsbPsu *InstancePtr,
488 const struct XUsbPsu_Event_Epevt *Event)
490 struct XUsbPsu_Ep *Ept;
492 Xil_AssertVoid(InstancePtr != NULL);
493 Xil_AssertVoid(Event != NULL);
495 Ept = &InstancePtr->eps[Event->Epnumber];
497 switch (Event->Status) {
498 case DEPEVT_STATUS_CONTROL_DATA:
500 * We already have a DATA transfer in the controller's cache,
501 * if we receive a XferNotReady(DATA) we will ignore it, unless
502 * it's for the wrong direction.
504 * In that case, we must issue END_TRANSFER command to the Data
505 * Phase we already have started and issue SetStall on the
508 if (Event->Epnumber != InstancePtr->ControlDir) {
509 XUsbPsu_Ep0_EndControlData(InstancePtr, Ept);
510 XUsbPsu_Ep0StallRestart(InstancePtr);
514 case DEPEVT_STATUS_CONTROL_STATUS:
515 XUsbPsu_Ep0StartStatus(InstancePtr, Event);
520 /****************************************************************************/
522 * Handles Interrupts of Control Endpoints EP0 OUT and EP0 IN.
524 * @param InstancePtr is a pointer to the XUsbPsu instance.
525 * @param Event is a pointer to the Endpoint event occured in core.
531 *****************************************************************************/
532 void XUsbPsu_Ep0Intr(struct XUsbPsu *InstancePtr,
533 const struct XUsbPsu_Event_Epevt *Event)
537 Xil_AssertVoid(InstancePtr != NULL);
538 Xil_AssertVoid(Event != NULL);
540 EpNum = Event->Epnumber;
541 switch (Event->Endpoint_Event) {
542 case XUSBPSU_DEPEVT_XFERCOMPLETE:
543 XUsbPsu_Ep0XferComplete(InstancePtr, Event);
546 case XUSBPSU_DEPEVT_XFERNOTREADY:
547 XUsbPsu_Ep0XferNotReady(InstancePtr, Event);
550 case XUSBPSU_DEPEVT_XFERINPROGRESS:
551 case XUSBPSU_DEPEVT_STREAMEVT:
552 case XUSBPSU_DEPEVT_EPCMDCMPLT:
557 /****************************************************************************/
559 * Initiates DMA to send data on Control Endpoint EP0 IN to Host.
561 * @param InstancePtr is a pointer to the XUsbPsu instance.
562 * @param BufferPtr is pointer to data.
563 * @param BufferLen is Length of data buffer.
565 * @return XST_SUCCESS else XST_FAILURE
569 *****************************************************************************/
570 int XUsbPsu_Ep0Send(struct XUsbPsu *InstancePtr, u8 *BufferPtr, u32 BufferLen)
572 /* Control IN - EP1 */
573 struct XUsbPsu_EpParams *Params;
574 struct XUsbPsu_Ep *Ept;
575 struct XUsbPsu_Trb *TrbPtr;
579 Xil_AssertNonvoid(InstancePtr != NULL);
580 Xil_AssertNonvoid(BufferPtr != NULL);
582 Ept = &InstancePtr->eps[1];
583 Params = XUsbPsu_GetEpParams(InstancePtr);
584 if (Ept->EpStatus & XUSBPSU_EP_BUSY) {
588 Ept->RequestedBytes = BufferLen;
590 Ept->BufferPtr = BufferPtr;
592 TrbPtr = &InstancePtr->Ep0_Trb;
594 TrbPtr->BufferPtrLow = (UINTPTR)BufferPtr;
595 TrbPtr->BufferPtrHigh = ((UINTPTR)BufferPtr >> 16) >> 16;
596 TrbPtr->Size = BufferLen;
597 TrbPtr->Ctrl = XUSBPSU_TRBCTL_CONTROL_DATA;
599 TrbPtr->Ctrl |= (XUSBPSU_TRB_CTRL_HWO
600 | XUSBPSU_TRB_CTRL_LST
601 | XUSBPSU_TRB_CTRL_IOC
602 | XUSBPSU_TRB_CTRL_ISP_IMI);
605 Params->Param1 = (UINTPTR)TrbPtr;
607 Xil_DCacheFlushRange(TrbPtr, sizeof(struct XUsbPsu_Trb));
608 Xil_DCacheFlushRange(BufferPtr, BufferLen);
610 InstancePtr->Ep0State = XUSBPSU_EP0_DATA_PHASE;
612 Ept->Cmd = XUSBPSU_DEPCMD_STARTTRANSFER;
613 Ret = XUsbPsu_SendEpCmd(InstancePtr, 0, XUSBPSU_EP_DIR_IN,
614 XUSBPSU_DEPCMD_STARTTRANSFER, Params);
615 if (Ret != XST_SUCCESS) {
619 Ept->EpStatus |= XUSBPSU_EP_BUSY;
620 Ept->ResourceIndex = XUsbPsu_EpGetTransferIndex(InstancePtr,
621 Ept->UsbEpNum, Ept->Direction);
626 /****************************************************************************/
628 * Initiates DMA to receive data on Control Endpoint EP0 OUT from Host.
630 * @param InstancePtr is a pointer to the XUsbPsu instance.
631 * @param BufferPtr is pointer to data.
632 * @param Length is Length of data to be received.
634 * @return XST_SUCCESS else XST_FAILURE
638 *****************************************************************************/
639 int XUsbPsu_Ep0Recv(struct XUsbPsu *InstancePtr, u8 *BufferPtr, u32 Length)
641 struct XUsbPsu_EpParams *Params;
642 struct XUsbPsu_Ep *Ept;
643 struct XUsbPsu_Trb *TrbPtr;
648 Xil_AssertNonvoid(InstancePtr != NULL);
649 Xil_AssertNonvoid(BufferPtr != NULL);
651 Ept = &InstancePtr->eps[0];
652 Params = XUsbPsu_GetEpParams(InstancePtr);
653 if (Ept->EpStatus & XUSBPSU_EP_BUSY) {
657 Size = Ept->RequestedBytes = Length;
659 Ept->BufferPtr = BufferPtr;
662 * 8.2.5 - An OUT transfer size (Total TRB buffer allocation)
663 * must be a multiple of MaxPacketSize even if software is expecting a
664 * fixed non-multiple of MaxPacketSize transfer from the Host.
666 if (!IS_ALIGNED(Length, Ept->MaxSize)) {
667 Size = roundup(Length, Ept->MaxSize);
668 InstancePtr->UnalignedTx = 1;
671 TrbPtr = &InstancePtr->Ep0_Trb;
673 TrbPtr->BufferPtrLow = (UINTPTR)BufferPtr;
674 TrbPtr->BufferPtrHigh = ((UINTPTR)BufferPtr >> 16) >> 16;
676 TrbPtr->Ctrl = XUSBPSU_TRBCTL_CONTROL_DATA;
678 TrbPtr->Ctrl |= (XUSBPSU_TRB_CTRL_HWO
679 | XUSBPSU_TRB_CTRL_LST
680 | XUSBPSU_TRB_CTRL_IOC
681 | XUSBPSU_TRB_CTRL_ISP_IMI);
683 Xil_DCacheFlushRange(TrbPtr, sizeof(struct XUsbPsu_Trb));
686 Params->Param1 = (UINTPTR)TrbPtr;
688 InstancePtr->Ep0State = XUSBPSU_EP0_DATA_PHASE;
690 Ept->Cmd = XUSBPSU_DEPCMD_STARTTRANSFER;
691 Ret = XUsbPsu_SendEpCmd(InstancePtr, 0, XUSBPSU_EP_DIR_OUT,
692 XUSBPSU_DEPCMD_STARTTRANSFER, Params);
697 Ept->EpStatus |= XUSBPSU_EP_BUSY;
698 Ept->ResourceIndex = XUsbPsu_EpGetTransferIndex(InstancePtr,
699 Ept->UsbEpNum, Ept->Direction);