1 /*
2  * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <stddef.h>
8 #include <stdint.h>
9 #include <string.h>
10 #include "sdkconfig.h"
11 #include "hal/usbh_hal.h"
12 #include "hal/usbh_ll.h"
13 #include "hal/assert.h"
14 
15 // ------------------------------------------------ Macros and Types ---------------------------------------------------
16 
17 // ---------------------- Constants ------------------------
18 
19 #define BENDPOINTADDRESS_NUM_MSK     0x0F   //Endpoint number mask of the bEndpointAddress field of an endpoint descriptor
20 #define BENDPOINTADDRESS_DIR_MSK     0x80   //Endpoint direction mask of the bEndpointAddress field of an endpoint descriptor
21 
22 #define CORE_REG_GSNPSID    0x4F54400A
23 #define CORE_REG_GHWCFG1    0x00000000
24 #define CORE_REG_GHWCFG2    0x224DD930
25 #define CORE_REG_GHWCFG3    0x00C804B5
26 #define CORE_REG_GHWCFG4    0xD3F0A030
27 
28 // -------------------- Configurable -----------------------
29 
30 /**
31  * The following core interrupts will be enabled (listed LSB to MSB). Some of these
32  * interrupts are enabled later than others.
33  * - USB_LL_INTR_CORE_PRTINT
34  * - USB_LL_INTR_CORE_HCHINT
35  * - USB_LL_INTR_CORE_DISCONNINT
36  * The following PORT interrupts cannot be masked, listed LSB to MSB
37  * - USBH_LL_INTR_HPRT_PRTCONNDET
38  * - USBH_LL_INTR_HPRT_PRTENCHNG
39  * - USBH_LL_INTR_HPRT_PRTOVRCURRCHNG
40  */
41 #define CORE_INTRS_EN_MSK   (USB_LL_INTR_CORE_DISCONNINT)
42 
43 //Interrupts that pertain to core events
44 #define CORE_EVENTS_INTRS_MSK (USB_LL_INTR_CORE_DISCONNINT | \
45                                USB_LL_INTR_CORE_HCHINT)
46 
47 //Interrupt that pertain to host port events
48 #define PORT_EVENTS_INTRS_MSK (USBH_LL_INTR_HPRT_PRTCONNDET | \
49                                USBH_LL_INTR_HPRT_PRTENCHNG | \
50                                USBH_LL_INTR_HPRT_PRTOVRCURRCHNG)
51 
52 /**
53  * The following channel interrupt bits are currently checked (in order LSB to MSB)
54  * - USBH_LL_INTR_CHAN_XFERCOMPL
55  * - USBH_LL_INTR_CHAN_CHHLTD
56  * - USBH_LL_INTR_CHAN_STALL
57  * - USBH_LL_INTR_CHAN_BBLEER
58  * - USBH_LL_INTR_CHAN_BNAINTR
59  * - USBH_LL_INTR_CHAN_XCS_XACT_ERR
60  *
61  * Note the following points about channel interrupts:
62  * - Not all bits are unmaskable under scatter/gather
63  * - Those bits proxy their interrupt through the USBH_LL_INTR_CHAN_CHHLTD bit
64  * - USBH_LL_INTR_CHAN_XCS_XACT_ERR is always unmasked
65  * - When USBH_LL_INTR_CHAN_BNAINTR occurs, USBH_LL_INTR_CHAN_CHHLTD will NOT.
66  * - USBH_LL_INTR_CHAN_AHBERR doesn't actually ever happen on our system (i.e., ESP32-S2, ESP32-S3):
67  *      - If the QTD list's starting address is an invalid address (e.g., NULL), the core will attempt to fetch that
68  *        address for a transfer descriptor and probably gets all zeroes. It will interpret the zero as a bad QTD and
69  *        return a USBH_LL_INTR_CHAN_BNAINTR instead.
70  *      - If the QTD's buffer pointer is an invalid address, the core will attempt to read/write data to/from that
71  *        invalid buffer address with NO INDICATION OF ERROR. The transfer will be acknowledged and treated as
72  *        successful. Bad buffer pointers MUST BE CHECKED FROM HIGHER LAYERS INSTEAD.
73  */
74 #define CHAN_INTRS_EN_MSK   (USBH_LL_INTR_CHAN_XFERCOMPL | \
75                              USBH_LL_INTR_CHAN_CHHLTD | \
76                              USBH_LL_INTR_CHAN_BNAINTR)
77 
78 #define CHAN_INTRS_ERROR_MSK  (USBH_LL_INTR_CHAN_STALL | \
79                                USBH_LL_INTR_CHAN_BBLEER | \
80                                USBH_LL_INTR_CHAN_BNAINTR | \
81                                USBH_LL_INTR_CHAN_XCS_XACT_ERR)
82 
83 // -------------------------------------------------- Core (Global) ----------------------------------------------------
84 
set_defaults(usbh_hal_context_t * hal)85 static void set_defaults(usbh_hal_context_t *hal)
86 {
87     //GAHBCFG register
88     usb_ll_en_dma_mode(hal->dev);
89 #ifdef CONFIG_IDF_TARGET_ESP32S2
90     usb_ll_set_hbstlen(hal->dev, 1);    //Use INCR AHB burst. See the ESP32-S2 and later chip ERRATA.
91 #elif CONFIG_IDF_TARGET_ESP32S3
92     usb_ll_set_hbstlen(hal->dev, 0);    //Do not use USB burst INCR mode for the ESP32-S3, to avoid interference with other peripherals.
93 #endif
94     //GUSBCFG register
95     usb_ll_dis_hnp_cap(hal->dev);       //Disable HNP
96     usb_ll_dis_srp_cap(hal->dev);       //Disable SRP
97     //Enable interruts
98     usb_ll_dis_intrs(hal->dev, 0xFFFFFFFF);     //Mask all interrupts first
99     usb_ll_en_intrs(hal->dev, CORE_INTRS_EN_MSK);   //Unmask global interrupts
100     usb_ll_intr_read_and_clear(hal->dev);   //Clear interrupts
101     usb_ll_en_global_intr(hal->dev);        //Enable interrupt signal
102     //Enable host mode
103     usb_ll_set_host_mode(hal->dev);
104 }
105 
usbh_hal_init(usbh_hal_context_t * hal)106 void usbh_hal_init(usbh_hal_context_t *hal)
107 {
108     //Check if a peripheral is alive by reading the core ID registers
109     usbh_dev_t *dev = &USBH;
110     uint32_t core_id = usb_ll_get_controller_core_id(dev);
111     HAL_ASSERT(core_id == CORE_REG_GSNPSID);
112     (void) core_id;     //Suppress unused variable warning if asserts are disabled
113     //Initialize HAL context
114     memset(hal, 0, sizeof(usbh_hal_context_t));
115     hal->dev = dev;
116     set_defaults(hal);
117 }
118 
usbh_hal_deinit(usbh_hal_context_t * hal)119 void usbh_hal_deinit(usbh_hal_context_t *hal)
120 {
121     //Disable and clear global interrupt
122     usb_ll_dis_intrs(hal->dev, 0xFFFFFFFF); //Disable all interrupts
123     usb_ll_intr_read_and_clear(hal->dev);   //Clear interrupts
124     usb_ll_dis_global_intr(hal->dev);       //Disable interrupt signal
125     hal->dev = NULL;
126 }
127 
usbh_hal_core_soft_reset(usbh_hal_context_t * hal)128 void usbh_hal_core_soft_reset(usbh_hal_context_t *hal)
129 {
130     usb_ll_core_soft_reset(hal->dev);
131     while (usb_ll_check_core_soft_reset(hal->dev)) {
132         ;   //Wait until core reset is done
133     }
134     while (!usb_ll_check_ahb_idle(hal->dev)) {
135         ;   //Wait until AHB Master bus is idle before doing any other operations
136     }
137     //Set the default bits
138     set_defaults(hal);
139     //Clear all the flags and channels
140     hal->periodic_frame_list = NULL;
141     hal->flags.val = 0;
142     hal->channels.num_allocd = 0;
143     hal->channels.chan_pend_intrs_msk = 0;
144     memset(hal->channels.hdls, 0, sizeof(usbh_hal_chan_t *) * USBH_HAL_NUM_CHAN);
145 }
146 
usbh_hal_set_fifo_size(usbh_hal_context_t * hal,const usbh_hal_fifo_config_t * fifo_config)147 void usbh_hal_set_fifo_size(usbh_hal_context_t *hal, const usbh_hal_fifo_config_t *fifo_config)
148 {
149     HAL_ASSERT((fifo_config->rx_fifo_lines + fifo_config->nptx_fifo_lines + fifo_config->ptx_fifo_lines) <= USBH_HAL_FIFO_TOTAL_USABLE_LINES);
150     //Check that none of the channels are active
151     for (int i = 0; i < USBH_HAL_NUM_CHAN; i++) {
152         if (hal->channels.hdls[i] != NULL) {
153             HAL_ASSERT(!hal->channels.hdls[i]->flags.active);
154         }
155     }
156     //Set the new FIFO lengths
157     usb_ll_set_rx_fifo_size(hal->dev, fifo_config->rx_fifo_lines);
158     usb_ll_set_nptx_fifo_size(hal->dev, fifo_config->rx_fifo_lines, fifo_config->nptx_fifo_lines);
159     usbh_ll_set_ptx_fifo_size(hal->dev, fifo_config->rx_fifo_lines + fifo_config->nptx_fifo_lines, fifo_config->ptx_fifo_lines);
160     //Flush the FIFOs
161     usb_ll_flush_nptx_fifo(hal->dev);
162     usb_ll_flush_ptx_fifo(hal->dev);
163     usb_ll_flush_rx_fifo(hal->dev);
164     hal->flags.fifo_sizes_set = 1;
165 }
166 
167 // ---------------------------------------------------- Host Port ------------------------------------------------------
168 
debounce_lock_enable(usbh_hal_context_t * hal)169 static inline void debounce_lock_enable(usbh_hal_context_t *hal)
170 {
171     //Disable the hprt (connection) and disconnection interrupts to prevent repeated triggerings
172     usb_ll_dis_intrs(hal->dev, USB_LL_INTR_CORE_PRTINT | USB_LL_INTR_CORE_DISCONNINT);
173     hal->flags.dbnc_lock_enabled = 1;
174 }
175 
usbh_hal_port_enable(usbh_hal_context_t * hal)176 void usbh_hal_port_enable(usbh_hal_context_t *hal)
177 {
178     usb_priv_speed_t speed = usbh_ll_hprt_get_speed(hal->dev);
179     //Host Configuration
180     usbh_ll_hcfg_set_defaults(hal->dev, speed);
181     //Configure HFIR
182     usbh_ll_hfir_set_defaults(hal->dev, speed);
183 }
184 
185 // ----------------------------------------------------- Channel -------------------------------------------------------
186 
187 // ----------------- Channel Allocation --------------------
188 
usbh_hal_chan_alloc(usbh_hal_context_t * hal,usbh_hal_chan_t * chan_obj,void * chan_ctx)189 bool usbh_hal_chan_alloc(usbh_hal_context_t *hal, usbh_hal_chan_t *chan_obj, void *chan_ctx)
190 {
191     HAL_ASSERT(hal->flags.fifo_sizes_set);  //FIFO sizes should be set befor attempting to allocate a channel
192     //Attempt to allocate channel
193     if (hal->channels.num_allocd == USBH_HAL_NUM_CHAN) {
194         return false;    //Out of free channels
195     }
196     int chan_idx = -1;
197     for (int i = 0; i < USBH_HAL_NUM_CHAN; i++) {
198         if (hal->channels.hdls[i] == NULL) {
199             hal->channels.hdls[i] = chan_obj;
200             chan_idx = i;
201             hal->channels.num_allocd++;
202             break;
203         }
204     }
205     HAL_ASSERT(chan_idx != -1);
206     //Initialize channel object
207     memset(chan_obj, 0, sizeof(usbh_hal_chan_t));
208     chan_obj->flags.chan_idx = chan_idx;
209     chan_obj->regs = usbh_ll_get_chan_regs(hal->dev, chan_idx);
210     chan_obj->chan_ctx = chan_ctx;
211     //Note: EP characteristics configured separately
212     //Clean and unmask the channel's interrupt
213     usbh_ll_chan_intr_read_and_clear(chan_obj->regs);            //Clear the interrupt bits for that channel
214     usbh_ll_haintmsk_en_chan_intr(hal->dev, 1 << chan_obj->flags.chan_idx);
215     usbh_ll_chan_set_intr_mask(chan_obj->regs, CHAN_INTRS_EN_MSK);  //Unmask interrupts for this channel
216     usbh_ll_chan_set_pid(chan_obj->regs, 0);        //Set the initial PID to zero
217     usbh_ll_chan_hctsiz_init(chan_obj->regs);       //Set the non changing parts of the HCTSIZ registers (e.g., do_ping and sched info)
218     return true;
219 }
220 
usbh_hal_chan_free(usbh_hal_context_t * hal,usbh_hal_chan_t * chan_obj)221 void usbh_hal_chan_free(usbh_hal_context_t *hal, usbh_hal_chan_t *chan_obj)
222 {
223     if (chan_obj->type == USB_PRIV_XFER_TYPE_INTR || chan_obj->type == USB_PRIV_XFER_TYPE_ISOCHRONOUS) {
224         //Unschedule this channel
225         for (int i = 0; i < hal->frame_list_len; i++) {
226             hal->periodic_frame_list[i] &= ~(1 << chan_obj->flags.chan_idx);
227         }
228     }
229     //Can only free a channel when in the disabled state and descriptor list released
230     HAL_ASSERT(!chan_obj->flags.active);
231     //Disable channel's interrupt
232     usbh_ll_haintmsk_dis_chan_intr(hal->dev, 1 << chan_obj->flags.chan_idx);
233     //Deallocate channel
234     hal->channels.hdls[chan_obj->flags.chan_idx] = NULL;
235     hal->channels.num_allocd--;
236     HAL_ASSERT(hal->channels.num_allocd >= 0);
237 }
238 
239 // ---------------- Channel Configuration ------------------
240 
usbh_hal_chan_set_ep_char(usbh_hal_context_t * hal,usbh_hal_chan_t * chan_obj,usbh_hal_ep_char_t * ep_char)241 void usbh_hal_chan_set_ep_char(usbh_hal_context_t *hal, usbh_hal_chan_t *chan_obj, usbh_hal_ep_char_t *ep_char)
242 {
243     //Cannot change ep_char whilst channel is still active or in error
244     HAL_ASSERT(!chan_obj->flags.active);
245     //Set the endpoint characteristics of the pipe
246     usbh_ll_chan_hcchar_init(chan_obj->regs,
247                              ep_char->dev_addr,
248                              ep_char->bEndpointAddress & BENDPOINTADDRESS_NUM_MSK,
249                              ep_char->mps,
250                              ep_char->type,
251                              ep_char->bEndpointAddress & BENDPOINTADDRESS_DIR_MSK,
252                              ep_char->ls_via_fs_hub);
253     //Save channel type
254     chan_obj->type = ep_char->type;
255     //If this is a periodic endpoint/channel, set its schedule in the frame list
256     if (ep_char->type == USB_PRIV_XFER_TYPE_ISOCHRONOUS || ep_char->type == USB_PRIV_XFER_TYPE_INTR) {
257         HAL_ASSERT((int)ep_char->periodic.interval <= (int)hal->frame_list_len);    //Interval cannot exceed the length of the frame list
258         //Find the effective offset in the frame list (in case the phase_offset_frames > interval)
259         int offset = ep_char->periodic.phase_offset_frames % ep_char->periodic.interval;
260         //Schedule the channel in the frame list
261         for (int i = offset; i < hal->frame_list_len; i+= ep_char->periodic.interval) {
262             hal->periodic_frame_list[i] |= 1 << chan_obj->flags.chan_idx;
263         }
264     }
265 }
266 
267 // ------------------- Channel Control ---------------------
268 
usbh_hal_chan_activate(usbh_hal_chan_t * chan_obj,void * xfer_desc_list,int desc_list_len,int start_idx)269 void usbh_hal_chan_activate(usbh_hal_chan_t *chan_obj, void *xfer_desc_list, int desc_list_len, int start_idx)
270 {
271     //Cannot activate a channel that has already been enabled or is pending error handling
272     HAL_ASSERT(!chan_obj->flags.active);
273     //Set start address of the QTD list and starting QTD index
274     usbh_ll_chan_set_dma_addr_non_iso(chan_obj->regs, xfer_desc_list, start_idx);
275     usbh_ll_chan_set_qtd_list_len(chan_obj->regs, desc_list_len);
276     usbh_ll_chan_start(chan_obj->regs); //Start the channel
277     chan_obj->flags.active = 1;
278 }
279 
usbh_hal_chan_request_halt(usbh_hal_chan_t * chan_obj)280 bool usbh_hal_chan_request_halt(usbh_hal_chan_t *chan_obj)
281 {
282     //Cannot request halt on a channel that is pending error handling
283     if (usbh_ll_chan_is_active(chan_obj->regs)) {
284         //If the register indicates that the channel is still active, the active flag must have been previously set
285         HAL_ASSERT(chan_obj->flags.active);
286         usbh_ll_chan_halt(chan_obj->regs);
287         chan_obj->flags.halt_requested = 1;
288         return false;
289     } else {
290         //We just clear the active flag here as it could still be set (if we have a pending channel interrupt)
291         chan_obj->flags.active = 0;
292         return true;
293     }
294 }
295 
296 // ------------------------------------------------- Event Handling ----------------------------------------------------
297 
usbh_hal_decode_intr(usbh_hal_context_t * hal)298 usbh_hal_port_event_t usbh_hal_decode_intr(usbh_hal_context_t *hal)
299 {
300     uint32_t intrs_core = usb_ll_intr_read_and_clear(hal->dev);  //Read and clear core interrupts
301     uint32_t intrs_port = 0;
302     if (intrs_core & USB_LL_INTR_CORE_PRTINT) {
303         //There are host port interrupts. Read and clear those as well.
304         intrs_port = usbh_ll_hprt_intr_read_and_clear(hal->dev);
305     }
306     //Note: Do not change order of checks. Regressing events (e.g. enable -> disabled, connected -> connected)
307     //always take precedence. ENABLED < DISABLED < CONN < DISCONN < OVRCUR
308     usbh_hal_port_event_t event = USBH_HAL_PORT_EVENT_NONE;
309 
310     //Check if this is a core or port event
311     if ((intrs_core & CORE_EVENTS_INTRS_MSK) || (intrs_port & PORT_EVENTS_INTRS_MSK)) {
312         //Do not change the order of the following checks. Some events/interrupts take precedence over others
313         if (intrs_core & USB_LL_INTR_CORE_DISCONNINT) {
314             event = USBH_HAL_PORT_EVENT_DISCONN;
315             debounce_lock_enable(hal);
316             //Mask the port connection and disconnection interrupts to prevent repeated triggering
317         } else if (intrs_port & USBH_LL_INTR_HPRT_PRTOVRCURRCHNG) {
318             //Check if this is an overcurrent or an overcurrent cleared
319             if (usbh_ll_hprt_get_port_overcur(hal->dev)) {
320                 event = USBH_HAL_PORT_EVENT_OVRCUR;
321             } else {
322                 event = USBH_HAL_PORT_EVENT_OVRCUR_CLR;
323             }
324         } else if (intrs_port & USBH_LL_INTR_HPRT_PRTENCHNG) {
325             if (usbh_ll_hprt_get_port_en(hal->dev)) {   //Host port was enabled
326                 event = USBH_HAL_PORT_EVENT_ENABLED;
327             } else {    //Host port has been disabled
328                 event = USBH_HAL_PORT_EVENT_DISABLED;
329             }
330         } else if (intrs_port & USBH_LL_INTR_HPRT_PRTCONNDET && !hal->flags.dbnc_lock_enabled) {
331             event = USBH_HAL_PORT_EVENT_CONN;
332             debounce_lock_enable(hal);
333         }
334     }
335     //Port events always take precedence over channel events
336     if (event == USBH_HAL_PORT_EVENT_NONE && (intrs_core & USB_LL_INTR_CORE_HCHINT)) {
337         //One or more channels have pending interrupts. Store the mask of those channels
338         hal->channels.chan_pend_intrs_msk = usbh_ll_get_chan_intrs_msk(hal->dev);
339         event = USBH_HAL_PORT_EVENT_CHAN;
340     }
341 
342     return event;
343 }
344 
usbh_hal_get_chan_pending_intr(usbh_hal_context_t * hal)345 usbh_hal_chan_t *usbh_hal_get_chan_pending_intr(usbh_hal_context_t *hal)
346 {
347     int chan_num = __builtin_ffs(hal->channels.chan_pend_intrs_msk);
348     if (chan_num) {
349         hal->channels.chan_pend_intrs_msk &= ~(1 << (chan_num - 1));      //Clear the pending bit for that channel
350         return hal->channels.hdls[chan_num - 1];
351     } else {
352         return NULL;
353     }
354 }
355 
usbh_hal_chan_decode_intr(usbh_hal_chan_t * chan_obj)356 usbh_hal_chan_event_t usbh_hal_chan_decode_intr(usbh_hal_chan_t *chan_obj)
357 {
358     uint32_t chan_intrs = usbh_ll_chan_intr_read_and_clear(chan_obj->regs);
359     usbh_hal_chan_event_t chan_event;
360     //Note: We don't assert on (chan_obj->flags.active) here as it could have been already cleared by usbh_hal_chan_request_halt()
361 
362     if (chan_intrs & CHAN_INTRS_ERROR_MSK) {    //Note: Errors are uncommon, so we check against the entire interrupt mask to reduce frequency of entering this call path
363         HAL_ASSERT(chan_intrs & USBH_LL_INTR_CHAN_CHHLTD);  //An error should have halted the channel
364         //Store the error in hal context
365         usbh_hal_chan_error_t error;
366         if (chan_intrs & USBH_LL_INTR_CHAN_STALL) {
367             error = USBH_HAL_CHAN_ERROR_STALL;
368         } else if (chan_intrs & USBH_LL_INTR_CHAN_BBLEER) {
369             error = USBH_HAL_CHAN_ERROR_PKT_BBL;
370         } else if (chan_intrs & USBH_LL_INTR_CHAN_BNAINTR) {
371             error = USBH_HAL_CHAN_ERROR_BNA;
372         } else {    //USBH_LL_INTR_CHAN_XCS_XACT_ERR
373             error = USBH_HAL_CHAN_ERROR_XCS_XACT;
374         }
375         //Update flags
376         chan_obj->error = error;
377         chan_obj->flags.active = 0;
378         //Save the error to be handled later
379         chan_event = USBH_HAL_CHAN_EVENT_ERROR;
380     } else if (chan_intrs & USBH_LL_INTR_CHAN_CHHLTD) {
381         if (chan_obj->flags.halt_requested) {
382             chan_obj->flags.halt_requested = 0;
383             chan_event = USBH_HAL_CHAN_EVENT_HALT_REQ;
384         } else {
385             //Must have been halted due to QTD HOC
386             chan_event = USBH_HAL_CHAN_EVENT_CPLT;
387         }
388         chan_obj->flags.active = 0;
389     } else if (chan_intrs & USBH_LL_INTR_CHAN_XFERCOMPL) {
390         /*
391         A transfer complete interrupt WITHOUT the channel halting only occurs when receiving a short interrupt IN packet
392         and the underlying QTD does not have the HOC bit set. This signifies the last packet of the Interrupt transfer
393         as all interrupt packets must MPS sized except the last.
394         */
395         //The channel isn't halted yet, so we need to halt it manually to stop the execution of the next QTD/packet
396         usbh_ll_chan_halt(chan_obj->regs);
397         /*
398         After setting the halt bit, this will generate another channel halted interrupt. We treat this interrupt as
399         a NONE event, then cycle back with the channel halted interrupt to handle the CPLT event.
400         */
401         chan_event = USBH_HAL_CHAN_EVENT_NONE;
402     } else {
403         abort();    //Should never reach this point
404     }
405     return chan_event;
406 }
407