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_intr.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 support for Non control endpoint interrupts.
48 *****************************************************************************/
50 /***************************** Include Files ********************************/
54 /************************** Constant Definitions *****************************/
56 /**************************** Type Definitions *******************************/
58 /***************** Macros (Inline Functions) Definitions *********************/
60 /************************** Function Prototypes ******************************/
62 /************************** Variable Definitions *****************************/
64 /****************************************************************************/
66 * Endpoint interrupt handler.
68 * @param InstancePtr is a pointer to the XUsbPsu instance.
69 * @param Event is endpoint Event occured in the core.
75 *****************************************************************************/
76 void XUsbPsu_EpInterrupt(struct XUsbPsu *InstancePtr,
77 const struct XUsbPsu_Event_Epevt *Event)
79 struct XUsbPsu_Ep *Ept;
82 Xil_AssertVoid(Event != NULL);
84 EpNum = Event->Epnumber;
85 Ept = &InstancePtr->eps[EpNum];
87 if (!(Ept->EpStatus & XUSBPSU_EP_ENABLED))
90 if (EpNum == 0 || EpNum == 1) {
91 XUsbPsu_Ep0Intr(InstancePtr, Event);
95 /* Handle other endpoint events */
96 switch (Event->Endpoint_Event) {
97 case XUSBPSU_DEPEVT_XFERCOMPLETE:
98 XUsbPsu_EpXferComplete(InstancePtr, Event);
101 case XUSBPSU_DEPEVT_XFERNOTREADY:
109 /****************************************************************************/
111 * Disconnect Interrupt handler.
113 * @param InstancePtr is a pointer to the XUsbPsu instance.
119 *****************************************************************************/
120 void XUsbPsu_DisconnectIntr(struct XUsbPsu *InstancePtr)
124 RegVal = XUsbPsu_ReadReg(InstancePtr, XUSBPSU_DCTL);
125 RegVal &= ~XUSBPSU_DCTL_INITU1ENA;
126 XUsbPsu_WriteReg(InstancePtr, XUSBPSU_DCTL, RegVal);
128 RegVal &= ~XUSBPSU_DCTL_INITU2ENA;
129 XUsbPsu_WriteReg(InstancePtr, XUSBPSU_DCTL, RegVal);
131 InstancePtr->IsConfigDone = 0;
132 InstancePtr->Speed = XUSBPSU_SPEED_UNKNOWN;
135 /****************************************************************************/
137 * Reset Interrupt handler.
139 * @param InstancePtr is a pointer to the XUsbPsu instance.
145 *****************************************************************************/
146 void XUsbPsu_ResetIntr(struct XUsbPsu *InstancePtr)
151 InstancePtr->State = XUSBPSU_STATE_DEFAULT;
153 RegVal = XUsbPsu_ReadReg(InstancePtr, XUSBPSU_DCTL);
154 RegVal &= ~XUSBPSU_DCTL_TSTCTRL_MASK;
155 XUsbPsu_WriteReg(InstancePtr, XUSBPSU_DCTL, RegVal);
156 InstancePtr->TestMode = 0;
158 for (Index = 0; Index < InstancePtr->NumInEps + InstancePtr->NumOutEps;
161 InstancePtr->eps[Index].EpStatus = 0;
164 InstancePtr->IsConfigDone = 0;
166 /* Reset device address to zero */
167 RegVal = XUsbPsu_ReadReg(InstancePtr, XUSBPSU_DCFG);
168 RegVal &= ~(XUSBPSU_DCFG_DEVADDR_MASK);
169 XUsbPsu_WriteReg(InstancePtr, XUSBPSU_DCFG, RegVal);
172 /****************************************************************************/
174 * Connection Done Interrupt handler.
176 * @param InstancePtr is a pointer to the XUsbPsu instance.
182 *****************************************************************************/
183 void XUsbPsu_ConnDoneIntr(struct XUsbPsu *InstancePtr)
190 RegVal = XUsbPsu_ReadReg(InstancePtr, XUSBPSU_DSTS);
191 Speed = RegVal & XUSBPSU_DSTS_CONNECTSPD;
192 InstancePtr->Speed = Speed;
196 case XUSBPSU_DCFG_SUPERSPEED:
198 InstancePtr->Speed = XUSBPSU_SPEED_SUPER;
200 case XUSBPSU_DCFG_HIGHSPEED:
202 InstancePtr->Speed = XUSBPSU_SPEED_HIGH;
204 case XUSBPSU_DCFG_FULLSPEED2:
205 case XUSBPSU_DCFG_FULLSPEED1:
207 InstancePtr->Speed = XUSBPSU_SPEED_FULL;
209 case XUSBPSU_DCFG_LOWSPEED:
211 InstancePtr->Speed = XUSBPSU_SPEED_LOW;
215 XUsbPsu_EnableControlEp(InstancePtr, Size);
216 XUsbPsu_RecvSetup(InstancePtr);
219 /****************************************************************************/
221 * Link Status Change Interrupt handler.
223 * @param InstancePtr is a pointer to the XUsbPsu instance.
224 * @param EvtInfo is Event information.
230 *****************************************************************************/
231 void XUsbPsu_LinkStsChangeIntr(struct XUsbPsu *InstancePtr, u32 EvtInfo)
233 u8 State = EvtInfo & XUSBPSU_LINK_STATE_MASK;
235 InstancePtr->LinkState = State;
238 /****************************************************************************/
240 * Interrupt handler for device specific events.
242 * @param InstancePtr is a pointer to the XUsbPsu instance.
243 * @param Event is the Device Event occured in core.
249 *****************************************************************************/
250 void XUsbPsu_DevInterrupt(struct XUsbPsu *InstancePtr,
251 const struct XUsbPsu_Event_Devt *Event)
253 Xil_AssertVoid(Event != NULL);
255 switch (Event->Type) {
256 case XUSBPSU_DEVICE_EVENT_DISCONNECT:
257 XUsbPsu_DisconnectIntr(InstancePtr);
259 case XUSBPSU_DEVICE_EVENT_RESET:
260 XUsbPsu_ResetIntr(InstancePtr);
262 case XUSBPSU_DEVICE_EVENT_CONNECT_DONE:
263 XUsbPsu_ConnDoneIntr(InstancePtr);
265 case XUSBPSU_DEVICE_EVENT_WAKEUP:
267 case XUSBPSU_DEVICE_EVENT_HIBER_REQ:
269 case XUSBPSU_DEVICE_EVENT_LINK_STATUS_CHANGE:
270 XUsbPsu_LinkStsChangeIntr(InstancePtr,
273 case XUSBPSU_DEVICE_EVENT_EOPF:
275 case XUSBPSU_DEVICE_EVENT_SOF:
277 case XUSBPSU_DEVICE_EVENT_ERRATIC_ERROR:
279 case XUSBPSU_DEVICE_EVENT_CMD_CMPL:
281 case XUSBPSU_DEVICE_EVENT_OVERFLOW:
288 /****************************************************************************/
290 * Processes an Event entry in Event Buffer.
292 * @param InstancePtr is a pointer to the XUsbPsu instance.
293 * @param Event is the Event entry.
299 *****************************************************************************/
300 void XUsbPsu_ProcessEvent(struct XUsbPsu *InstancePtr,
301 const union XUsbPsu_Event *Event)
303 Xil_AssertVoid(Event != NULL);
305 if (Event->Type.Is_DevEvt == 0) {
306 /* Device Endpoint Event */
307 return XUsbPsu_EpInterrupt(InstancePtr, &Event->Epevt);
310 switch (Event->Type.Type) {
311 case XUSBPSU_EVENT_TYPE_DEV:
312 XUsbPsu_DevInterrupt(InstancePtr, &Event->Devt);
314 /* Carkit and I2C events not supported now */
320 /****************************************************************************/
322 * Processes events in an Event Buffer.
324 * @param InstancePtr is a pointer to the XUsbPsu instance.
325 * @bus Event buffer number.
331 *****************************************************************************/
332 void XUsbPsu_ProcessEvtBuffer(struct XUsbPsu *InstancePtr)
334 struct XUsbPsu_EvtBuffer *Evt;
335 union XUsbPsu_Event Event;
339 Evt = &InstancePtr->Evt;
340 RemainingEvnts = Evt->Count;
342 Xil_DCacheInvalidateRange(Evt->BuffAddr, XUSBPSU_EVENT_BUFFERS_SIZE);
344 while (RemainingEvnts > 0) {
345 Event.Raw = *(u32 *) (Evt->BuffAddr + Evt->Offset);
347 XUsbPsu_ProcessEvent(InstancePtr, &Event);
349 Evt->Offset = (Evt->Offset + 4) % XUSBPSU_EVENT_BUFFERS_SIZE;
351 XUsbPsu_WriteReg(InstancePtr, XUSBPSU_GEVNTCOUNT(0), 4);
355 Evt->Flags &= ~XUSBPSU_EVENT_PENDING;
357 /* Unmask interrupt */
358 RegVal = XUsbPsu_ReadReg(InstancePtr, XUSBPSU_GEVNTSIZ(0));
359 RegVal &= ~XUSBPSU_GEVNTSIZ_INTMASK;
360 XUsbPsu_WriteReg(InstancePtr, XUSBPSU_GEVNTSIZ(0), RegVal);
363 /****************************************************************************/
365 * Main Interrupt Handler.
371 *****************************************************************************/
372 void XUsbPsu_IntrHandler(void *XUsbPsu)
374 struct XUsbPsu *InstancePtr;
375 struct XUsbPsu_EvtBuffer *Evt;
379 Xil_AssertVoid(XUsbPsu != NULL);
381 InstancePtr = XUsbPsu;
382 Evt = &InstancePtr->Evt;
384 Count = XUsbPsu_ReadReg(InstancePtr, XUSBPSU_GEVNTCOUNT(0));
385 Count &= XUSBPSU_GEVNTCOUNT_MASK;
387 * As per data book software should only process Events if Event count
388 * is greater than zero.
394 Evt->Flags |= XUSBPSU_EVENT_PENDING;
397 RegVal = XUsbPsu_ReadReg(InstancePtr, XUSBPSU_GEVNTSIZ(0));
398 RegVal |= XUSBPSU_GEVNTSIZ_INTMASK;
399 XUsbPsu_WriteReg(InstancePtr, XUSBPSU_GEVNTSIZ(0), RegVal);
401 XUsbPsu_ProcessEvtBuffer(InstancePtr);