@@ -29,32 +29,14 @@ enum dwc2_drv_event_type {
2929 DWC2_DRV_EVT_XFER ,
3030 /* Setup packet received */
3131 DWC2_DRV_EVT_SETUP ,
32- /* OUT transaction for specific endpoint is finished */
33- DWC2_DRV_EVT_DOUT ,
34- /* IN transaction for specific endpoint is finished */
35- DWC2_DRV_EVT_DIN ,
36- /* Core should exit hibernation */
37- DWC2_DRV_EVT_HIBERNATION_EXIT ,
32+ /* Transaction on endpoint is finished */
33+ DWC2_DRV_EVT_EP_FINISHED ,
34+ /* Core should exit hibernation due to bus reset */
35+ DWC2_DRV_EVT_HIBERNATION_EXIT_BUS_RESET ,
36+ /* Core should exit hibernation due to host resume */
37+ DWC2_DRV_EVT_HIBERNATION_EXIT_HOST_RESUME ,
3838};
3939
40- enum dwc2_hibernation_exit_reason {
41- DWC2_HIBERNATION_EXIT_BUS_RESET ,
42- DWC2_HIBERNATION_EXIT_HOST_WAKEUP ,
43- };
44-
45- struct dwc2_drv_event {
46- const struct device * dev ;
47- enum dwc2_drv_event_type type ;
48- union {
49- uint8_t ep ;
50- enum dwc2_hibernation_exit_reason exit_reason ;
51- };
52- };
53-
54- K_MSGQ_DEFINE (drv_msgq , sizeof (struct dwc2_drv_event ),
55- CONFIG_UDC_DWC2_MAX_QMESSAGES , sizeof (void * ));
56-
57-
5840/* Minimum RX FIFO size in 32-bit words considering the largest used OUT packet
5941 * of 512 bytes. The value must be adjusted according to the number of OUT
6042 * endpoints.
@@ -111,6 +93,12 @@ struct dwc2_reg_backup {
11193/* Driver private data per instance */
11294struct udc_dwc2_data {
11395 struct k_thread thread_data ;
96+ /* Main events the driver thread waits for */
97+ struct k_event drv_evt ;
98+ /* Transfer triggers (OUT on bits 0-15, IN on bits 16-31) */
99+ struct k_event xfer_new ;
100+ /* Finished transactions (OUT on bits 0-15, IN on bits 16-31) */
101+ struct k_event xfer_finished ;
114102 struct dwc2_reg_backup backup ;
115103 uint32_t ghwcfg1 ;
116104 uint32_t txf_set ;
@@ -1502,12 +1490,9 @@ static int udc_dwc2_ep_set_halt(const struct device *dev,
15021490static int udc_dwc2_ep_clear_halt (const struct device * dev ,
15031491 struct udc_ep_config * const cfg )
15041492{
1493+ struct udc_dwc2_data * const priv = udc_get_private (dev );
15051494 mem_addr_t dxepctl_reg = dwc2_get_dxepctl_reg (dev , cfg -> addr );
15061495 uint32_t dxepctl ;
1507- struct dwc2_drv_event evt = {
1508- .ep = cfg -> addr ,
1509- .type = DWC2_DRV_EVT_XFER ,
1510- };
15111496
15121497 dxepctl = sys_read32 (dxepctl_reg );
15131498 dxepctl &= ~USB_DWC2_DEPCTL_STALL ;
@@ -1519,7 +1504,16 @@ static int udc_dwc2_ep_clear_halt(const struct device *dev,
15191504
15201505 /* Resume queued transfers if any */
15211506 if (udc_buf_peek (dev , cfg -> addr )) {
1522- k_msgq_put (& drv_msgq , & evt , K_NO_WAIT );
1507+ uint32_t ep_bit ;
1508+
1509+ if (USB_EP_DIR_IS_IN (cfg -> addr )) {
1510+ ep_bit = BIT (16 + USB_EP_GET_IDX (cfg -> addr ));
1511+ } else {
1512+ ep_bit = BIT (USB_EP_GET_IDX (cfg -> addr ));
1513+ }
1514+
1515+ k_event_post (& priv -> xfer_new , ep_bit );
1516+ k_event_post (& priv -> drv_evt , BIT (DWC2_DRV_EVT_XFER ));
15231517 }
15241518
15251519 return 0 ;
@@ -1529,16 +1523,22 @@ static int udc_dwc2_ep_enqueue(const struct device *dev,
15291523 struct udc_ep_config * const cfg ,
15301524 struct net_buf * const buf )
15311525{
1532- struct dwc2_drv_event evt = {
1533- .ep = cfg -> addr ,
1534- .type = DWC2_DRV_EVT_XFER ,
1535- };
1526+ struct udc_dwc2_data * const priv = udc_get_private (dev );
15361527
15371528 LOG_DBG ("%p enqueue %x %p" , dev , cfg -> addr , buf );
15381529 udc_buf_put (cfg , buf );
15391530
15401531 if (!cfg -> stat .halted ) {
1541- k_msgq_put (& drv_msgq , & evt , K_NO_WAIT );
1532+ uint32_t ep_bit ;
1533+
1534+ if (USB_EP_DIR_IS_IN (cfg -> addr )) {
1535+ ep_bit = BIT (16 + USB_EP_GET_IDX (cfg -> addr ));
1536+ } else {
1537+ ep_bit = BIT (USB_EP_GET_IDX (cfg -> addr ));
1538+ }
1539+
1540+ k_event_post (& priv -> xfer_new , ep_bit );
1541+ k_event_post (& priv -> drv_evt , BIT (DWC2_DRV_EVT_XFER ));
15421542 }
15431543
15441544 return 0 ;
@@ -2016,6 +2016,7 @@ static int udc_dwc2_shutdown(const struct device *dev)
20162016static int dwc2_driver_preinit (const struct device * dev )
20172017{
20182018 const struct udc_dwc2_config * config = dev -> config ;
2019+ struct udc_dwc2_data * const priv = udc_get_private (dev );
20192020 struct udc_data * data = dev -> data ;
20202021 uint16_t mps = 1023 ;
20212022 uint32_t numdeveps ;
@@ -2024,6 +2025,10 @@ static int dwc2_driver_preinit(const struct device *dev)
20242025
20252026 k_mutex_init (& data -> mutex );
20262027
2028+ k_event_init (& priv -> drv_evt );
2029+ k_event_init (& priv -> xfer_new );
2030+ k_event_init (& priv -> xfer_finished );
2031+
20272032 data -> caps .addr_before_status = true;
20282033 data -> caps .mps0 = UDC_MPS0_64 ;
20292034
@@ -2264,7 +2269,6 @@ static inline void dwc2_handle_in_xfercompl(const struct device *dev,
22642269{
22652270 struct udc_dwc2_data * const priv = udc_get_private (dev );
22662271 struct udc_ep_config * ep_cfg ;
2267- struct dwc2_drv_event evt ;
22682272 struct net_buf * buf ;
22692273
22702274 ep_cfg = udc_get_ep_cfg (dev , ep_idx | USB_EP_DIR_IN );
@@ -2279,10 +2283,8 @@ static inline void dwc2_handle_in_xfercompl(const struct device *dev,
22792283 return ;
22802284 }
22812285
2282- evt .dev = dev ;
2283- evt .ep = ep_cfg -> addr ;
2284- evt .type = DWC2_DRV_EVT_DIN ;
2285- k_msgq_put (& drv_msgq , & evt , K_NO_WAIT );
2286+ k_event_post (& priv -> xfer_finished , BIT (16 + ep_idx ));
2287+ k_event_post (& priv -> drv_evt , BIT (DWC2_DRV_EVT_EP_FINISHED ));
22862288}
22872289
22882290static inline void dwc2_handle_iepint (const struct device * dev )
@@ -2326,7 +2328,6 @@ static inline void dwc2_handle_out_xfercompl(const struct device *dev,
23262328 struct udc_ep_config * ep_cfg = udc_get_ep_cfg (dev , ep_idx );
23272329 struct udc_dwc2_data * const priv = udc_get_private (dev );
23282330 struct usb_dwc2_reg * const base = dwc2_get_base (dev );
2329- struct dwc2_drv_event evt ;
23302331 uint32_t bcnt ;
23312332 struct net_buf * buf ;
23322333 uint32_t doeptsiz ;
@@ -2341,9 +2342,6 @@ static inline void dwc2_handle_out_xfercompl(const struct device *dev,
23412342 return ;
23422343 }
23432344
2344- evt .type = DWC2_DRV_EVT_DOUT ;
2345- evt .ep = ep_cfg -> addr ;
2346-
23472345 /* The original transfer size value is necessary here because controller
23482346 * decreases the value for every byte stored.
23492347 */
@@ -2391,7 +2389,8 @@ static inline void dwc2_handle_out_xfercompl(const struct device *dev,
23912389 net_buf_tailroom (buf )) {
23922390 dwc2_prep_rx (dev , buf , ep_cfg );
23932391 } else {
2394- k_msgq_put (& drv_msgq , & evt , K_NO_WAIT );
2392+ k_event_post (& priv -> xfer_finished , BIT (ep_idx ));
2393+ k_event_post (& priv -> drv_evt , BIT (DWC2_DRV_EVT_EP_FINISHED ));
23952394 }
23962395}
23972396
@@ -2443,12 +2442,7 @@ static inline void dwc2_handle_oepint(const struct device *dev)
24432442 }
24442443
24452444 if (status & USB_DWC2_DOEPINT_SETUP ) {
2446- struct dwc2_drv_event evt = {
2447- .type = DWC2_DRV_EVT_SETUP ,
2448- .ep = USB_CONTROL_EP_OUT ,
2449- };
2450-
2451- k_msgq_put (& drv_msgq , & evt , K_NO_WAIT );
2445+ k_event_post (& priv -> drv_evt , BIT (DWC2_DRV_EVT_SETUP ));
24522446 }
24532447
24542448 if (status & USB_DWC2_DOEPINT_STSPHSERCVD ) {
@@ -2583,30 +2577,24 @@ static void udc_dwc2_isr_handler(const struct device *dev)
25832577 if (priv -> hibernated ) {
25842578 uint32_t gpwrdn = sys_read32 ((mem_addr_t )& base -> gpwrdn );
25852579 bool reset , resume = false;
2586- enum dwc2_hibernation_exit_reason exit_reason ;
25872580
25882581 /* Clear interrupts */
25892582 sys_write32 (gpwrdn , (mem_addr_t )& base -> gpwrdn );
25902583
25912584 if (gpwrdn & USB_DWC2_GPWRDN_LNSTSCHNG ) {
25922585 resume = usb_dwc2_get_gpwrdn_linestate (gpwrdn ) ==
25932586 USB_DWC2_GPWRDN_LINESTATE_DM1DP0 ;
2594- exit_reason = DWC2_HIBERNATION_EXIT_HOST_WAKEUP ;
25952587 }
25962588
25972589 reset = gpwrdn & USB_DWC2_GPWRDN_RESETDETECTED ;
2598- if (reset ) {
2599- exit_reason = DWC2_HIBERNATION_EXIT_BUS_RESET ;
2600- }
26012590
2602- if (reset || resume ) {
2603- struct dwc2_drv_event evt = {
2604- .dev = dev ,
2605- .type = DWC2_DRV_EVT_HIBERNATION_EXIT ,
2606- .exit_reason = exit_reason ,
2607- };
2591+ if (resume ) {
2592+ k_event_post (& priv -> drv_evt ,
2593+ BIT (DWC2_DRV_EVT_HIBERNATION_EXIT_HOST_RESUME ));
2594+ }
26082595
2609- k_msgq_put (& drv_msgq , & evt , K_NO_WAIT );
2596+ if (reset ) {
2597+ k_event_post (& priv -> drv_evt , BIT (DWC2_DRV_EVT_HIBERNATION_EXIT_BUS_RESET ));
26102598 }
26112599
26122600 (void )dwc2_quirk_irq_clear (dev );
@@ -2700,60 +2688,111 @@ static void udc_dwc2_isr_handler(const struct device *dev)
27002688 (void )dwc2_quirk_irq_clear (dev );
27012689}
27022690
2691+ static uint8_t pull_next_ep_from_bitmap (uint32_t * bitmap )
2692+ {
2693+ unsigned int bit ;
2694+
2695+ __ASSERT_NO_MSG (bitmap && * bitmap );
2696+
2697+ bit = find_lsb_set (* bitmap ) - 1 ;
2698+ * bitmap &= ~BIT (bit );
2699+
2700+ if (bit >= 16 ) {
2701+ return USB_EP_DIR_IN | (bit - 16 );
2702+ } else {
2703+ return USB_EP_DIR_OUT | bit ;
2704+ }
2705+ }
2706+
27032707static ALWAYS_INLINE void dwc2_thread_handler (void * const arg )
27042708{
27052709 const struct device * dev = (const struct device * )arg ;
27062710 struct udc_dwc2_data * const priv = udc_get_private (dev );
27072711 const struct udc_dwc2_config * const config = dev -> config ;
27082712 struct udc_ep_config * ep_cfg ;
2709- struct dwc2_drv_event evt ;
2713+ const uint32_t hibernation_exit_events = (BIT (DWC2_DRV_EVT_HIBERNATION_EXIT_BUS_RESET ) |
2714+ BIT (DWC2_DRV_EVT_HIBERNATION_EXIT_HOST_RESUME ));
2715+ uint32_t prev ;
2716+ uint32_t evt ;
2717+ uint32_t eps ;
2718+ uint8_t ep ;
27102719
27112720 /* This is the bottom-half of the ISR handler and the place where
27122721 * a new transfer can be fed.
27132722 */
2714- k_msgq_get (& drv_msgq , & evt , K_FOREVER );
2715- ep_cfg = udc_get_ep_cfg (dev , evt .ep );
2723+ evt = k_event_wait (& priv -> drv_evt , UINT32_MAX , false, K_FOREVER );
2724+
2725+ if (evt & BIT (DWC2_DRV_EVT_XFER )) {
2726+ k_event_clear (& priv -> drv_evt , BIT (DWC2_DRV_EVT_XFER ));
2727+
2728+ LOG_DBG ("New transfer(s) in the queue" );
2729+ eps = k_event_test (& priv -> xfer_new , UINT32_MAX );
2730+ k_event_clear (& priv -> xfer_new , eps );
2731+
2732+ while (eps ) {
2733+ ep = pull_next_ep_from_bitmap (& eps );
2734+ ep_cfg = udc_get_ep_cfg (dev , ep );
2735+
2736+ if (!udc_ep_is_busy (dev , ep_cfg -> addr )) {
2737+ dwc2_handle_xfer_next (dev , ep_cfg );
2738+ } else {
2739+ LOG_DBG ("ep 0x%02x busy" , ep_cfg -> addr );
2740+ }
2741+ }
2742+ }
2743+
2744+ if (evt & BIT (DWC2_DRV_EVT_EP_FINISHED )) {
2745+ k_event_clear (& priv -> drv_evt , BIT (DWC2_DRV_EVT_EP_FINISHED ));
2746+
2747+ eps = k_event_test (& priv -> xfer_finished , UINT32_MAX );
2748+ k_event_clear (& priv -> xfer_finished , eps );
2749+
2750+ while (eps ) {
2751+ ep = pull_next_ep_from_bitmap (& eps );
2752+ ep_cfg = udc_get_ep_cfg (dev , ep );
2753+
2754+ if (USB_EP_DIR_IS_IN (ep )) {
2755+ LOG_DBG ("DIN event ep 0x%02x" , ep );
2756+ dwc2_handle_evt_din (dev , ep_cfg );
2757+ } else {
2758+ LOG_DBG ("DOUT event ep 0x%02x" , ep_cfg -> addr );
2759+ dwc2_handle_evt_dout (dev , ep_cfg );
2760+ }
2761+
2762+ if (!udc_ep_is_busy (dev , ep_cfg -> addr )) {
2763+ dwc2_handle_xfer_next (dev , ep_cfg );
2764+ } else {
2765+ LOG_DBG ("ep 0x%02x busy" , ep_cfg -> addr );
2766+ }
2767+ }
2768+ }
2769+
2770+ if (evt & BIT (DWC2_DRV_EVT_SETUP )) {
2771+ k_event_clear (& priv -> drv_evt , BIT (DWC2_DRV_EVT_SETUP ));
27162772
2717- switch (evt .type ) {
2718- case DWC2_DRV_EVT_XFER :
2719- LOG_DBG ("New transfer in the queue" );
2720- break ;
2721- case DWC2_DRV_EVT_SETUP :
27222773 LOG_DBG ("SETUP event" );
27232774 dwc2_handle_evt_setup (dev );
2724- break ;
2725- case DWC2_DRV_EVT_DOUT :
2726- LOG_DBG ("DOUT event ep 0x%02x" , ep_cfg -> addr );
2727- dwc2_handle_evt_dout (dev , ep_cfg );
2728- break ;
2729- case DWC2_DRV_EVT_DIN :
2730- LOG_DBG ("DIN event" );
2731- dwc2_handle_evt_din (dev , ep_cfg );
2732- break ;
2733- case DWC2_DRV_EVT_HIBERNATION_EXIT :
2775+ }
2776+
2777+ if (evt & hibernation_exit_events ) {
27342778 LOG_DBG ("Hibernation exit event" );
27352779 config -> irq_disable_func (dev );
27362780
2781+ prev = k_event_clear (& priv -> drv_evt , hibernation_exit_events );
2782+
27372783 if (priv -> hibernated ) {
27382784 dwc2_exit_hibernation (dev );
27392785
27402786 /* Let stack know we are no longer suspended */
27412787 udc_set_suspended (dev , false);
27422788 udc_submit_event (dev , UDC_EVT_RESUME , 0 );
27432789
2744- if (evt . exit_reason == DWC2_HIBERNATION_EXIT_BUS_RESET ) {
2790+ if (prev & BIT ( DWC2_DRV_EVT_HIBERNATION_EXIT_BUS_RESET ) ) {
27452791 dwc2_on_bus_reset (dev );
27462792 }
27472793 }
27482794
27492795 config -> irq_enable_func (dev );
2750- break ;
2751- }
2752-
2753- if (ep_cfg -> addr != USB_CONTROL_EP_OUT && !udc_ep_is_busy (dev , ep_cfg -> addr )) {
2754- dwc2_handle_xfer_next (dev , ep_cfg );
2755- } else {
2756- LOG_DBG ("ep 0x%02x busy" , ep_cfg -> addr );
27572796 }
27582797}
27592798
0 commit comments