tinyusb  0.4
Click here to lend your support to tinyusb donation and make a donation at pledgie.com
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Groups Pages
ehci.h
Go to the documentation of this file.
1 /**************************************************************************/
37 /**************************************************************************/
38 
46 #ifndef _TUSB_EHCI_H_
47 #define _TUSB_EHCI_H_
48 
49 #include "common/common.h"
50 
51 /* Abbreviation
52  * HC: Host Controller
53  * HCD: Host Controller Driver
54  * QHD: Queue Head for non-ISO transfer
55  * QTD: Queue Transfer Descriptor for non-ISO transfer
56  * ITD: Iso Transfer Descriptor for highspeed
57  * SITD: Split ISO Transfer Descriptor for full-speed
58  * SMASK: Start Split mask for Slipt Transaction
59  * CMASK: Complete Split mask for Slipt Transaction
60  * RO: Read Only
61  * R/WC: Read, Write to Clear
62 */
63 
64 #ifdef __cplusplus
65  extern "C" {
66 #endif
67 
68 //--------------------------------------------------------------------+
69 // EHCI CONFIGURATION & CONSTANTS
70 //--------------------------------------------------------------------+
71 #define HOST_HCD_XFER_INTERRUPT // TODO interrupt is used widely, should always be enalbed
72 #define EHCI_PERIODIC_LIST (defined HOST_HCD_XFER_INTERRUPT || defined HOST_HCD_XFER_ISOCHRONOUS)
73 
74 #define EHCI_CFG_FRAMELIST_SIZE_BITS 7
75 #define EHCI_FRAMELIST_SIZE (1024 >> EHCI_CFG_FRAMELIST_SIZE_BITS)
76 
77 // TODO merge OHCI with EHCI
78 enum {
79  EHCI_MAX_ITD = 4,
80  EHCI_MAX_SITD = 16
81 };
82 
83 //------------- Validation -------------//
84 STATIC_ASSERT(EHCI_CFG_FRAMELIST_SIZE_BITS <= 7, "incorrect value");
85 
86 //--------------------------------------------------------------------+
87 // EHCI Data Structure
88 //--------------------------------------------------------------------+
94 };
95 
97 enum tusb_pid_{
98  EHCI_PID_OUT = 0 ,
99  EHCI_PID_IN ,
100  EHCI_PID_SETUP
101 };
102 
104 typedef union {
105  uint32_t address;
106  struct {
107  uint32_t terminate : 1;
108  uint32_t type : 2;
109  };
110 }ehci_link_t;
111 
113 typedef struct {
114 
117 
119  union{
120  ehci_link_t alternate;
121  struct {
122  uint32_t : 5;
123  uint32_t used : 1;
124  uint32_t : 10;
125  uint32_t expected_bytes : 16;
126  };
127  };
128 
130  volatile uint32_t pingstate_err : 1 ;
131  volatile uint32_t non_hs_split_state : 1 ;
132  volatile uint32_t non_hs_period_missed_uframe : 1 ;
133  volatile uint32_t xact_err : 1 ;
134  volatile uint32_t babble_err : 1 ;
135  volatile uint32_t buffer_err : 1 ;
136  volatile uint32_t halted : 1 ;
137  volatile uint32_t active : 1 ;
138 
139  uint32_t pid : 2 ;
140  volatile uint32_t cerr : 2 ;
141  volatile uint32_t current_page : 3 ;
142  uint32_t int_on_complete : 1 ;
143 
144  volatile uint32_t total_bytes : 15 ;
145  volatile uint32_t data_toggle : 1 ;
146  uint32_t : 0 ; // padding to the end of current storage unit
147  // End of Word 2
148 
150  uint32_t buffer[5];
151 } ehci_qtd_t; // XXX qtd is used to declare overlay in ehci_qhd_t -> cannot be declared with ATTR_ALIGNED(32)
152 
153 STATIC_ASSERT( sizeof(ehci_qtd_t) == 32, "size is not correct" );
154 
156 typedef struct {
159 
161  uint32_t device_address : 7 ;
162  uint32_t non_hs_period_inactive_next_xact : 1 ;
163  uint32_t endpoint_number : 4 ;
164  uint32_t endpoint_speed : 2 ;
165  uint32_t data_toggle_control : 1 ;
166  uint32_t head_list_flag : 1 ;
167  uint32_t max_package_size : 11 ;
168  uint32_t non_hs_control_endpoint : 1 ;
169  uint32_t nak_count_reload : 4 ;
170  uint32_t : 0 ; // padding to the end of current storage unit
171  // End of Word 1
172 
174  uint32_t interrupt_smask : 8 ;
175  uint32_t non_hs_interrupt_cmask : 8 ;
176  uint32_t hub_address : 7 ;
177  uint32_t hub_port : 7 ;
178  uint32_t mult : 2 ;
179  uint32_t : 0 ; // padding to the end of current storage unit
180  // End of Word 2
181 
183  volatile uint32_t qtd_addr;
184 
187 
188  //--------------------------------------------------------------------+
191  //--------------------------------------------------------------------+
192  uint8_t used;
193  uint8_t is_removing;
194  uint8_t pid_non_control;
195  uint8_t class_code;
196 
197  uint16_t total_xferred_bytes; // number of bytes xferred until a qtd with ioc bit set
198  uint8_t interval_ms; // polling interval in frames (or milisecond)
199  uint8_t reserved;
200 
201  ehci_qtd_t * volatile p_qtd_list_head; // head of the scheduled TD list
202  ehci_qtd_t * volatile p_qtd_list_tail; // tail of the scheduled TD list
203 } ehci_qhd_t;
204 
205 STATIC_ASSERT( sizeof(ehci_qhd_t) == 64, "size is not correct" );
206 
208 typedef struct ATTR_ALIGNED(32) {
211 
213  struct {
214  // iTD Control
215  volatile uint32_t offset : 12 ;
216  volatile uint32_t page_select : 3 ;
217  uint32_t int_on_complete : 1 ;
218  volatile uint32_t length : 12 ;
219  // iTD Status
221  volatile uint32_t error : 1 ;
222  volatile uint32_t babble_err : 1 ;
223  volatile uint32_t buffer_err : 1 ;
224  volatile uint32_t active : 1 ;
225  } xact[8];
226 
228  uint32_t BufferPointer[7];
229 
230 // // FIXME: Store meta data into buffer pointer reserved for saving memory
231 // /*---------- HCD Area ----------*/
232 // uint32_t used;
233 // uint32_t IhdIdx;
234 // uint32_t reserved[6];
235 } ehci_itd_t;
236 
237 STATIC_ASSERT( sizeof(ehci_itd_t) == 64, "size is not correct" );
238 
240 typedef struct ATTR_ALIGNED(32) {
243 
245  uint32_t device_address : 7;
246  uint32_t : 1;
247  uint32_t endpoint_number : 4;
248  uint32_t : 4;
249  uint32_t hub_address : 7;
250  uint32_t : 1;
251  uint32_t port_number : 7;
252  uint32_t direction : 1;
253  uint32_t : 0; // padding to the end of current storage unit
254  // End of Word 1
255 
257  uint8_t interrupt_smask ;
259  uint16_t reserved ;
260  // End of Word 2
261 
263  // Status [7:0] TODO indentical to qTD Token'status --> refractor later
264  volatile uint32_t : 1 ; // reserved
265  volatile uint32_t split_state : 1 ;
266  volatile uint32_t missed_uframe : 1 ;
267  volatile uint32_t xact_err : 1 ;
268  volatile uint32_t babble_err : 1 ;
269  volatile uint32_t buffer_err : 1 ;
270  volatile uint32_t error : 1 ;
271  volatile uint32_t active : 1 ;
272  // Micro-frame Schedule Control
273  volatile uint32_t cmask_progress : 8 ;
274  volatile uint32_t total_bytes : 10 ;
275  volatile uint32_t : 4 ;
276  volatile uint32_t page_select : 1 ;
277  uint32_t int_on_complete : 1 ;
278  uint32_t : 0 ; // padding to the end of current storage unit
279  // End of Word 3
280 
282  uint32_t buffer[2]; // buffer[1] TP: Transaction Position - T-Count: Transaction Count
283 
284 // union{
285 // uint32_t BufferPointer1;
286 // struct {
287 // volatile uint32_t TCount : 3;
288 // volatile uint32_t TPosition : 2;
289 // };
290 // };
291 
292  /*---------- Word 6 ----------*/
293  ehci_link_t back;
294 
296  uint8_t used;
297  uint8_t ihd_idx;
298  uint8_t reserved2[2];
299 } ehci_sitd_t;
300 
301 STATIC_ASSERT( sizeof(ehci_sitd_t) == 32, "size is not correct" );
302 
303 //--------------------------------------------------------------------+
304 // EHCI Operational Register
305 //--------------------------------------------------------------------+
306 enum ehci_interrupt_mask_{
307  EHCI_INT_MASK_USB = BIT_(0),
308  EHCI_INT_MASK_ERROR = BIT_(1),
309  EHCI_INT_MASK_PORT_CHANGE = BIT_(2),
310 
311  EHCI_INT_MASK_FRAMELIST_ROLLOVER = BIT_(3),
312  EHCI_INT_MASK_PCI_HOST_SYSTEM_ERROR = BIT_(4),
313  EHCI_INT_MASK_ASYNC_ADVANCE = BIT_(5),
314  EHCI_INT_MASK_NXP_SOF = BIT_(7),
315 
316  EHCI_INT_MASK_NXP_ASYNC = BIT_(18),
317  EHCI_INT_MASK_NXP_PERIODIC = BIT_(19),
318 
319  EHCI_INT_MASK_ALL =
320  EHCI_INT_MASK_USB | EHCI_INT_MASK_ERROR | EHCI_INT_MASK_PORT_CHANGE |
321  EHCI_INT_MASK_FRAMELIST_ROLLOVER | EHCI_INT_MASK_PCI_HOST_SYSTEM_ERROR |
322  EHCI_INT_MASK_ASYNC_ADVANCE | EHCI_INT_MASK_NXP_SOF |
323  EHCI_INT_MASK_NXP_ASYNC | EHCI_INT_MASK_NXP_PERIODIC
324 };
325 
326 enum ehci_usbcmd_pos_ {
327  EHCI_USBCMD_POS_RUN_STOP = 0,
328  EHCI_USBCMD_POS_FRAMELIST_SZIE = 2,
329  EHCI_USBCMD_POS_PERIOD_ENABLE = 4,
330  EHCI_USBCMD_POS_ASYNC_ENABLE = 5,
331  EHCI_USBCMD_POS_NXP_FRAMELIST_SIZE_MSB = 15,
332  EHCI_USBCMD_POS_INTERRUPT_THRESHOLD = 16
333 };
334 
335 enum ehci_portsc_change_mask_{
336  EHCI_PORTSC_MASK_CONNECT_STATUS_CHANGE = BIT_(1),
337  EHCI_PORTSC_MASK_PORT_ENABLE_CHAGNE = BIT_(3),
338  EHCI_PORTSC_MASK_OVER_CURRENT_CHANGE = BIT_(5),
339 
340  EHCI_PORTSC_MASK_ALL =
341  EHCI_PORTSC_MASK_CONNECT_STATUS_CHANGE |
342  EHCI_PORTSC_MASK_PORT_ENABLE_CHAGNE |
343  EHCI_PORTSC_MASK_OVER_CURRENT_CHANGE
344 };
345 
346 typedef volatile struct {
347  union {
348  uint32_t usb_cmd ;
349  struct {
350  uint32_t run_stop : 1 ;
351  uint32_t reset : 1 ;
352  uint32_t framelist_size : 2 ;
353  uint32_t periodic_enable : 1 ;
354  uint32_t async_enable : 1 ;
355  uint32_t advacne_async : 1 ;
356  uint32_t light_reset : 1 ;
357  uint32_t async_park : 2 ;
358  uint32_t : 1 ;
359  uint32_t async_park_enable : 1 ;
360  uint32_t : 3 ;
361  uint32_t nxp_framelist_size_msb : 1 ;
362  uint32_t int_threshold : 8 ;
363  uint32_t : 0 ; // padding to the boundary of storage unit
364  }usb_cmd_bit;
365  };
366 
367  union {
368  uint32_t usb_sts ;
369  struct {
370  uint32_t usb : 1 ;
371  uint32_t usb_error : 1 ;
372  uint32_t port_change_detect : 1 ;
373  uint32_t framelist_rollover : 1 ;
374  uint32_t pci_host_system_error : 1 ;
375  uint32_t async_advance : 1 ;
376  uint32_t : 1 ;
377  uint32_t nxp_int_sof : 1 ;
378  uint32_t : 4 ;
379  uint32_t hc_halted : 1 ;
380  uint32_t reclamation : 1 ;
381  uint32_t period_schedule_status : 1 ;
382  uint32_t async_schedule_status : 1 ;
383  uint32_t : 2 ;
384  uint32_t nxp_int_async : 1 ;
385  uint32_t nxp_int_period : 1 ;
386  uint32_t : 12 ;
387  uint32_t : 0 ; // padding to the boundary of storage unit
388  }usb_sts_bit;
389  };
390 
391  union{
392  uint32_t usb_int_enable ;
393  struct {
394  uint32_t usb : 1 ;
395  uint32_t usb_error : 1 ;
396  uint32_t port_change_detect : 1 ;
397  uint32_t framelist_rollover : 1 ;
398  uint32_t pci_host_system_error : 1 ;
399  uint32_t async_advance : 1 ;
400  uint32_t : 1 ;
401  uint32_t nxp_int_sof : 1 ;
402  uint32_t : 10 ;
403  uint32_t nxp_int_async : 1 ;
404  uint32_t nxp_int_period : 1 ;
405  uint32_t : 12 ;
406  uint32_t : 0 ; // padding to the boundary of storage unit
407  }usb_int_enable_bit;
408  };
409 
410  uint32_t frame_index ;
411  uint32_t ctrl_ds_seg ;
412  uint32_t periodic_list_base ;
413  uint32_t async_list_base ;
414  uint32_t tt_control ;
415  uint32_t reserved[8] ;
416  uint32_t config_flag ;
417 
418  union {
419  uint32_t portsc ;
420  struct {
421  uint32_t current_connect_status : 1;
422  uint32_t connect_status_change : 1;
423  uint32_t port_enable : 1;
424  uint32_t port_enable_change : 1;
425  uint32_t over_current_active : 1;
426  uint32_t over_current_change : 1;
427  uint32_t force_port_resume : 1;
428  uint32_t suspend : 1;
429  uint32_t port_reset : 1;
430  uint32_t nxp_highspeed_status : 1;
431  uint32_t line_status : 2;
432  uint32_t port_power : 1;
433  uint32_t port_owner : 1;
434  uint32_t port_indicator_control : 2;
435  uint32_t port_test_control : 4;
436  uint32_t wake_on_connect_enable : 1;
437  uint32_t wake_on_disconnect_enable : 1;
438  uint32_t wake_on_over_current_enable : 1;
439  uint32_t nxp_phy_clock_disable : 1;
440  uint32_t nxp_port_force_fullspeed : 1;
441  uint32_t : 1;
442  uint32_t nxp_port_speed : 2;
443  uint32_t : 0; // padding to the boundary of storage unit
444  }portsc_bit;
445  };
447 
448 //--------------------------------------------------------------------+
449 // EHCI Data Organization
450 //--------------------------------------------------------------------+
451 typedef struct {
452  //------------- Static Async/Period List Head, Each for one controller -------------//
453  ehci_qhd_t async_head[CONTROLLER_HOST_NUMBER];
454 
455 #if EHCI_PERIODIC_LIST
456  // for NXP ECHI, only implement 1 ms & 2 ms & 4 ms, 8 ms (framelist)
457  // [0] : 1ms, [1] : 2ms, [2] : 4ms, [3] : 8 ms
458  ehci_qhd_t period_head_arr[CONTROLLER_HOST_NUMBER][4];
459 #endif
460 
461  //------------- Data for Address 0 (use async head as its queue head) -------------//
462  ehci_qtd_t addr0_qtd[3];
463 
464  struct {
465  struct {
467  ehci_qtd_t qtd[3];
468  }control;
469 
470  ehci_qhd_t qhd[HCD_MAX_ENDPOINT] ;
471  ehci_qtd_t qtd[HCD_MAX_XFER] ATTR_ALIGNED(32) ;
472 // ehci_itd_t itd[EHCI_MAX_ITD] ; ///< Iso Transfer Pool
473 // ehci_sitd_t sitd[EHCI_MAX_SITD] ; ///< Split (FS) Isochronous Transfer Pool
474  }device[TUSB_CFG_HOST_DEVICE_MAX];
475 }ehci_data_t;
476 
477 #ifdef __cplusplus
478  }
479 #endif
480 
481 #endif /* _TUSB_EHCI_H_ */
482 
volatile ehci_qtd_t qtd_overlay
Word 4-11: Transfer Overlay.
Definition: ehci.h:186
#define BIT_(n)
n-th Bit
Definition: binary.h:54
uint32_t ctrl_ds_seg
(not used by NXP) This 32-bit register corresponds to the most significant address bits [63:32] for a...
Definition: ehci.h:411
ehci_qhd_t qhd
Queue Head Pool.
Definition: ehci.h:466
uint16_t reserved
reserved
Definition: ehci.h:259
#define TUSB_CFG_HOST_DEVICE_MAX
Maximum number of device host stack can manage If hub class is not enabled, set this equal to numbe...
uint32_t periodic_list_base
This 32-bit register contains the beginning address of the Periodic Frame List in the system memory...
Definition: ehci.h:412
tusb_pid_
EHCI PID.
Definition: ehci.h:97
volatile uint32_t qtd_addr
Word 3: Current qTD Pointer.
Definition: ehci.h:183
uint32_t config_flag
(not used by NXP) configured flag register
Definition: ehci.h:416
uint8_t used
thus there are 16 bytes padding free that we can make use of.
Definition: ehci.h:192
uint32_t frame_index
This register is used by the host controller to index into the periodic frame list. The register updates every 125 microseconds (once each micro-frame). Bits [N:3] are used to select a particular entry in the Periodic Frame List during periodic schedule execution. The number of bits used for the index depends on the size of the frame list as set by system software in the Frame List Sizefield in the USBCMD register.
Definition: ehci.h:410
ehci_queue_element_type_
Definition: ehci.h:89
ehci_link_t next
Word 0: Next Link Pointer.
Definition: ehci.h:242
Queue Head (section 3.6)
Definition: ehci.h:156
uint32_t portsc
port status and control
Definition: ehci.h:419
ehci_link_t next
Word 0: Next QTD Pointer.
Definition: ehci.h:116
uint32_t async_list_base
This 32-bit register contains the address of the next asynchronous queue head to be executed...
Definition: ehci.h:413
uint32_t usb_int_enable
This register enables and disables reporting of the corresponding interrupt to the software...
Definition: ehci.h:392
ehci_link_t next
Word 0: Next Link Pointer.
Definition: ehci.h:210
uint8_t used
SITD is 32-byte aligned but occupies only 28 –> 4 bytes for storing extra data.
Definition: ehci.h:296
uint32_t usb_sts
This register indicates pending interrupts and various states of the Host Controller. The status resulting from a transaction on the serial bus is not indicated in this register. Software sets a bit to 0 in this register by writing a 1 to it. See Section 4.15 for additional information concerning USB interrupt conditions.
Definition: ehci.h:368
#define ATTR_ALIGNED(Bytes)
This attribute specifies a minimum alignment for the variable or structure field, measured in bytes...
Definition: compiler_gcc.h:72
ehci_link_t next
Word 0: Queue Head Horizontal Link Pointer.
Definition: ehci.h:158
uint32_t usb_cmd
The Command Register indicates the command to be executed by the serial bus host controller. Writing to the register causes a command to be executed.
Definition: ehci.h:348
Split (Full-Speed) Isochronous Transfer Descriptor.
Definition: ehci.h:240
Queue Element Transfer Descriptor (section 3.5)
Definition: ehci.h:113
uint8_t interrupt_smask
Word 2: Micro-frame Schedule Control.
Definition: ehci.h:257
uint8_t non_hs_interrupt_cmask
This field (along with the Activeand SplitX-statefields in the Statusbyte) are used to determine duri...
Definition: ehci.h:258
Highspeed Isochronous Transfer Descriptor (section 3.3)
Definition: ehci.h:208
uint32_t tt_control
nxp embedded transaction translator (reserved by EHCI specs)
Definition: ehci.h:414