]> git.sur5r.net Git - freertos/blob
a1840b6f8cebe7902e1a9220ee703973d2cddbe2
[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_intr.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 support for Non control endpoint interrupts.
45 *
46 * </pre>
47 *
48 *****************************************************************************/
49
50 /***************************** Include Files ********************************/
51
52 #include "xusbpsu.h"
53
54 /************************** Constant Definitions *****************************/
55
56 /**************************** Type Definitions *******************************/
57
58 /***************** Macros (Inline Functions) Definitions *********************/
59
60 /************************** Function Prototypes ******************************/
61
62 /************************** Variable Definitions *****************************/
63
64 /****************************************************************************/
65 /**
66 * Endpoint interrupt handler.
67 *
68 * @param        InstancePtr is a pointer to the XUsbPsu instance.
69 * @param        Event is endpoint Event occured in the core.
70 *
71 * @return       None.
72 *
73 * @note         None.
74 *
75 *****************************************************************************/
76 void XUsbPsu_EpInterrupt(struct XUsbPsu *InstancePtr,
77                 const struct XUsbPsu_Event_Epevt *Event)
78 {
79         struct XUsbPsu_Ep *Ept;
80         u32 EpNum;
81
82         Xil_AssertVoid(Event != NULL);
83
84         EpNum = Event->Epnumber;
85         Ept = &InstancePtr->eps[EpNum];
86
87         if (!(Ept->EpStatus & XUSBPSU_EP_ENABLED))
88                 return;
89
90         if (EpNum == 0 || EpNum == 1) {
91                 XUsbPsu_Ep0Intr(InstancePtr, Event);
92                 return;
93         }
94
95         /* Handle other endpoint events */
96         switch (Event->Endpoint_Event) {
97         case XUSBPSU_DEPEVT_XFERCOMPLETE:
98                 XUsbPsu_EpXferComplete(InstancePtr, Event);
99                 break;
100
101         case XUSBPSU_DEPEVT_XFERNOTREADY:
102                 break;
103
104         default:
105                 break;
106         }
107 }
108
109 /****************************************************************************/
110 /**
111 * Disconnect Interrupt handler.
112 *
113 * @param        InstancePtr is a pointer to the XUsbPsu instance.
114 *
115 * @return       None.
116 *
117 * @note         None.
118 *
119 *****************************************************************************/
120 void XUsbPsu_DisconnectIntr(struct XUsbPsu *InstancePtr)
121 {
122         u32 RegVal;
123
124         RegVal = XUsbPsu_ReadReg(InstancePtr, XUSBPSU_DCTL);
125         RegVal &= ~XUSBPSU_DCTL_INITU1ENA;
126         XUsbPsu_WriteReg(InstancePtr, XUSBPSU_DCTL, RegVal);
127
128         RegVal &= ~XUSBPSU_DCTL_INITU2ENA;
129         XUsbPsu_WriteReg(InstancePtr, XUSBPSU_DCTL, RegVal);
130
131         InstancePtr->IsConfigDone = 0;
132         InstancePtr->Speed = XUSBPSU_SPEED_UNKNOWN;
133 }
134
135 /****************************************************************************/
136 /**
137 * Reset Interrupt handler.
138 *
139 * @param        InstancePtr is a pointer to the XUsbPsu instance.
140 *
141 * @return       None.
142 *
143 * @note         None.
144 *
145 *****************************************************************************/
146 void XUsbPsu_ResetIntr(struct XUsbPsu *InstancePtr)
147 {
148         u32     RegVal;
149         int     Index;
150
151         InstancePtr->State = XUSBPSU_STATE_DEFAULT;
152
153         RegVal = XUsbPsu_ReadReg(InstancePtr, XUSBPSU_DCTL);
154         RegVal &= ~XUSBPSU_DCTL_TSTCTRL_MASK;
155         XUsbPsu_WriteReg(InstancePtr, XUSBPSU_DCTL, RegVal);
156         InstancePtr->TestMode = 0;
157
158         for (Index = 0; Index < InstancePtr->NumInEps + InstancePtr->NumOutEps;
159                         Index++)
160         {
161                 InstancePtr->eps[Index].EpStatus = 0;
162         }
163
164         InstancePtr->IsConfigDone = 0;
165
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);
170 }
171
172 /****************************************************************************/
173 /**
174 * Connection Done Interrupt handler.
175 *
176 * @param        InstancePtr is a pointer to the XUsbPsu instance.
177 *
178 * @return       None.
179 *
180 * @note         None.
181 *
182 *****************************************************************************/
183 void XUsbPsu_ConnDoneIntr(struct XUsbPsu *InstancePtr)
184 {
185         int                     Ret;
186         u32                     RegVal;
187         u16                     Size;
188         u8                      Speed;
189
190         RegVal = XUsbPsu_ReadReg(InstancePtr, XUSBPSU_DSTS);
191         Speed = RegVal & XUSBPSU_DSTS_CONNECTSPD;
192         InstancePtr->Speed = Speed;
193         Size = 64;
194
195         switch (Speed) {
196         case XUSBPSU_DCFG_SUPERSPEED:
197                 Size = 512;
198                 InstancePtr->Speed = XUSBPSU_SPEED_SUPER;
199                 break;
200         case XUSBPSU_DCFG_HIGHSPEED:
201                 Size = 64;
202                 InstancePtr->Speed = XUSBPSU_SPEED_HIGH;
203                 break;
204         case XUSBPSU_DCFG_FULLSPEED2:
205         case XUSBPSU_DCFG_FULLSPEED1:
206                 Size = 64;
207                 InstancePtr->Speed = XUSBPSU_SPEED_FULL;
208                 break;
209         case XUSBPSU_DCFG_LOWSPEED:
210                 Size = 64;
211                 InstancePtr->Speed = XUSBPSU_SPEED_LOW;
212                 break;
213         }
214
215         XUsbPsu_EnableControlEp(InstancePtr, Size);
216         XUsbPsu_RecvSetup(InstancePtr);
217 }
218
219 /****************************************************************************/
220 /**
221 * Link Status Change Interrupt handler.
222 *
223 * @param        InstancePtr is a pointer to the XUsbPsu instance.
224 * @param        EvtInfo is Event information.
225 *
226 * @return       None.
227 *
228 * @note         None.
229 *
230 *****************************************************************************/
231 void XUsbPsu_LinkStsChangeIntr(struct XUsbPsu *InstancePtr, u32 EvtInfo)
232 {
233         u8      State = EvtInfo & XUSBPSU_LINK_STATE_MASK;
234
235         InstancePtr->LinkState = State;
236 }
237
238 /****************************************************************************/
239 /**
240 * Interrupt handler for device specific events.
241 *
242 * @param        InstancePtr is a pointer to the XUsbPsu instance.
243 * @param        Event is the Device Event occured in core.
244 *
245 * @return       None.
246 *
247 * @note         None.
248 *
249 *****************************************************************************/
250 void XUsbPsu_DevInterrupt(struct XUsbPsu *InstancePtr,
251                 const struct XUsbPsu_Event_Devt *Event)
252 {
253         Xil_AssertVoid(Event != NULL);
254
255         switch (Event->Type) {
256         case XUSBPSU_DEVICE_EVENT_DISCONNECT:
257                 XUsbPsu_DisconnectIntr(InstancePtr);
258                 break;
259         case XUSBPSU_DEVICE_EVENT_RESET:
260                 XUsbPsu_ResetIntr(InstancePtr);
261                 break;
262         case XUSBPSU_DEVICE_EVENT_CONNECT_DONE:
263                 XUsbPsu_ConnDoneIntr(InstancePtr);
264                 break;
265         case XUSBPSU_DEVICE_EVENT_WAKEUP:
266                 break;
267         case XUSBPSU_DEVICE_EVENT_HIBER_REQ:
268                 break;
269         case XUSBPSU_DEVICE_EVENT_LINK_STATUS_CHANGE:
270                 XUsbPsu_LinkStsChangeIntr(InstancePtr,
271                                 Event->Event_Info);
272                 break;
273         case XUSBPSU_DEVICE_EVENT_EOPF:
274                 break;
275         case XUSBPSU_DEVICE_EVENT_SOF:
276                 break;
277         case XUSBPSU_DEVICE_EVENT_ERRATIC_ERROR:
278                 break;
279         case XUSBPSU_DEVICE_EVENT_CMD_CMPL:
280                 break;
281         case XUSBPSU_DEVICE_EVENT_OVERFLOW:
282                 break;
283         default:
284                 break;
285         }
286 }
287
288 /****************************************************************************/
289 /**
290 * Processes an Event entry in Event Buffer.
291 *
292 * @param        InstancePtr is a pointer to the XUsbPsu instance.
293 * @param        Event is the Event entry.
294 *
295 * @return       None.
296 *
297 * @note         None.
298 *
299 *****************************************************************************/
300 void XUsbPsu_ProcessEvent(struct XUsbPsu *InstancePtr,
301                         const union XUsbPsu_Event *Event)
302 {
303         Xil_AssertVoid(Event != NULL);
304
305         if (Event->Type.Is_DevEvt == 0) {
306                 /* Device Endpoint Event */
307                 return XUsbPsu_EpInterrupt(InstancePtr, &Event->Epevt);
308         }
309
310         switch (Event->Type.Type) {
311         case XUSBPSU_EVENT_TYPE_DEV:
312                 XUsbPsu_DevInterrupt(InstancePtr, &Event->Devt);
313                 break;
314         /* Carkit and I2C events not supported now */
315         default:
316                 break;
317         }
318 }
319
320 /****************************************************************************/
321 /**
322 * Processes events in an Event Buffer.
323 *
324 * @param        InstancePtr is a pointer to the XUsbPsu instance.
325 * @bus          Event buffer number.
326 *
327 * @return       None.
328 *
329 * @note         None.
330 *
331 *****************************************************************************/
332 void XUsbPsu_ProcessEvtBuffer(struct XUsbPsu *InstancePtr)
333 {
334         struct XUsbPsu_EvtBuffer *Evt;
335         union XUsbPsu_Event Event;
336         int RemainingEvnts;
337         u32 RegVal;
338
339         Evt = &InstancePtr->Evt;
340         RemainingEvnts = Evt->Count;
341
342         Xil_DCacheInvalidateRange(Evt->BuffAddr, XUSBPSU_EVENT_BUFFERS_SIZE);
343
344         while (RemainingEvnts > 0) {
345                 Event.Raw = *(u32 *) (Evt->BuffAddr + Evt->Offset);
346
347                 XUsbPsu_ProcessEvent(InstancePtr, &Event);
348
349                 Evt->Offset = (Evt->Offset + 4) % XUSBPSU_EVENT_BUFFERS_SIZE;
350                 RemainingEvnts -= 4;
351                 XUsbPsu_WriteReg(InstancePtr, XUSBPSU_GEVNTCOUNT(0), 4);
352         }
353
354         Evt->Count = 0;
355         Evt->Flags &= ~XUSBPSU_EVENT_PENDING;
356
357         /* Unmask interrupt */
358         RegVal = XUsbPsu_ReadReg(InstancePtr, XUSBPSU_GEVNTSIZ(0));
359         RegVal &= ~XUSBPSU_GEVNTSIZ_INTMASK;
360         XUsbPsu_WriteReg(InstancePtr, XUSBPSU_GEVNTSIZ(0), RegVal);
361 }
362
363 /****************************************************************************/
364 /**
365 * Main Interrupt Handler.
366 *
367 * @return       None.
368 *
369 * @note         None.
370 *
371 *****************************************************************************/
372 void XUsbPsu_IntrHandler(void *XUsbPsu)
373 {
374         struct XUsbPsu  *InstancePtr;
375         struct XUsbPsu_EvtBuffer *Evt;
376         u32 Count;
377         u32 RegVal;
378
379         Xil_AssertVoid(XUsbPsu != NULL);
380
381         InstancePtr = XUsbPsu;
382         Evt = &InstancePtr->Evt;
383
384         Count = XUsbPsu_ReadReg(InstancePtr, XUSBPSU_GEVNTCOUNT(0));
385         Count &= XUSBPSU_GEVNTCOUNT_MASK;
386         /*
387          * As per data book software should only process Events if Event count
388          * is greater than zero.
389          */
390         if (!Count)
391                 return;
392
393         Evt->Count = Count;
394         Evt->Flags |= XUSBPSU_EVENT_PENDING;
395
396         /* Mask interrupt */
397         RegVal = XUsbPsu_ReadReg(InstancePtr, XUSBPSU_GEVNTSIZ(0));
398         RegVal |= XUSBPSU_GEVNTSIZ_INTMASK;
399         XUsbPsu_WriteReg(InstancePtr, XUSBPSU_GEVNTSIZ(0), RegVal);
400
401         XUsbPsu_ProcessEvtBuffer(InstancePtr);
402 }
403