LPCOpen Platform  v1.03
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_QTD 8 /* USBD_USB_HC_EHCI */
53 #define HCD_MAX_HS_ITD 4 /* USBD_USB_HC_EHCI */
54 #define HCD_MAX_SITD 16 /* USBD_USB_HC_EHCI */
55 
56 #define FRAMELIST_SIZE_BITS 5 /* (0:1024) - (1:512) - (2:256) - (3:128) - (4:64) - (5:32) - (6:16) - (7:8) */
57 #define FRAME_LIST_SIZE (1024 >> FRAMELIST_SIZE_BITS)
58 
59 /**********************/
60 /* USBCMD Register */
61 /**********************/
62 #define INT_THRESHOLD_CTRL 0x00080000UL/* Max Int Interval = 8 uframes */
63 #define ASYNC_SCHEDULE_PARK_MODE_ENABLE NO
64 #define ASYNC_SCHEDULE_PARK_MODE_COUNT 0
65 
66 /****************************/
67 /* USBSTS Register */
68 /****************************/
69 
70 /**************************************************/
71 /* USBINTR Register */
72 /**************************************************/
73 #define INT_SOF_RECEIVED_ENABLE NO
74 // #define INT_ASYNC_ADVANCE_ENABLE Must be YES
75 // #define INT_SYSTEM_ERR_ENABLE Must be YES
76 #define INT_FRAME_ROLL_OVER_ENABLE NO
77 // #define INT_PORT_CHANGE_ENABLE Must be YES
78 // #define INT_USB_ERR_ENABLE Must be YES
79 // #define INT_USB_ENABLE Must be YES (NO for NXP chips in favor of UAI, UPI)
80 // #define INT_USB_ASYNC_INT_ENABLE Must be YES
81 // #define INT_USB_PERIOD_INT_ENABLE Must be YES
82 
83 /********************************************/
84 /* PORTSC Register */
85 /********************************************/
86 #define PORT_WAKE_OVER_CURRENT NO
87 #define PORT_WAKE_ON_DISCONNECT NO
88 #define PORT_WAKE_ON_CONNECT NO
89 #define PORT_INDICATOR NO
90 
91 /*==========================================================================*/
92 /* EHCI LOCAL DECLARATIONS */
93 /*==========================================================================*/
94 
95 /*==========================================================================*/
96 /* EHCI REGISTERS */
97 /*==========================================================================*/
98 /* Bit field definition for USBMODE_H */
99 #define USBMODE_DeviceController (2)
100 #define USBMODE_HostController (3)
101 #define USBMODE_VBusPowerSelect_High (1 << 5)
102 
103 /* Bit field definition for register UsbCmd */
104 #define EHC_USBCMD_RunStop 0x00000001UL /* Run or Stop */
105 #define EHC_USBCMD_HostReset 0x00000002UL /* Host Controller Reset */
106 #define EHC_USBCMD_FrameListSize 0x0000000CUL /* Frame List Size */
107 #define EHC_USBCMD_PeriodScheduleEnable 0x00000010UL /* Periodic Schedule Enable */
108 #define EHC_USBCMD_AsynScheduleEnable 0x00000020UL /* Asynchronous Schedule Enable */
109 #define EHC_USBCMD_IntAsyncAdvanceDoorbell 0x00000040UL /* Interrupt on Async Advance Doorbell */
110 #define EHC_USBCMD_LightReset 0x00000080UL /* Light Host Controller Reset */
111 #define EHC_USBCMD_AsyncScheduleParkCount 0x00000300UL /* Asynchronous Schedule Park Mode Count */
112 #define EHC_USBCMD_AsyncScheduleParkEnable 0x00000800UL /* Asynchronous Schedule Park Mode Enable */
113 #define EHC_USBCMD_FrameListSizeBit2 0x00008000UL /* Frame List Size bit 2 - EHCI derivation */
114 #define EHC_USBCMD_InterruptThresholdControl 0x00FF0000UL /* Interrupt Threshold control */
115 
116 /* Bit field definition for register UsbStatus */
117 #define EHC_USBSTS_UsbInt 0x00000001UL /* USB Interrupt */
118 #define EHC_USBSTS_UsbErrorInt 0x00000002UL /* USB Error Interrupt */
119 #define EHC_USBSTS_PortChangeDetect 0x00000004UL /* Port Change Detect */
120 #define EHC_USBSTS_FrameListRollover 0x00000008UL /* Frame List Rollover */
121 #define EHC_USBSTS_HostSystemError 0x00000010UL /* Host System Error */
122 #define EHC_USBSTS_IntAsyncAdvance 0x00000020UL /* Interrupt on Async Advance */
123 #define EHC_USBSTS_SofRecieveInt 0x00000080UL /* SOF - EHCI derivation */
124 #define EHC_USBSTS_HCHalted 0x00001000UL /* HCHalted */
125 #define EHC_USBSTS_Reclamation 0x00002000UL /* Reclamation */
126 #define EHC_USBSTS_PeriodScheduleStatus 0x00004000UL /* Periodic Schedule Status */
127 #define EHC_USBSTS_AsyncScheduleStatus 0x00008000UL /* Asynchronous Schedule Status */
128 #define EHC_USBSTS_UsbAsyncInt 0x00040000UL /* USB Asynchronous Interrupt - EHCI derivation */
129 #define EHC_USBSTS_UsbPeriodInt 0x00080000UL /* USB Period Interrupt - EHCI derivation */
130 
131 /* Bit field definition for register UsbIntr */
132 #define EHC_USBINTR_UsbIntEnable 0x00000001UL /* USB Interrupt Enable */
133 #define EHC_USBINTR_UsbErroIntEnable 0x00000002UL /* USB Error Interrupt Enable */
134 #define EHC_USBINTR_PortChangeIntEnable 0x00000004UL /* Port Change Interrupt Enable */
135 #define EHC_USBINTR_FrameListRolloverEnable 0x00000008UL /* Frame List Rollover Enable */
136 #define EHC_USBINTR_HostSystemErrorEnable 0x00000010UL /* Host System Error Enable */
137 #define EHC_USBINTR_IntAsyncAdvanceEnable 0x00000020UL /* Interrupt on Async Advance Enable */
138 #define EHC_USBINTR_SofRecieveEnable 0x00000080UL /* SOF - EHCI derivation */
139 #define EHC_USBINTR_UsbAsyncEnable 0x00040000UL /* USB Asynchronous Interrupt - EHCI derivation */
140 #define EHC_USBINTR_UsbPeriodEnable 0x00080000UL /* USB Period Interrupt - EHCI derivation */
141 #define EHC_USBINTR_ALL 0x000C00BFUL /* All Interrupt */
142 
143 /* Bit field definition for register FrIndex */
144 #define EHC_FRINDEX_MASK 0x000003FFUL /* Frame Index */
145 #define EHC_UFRAME_MASK 0x00000007UL /* u-Frame Index */
146 #define EHC_MFRAME_MASK 0x00001FF8UL /* m-Frame Index */
147 
148 /* Bit field definition for register PortSC */
149 #define EHC_PORTSC_CurrentConnectStatus 0x00000001UL /* Current Connect Status */
150 #define EHC_PORTSC_ConnectStatusChange 0x00000002UL /* Connect Status Change */
151 #define EHC_PORTSC_PortEnable 0x00000004UL /* Port Enabled Status */
152 #define EHC_PORTSC_PortEnableChange 0x00000008UL /* Port Enabled/Disabled Change */
153 #define EHC_PORTSC_OvercurrentActive 0x00000010UL /* Over-current Status */
154 #define EHC_PORTSC_OvercurrentChange 0x00000020UL /* Over-current Change */
155 #define EHC_PORTSC_ForcePortResume 0x00000040UL /* Force Port Resume */
156 #define EHC_PORTSC_PortSuspend 0x00000080UL /* Port Suspend */
157 #define EHC_PORTSC_PortReset 0x00000100UL /* Port Reset */
158 #define EHC_PORTSC_LineStatus 0x00000C00UL /* Line Status */
159 #define EHC_PORTSC_PortPowerControl 0x00001000UL /* Port Power Status */
160 #define EHC_PORTSC_PortOwner 0x00002000UL /* Port Owner Status */
161 #define EHC_PORTSC_PortIndicatorControl 0x0000C000UL /* Port Indicator Control */
162 #define EHC_PORTSC_PortTestControl 0x000F0000UL /* Port Test Control */
163 #define EHC_PORTSC_WakeonConnectEnable 0x00100000UL /* Wake on Connect Enable */
164 #define EHC_PORTSC_WakeonDisconnectEnable 0x00200000UL /* Wake on Disconnect Enable */
165 #define EHC_PORTSC_WakeonOvercurrentEnable 0x00400000UL /* Wake on Over-Current Enable */
166 #define EHC_PORTSC_PhyClockDisable 0x00800000UL /* PHY Clock Disable - EHCI derivation */
167 #define EHC_PORTSC_PortForceFullspeedConnect 0x01000000UL /* Force Device on Fullspeed mode (disable chirp sequences) - EHCI derivation */
168 #define EHC_PORTSC_PortSpeed 0x0C000000UL /* Device Speed - EHCI derivation */
169 
170 /* Definitions for Frame List Element Pointer */
171 #define QTD_MAX_XFER_LENGTH 0x5000
172 #define FRAMELIST_ALIGNMENT 4096 /* Frame List Alignment */
173 //#define LINK_TERMINATE 0x01
174 #define SPLIT_MAX_LEN_UFRAME 188
175 
176 /*=======================================================================*/
177 /* E H C I S T R U C T U R E S */
178 /*=======================================================================*/
179 
180 /* Memory for EHCI Structures, docs for more information */
181 
182 typedef union un_EHCD_Link {
184  struct {
185  uint32_t Terminate : 1;
187  };
188 
190 
191 typedef struct st_EHCD_QTD {
192  /*---------- Word 1 ----------*/
194 
195  /*---------- Word 2 ----------*/
196  /*-- Take advantage of this to store HCD information --*/
197  union {
199  struct {
200  uint32_t Terminate : 1;
201  uint32_t : 4;
202 
203  // === TODO: used reserved space, need to move to other place ===
204  /*-- HCD Area --*/
206  uint32_t : 0;
207  };
208 
209  };
210 
211  /*---------- Word 3 ----------*/
212  /* Status [7:0] */
213  __IO uint32_t PingState_Err : 1;
217  __IO uint32_t Babble : 1;
219  __IO uint32_t Halted : 1;
220  __IO uint32_t Active : 1;
221 
222  uint32_t PIDCode : 2;
223  __IO uint32_t ErrorCounter : 2;
224  __IO uint32_t CurrentPage : 3;
228  uint32_t : 0;/* Force next member on next storage unit */
229  /*---------- End Word 3 ----------*/
230 
231  /*---------- Buffer Pointer Word 4-7 ----------*/
233 } HCD_QTD, *PHCD_QTD; // TODO: because QTD is used to declare overlay in HCD_QHD, we cannot put aligned 32 here ATTR_ALIGNED(32)
234 
235 typedef struct st_EHCD_QHD {
236  /*---------- Word 1 ----------*/
238 
239  /*---------- Word 2 ----------*/
249  uint32_t : 0;/* Force next member on next storage unit */
250  /*---------- End Word 2 ----------*/
251 
252  /*---------- Word 3 ----------*/
258  uint32_t : 0;/* Force next member on next storage unit */
259  /*---------- End Word 3 ----------*/
260 
261  /*---------- Word 4 ----------*/
263 
264  /*---------- Overlay Area ----------*/
266 
267  /*---------- HCD Area : 16 Bytes----------*/
271  uint32_t ListIndex : 20;/* not support full period list */
272  uint32_t : 0;/* Force next member on next storage unit */
273 
274  __IO uint32_t status; // TODO will remove __IO after remove all HcdQHD function
275  uint32_t FirstQtd; /* used as TD head to clean up TD chain when transfer done */
276  uint16_t *pActualTransferCount; /* total transferred bytes of a usb request */
277 } ATTR_ALIGNED (32) HCD_QHD, *PHCD_QHD;
278 
279 typedef struct st_EHCD_ITD {
280  /*---------- Word 1 ----------*/
283  /*---------- Word 2-9 ----------*/
284  struct {
285  __IO uint32_t Offset : 12;
288  __IO uint32_t Length : 12;
289  /*-- status [31:28] --*/
290  __IO uint32_t Error : 1;
291  __IO uint32_t Babble : 1;
293  __IO uint32_t Active : 1;
294  } Transaction[8];
296  /*---------- Word 10-16 ----------*/
299  // FIXME: refractor to save memory HCD Area
300  /*---------- HCD Area ----------*/
304 } ATTR_ALIGNED (32) HCD_HS_ITD, *PHCD_HS_ITD;
305 
306 typedef struct st_EHCD_SITD {
308 
309  /*---------- Word 2: static endpoint ----------*/
311  uint32_t : 1;
313  uint32_t : 4;
315  uint32_t : 1;
318  uint32_t : 0;/* Force next member on next storage unit */
319  /*---------- End Word 2 ----------*/
320 
321  /*---------- Word 3: Slipt Mask ----------*/
322  uint8_t uFrameSMask;
323  uint8_t uFrameCMask;
324  uint16_t reserved; /* Force next member on next storage unit */
325  /*---------- End Word 3 ----------*/
326 
327  /*---------- Word 4: ----------*/
328  /* Status [7:0] */
329  __IO uint32_t : 1;
333  __IO uint32_t Babble : 1;
335  __IO uint32_t ERR : 1;
336  __IO uint32_t Active : 1;
337 
340  __IO uint32_t : 4;
343  uint32_t : 0;
344  /*---------- End Word 4 ----------*/
345 
346  /*---------- Word 5-6 ----------*/
347  uint32_t BufferPointer[2]; /*-- in BufferPointer[1] TP: Transaction Position - T-Count: Transaction Count --*/
348 
349  // union{
350  // uint32_t BufferPointer1;
351  // struct {
352  // __IO uint32_t TCount : 3;
353  // __IO uint32_t TPosition : 2;
354  // };
355  // };
356 
357  /*---------- Word 7 ----------*/
359 
360  /*-- HCD ARERA 4 bytes --*/
361  uint8_t inUse;
362  uint8_t IhdIdx;
363  uint8_t reserved2[2];
364 } ATTR_ALIGNED (32) HCD_SITD, *PHCD_SITD;
365 
366 typedef struct st_EHCI_HOST_DATA {
367  HCD_HS_ITD iTDs[HCD_MAX_HS_ITD]; /* Iso Transfer Descriptor */
368  HCD_QHD AsyncHeadQhd; /* Serve as H-Queue Head in Async Schedule */
369  HCD_QHD IntHeadQhd; /* Serve as Static 1ms Interrupt Heads */
370  HCD_QHD qHDs[HCD_MAX_QHD]; /* Queue Head */
371  HCD_QTD qTDs[HCD_MAX_QTD]; /* Queue Transfer Descriptor (Queue Element) */
372  HCD_SITD siTDs[HCD_MAX_SITD]; /* Split Iso Transfer Descriptor */
374 
375 typedef enum {
376  ITD_TYPE = 0,
380 } TD_TYPE;
381 
382 typedef struct st_PipeHandle {
383  uint8_t Idx;
384  uint8_t Type;
385  uint8_t PortNumber;
386  uint8_t HostId;
389 typedef struct st_PipeStreamHandle {
390  uint32_t BufferAddress;
392  uint16_t PacketSize;
393  uint8_t DataToggle;
395 
396 /*=======================================================================*/
397 /* LOCAL S Y M B O L D E C L A R A T I O N S */
398 /*=======================================================================*/
399 extern EHCI_HOST_DATA_T ehci_data[MAX_USB_CORE];
400 // extern EHCI_HOST_DATA_T ehci_data;
401 extern NextLinkPointer PeriodFrameList0[FRAME_LIST_SIZE]; /* Period Frame List */
402 extern NextLinkPointer PeriodFrameList1[FRAME_LIST_SIZE]; /* Period Frame List */
403 #define EHCI_FRAME_LIST(HostID) ((HostID) ? PeriodFrameList1 : PeriodFrameList0 )
404 
405 /*=======================================================================*/
406 /* G L O B A L S Y M B O L D E C L A R A T I O N S */
407 /*=======================================================================*/
408 void USB_Host_Enumerate (uint8_t HostID);
409 
410 void USB_Host_DeEnumerate(uint8_t HostID);
411 
412 /*=======================================================================*/
413 /* L O C A L F U N C T I O N P R O T O T Y P E S */
414 /*=======================================================================*/
415 /********************************* HOST API *********************************/
416 static INLINE HCD_STATUS EHciHostInit(uint8_t HostID);
417 
418 static INLINE HCD_STATUS EHciHostRun(uint8_t HostID);
419 
420 static INLINE HCD_STATUS EHciHostStop(uint8_t HostID);
422 static INLINE HCD_STATUS EHciHostReset(uint8_t HostID);
423 
424 static void DisableAsyncSchedule(uint8_t HostID);
425 
426 static void EnableAsyncSchedule(uint8_t HostID);
427 
428 #if !defined(__ICCARM__)
429 static void DisablePeriodSchedule(uint8_t HostID) __attribute__ ((unused)); // TODO temporarily suppress unused warnnings for DisablePeriodSchedule & EnablePeriodSchedule
430 
431 static void EnablePeriodSchedule(uint8_t HostID) __attribute__ ((unused)); // TODO temporarily suppress unused warnnings for DisablePeriodSchedule & EnablePeriodSchedule
432 
433 #else
434 static void DisablePeriodSchedule(uint8_t HostID); // TODO temporarily suppress unused warnnings for DisablePeriodSchedule & EnablePeriodSchedule
435 
436 static void EnablePeriodSchedule(uint8_t HostID); // TODO temporarily suppress unused warnnings for DisablePeriodSchedule & EnablePeriodSchedule
437 
438 #endif
439 static INLINE void DisableSchedule(uint8_t HostID, uint8_t isPeriod);
440 
441 static INLINE void EnableSchedule(uint8_t HostID, uint8_t isPeriod);
442 
443 /********************************* HELPER *********************************/
444 static INLINE PHCD_QHD HcdAsyncHead(uint8_t HostID);
445 
446 static INLINE PHCD_QHD HcdIntHead(uint8_t HostID);
447 
448 static INLINE PHCD_QHD HcdQHD(uint8_t HostID, uint8_t idx);
449 
450 static INLINE PHCD_QTD HcdQTD(uint8_t HostID, uint8_t idx);
451 
452 static INLINE PHCD_HS_ITD HcdHsITD(uint8_t HostID, uint8_t idx);
453 
454 static INLINE PHCD_SITD HcdSITD(uint8_t HostID, uint8_t idx);
455 
456 static INLINE bool isValidLink(uint32_t link);
457 
458 static INLINE bool IsInterruptQhd (uint8_t HostID, uint8_t QhdIdx);
459 
460 /********************************* Queue Head & Queue TD *********************************/
461 static void FreeQhd(uint8_t HostID, uint8_t QhdIdx);
462 
463 static HCD_STATUS AllocQhd(uint8_t HostID,
464  uint8_t DeviceAddr,
465  HCD_USB_SPEED DeviceSpeed,
466  uint8_t EndpointNumber,
467  HCD_TRANSFER_TYPE TransferType,
468  HCD_TRANSFER_DIR TransferDir,
469  uint16_t MaxPacketSize,
470  uint8_t Interval,
471  uint8_t Mult,
472  uint8_t HSHubDevAddr,
473  uint8_t HSHubPortNum,
474  uint32_t *pQhdIdx);
475 
476 static HCD_STATUS InsertLinkPointer(NextLinkPointer *pList, NextLinkPointer *pNew, uint8_t type);
477 
478 static HCD_STATUS RemoveQueueHead(uint8_t HostID, uint8_t QhdIdx);
479 
480 static void FreeQtd(PHCD_QTD pQtd);
481 
482 static HCD_STATUS AllocQTD (uint8_t HostID,
483  uint32_t *pTdIdx,
484  uint8_t *const BufferPointer,
485  uint32_t xferLen,
486  HCD_TRANSFER_DIR PIDCode,
487  uint8_t DataToggle,
488  uint8_t IOC);
489 
490 static HCD_STATUS QueueQTDs (uint8_t HostID,
491  uint32_t* pTdIdx,
492  uint8_t* dataBuff,
493  uint32_t xferLen,
494  HCD_TRANSFER_DIR PIDCode,
495  uint8_t DataToggle);
496 
497 /********************************* ISO Head & ISO TD & Split ISO *********************************/
498 static void FreeHsItd(PHCD_HS_ITD pItd);
499 
500 static HCD_STATUS AllocHsItd(uint8_t HostID,
501  uint32_t *pTdIdx,
502  uint8_t IhdIdx,
503  uint8_t *dataBuff,
504  uint32_t TDLen,
505  uint8_t XactPerITD,
506  uint8_t IntOnComplete);
507 
508 static HCD_STATUS QueueITDs(uint8_t HostID, uint8_t IhdIdx, uint8_t *dataBuff, uint32_t xferLen);
509 
510 static void FreeSItd(PHCD_SITD pSItd);
511 
512 static HCD_STATUS AllocSItd(uint8_t HostID,
513  uint32_t *TdIdx,
514  uint8_t HeadIdx,
515  uint8_t *dataBuff,
516  uint32_t TDLen,
517  uint8_t IntOnComplete);
518 
519 static HCD_STATUS QueueSITDs(uint8_t HostID, uint8_t HeadIdx, uint8_t *dataBuff, uint32_t xferLen);
520 
521 /********************************* Transfer Routines *********************************/
522 static HCD_STATUS WaitForTransferComplete(uint8_t HostID, uint8_t EpIdx);
523 
524 static HCD_STATUS PipehandleParse(uint32_t Pipehandle, uint8_t *pHostID, HCD_TRANSFER_TYPE *XferType, uint8_t *pIdx);
525 
526 static void PipehandleCreate(uint32_t *pPipeHandle, uint8_t HostID, HCD_TRANSFER_TYPE XferType, uint8_t idx);
527 
528 /********************************* Interrupt Service Routines *********************************/
529 static void AsyncScheduleIsr(uint8_t HostID);
530 
531 static void PeriodScheduleIsr(uint8_t HostID);
532 
533 static HCD_STATUS PortStatusChangeIsr(uint8_t HostID, uint32_t deviceConnect);
534 
535 static void AsyncAdvanceIsr(uint8_t HostID);
536 
537 static void UsbErrorIsr(uint8_t HostID);
538 
539 #endif
540