1 /*!
2     \file    drv_usb_dev.c
3     \brief   USB device mode low level driver
4 
5     \version 2020-08-04, V1.1.0, firmware for GD32VF103
6 */
7 
8 /*
9     Copyright (c) 2020, GigaDevice Semiconductor Inc.
10 
11     Redistribution and use in source and binary forms, with or without modification,
12 are permitted provided that the following conditions are met:
13 
14     1. Redistributions of source code must retain the above copyright notice, this
15        list of conditions and the following disclaimer.
16     2. Redistributions in binary form must reproduce the above copyright notice,
17        this list of conditions and the following disclaimer in the documentation
18        and/or other materials provided with the distribution.
19     3. Neither the name of the copyright holder nor the names of its contributors
20        may be used to endorse or promote products derived from this software without
21        specific prior written permission.
22 
23     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
32 OF SUCH DAMAGE.
33 */
34 
35 #include "drv_usb_hw.h"
36 #include "drv_usb_core.h"
37 #include "drv_usb_dev.h"
38 
39 /* endpoint 0 max packet length */
40 static const uint8_t EP0_MAXLEN[4] = {
41     [DSTAT_EM_HS_PHY_30MHZ_60MHZ] = EP0MPL_64,
42     [DSTAT_EM_FS_PHY_30MHZ_60MHZ] = EP0MPL_64,
43     [DSTAT_EM_FS_PHY_48MHZ] = EP0MPL_64,
44     [DSTAT_EM_LS_PHY_6MHZ] = EP0MPL_8
45 };
46 
47 #ifdef USB_FS_CORE
48 
49 /* USB endpoint Tx FIFO size */
50 static uint16_t USBFS_TX_FIFO_SIZE[USBFS_MAX_EP_COUNT] =
51 {
52     (uint16_t)TX0_FIFO_FS_SIZE,
53     (uint16_t)TX1_FIFO_FS_SIZE,
54     (uint16_t)TX2_FIFO_FS_SIZE,
55     (uint16_t)TX3_FIFO_FS_SIZE
56 };
57 
58 #endif /* USBFS_CORE */
59 
60 /*!
61     \brief      initialize USB core registers for device mode
62     \param[in]  udev: pointer to USB device
63     \param[out] none
64     \retval     operation status
65 */
usb_devcore_init(usb_core_driver * udev)66 usb_status usb_devcore_init (usb_core_driver *udev)
67 {
68     uint8_t i;
69 
70     /* restart the PHY clock (maybe don't need to...) */
71     *udev->regs.PWRCLKCTL = 0U;
72 
73     /* config periodic frame interval to default value */
74     udev->regs.dr->DCFG &= ~DCFG_EOPFT;
75     udev->regs.dr->DCFG |= FRAME_INTERVAL_80;
76 
77     udev->regs.dr->DCFG &= ~DCFG_DS;
78 
79 #ifdef USB_FS_CORE
80     if (udev->bp.core_enum == (uint8_t)USB_CORE_ENUM_FS) {
81         /* set full-speed PHY */
82         udev->regs.dr->DCFG |= USB_SPEED_INP_FULL;
83 
84         /* set Rx FIFO size */
85         usb_set_rxfifo(&udev->regs, RX_FIFO_FS_SIZE);
86 
87         /* set endpoint 0 to 3's Tx FIFO length and RAM address */
88         for (i = 0U; i < USBFS_MAX_EP_COUNT; i++) {
89             usb_set_txfifo(&udev->regs, i, USBFS_TX_FIFO_SIZE[i]);
90         }
91     }
92 #endif /* USB_FS_CORE */
93 
94     /* make sure all FIFOs are flushed */
95 
96     /* flush all Tx FIFOs */
97     (void)usb_txfifo_flush (&udev->regs, 0x10U);
98 
99     /* flush entire Rx FIFO */
100     (void)usb_rxfifo_flush (&udev->regs);
101 
102     /* clear all pending device interrupts */
103     udev->regs.dr->DIEPINTEN = 0U;
104     udev->regs.dr->DOEPINTEN = 0U;
105     udev->regs.dr->DAEPINT = 0xFFFFFFFFU;
106     udev->regs.dr->DAEPINTEN = 0U;
107 
108     /* configure all IN/OUT endpoints */
109     for (i = 0U; i < udev->bp.num_ep; i++) {
110         if (udev->regs.er_in[i]->DIEPCTL & DEPCTL_EPEN) {
111             udev->regs.er_in[i]->DIEPCTL |= DEPCTL_EPD | DEPCTL_SNAK;
112         } else {
113             udev->regs.er_in[i]->DIEPCTL = 0U;
114         }
115 
116         /* set IN endpoint transfer length to 0 */
117         udev->regs.er_in[i]->DIEPLEN = 0U;
118 
119         /* clear all pending IN endpoint interrupts */
120         udev->regs.er_in[i]->DIEPINTF = 0xFFU;
121 
122         if (udev->regs.er_out[i]->DOEPCTL & DEPCTL_EPEN) {
123             udev->regs.er_out[i]->DOEPCTL |= DEPCTL_EPD | DEPCTL_SNAK;
124         } else {
125             udev->regs.er_out[i]->DOEPCTL = 0U;
126         }
127 
128         /* set OUT endpoint transfer length to 0 */
129         udev->regs.er_out[i]->DOEPLEN = 0U;
130 
131         /* clear all pending OUT endpoint interrupts */
132         udev->regs.er_out[i]->DOEPINTF = 0xFFU;
133     }
134 
135     udev->regs.dr->DIEPINTEN |= DIEPINTEN_EPTXFUDEN;
136 
137     (void)usb_devint_enable (udev);
138 
139     return USB_OK;
140 }
141 
142 /*!
143     \brief      enable the USB device mode interrupts
144     \param[in]  udev: pointer to USB device
145     \param[out] none
146     \retval     operation status
147 */
usb_devint_enable(usb_core_driver * udev)148 usb_status usb_devint_enable (usb_core_driver *udev)
149 {
150     /* clear any pending USB OTG interrupts */
151     udev->regs.gr->GOTGINTF = 0xFFFFFFFFU;
152 
153     /* clear any pending interrupts */
154     udev->regs.gr->GINTF = 0xBFFFFFFFU;
155 
156     /* enable the USB wakeup and suspend interrupts */
157     udev->regs.gr->GINTEN = GINTEN_WKUPIE | GINTEN_SPIE;
158 
159     /* enable device_mode-related interrupts */
160     if ((uint8_t)USB_USE_FIFO == udev->bp.transfer_mode) {
161         udev->regs.gr->GINTEN |= GINTEN_RXFNEIE;
162     }
163 
164     udev->regs.gr->GINTEN |= GINTEN_RSTIE | GINTEN_ENUMFIE | GINTEN_IEPIE |\
165                              GINTEN_OEPIE | GINTEN_SOFIE | GINTEN_ISOONCIE | GINTEN_ISOINCIE;
166 
167 #ifdef VBUS_SENSING_ENABLED
168     udev->regs.gr->GINTEN |= GINTEN_SESIE | GINTEN_OTGIE;
169 #endif /* VBUS_SENSING_ENABLED */
170 
171     return USB_OK;
172 }
173 
174 /*!
175     \brief      active the USB endpoint0 transaction
176     \param[in]  udev: pointer to USB device
177     \param[in]  transc: the USB endpoint0 transaction
178     \param[out] none
179     \retval     operation status
180 */
usb_transc0_active(usb_core_driver * udev,usb_transc * transc)181 usb_status usb_transc0_active (usb_core_driver *udev, usb_transc *transc)
182 {
183     __IO uint32_t *reg_addr = NULL;
184 
185     /* get the endpoint number */
186     uint8_t ep_num = transc->ep_addr.num;
187 
188     if (ep_num) {
189         /* not endpoint 0 */
190         return USB_FAIL;
191     }
192 
193     if (transc->ep_addr.dir) {
194         reg_addr = &udev->regs.er_in[0]->DIEPCTL;
195     } else {
196         reg_addr = &udev->regs.er_out[0]->DOEPCTL;
197     }
198 
199     /* endpoint 0 is activated after USB clock is enabled */
200 
201     *reg_addr &= ~(DEPCTL_MPL | DEPCTL_EPTYPE | DIEPCTL_TXFNUM);
202 
203     /* set endpoint 0 maximum packet length */
204     *reg_addr |= EP0_MAXLEN[udev->regs.dr->DSTAT & DSTAT_ES];
205 
206     /* activate endpoint */
207     *reg_addr |= ((uint32_t)transc->ep_type << 18U) | ((uint32_t)ep_num << 22U) | DEPCTL_SD0PID | DEPCTL_EPACT;
208 
209     return USB_OK;
210 }
211 
212 /*!
213     \brief      active the USB transaction
214     \param[in]  udev: pointer to USB device
215     \param[in]  transc: the USB transaction
216     \param[out] none
217     \retval     status
218 */
usb_transc_active(usb_core_driver * udev,usb_transc * transc)219 usb_status usb_transc_active (usb_core_driver *udev, usb_transc *transc)
220 {
221     __IO uint32_t *reg_addr = NULL;
222     __IO uint32_t epinten = 0U;
223 
224     /* get the endpoint number */
225     uint8_t ep_num = transc->ep_addr.num;
226 
227     /* enable endpoint interrupt number */
228     if (transc->ep_addr.dir) {
229         reg_addr = &udev->regs.er_in[ep_num]->DIEPCTL;
230 
231         epinten = 1U << ep_num;
232     } else {
233         reg_addr = &udev->regs.er_out[ep_num]->DOEPCTL;
234 
235         epinten = 1U << (16U + ep_num);
236     }
237 
238     /* if the endpoint is not active, need change the endpoint control register */
239     if (!(*reg_addr & DEPCTL_EPACT)) {
240         *reg_addr &= ~(DEPCTL_MPL | DEPCTL_EPTYPE | DIEPCTL_TXFNUM);
241 
242         /* set endpoint maximum packet length */
243         if (0U == ep_num) {
244             *reg_addr |= EP0_MAXLEN[udev->regs.dr->DSTAT & DSTAT_ES];
245         } else {
246             *reg_addr |= transc->max_len;
247         }
248 
249         /* activate endpoint */
250         *reg_addr |= ((uint32_t)transc->ep_type << 18U) | ((uint32_t)ep_num << 22U) | DEPCTL_SD0PID | DEPCTL_EPACT;
251     }
252 
253 
254     /* enable the interrupts for this endpoint */
255     udev->regs.dr->DAEPINTEN |= epinten;
256 
257     return USB_OK;
258 }
259 
260 /*!
261     \brief      deactivate the USB transaction
262     \param[in]  udev: pointer to USB device
263     \param[in]  transc: the USB transaction
264     \param[out] none
265     \retval     status
266 */
usb_transc_deactivate(usb_core_driver * udev,usb_transc * transc)267 usb_status usb_transc_deactivate(usb_core_driver *udev, usb_transc *transc)
268 {
269     uint32_t epinten = 0U;
270 
271     uint8_t ep_num = transc->ep_addr.num;
272 
273     /* disable endpoint interrupt number */
274     if (transc->ep_addr.dir) {
275         epinten = 1U << ep_num;
276 
277         udev->regs.er_in[ep_num]->DIEPCTL &= ~DEPCTL_EPACT;
278     } else {
279         epinten = 1U << (ep_num + 16U);
280 
281         udev->regs.er_out[ep_num]->DOEPCTL &= ~DEPCTL_EPACT;
282     }
283 
284 
285     /* disable the interrupts for this endpoint */
286     udev->regs.dr->DAEPINTEN &= ~epinten;
287 
288     return USB_OK;
289 }
290 
291 /*!
292     \brief      configure USB transaction to start IN transfer
293     \param[in]  udev: pointer to USB device
294     \param[in]  transc: the USB IN transaction
295     \param[out] none
296     \retval     operation status
297 */
usb_transc_inxfer(usb_core_driver * udev,usb_transc * transc)298 usb_status usb_transc_inxfer (usb_core_driver *udev, usb_transc *transc)
299 {
300     usb_status status = USB_OK;
301 
302     uint8_t ep_num = transc->ep_addr.num;
303 
304     __IO uint32_t epctl = udev->regs.er_in[ep_num]->DIEPCTL;
305     __IO uint32_t eplen = udev->regs.er_in[ep_num]->DIEPLEN;
306 
307     eplen &= ~(DEPLEN_TLEN | DEPLEN_PCNT);
308 
309     /* zero length packet or endpoint 0 */
310     if (0U == transc->xfer_len) {
311         /* set transfer packet count to 1 */
312         eplen |= 1U << 19U;
313     } else {
314         /* set transfer packet count */
315         if (0U == ep_num) {
316             transc->xfer_len = USB_MIN(transc->xfer_len, transc->max_len);
317 
318             eplen |= 1U << 19U;
319         } else {
320             eplen |= (((transc->xfer_len - 1U) + transc->max_len) / transc->max_len) << 19U;
321         }
322 
323         /* set endpoint transfer length */
324         eplen |= transc->xfer_len;
325 
326         if (transc->ep_type == (uint8_t)USB_EPTYPE_ISOC) {
327             eplen |= DIEPLEN_MCNT & (1U << 29U);
328         }
329     }
330 
331     udev->regs.er_in[ep_num]->DIEPLEN = eplen;
332 
333     if (transc->ep_type == (uint8_t)USB_EPTYPE_ISOC) {
334         if (((udev->regs.dr->DSTAT & DSTAT_FNRSOF) >> 8U) & 0x01U) {
335             epctl |= DEPCTL_SEVNFRM;
336         } else {
337             epctl |= DEPCTL_SODDFRM;
338         }
339     }
340 
341     if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) {
342         udev->regs.er_in[ep_num]->DIEPDMAADDR = transc->dma_addr;
343     }
344 
345     /* enable the endpoint and clear the NAK */
346     epctl |= DEPCTL_CNAK | DEPCTL_EPEN;
347 
348     udev->regs.er_in[ep_num]->DIEPCTL = epctl;
349 
350     if ((uint8_t)USB_USE_FIFO == udev->bp.transfer_mode) {
351         udev->regs.er_in[ep_num]->DIEPCTL = epctl;
352 
353         if (transc->ep_type != (uint8_t)USB_EPTYPE_ISOC) {
354             /* enable the Tx FIFO empty interrupt for this endpoint */
355             if (transc->xfer_len > 0U) {
356                 udev->regs.dr->DIEPFEINTEN |= 1U << ep_num;
357             }
358         } else {
359             (void)usb_txfifo_write (&udev->regs, transc->xfer_buf, ep_num, (uint16_t)transc->xfer_len);
360         }
361     }
362 
363     return status;
364 }
365 
366 /*!
367     \brief      configure usb transaction to start OUT transfer
368     \param[in]  udev: pointer to usb device
369     \param[in]  transc: the usb OUT transaction
370     \param[out] none
371     \retval     status
372 */
usb_transc_outxfer(usb_core_driver * udev,usb_transc * transc)373 usb_status usb_transc_outxfer (usb_core_driver *udev, usb_transc *transc)
374 {
375     usb_status status = USB_OK;
376 
377     uint8_t ep_num = transc->ep_addr.num;
378 
379     uint32_t epctl = udev->regs.er_out[ep_num]->DOEPCTL;
380     uint32_t eplen = udev->regs.er_out[ep_num]->DOEPLEN;
381 
382     eplen &= ~(DEPLEN_TLEN | DEPLEN_PCNT);
383 
384     /* zero length packet or endpoint 0 */
385     if ((0U == transc->xfer_len) || (0U == ep_num)) {
386         /* set the transfer length to max packet size */
387         eplen |= transc->max_len;
388 
389         /* set the transfer packet count to 1 */
390         eplen |= 1U << 19U;
391     } else {
392         /* configure the transfer size and packet count as follows:
393          * pktcnt = N
394          * xfersize = N * maxpacket
395          */
396         uint32_t packet_count = (transc->xfer_len + transc->max_len - 1U) / transc->max_len;
397 
398         eplen |= packet_count << 19U;
399         eplen |= packet_count * transc->max_len;
400     }
401 
402     udev->regs.er_out[ep_num]->DOEPLEN = eplen;
403 
404     if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) {
405         udev->regs.er_out[ep_num]->DOEPDMAADDR = transc->dma_addr;
406     }
407 
408     if (transc->ep_type == (uint8_t)USB_EPTYPE_ISOC) {
409         if (transc->frame_num) {
410             epctl |= DEPCTL_SD1PID;
411         } else {
412             epctl |= DEPCTL_SD0PID;
413         }
414     }
415 
416     /* enable the endpoint and clear the NAK */
417     epctl |= DEPCTL_EPEN | DEPCTL_CNAK;
418 
419     udev->regs.er_out[ep_num]->DOEPCTL = epctl;
420 
421     return status;
422 }
423 
424 /*!
425     \brief      set the USB transaction STALL status
426     \param[in]  udev: pointer to USB device
427     \param[in]  transc: the USB transaction
428     \param[out] none
429     \retval     status
430 */
usb_transc_stall(usb_core_driver * udev,usb_transc * transc)431 usb_status usb_transc_stall (usb_core_driver *udev, usb_transc *transc)
432 {
433     __IO uint32_t *reg_addr = NULL;
434 
435     uint8_t ep_num = transc->ep_addr.num;
436 
437     if (transc->ep_addr.dir) {
438         reg_addr = &(udev->regs.er_in[ep_num]->DIEPCTL);
439 
440         /* set the endpoint disable bit */
441         if (*reg_addr & DEPCTL_EPEN) {
442             *reg_addr |= DEPCTL_EPD;
443         }
444     } else {
445         /* set the endpoint stall bit */
446         reg_addr = &(udev->regs.er_out[ep_num]->DOEPCTL);
447     }
448 
449     /* set the endpoint stall bit */
450     *reg_addr |= DEPCTL_STALL;
451 
452     return USB_OK;
453 }
454 
455 /*!
456     \brief      clear the USB transaction STALL status
457     \param[in]  udev: pointer to USB device
458     \param[in]  transc: the USB transaction
459     \param[out] none
460     \retval     operation status
461 */
usb_transc_clrstall(usb_core_driver * udev,usb_transc * transc)462 usb_status usb_transc_clrstall(usb_core_driver *udev, usb_transc *transc)
463 {
464     __IO uint32_t *reg_addr = NULL;
465 
466     uint8_t ep_num = transc->ep_addr.num;
467 
468     if (transc->ep_addr.dir) {
469         reg_addr = &(udev->regs.er_in[ep_num]->DIEPCTL);
470     } else {
471         reg_addr = &(udev->regs.er_out[ep_num]->DOEPCTL);
472     }
473 
474     /* clear the endpoint stall bits */
475     *reg_addr &= ~DEPCTL_STALL;
476 
477     /* reset data PID of the periodic endpoints */
478     if ((transc->ep_type == (uint8_t)USB_EPTYPE_INTR) || (transc->ep_type == (uint8_t)USB_EPTYPE_BULK)) {
479         *reg_addr |= DEPCTL_SD0PID;
480     }
481 
482     return USB_OK;
483 }
484 
485 /*!
486     \brief      read device IN endpoint interrupt flag register
487     \param[in]  udev: pointer to USB device
488     \param[in]  ep_num: endpoint number
489     \param[out] none
490     \retval     interrupt value
491 */
usb_iepintr_read(usb_core_driver * udev,uint8_t ep_num)492 uint32_t usb_iepintr_read (usb_core_driver *udev, uint8_t ep_num)
493 {
494     uint32_t value = 0U, fifoemptymask, commonintmask;
495 
496     commonintmask = udev->regs.dr->DIEPINTEN;
497     fifoemptymask = udev->regs.dr->DIEPFEINTEN;
498 
499     /* check FIFO empty interrupt enable bit */
500     commonintmask |= ((fifoemptymask >> ep_num) & 0x1U) << 7;
501 
502     value = udev->regs.er_in[ep_num]->DIEPINTF & commonintmask;
503 
504     return value;
505 }
506 
507 /*!
508     \brief      configures OUT endpoint 0 to receive SETUP packets
509     \param[in]  udev: pointer to USB device
510     \param[out] none
511     \retval     none
512 */
usb_ctlep_startout(usb_core_driver * udev)513 void usb_ctlep_startout (usb_core_driver *udev)
514 {
515     /* set OUT endpoint 0 receive length to 24 bytes, 1 packet and 3 setup packets */
516     udev->regs.er_out[0]->DOEPLEN = DOEP0_TLEN(8U * 3U) | DOEP0_PCNT(1U) | DOEP0_STPCNT(3U);
517 
518     if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) {
519         udev->regs.er_out[0]->DOEPDMAADDR = (uint32_t)&udev->dev.control.req;
520 
521         /* endpoint enable */
522         udev->regs.er_out[0]->DOEPCTL |= DEPCTL_EPACT | DEPCTL_EPEN;
523     }
524 }
525 
526 /*!
527     \brief      active remote wakeup signaling
528     \param[in]  udev: pointer to USB device
529     \param[out] none
530     \retval     none
531 */
usb_rwkup_active(usb_core_driver * udev)532 void usb_rwkup_active (usb_core_driver *udev)
533 {
534     if (udev->dev.pm.dev_remote_wakeup)  {
535         if (udev->regs.dr->DSTAT & DSTAT_SPST) {
536             if (udev->bp.low_power) {
537                 /* ungate USB core clock */
538                 *udev->regs.PWRCLKCTL &= ~(PWRCLKCTL_SHCLK | PWRCLKCTL_SUCLK);
539             }
540 
541             /* active remote wakeup signaling */
542             udev->regs.dr->DCTL |= DCTL_RWKUP;
543 
544             usb_mdelay(5U);
545 
546             udev->regs.dr->DCTL &= ~DCTL_RWKUP;
547         }
548     }
549 }
550 
551 /*!
552     \brief      active USB core clock
553     \param[in]  udev: pointer to USB device
554     \param[out] none
555     \retval     none
556 */
usb_clock_active(usb_core_driver * udev)557 void usb_clock_active (usb_core_driver *udev)
558 {
559     if (udev->bp.low_power) {
560         if (udev->regs.dr->DSTAT & DSTAT_SPST) {
561             /* un-gate USB Core clock */
562             *udev->regs.PWRCLKCTL &= ~(PWRCLKCTL_SHCLK | PWRCLKCTL_SUCLK);
563         }
564     }
565 }
566 
567 /*!
568     \brief      USB device suspend
569     \param[in]  udev: pointer to USB device
570     \param[out] none
571     \retval     none
572 */
usb_dev_suspend(usb_core_driver * udev)573 void usb_dev_suspend (usb_core_driver *udev)
574 {
575     __IO uint32_t devstat = udev->regs.dr->DSTAT;
576 
577     if ((udev->bp.low_power) && (devstat & DSTAT_SPST)) {
578         /* switch-off the USB clocks */
579         *udev->regs.PWRCLKCTL |= PWRCLKCTL_SHCLK;
580 
581         /* enter DEEP_SLEEP mode with LDO in low power mode */
582         pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, WFI_CMD);
583     }
584 }
585 
586 /*!
587     \brief      stop the device and clean up FIFOs
588     \param[in]  udev: pointer to USB device
589     \param[out] none
590     \retval     none
591 */
usb_dev_stop(usb_core_driver * udev)592 void usb_dev_stop (usb_core_driver *udev)
593 {
594     uint32_t i;
595 
596     udev->dev.cur_status = 1U;
597 
598     /* clear all interrupt flag and enable bits */
599     for (i = 0U; i < udev->bp.num_ep; i++) {
600         udev->regs.er_in[i]->DIEPINTF = 0xFFU;
601         udev->regs.er_out[i]->DOEPINTF = 0xFFU;
602     }
603 
604     udev->regs.dr->DIEPINTEN = 0U;
605     udev->regs.dr->DOEPINTEN = 0U;
606     udev->regs.dr->DAEPINTEN = 0U;
607     udev->regs.dr->DAEPINT = 0xFFFFFFFFU;
608 
609     /* flush the FIFO */
610     (void)usb_rxfifo_flush (&udev->regs);
611     (void)usb_txfifo_flush (&udev->regs, 0x10U);
612 }
613