LPCOpen Platform
LPCOpen Platform for NXP LPC Microcontrollers
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
EHCI.h
Go to the documentation of this file.
1 /*
2  * @brief Enhanced Host Controller Interface
3  *
4  * @note
5  * Copyright(C) NXP Semiconductors, 2012
6  * All rights reserved.
7  *
8  * @par
9  * Software that is described herein is for illustrative purposes only
10  * which provides customers with programming information regarding the
11  * LPC products. This software is supplied "AS IS" without any warranties of
12  * any kind, and NXP Semiconductors and its licensor disclaim any and
13  * all warranties, express or implied, including all implied warranties of
14  * merchantability, fitness for a particular purpose and non-infringement of
15  * intellectual property rights. NXP Semiconductors assumes no responsibility
16  * or liability for the use of the software, conveys no license or rights under any
17  * patent, copyright, mask work right, or any other intellectual property rights in
18  * or to any products. NXP Semiconductors reserves the right to make changes
19  * in the software without notification. NXP Semiconductors also makes no
20  * representation or warranty that such application will be suitable for the
21  * specified use without further testing or modification.
22  *
23  * @par
24  * Permission to use, copy, modify, and distribute this software and its
25  * documentation is hereby granted, under NXP Semiconductors' and its
26  * licensor's relevant copyrights in the software, without fee, provided that it
27  * is used in conjunction with NXP Semiconductors microcontrollers. This
28  * copyright, permission, and disclaimer notice must appear in all copies of
29  * this code.
30  */
35 #ifndef __LPC_EHCI_H__
36 #define __LPC_EHCI_H__
37 
38 #ifndef __LPC_EHCI_C__ // TODO INCLUDE FROM EHCI.C
39  #error "EHCI.h is private header and can only be included by EHCI.c, try to include HCD.h instead"
40 #endif
41 
42 #ifdef __TEST__ // suppress static/inline for Testing purpose
43  #define static
44  #define inline
45 #endif
46 
47 /*=======================================================================*/
48 /* EHCI C O N F I G U R A T I O N */
49 /*=======================================================================*/
50 #define HCD_MAX_QHD HCD_MAX_ENDPOINT /* USBD_USB_HC_EHCI */
51 #define HCD_MAX_QTD (HCD_MAX_ENDPOINT + 3) /* USBD_USB_HC_EHCI */
52 #define HCD_MAX_HS_ITD 4 /* USBD_USB_HC_EHCI */
53 #define HCD_MAX_SITD 16 /* USBD_USB_HC_EHCI */
54 
55 #define FRAMELIST_SIZE_BITS 5 /* (0:1024) - (1:512) - (2:256) - (3:128) - (4:64) - (5:32) - (6:16) - (7:8) */
56 #define FRAME_LIST_SIZE (1024 >> FRAMELIST_SIZE_BITS)
57 
58 /**********************/
59 /* USBCMD Register */
60 /**********************/
61 #define INT_THRESHOLD_CTRL 0x00080000UL/* Max Int Interval = 8 uframes */
62 #define ASYNC_SCHEDULE_PARK_MODE_ENABLE NO
63 #define ASYNC_SCHEDULE_PARK_MODE_COUNT 0
64 
65 /****************************/
66 /* USBSTS Register */
67 /****************************/
68 
69 /**************************************************/
70 /* USBINTR Register */
71 /**************************************************/
72 #define INT_SOF_RECEIVED_ENABLE NO
73 // #define INT_ASYNC_ADVANCE_ENABLE Must be YES
74 // #define INT_SYSTEM_ERR_ENABLE Must be YES
75 #define INT_FRAME_ROLL_OVER_ENABLE NO
76 // #define INT_PORT_CHANGE_ENABLE Must be YES
77 // #define INT_USB_ERR_ENABLE Must be YES
78 // #define INT_USB_ENABLE Must be YES (NO for NXP chips in favor of UAI, UPI)
79 // #define INT_USB_ASYNC_INT_ENABLE Must be YES
80 // #define INT_USB_PERIOD_INT_ENABLE Must be YES
81 
82 /********************************************/
83 /* PORTSC Register */
84 /********************************************/
85 #define PORT_WAKE_OVER_CURRENT NO
86 #define PORT_WAKE_ON_DISCONNECT NO
87 #define PORT_WAKE_ON_CONNECT NO
88 #define PORT_INDICATOR NO
89 
90 /*==========================================================================*/
91 /* EHCI LOCAL DECLARATIONS */
92 /*==========================================================================*/
93 
94 /*==========================================================================*/
95 /* EHCI REGISTERS */
96 /*==========================================================================*/
97 /* Bit field definition for USBMODE_H */
98 #define USBMODE_DeviceController (2)
99 #define USBMODE_HostController (3)
100 #define USBMODE_VBusPowerSelect_High (1 << 5)
101 
102 /* Bit field definition for register UsbCmd */
103 #define EHC_USBCMD_RunStop 0x00000001UL /* Run or Stop */
104 #define EHC_USBCMD_HostReset 0x00000002UL /* Host Controller Reset */
105 #define EHC_USBCMD_FrameListSize 0x0000000CUL /* Frame List Size */
106 #define EHC_USBCMD_PeriodScheduleEnable 0x00000010UL /* Periodic Schedule Enable */
107 #define EHC_USBCMD_AsynScheduleEnable 0x00000020UL /* Asynchronous Schedule Enable */
108 #define EHC_USBCMD_IntAsyncAdvanceDoorbell 0x00000040UL /* Interrupt on Async Advance Doorbell */
109 #define EHC_USBCMD_LightReset 0x00000080UL /* Light Host Controller Reset */
110 #define EHC_USBCMD_AsyncScheduleParkCount 0x00000300UL /* Asynchronous Schedule Park Mode Count */
111 #define EHC_USBCMD_AsyncScheduleParkEnable 0x00000800UL /* Asynchronous Schedule Park Mode Enable */
112 #define EHC_USBCMD_FrameListSizeBit2 0x00008000UL /* Frame List Size bit 2 - EHCI derivation */
113 #define EHC_USBCMD_InterruptThresholdControl 0x00FF0000UL /* Interrupt Threshold control */
114 
115 /* Bit field definition for register UsbStatus */
116 #define EHC_USBSTS_UsbInt 0x00000001UL /* USB Interrupt */
117 #define EHC_USBSTS_UsbErrorInt 0x00000002UL /* USB Error Interrupt */
118 #define EHC_USBSTS_PortChangeDetect 0x00000004UL /* Port Change Detect */
119 #define EHC_USBSTS_FrameListRollover 0x00000008UL /* Frame List Rollover */
120 #define EHC_USBSTS_HostSystemError 0x00000010UL /* Host System Error */
121 #define EHC_USBSTS_IntAsyncAdvance 0x00000020UL /* Interrupt on Async Advance */
122 #define EHC_USBSTS_SofRecieveInt 0x00000080UL /* SOF - EHCI derivation */
123 #define EHC_USBSTS_HCHalted 0x00001000UL /* HCHalted */
124 #define EHC_USBSTS_Reclamation 0x00002000UL /* Reclamation */
125 #define EHC_USBSTS_PeriodScheduleStatus 0x00004000UL /* Periodic Schedule Status */
126 #define EHC_USBSTS_AsyncScheduleStatus 0x00008000UL /* Asynchronous Schedule Status */
127 #define EHC_USBSTS_UsbAsyncInt 0x00040000UL /* USB Asynchronous Interrupt - EHCI derivation */
128 #define EHC_USBSTS_UsbPeriodInt 0x00080000UL /* USB Period Interrupt - EHCI derivation */
129 
130 /* Bit field definition for register UsbIntr */
131 #define EHC_USBINTR_UsbIntEnable 0x00000001UL /* USB Interrupt Enable */
132 #define EHC_USBINTR_UsbErroIntEnable 0x00000002UL /* USB Error Interrupt Enable */
133 #define EHC_USBINTR_PortChangeIntEnable 0x00000004UL /* Port Change Interrupt Enable */
134 #define EHC_USBINTR_FrameListRolloverEnable 0x00000008UL /* Frame List Rollover Enable */
135 #define EHC_USBINTR_HostSystemErrorEnable 0x00000010UL /* Host System Error Enable */
136 #define EHC_USBINTR_IntAsyncAdvanceEnable 0x00000020UL /* Interrupt on Async Advance Enable */
137 #define EHC_USBINTR_SofRecieveEnable 0x00000080UL /* SOF - EHCI derivation */
138 #define EHC_USBINTR_UsbAsyncEnable 0x00040000UL /* USB Asynchronous Interrupt - EHCI derivation */
139 #define EHC_USBINTR_UsbPeriodEnable 0x00080000UL /* USB Period Interrupt - EHCI derivation */
140 #define EHC_USBINTR_ALL 0x000C00BFUL /* All Interrupt */
141 
142 /* Bit field definition for register FrIndex */
143 #define EHC_FRINDEX_MASK 0x000003FFUL /* Frame Index */
144 #define EHC_UFRAME_MASK 0x00000007UL /* u-Frame Index */
145 #define EHC_MFRAME_MASK 0x00001FF8UL /* m-Frame Index */
146 
147 /* Bit field definition for register PortSC */
148 #define EHC_PORTSC_CurrentConnectStatus 0x00000001UL /* Current Connect Status */
149 #define EHC_PORTSC_ConnectStatusChange 0x00000002UL /* Connect Status Change */
150 #define EHC_PORTSC_PortEnable 0x00000004UL /* Port Enabled Status */
151 #define EHC_PORTSC_PortEnableChange 0x00000008UL /* Port Enabled/Disabled Change */
152 #define EHC_PORTSC_OvercurrentActive 0x00000010UL /* Over-current Status */
153 #define EHC_PORTSC_OvercurrentChange 0x00000020UL /* Over-current Change */
154 #define EHC_PORTSC_ForcePortResume 0x00000040UL /* Force Port Resume */
155 #define EHC_PORTSC_PortSuspend 0x00000080UL /* Port Suspend */
156 #define EHC_PORTSC_PortReset 0x00000100UL /* Port Reset */
157 #define EHC_PORTSC_LineStatus 0x00000C00UL /* Line Status */
158 #define EHC_PORTSC_PortPowerControl 0x00001000UL /* Port Power Status */
159 #define EHC_PORTSC_PortOwner 0x00002000UL /* Port Owner Status */
160 #define EHC_PORTSC_PortIndicatorControl 0x0000C000UL /* Port Indicator Control */
161 #define EHC_PORTSC_PortTestControl 0x000F0000UL /* Port Test Control */
162 #define EHC_PORTSC_WakeonConnectEnable 0x00100000UL /* Wake on Connect Enable */
163 #define EHC_PORTSC_WakeonDisconnectEnable 0x00200000UL /* Wake on Disconnect Enable */
164 #define EHC_PORTSC_WakeonOvercurrentEnable 0x00400000UL /* Wake on Over-Current Enable */
165 #define EHC_PORTSC_PhyClockDisable 0x00800000UL /* PHY Clock Disable - EHCI derivation */
166 #define EHC_PORTSC_PortForceFullspeedConnect 0x01000000UL /* Force Device on Fullspeed mode (disable chirp sequences) - EHCI derivation */
167 #define EHC_PORTSC_PortSpeed 0x0C000000UL /* Device Speed - EHCI derivation */
168 
169 /* Definitions for Frame List Element Pointer */
170 #define QTD_MAX_XFER_LENGTH 0x5000
171 #define FRAMELIST_ALIGNMENT 4096 /* Frame List Alignment */
172 //#define LINK_TERMINATE 0x01
173 #define SPLIT_MAX_LEN_UFRAME 188
174 
175 /*=======================================================================*/
176 /* E H C I S T R U C T U R E S */
177 /*=======================================================================*/
178 
179 /* Memory for EHCI Structures, docs for more information */
180 
181 typedef union un_EHCD_Link {
183  struct {
184  uint32_t Terminate : 1;
186  };
187 
189 
190 typedef struct st_EHCD_QTD {
191  /*---------- Word 1 ----------*/
193 
194  /*---------- Word 2 ----------*/
195  /*-- Take advantage of this to store HCD information --*/
196  union {
198  struct {
199  uint32_t Terminate : 1;
200  uint32_t : 4;
201 
202  // === TODO: used reserved space, need to move to other place ===
203  /*-- HCD Area --*/
205  uint32_t : 0;
206  };
207 
208  };
209 
210  /*---------- Word 3 ----------*/
211  /* Status [7:0] */
212  __IO uint32_t PingState_Err : 1;
216  __IO uint32_t Babble : 1;
218  __IO uint32_t Halted : 1;
219  __IO uint32_t Active : 1;
220 
221  uint32_t PIDCode : 2;
222  __IO uint32_t ErrorCounter : 2;
223  __IO uint32_t CurrentPage : 3;
227  uint32_t : 0;/* Force next member on next storage unit */
228  /*---------- End Word 3 ----------*/
229 
230  /*---------- Buffer Pointer Word 4-7 ----------*/
232 } HCD_QTD, *PHCD_QTD; // TODO: because QTD is used to declare overlay in HCD_QHD, we cannot put aligned 32 here ATTR_ALIGNED(32)
233 
234 typedef struct st_EHCD_QHD {
235  /*---------- Word 1 ----------*/
237 
238  /*---------- Word 2 ----------*/
248  uint32_t : 0;/* Force next member on next storage unit */
249  /*---------- End Word 2 ----------*/
250 
251  /*---------- Word 3 ----------*/
257  uint32_t : 0;/* Force next member on next storage unit */
258  /*---------- End Word 3 ----------*/
259 
260  /*---------- Word 4 ----------*/
262 
263  /*---------- Overlay Area ----------*/
265 
266  /*---------- HCD Area : 16 Bytes----------*/
270  uint32_t ListIndex : 20;/* not support full period list */
271  uint32_t : 0;/* Force next member on next storage unit */
272 
273  __IO uint32_t status; // TODO will remove __IO after remove all HcdQHD function
274  uint32_t FirstQtd; /* used as TD head to clean up TD chain when transfer done */
275  uint16_t *pActualTransferCount; /* total transferred bytes of a usb request */
276 } ATTR_ALIGNED (32) HCD_QHD, *PHCD_QHD;
277 
278 typedef struct st_EHCD_ITD {
279  /*---------- Word 1 ----------*/
282  /*---------- Word 2-9 ----------*/
283  struct {
284  __IO uint32_t Offset : 12;
287  __IO uint32_t Length : 12;
288  /*-- status [31:28] --*/
289  __IO uint32_t Error : 1;
290  __IO uint32_t Babble : 1;
292  __IO uint32_t Active : 1;
293  } Transaction[8];
295  /*---------- Word 10-16 ----------*/
298  // FIXME: refractor to save memory HCD Area
299  /*---------- HCD Area ----------*/
303 } ATTR_ALIGNED (32) HCD_HS_ITD, *PHCD_HS_ITD;
304 
305 typedef struct st_EHCD_SITD {
307 
308  /*---------- Word 2: static endpoint ----------*/
310  uint32_t : 1;
312  uint32_t : 4;
314  uint32_t : 1;
317  uint32_t : 0;/* Force next member on next storage unit */
318  /*---------- End Word 2 ----------*/
319 
320  /*---------- Word 3: Slipt Mask ----------*/
321  uint8_t uFrameSMask;
322  uint8_t uFrameCMask;
323  uint16_t reserved; /* Force next member on next storage unit */
324  /*---------- End Word 3 ----------*/
325 
326  /*---------- Word 4: ----------*/
327  /* Status [7:0] */
328  __IO uint32_t : 1;
332  __IO uint32_t Babble : 1;
334  __IO uint32_t ERR : 1;
335  __IO uint32_t Active : 1;
336 
339  __IO uint32_t : 4;
342  uint32_t : 0;
343  /*---------- End Word 4 ----------*/
344 
345  /*---------- Word 5-6 ----------*/
346  uint32_t BufferPointer[2]; /*-- in BufferPointer[1] TP: Transaction Position - T-Count: Transaction Count --*/
347 
348  // union{
349  // uint32_t BufferPointer1;
350  // struct {
351  // __IO uint32_t TCount : 3;
352  // __IO uint32_t TPosition : 2;
353  // };
354  // };
355 
356  /*---------- Word 7 ----------*/
358 
359  /*-- HCD ARERA 4 bytes --*/
360  uint8_t inUse;
361  uint8_t IhdIdx;
362  uint8_t reserved2[2];
363 } ATTR_ALIGNED (32) HCD_SITD, *PHCD_SITD;
364 
365 typedef struct st_EHCI_HOST_DATA {
366  HCD_HS_ITD iTDs[HCD_MAX_HS_ITD]; /* Iso Transfer Descriptor */
367  HCD_QHD AsyncHeadQhd; /* Serve as H-Queue Head in Async Schedule */
368  HCD_QHD IntHeadQhd; /* Serve as Static 1ms Interrupt Heads */
369  HCD_QHD qHDs[HCD_MAX_QHD]; /* Queue Head */
370  HCD_QTD qTDs[HCD_MAX_QTD]; /* Queue Transfer Descriptor (Queue Element) */
371  HCD_SITD siTDs[HCD_MAX_SITD]; /* Split Iso Transfer Descriptor */
373 
374 typedef enum {
375  ITD_TYPE = 0,
379 } TD_TYPE;
380 
381 typedef struct st_PipeHandle {
382  uint8_t Idx;
383  uint8_t Type;
384  uint8_t PortNumber;
385  uint8_t HostId;
388 /*=======================================================================*/
389 /* LOCAL S Y M B O L D E C L A R A T I O N S */
390 /*=======================================================================*/
391 extern EHCI_HOST_DATA_Type ehci_data[MAX_USB_CORE];
392 // extern EHCI_HOST_DATA_Type ehci_data;
393 extern NextLinkPointer PeriodFrameList0[FRAME_LIST_SIZE]; /* Period Frame List */
394 extern NextLinkPointer PeriodFrameList1[FRAME_LIST_SIZE]; /* Period Frame List */
395 #define EHCI_FRAME_LIST(HostID) ((HostID) ? PeriodFrameList1 : PeriodFrameList0 )
397 /*=======================================================================*/
398 /* G L O B A L S Y M B O L D E C L A R A T I O N S */
399 /*=======================================================================*/
400 void USB_Host_Enumerate (uint8_t HostID);
401 
402 void USB_Host_DeEnumerate(uint8_t HostID);
403 
404 /*=======================================================================*/
405 /* L O C A L F U N C T I O N P R O T O T Y P E S */
406 /*=======================================================================*/
407 /********************************* HOST API *********************************/
408 static INLINE HCD_STATUS EHciHostInit(uint8_t HostID);
409 
410 static INLINE HCD_STATUS EHciHostRun(uint8_t HostID);
411 
412 static INLINE HCD_STATUS EHciHostStop(uint8_t HostID);
413 
414 static INLINE HCD_STATUS EHciHostReset(uint8_t HostID);
416 static void DisableAsyncSchedule(uint8_t HostID);
417 
418 static void EnableAsyncSchedule(uint8_t HostID);
419 
420 #if !defined(__ICCARM__)
421 static void DisablePeriodSchedule(uint8_t HostID) __attribute__ ((unused)); // TODO temporarily suppress unused warnnings for DisablePeriodSchedule & EnablePeriodSchedule
422 
423 static void EnablePeriodSchedule(uint8_t HostID) __attribute__ ((unused)); // TODO temporarily suppress unused warnnings for DisablePeriodSchedule & EnablePeriodSchedule
424 
425 #else
426 static void DisablePeriodSchedule(uint8_t HostID); // TODO temporarily suppress unused warnnings for DisablePeriodSchedule & EnablePeriodSchedule
427 
428 static void EnablePeriodSchedule(uint8_t HostID); // TODO temporarily suppress unused warnnings for DisablePeriodSchedule & EnablePeriodSchedule
429 
430 #endif
431 static INLINE void DisableSchedule(uint8_t HostID, uint8_t isPeriod);
432 
433 static INLINE void EnableSchedule(uint8_t HostID, uint8_t isPeriod);
434 
435 /********************************* HELPER *********************************/
436 static INLINE PHCD_QHD HcdAsyncHead(uint8_t HostID);
437 
438 static INLINE PHCD_QHD HcdIntHead(uint8_t HostID);
439 
440 static INLINE PHCD_QHD HcdQHD(uint8_t HostID, uint8_t idx);
441 
442 static INLINE PHCD_QTD HcdQTD(uint8_t HostID, uint8_t idx);
443 
444 static INLINE PHCD_HS_ITD HcdHsITD(uint8_t HostID, uint8_t idx);
445 
446 static INLINE PHCD_SITD HcdSITD(uint8_t HostID, uint8_t idx);
447 
448 static INLINE bool isValidLink(uint32_t link);
449 
450 static INLINE bool IsInterruptQhd (uint8_t HostID, uint8_t QhdIdx);
451 
452 /********************************* Queue Head & Queue TD *********************************/
453 static void FreeQhd(uint8_t HostID, uint8_t QhdIdx);
454 
455 static HCD_STATUS AllocQhd(uint8_t HostID,
456  uint8_t DeviceAddr,
457  HCD_USB_SPEED DeviceSpeed,
458  uint8_t EndpointNumber,
459  HCD_TRANSFER_TYPE TransferType,
460  HCD_TRANSFER_DIR TransferDir,
461  uint16_t MaxPacketSize,
462  uint8_t Interval,
463  uint8_t Mult,
464  uint8_t HSHubDevAddr,
465  uint8_t HSHubPortNum,
466  uint32_t *pQhdIdx);
467 
468 static HCD_STATUS InsertLinkPointer(NextLinkPointer *pList, NextLinkPointer *pNew, uint8_t type);
469 
470 static HCD_STATUS RemoveQueueHead(uint8_t HostID, uint8_t QhdIdx);
471 
472 static void FreeQtd(PHCD_QTD pQtd);
473 
474 static HCD_STATUS AllocQTD (uint8_t HostID,
475  uint32_t *pTdIdx,
476  uint8_t *const BufferPointer,
477  uint32_t xferLen,
478  HCD_TRANSFER_DIR PIDCode,
479  uint8_t DataToggle,
480  uint8_t IOC);
481 
482 /*static HCD_STATUS QueueQTDs (uint32_t* pTdIdx, uint8_t* dataBuff, uint32_t xferLen, HCD_TRANSFER_DIR PIDCode, uint8_t DataToggle);*/
483 /********************************* ISO Head & ISO TD & Split ISO *********************************/
484 static void FreeHsItd(PHCD_HS_ITD pItd);
485 
486 static HCD_STATUS AllocHsItd(uint8_t HostID,
487  uint32_t *pTdIdx,
488  uint8_t IhdIdx,
489  uint8_t *dataBuff,
490  uint32_t TDLen,
491  uint8_t XactPerITD,
492  uint8_t IntOnComplete);
493 
494 static HCD_STATUS QueueITDs(uint8_t HostID, uint8_t IhdIdx, uint8_t *dataBuff, uint32_t xferLen);
495 
496 static void FreeSItd(PHCD_SITD pSItd);
497 
498 static HCD_STATUS AllocSItd(uint8_t HostID,
499  uint32_t *TdIdx,
500  uint8_t HeadIdx,
501  uint8_t *dataBuff,
502  uint32_t TDLen,
503  uint8_t IntOnComplete);
504 
505 static HCD_STATUS QueueSITDs(uint8_t HostID, uint8_t HeadIdx, uint8_t *dataBuff, uint32_t xferLen);
506 
507 /********************************* Transfer Routines *********************************/
508 static HCD_STATUS WaitForTransferComplete(uint8_t HostID, uint8_t EpIdx);
509 
510 static HCD_STATUS PipehandleParse(uint32_t Pipehandle, uint8_t *pHostID, HCD_TRANSFER_TYPE *XferType, uint8_t *pIdx);
511 
512 static void PipehandleCreate(uint32_t *pPipeHandle, uint8_t HostID, HCD_TRANSFER_TYPE XferType, uint8_t idx);
513 
514 /********************************* Interrupt Service Routines *********************************/
515 static void AsyncScheduleIsr(uint8_t HostID);
516 
517 static void PeriodScheduleIsr(uint8_t HostID);
518 
519 static HCD_STATUS PortStatusChangeIsr(uint8_t HostID, uint32_t deviceConnect);
520 
521 static void AsyncAdvanceIsr(uint8_t HostID);
522 
523 static void UsbErrorIsr(uint8_t HostID);
524 
525 #endif
526