@@ -79,14 +79,35 @@ typedef struct
79
79
ehci_qhd_t qhd_pool [QHD_MAX ];
80
80
ehci_qtd_t qtd_pool [QTD_MAX ] TU_ATTR_ALIGNED (32 );
81
81
82
- ehci_registers_t * regs ;
82
+ ehci_registers_t * regs ; // operational register
83
+ ehci_cap_registers_t * cap_regs ; // capability register
83
84
84
85
volatile uint32_t uframe_number ;
85
86
}ehci_data_t ;
86
87
87
88
// Periodic frame list must be 4K alignment
88
89
CFG_TUH_MEM_SECTION TU_ATTR_ALIGNED (4096 ) static ehci_data_t ehci_data ;
89
90
91
+ //--------------------------------------------------------------------+
92
+ // Debug
93
+ //--------------------------------------------------------------------+
94
+ #if CFG_TUSB_DEBUG >= EHCI_DBG
95
+ static inline void print_portsc (ehci_registers_t * regs )
96
+ {
97
+ TU_LOG_HEX (EHCI_DBG , regs -> portsc );
98
+ TU_LOG (EHCI_DBG , " Current Connect Status: %u\r\n" , regs -> portsc_bm .current_connect_status );
99
+ TU_LOG (EHCI_DBG , " Connect Status Change : %u\r\n" , regs -> portsc_bm .connect_status_change );
100
+ TU_LOG (EHCI_DBG , " Port Enabled : %u\r\n" , regs -> portsc_bm .port_enabled );
101
+ TU_LOG (EHCI_DBG , " Port Enabled Change : %u\r\n" , regs -> portsc_bm .port_enable_change );
102
+
103
+ TU_LOG (EHCI_DBG , " Port Reset : %u\r\n" , regs -> portsc_bm .port_reset );
104
+ TU_LOG (EHCI_DBG , " Port Power : %u\r\n" , regs -> portsc_bm .port_power );
105
+ }
106
+
107
+ #else
108
+ #define print_portsc (_reg )
109
+ #endif
110
+
90
111
//--------------------------------------------------------------------+
91
112
// PROTOTYPE
92
113
//--------------------------------------------------------------------+
@@ -152,11 +173,11 @@ void hcd_port_reset(uint8_t rhport)
152
173
153
174
ehci_registers_t * regs = ehci_data .regs ;
154
175
155
- // regs->portsc_bm.port_enabled = 0; // disable port before reset
156
- // regs->portsc_bm.port_reset = 1;
157
-
158
- uint32_t portsc = regs -> portsc ;
176
+ // mask out all change bits since they are Write 1 to clear
177
+ uint32_t portsc = regs -> portsc & ~EHCI_PORTSC_MASK_CHANGE_ALL ;
159
178
179
+ // EHCI Table 2-16 PortSC
180
+ // when software writes Port Reset bit to a one, it must also write a zero to the Port Enable bit.
160
181
portsc &= ~(EHCI_PORTSC_MASK_PORT_EANBLED );
161
182
portsc |= EHCI_PORTSC_MASK_PORT_RESET ;
162
183
@@ -167,9 +188,14 @@ void hcd_port_reset_end(uint8_t rhport)
167
188
{
168
189
(void ) rhport ;
169
190
170
- #if 0
191
+ #if 0 // TODO check if this is necessary
171
192
ehci_registers_t * regs = ehci_data .regs ;
172
- regs -> portsc_bm .port_reset = 0 ;
193
+
194
+ // mask out all change bits since they are Write 1 to clear
195
+ uint32_t portsc = regs -> portsc & ~EHCI_PORTSC_MASK_CHANGE_ALL ;
196
+ portsc &= ~(EHCI_PORTSC_MASK_PORT_RESET );
197
+
198
+ regs -> portsc = portsc ;
173
199
#endif
174
200
}
175
201
@@ -240,19 +266,26 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr)
240
266
241
267
bool ehci_init (uint8_t rhport , uint32_t capability_reg , uint32_t operatial_reg )
242
268
{
243
- (void ) capability_reg ; // not used yet
244
-
245
269
tu_memclr (& ehci_data , sizeof (ehci_data_t ));
246
270
247
- ehci_data .regs = (ehci_registers_t * ) operatial_reg ;
271
+ ehci_data .regs = (ehci_registers_t * ) operatial_reg ;
272
+ ehci_data .cap_regs = (ehci_cap_registers_t * ) capability_reg ;
248
273
249
274
ehci_registers_t * regs = ehci_data .regs ;
250
275
276
+ // EHCI 4.1 Host Controller Initialization
277
+
251
278
//------------- CTRLDSSEGMENT Register (skip) -------------//
279
+
252
280
//------------- USB INT Register -------------//
253
- regs -> inten = 0 ; // 1. disable all the interrupt
254
- regs -> status = EHCI_INT_MASK_ALL ; // 2. clear all status
255
281
282
+ // disable all the interrupt
283
+ regs -> inten = 0 ;
284
+
285
+ // clear all status except port change since device maybe connected before this driver is initialized
286
+ regs -> status = (EHCI_INT_MASK_ALL & ~EHCI_INT_MASK_PORT_CHANGE );
287
+
288
+ // Enable interrupts
256
289
regs -> inten = EHCI_INT_MASK_ERROR | EHCI_INT_MASK_PORT_CHANGE | EHCI_INT_MASK_ASYNC_ADVANCE |
257
290
EHCI_INT_MASK_NXP_PERIODIC | EHCI_INT_MASK_NXP_ASYNC | EHCI_INT_MASK_FRAMELIST_ROLLOVER ;
258
291
@@ -316,7 +349,16 @@ bool ehci_init(uint8_t rhport, uint32_t capability_reg, uint32_t operatial_reg)
316
349
FRAMELIST_SIZE_USBCMD_VALUE ;
317
350
318
351
//------------- ConfigFlag Register (skip) -------------//
319
- regs -> portsc_bm .port_power = 1 ; // enable port power
352
+
353
+ // enable port power bit in portsc. The function of this bit depends on the value of the Port
354
+ // Power Control (PPC) field in the HCSPARAMS register.
355
+ if (ehci_data .cap_regs -> hcsparams_bm .port_power_control ) {
356
+ // mask out all change bits since they are Write 1 to clear
357
+ uint32_t portsc = (regs -> portsc & ~EHCI_PORTSC_MASK_CHANGE_ALL );
358
+ portsc |= ECHI_PORTSC_MASK_PORT_POWER ;
359
+
360
+ regs -> portsc = portsc ;
361
+ }
320
362
321
363
return true;
322
364
}
@@ -656,26 +698,6 @@ static void xfer_error_isr(uint8_t hostid)
656
698
}
657
699
}
658
700
659
- #if CFG_TUSB_DEBUG >= EHCI_DBG
660
-
661
- static inline void print_portsc (ehci_registers_t * regs )
662
- {
663
- TU_LOG_HEX (EHCI_DBG , regs -> portsc );
664
- TU_LOG (EHCI_DBG , " Current Connect Status: %u\r\n" , regs -> portsc_bm .current_connect_status );
665
- TU_LOG (EHCI_DBG , " Connect Status Change : %u\r\n" , regs -> portsc_bm .connect_status_change );
666
- TU_LOG (EHCI_DBG , " Port Enabled : %u\r\n" , regs -> portsc_bm .port_enabled );
667
- TU_LOG (EHCI_DBG , " Port Enabled Change : %u\r\n" , regs -> portsc_bm .port_enable_change );
668
-
669
- TU_LOG (EHCI_DBG , " Port Reset : %u\r\n" , regs -> portsc_bm .port_reset );
670
- TU_LOG (EHCI_DBG , " Port Power : %u\r\n" , regs -> portsc_bm .port_power );
671
- }
672
-
673
- #else
674
-
675
- #define print_portsc (_reg )
676
-
677
- #endif
678
-
679
701
//------------- Host Controller Driver's Interrupt Handler -------------//
680
702
void hcd_int_handler (uint8_t rhport )
681
703
{
@@ -695,7 +717,7 @@ void hcd_int_handler(uint8_t rhport)
695
717
696
718
if (int_status & EHCI_INT_MASK_PORT_CHANGE )
697
719
{
698
- uint32_t const port_status = regs -> portsc & EHCI_PORTSC_MASK_ALL ;
720
+ uint32_t const port_status = regs -> portsc & EHCI_PORTSC_MASK_CHANGE_ALL ;
699
721
print_portsc (regs );
700
722
701
723
if (regs -> portsc_bm .connect_status_change )
0 commit comments