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