diff --git a/drivers/usb/udc/Kconfig b/drivers/usb/udc/Kconfig index b6c49e6b3e7a6..b2c646343156d 100644 --- a/drivers/usb/udc/Kconfig +++ b/drivers/usb/udc/Kconfig @@ -42,6 +42,12 @@ config UDC_BUF_FORCE_NOCACHE Place the buffer pools in the nocache memory region if the driver cannot handle buffers in cached memory. +config UDC_ENABLE_SOF + bool "SOF interrupt processing" + help + Enabled SoF interrupts can cause a very high CPU load on high-speed + controllers because the interrupt rate would be 125 µs. + config UDC_WORKQUEUE bool "Use a dedicate work queue for UDC drivers" help diff --git a/drivers/usb/udc/udc_ambiq.c b/drivers/usb/udc/udc_ambiq.c index 6e5f2603edd5c..9b2fdc0addbd6 100644 --- a/drivers/usb/udc/udc_ambiq.c +++ b/drivers/usb/udc/udc_ambiq.c @@ -156,8 +156,9 @@ static void udc_ambiq_evt_callback(const struct device *dev, am_hal_usb_dev_even case AM_HAL_USB_DEV_EVT_BUS_RESET: /* enable usb bus interrupts */ am_hal_usb_intr_usb_enable(priv->usb_handle, - USB_CFG2_SOFE_Msk | USB_CFG2_ResumeE_Msk | - USB_CFG2_SuspendE_Msk | USB_CFG2_ResetE_Msk); + IF_ENABLED(CONFIG_UDC_ENABLE_SOF, (USB_CFG2_SOFE_Msk |)) + USB_CFG2_ResumeE_Msk | + USB_CFG2_SuspendE_Msk | USB_CFG2_ResetE_Msk); /* init the endpoint */ am_hal_usb_ep_init(priv->usb_handle, 0, 0, EP0_MPS); /* Set USB device speed to HAL */ @@ -174,7 +175,7 @@ static void udc_ambiq_evt_callback(const struct device *dev, am_hal_usb_dev_even udc_submit_event(dev, UDC_EVT_RESUME, 0); break; case AM_HAL_USB_DEV_EVT_SOF: - udc_submit_event(dev, UDC_EVT_SOF, 0); + udc_submit_sof_event(dev); break; case AM_HAL_USB_DEV_EVT_SUSPEND: /* Handle USB Suspend event, then set device state to suspended */ diff --git a/drivers/usb/udc/udc_common.h b/drivers/usb/udc/udc_common.h index 8cad6b6dd1c5f..ed6712e95ae89 100644 --- a/drivers/usb/udc/udc_common.h +++ b/drivers/usb/udc/udc_common.h @@ -156,6 +156,29 @@ int udc_submit_event(const struct device *dev, int udc_submit_ep_event(const struct device *dev, struct net_buf *const buf, const int err); + +/** + * @brief Helper function to send UDC SOF event to a higher level. + * + * Type of this event is hardcoded to UDC_EVT_SOF. + * + * @param[in] dev Pointer to device struct of the driver instance + */ +#if defined(CONFIG_UDC_ENABLE_SOF) +static inline void udc_submit_sof_event(const struct device *dev) +{ + struct udc_data *data = dev->data; + struct udc_event drv_evt = { + .type = UDC_EVT_SOF, + .dev = dev, + }; + + (void)data->event_cb(dev, &drv_evt); +} +#else +#define udc_submit_sof_event(dev) ARG_UNUSED(dev) +#endif + /** * @brief Helper function to enable endpoint. * diff --git a/drivers/usb/udc/udc_dwc2.c b/drivers/usb/udc/udc_dwc2.c index 9b57436bc4b6a..d641d3cbb4410 100644 --- a/drivers/usb/udc/udc_dwc2.c +++ b/drivers/usb/udc/udc_dwc2.c @@ -2162,11 +2162,12 @@ static int udc_dwc2_init_controller(const struct device *dev) } /* Unmask interrupts */ - sys_write32(USB_DWC2_GINTSTS_OEPINT | USB_DWC2_GINTSTS_IEPINT | + sys_write32(IF_ENABLED(CONFIG_UDC_ENABLE_SOF, (USB_DWC2_GINTSTS_SOF | + USB_DWC2_GINTSTS_INCOMPISOOUT | + USB_DWC2_GINTSTS_INCOMPISOIN |)) + USB_DWC2_GINTSTS_OEPINT | USB_DWC2_GINTSTS_IEPINT | USB_DWC2_GINTSTS_ENUMDONE | USB_DWC2_GINTSTS_USBRST | - USB_DWC2_GINTSTS_WKUPINT | USB_DWC2_GINTSTS_USBSUSP | - USB_DWC2_GINTSTS_INCOMPISOOUT | USB_DWC2_GINTSTS_INCOMPISOIN | - USB_DWC2_GINTSTS_SOF, + USB_DWC2_GINTSTS_WKUPINT | USB_DWC2_GINTSTS_USBSUSP, (mem_addr_t)&base->gintmsk); return 0; @@ -2890,7 +2891,8 @@ static void udc_dwc2_isr_handler(const struct device *dev) LOG_DBG("GINTSTS 0x%x", int_status); - if (int_status & USB_DWC2_GINTSTS_SOF) { + if (IS_ENABLED(CONFIG_UDC_ENABLE_SOF) && + int_status & USB_DWC2_GINTSTS_SOF) { uint32_t dsts; /* Clear USB SOF interrupt. */ @@ -2898,7 +2900,7 @@ static void udc_dwc2_isr_handler(const struct device *dev) dsts = sys_read32((mem_addr_t)&base->dsts); priv->sof_num = usb_dwc2_get_dsts_soffn(dsts); - udc_submit_event(dev, UDC_EVT_SOF, 0); + udc_submit_sof_event(dev); } if (int_status & USB_DWC2_GINTSTS_USBRST) { @@ -2941,11 +2943,13 @@ static void udc_dwc2_isr_handler(const struct device *dev) dwc2_handle_oepint(dev); } - if (int_status & USB_DWC2_GINTSTS_INCOMPISOIN) { + if (IS_ENABLED(CONFIG_UDC_ENABLE_SOF) && + int_status & USB_DWC2_GINTSTS_INCOMPISOIN) { dwc2_handle_incompisoin(dev); } - if (int_status & USB_DWC2_GINTSTS_INCOMPISOOUT) { + if (IS_ENABLED(CONFIG_UDC_ENABLE_SOF) && + int_status & USB_DWC2_GINTSTS_INCOMPISOOUT) { dwc2_handle_incompisoout(dev); } diff --git a/drivers/usb/udc/udc_it82xx2.c b/drivers/usb/udc/udc_it82xx2.c index 85ec9431c6352..6b41cb162d49c 100644 --- a/drivers/usb/udc/udc_it82xx2.c +++ b/drivers/usb/udc/udc_it82xx2.c @@ -17,9 +17,6 @@ LOG_MODULE_REGISTER(udc_it82xx2, CONFIG_UDC_DRIVER_LOG_LEVEL); #define DT_DRV_COMPAT ite_it82xx2_usb -/* TODO: Replace this definition by Kconfig option */ -#define USB_DEVICE_CONFIG_SOF_NOTIFICATIONS (0U) - #define IT8XXX2_IS_EXTEND_ENDPOINT(n) (USB_EP_GET_IDX(n) >= 4) #define IT82xx2_STATE_OUT_SHARED_FIFO_BUSY 0 @@ -1357,11 +1354,11 @@ static void it82xx2_usb_dc_isr(const void *arg) /* sof received */ if (status & DC_SOF_RECEIVED) { - if (!USB_DEVICE_CONFIG_SOF_NOTIFICATIONS) { + if (!IS_ENABLED(CONFIG_UDC_ENABLE_SOF)) { it82xx2_enable_sof_int(dev, false); } else { usb_regs->dc_interrupt_status = DC_SOF_RECEIVED; - udc_submit_event(dev, UDC_EVT_SOF, 0); + udc_submit_sof_event(dev); } it82xx2_enable_resume_int(dev, false); emit_resume_event(dev); @@ -1411,7 +1408,7 @@ static void suspended_handler(struct k_work *item) it82xx2_enable_resume_int(dev, true); - if (!USB_DEVICE_CONFIG_SOF_NOTIFICATIONS) { + if (!IS_ENABLED(CONFIG_UDC_ENABLE_SOF)) { it82xx2_enable_sof_int(dev, true); } diff --git a/drivers/usb/udc/udc_kinetis.c b/drivers/usb/udc/udc_kinetis.c index 8858ee129c4f9..7d22730160396 100644 --- a/drivers/usb/udc/udc_kinetis.c +++ b/drivers/usb/udc/udc_kinetis.c @@ -653,7 +653,7 @@ static void usbfsotg_isr_handler(const struct device *dev) } if (istatus == USB_ISTAT_SOFTOK_MASK) { - udc_submit_event(dev, UDC_EVT_SOF, 0); + udc_submit_sof_event(dev); } if (istatus == USB_ISTAT_ERROR_MASK) { @@ -1016,7 +1016,7 @@ static int usbfsotg_init(const struct device *dev) base->INTEN = (USB_INTEN_SLEEPEN_MASK | USB_INTEN_STALLEN_MASK | USB_INTEN_TOKDNEEN_MASK | - USB_INTEN_SOFTOKEN_MASK | + IF_ENABLED(CONFIG_UDC_ENABLE_SOF, (USB_INTEN_SOFTOKEN_MASK |)) USB_INTEN_ERROREN_MASK | USB_INTEN_USBRSTEN_MASK); diff --git a/drivers/usb/udc/udc_max32.c b/drivers/usb/udc/udc_max32.c index 1e09f5ef7c6dd..526a49b8ba917 100644 --- a/drivers/usb/udc/udc_max32.c +++ b/drivers/usb/udc/udc_max32.c @@ -533,7 +533,7 @@ static int udc_max32_event_callback(maxusb_event_t event, void *cbdata) case MAXUSB_EVENT_DPACT: LOG_DBG("DPACT event occurred"); udc_set_suspended(dev, false); - udc_submit_event(dev, UDC_EVT_SOF, 0); + udc_submit_sof_event(dev); break; case MAXUSB_EVENT_BRST: LOG_DBG("BRST event occurred"); diff --git a/drivers/usb/udc/udc_mcux_ehci.c b/drivers/usb/udc/udc_mcux_ehci.c index fc95f7a91d7eb..041f9b759b199 100644 --- a/drivers/usb/udc/udc_mcux_ehci.c +++ b/drivers/usb/udc/udc_mcux_ehci.c @@ -531,7 +531,7 @@ usb_status_t USB_DeviceNotificationTrigger(void *handle, void *msg) udc_submit_event(dev, UDC_EVT_VBUS_READY, 0); break; case kUSB_DeviceNotifySOF: - udc_submit_event(dev, UDC_EVT_SOF, 0); + udc_submit_sof_event(dev); break; default: udc_mcux_event_submit(dev, mcux_msg); diff --git a/drivers/usb/udc/udc_mcux_ip3511.c b/drivers/usb/udc/udc_mcux_ip3511.c index 312acae17845b..c6aab0d0bb1b1 100644 --- a/drivers/usb/udc/udc_mcux_ip3511.c +++ b/drivers/usb/udc/udc_mcux_ip3511.c @@ -531,7 +531,7 @@ usb_status_t USB_DeviceNotificationTrigger(void *handle, void *msg) udc_submit_event(dev, UDC_EVT_VBUS_READY, 0); break; case kUSB_DeviceNotifySOF: - udc_submit_event(dev, UDC_EVT_SOF, 0); + udc_submit_sof_event(dev); break; default: udc_mcux_event_submit(dev, mcux_msg); diff --git a/drivers/usb/udc/udc_nrf.c b/drivers/usb/udc/udc_nrf.c index 71eebbd70d3e5..7b18862fa5966 100644 --- a/drivers/usb/udc/udc_nrf.c +++ b/drivers/usb/udc/udc_nrf.c @@ -436,7 +436,7 @@ static void ev_sof_handler(void) m_ep_armed &= ~USBD_EPISO_BIT_MASK; - udc_submit_event(udc_nrf_dev, UDC_EVT_SOF, 0); + udc_submit_sof_event(udc_nrf_dev); } static void usbd_in_packet_sent(uint8_t ep) @@ -1547,7 +1547,7 @@ static void udc_nrf_power_handler(nrfx_power_usb_evt_t pwr_evt) break; case NRFX_POWER_USB_EVT_READY: LOG_DBG("POWER event ready"); - nrf_usbd_legacy_start(true); + nrf_usbd_legacy_start(IS_ENABLED(CONFIG_UDC_ENABLE_SOF)); break; case NRFX_POWER_USB_EVT_REMOVED: LOG_DBG("POWER event removed"); diff --git a/drivers/usb/udc/udc_numaker.c b/drivers/usb/udc/udc_numaker.c index bbc016ecf7062..43630010caa28 100644 --- a/drivers/usb/udc/udc_numaker.c +++ b/drivers/usb/udc/udc_numaker.c @@ -171,7 +171,9 @@ static inline void numaker_usbd_sw_connect(const struct device *dev) base->INTSTS = base->INTSTS; /* Enable relevant interrupts */ - base->INTEN = USBD_INT_BUS | USBD_INT_USB | USBD_INT_FLDET | USBD_INT_WAKEUP | USBD_INT_SOF; + base->INTEN = USBD_INT_BUS | USBD_INT_USB | USBD_INT_FLDET | + IF_ENABLED(CONFIG_UDC_ENABLE_SOF, (USBD_INT_SOF |)) + USBD_INT_WAKEUP; /* Clear SE0 for connect */ base->SE0 &= ~USBD_DRVSE0; @@ -1298,7 +1300,7 @@ static void numaker_udbd_isr(const struct device *dev) base->INTSTS = USBD_INTSTS_SOFIF_Msk; /* UDC stack would handle bottom-half processing */ - udc_submit_event(dev, UDC_EVT_SOF, 0); + udc_submit_sof_event(dev); } /* USB Setup/EP */ diff --git a/drivers/usb/udc/udc_renesas_ra.c b/drivers/usb/udc/udc_renesas_ra.c index fa98fda46ace4..4a3123ec2b9c8 100644 --- a/drivers/usb/udc/udc_renesas_ra.c +++ b/drivers/usb/udc/udc_renesas_ra.c @@ -79,7 +79,7 @@ static void udc_renesas_ra_event_handler(usbd_callback_arg_t *p_args) break; case USBD_EVENT_SOF: - udc_submit_event(dev, UDC_EVT_SOF, 0); + udc_submit_sof_event(dev); break; default: diff --git a/drivers/usb/udc/udc_rpi_pico.c b/drivers/usb/udc/udc_rpi_pico.c index 31561f6fce6b2..70ebf047399dc 100644 --- a/drivers/usb/udc/udc_rpi_pico.c +++ b/drivers/usb/udc/udc_rpi_pico.c @@ -678,7 +678,7 @@ static void rpi_pico_isr_handler(const struct device *dev) if (status & USB_INTS_DEV_SOF_BITS) { handled |= USB_INTS_DEV_SOF_BITS; - sys_read32((mm_reg_t)&base->sof_rd); + udc_submit_sof_event(dev); } if (status & USB_INTS_DEV_CONN_DIS_BITS) { @@ -1048,7 +1048,7 @@ static int udc_rpi_pico_enable(const struct device *dev) sys_write32(USB_SIE_CTRL_EP0_INT_1BUF_BITS, (mm_reg_t)&base->sie_ctrl); /* Enable interrupts */ - sys_write32(USB_INTE_DEV_SOF_BITS | + sys_write32(IF_ENABLED(CONFIG_UDC_ENABLE_SOF, (USB_INTE_DEV_SOF_BITS |)) USB_INTE_SETUP_REQ_BITS | USB_INTE_DEV_RESUME_FROM_HOST_BITS | USB_INTE_DEV_SUSPEND_BITS | diff --git a/drivers/usb/udc/udc_sam0.c b/drivers/usb/udc/udc_sam0.c index dab462a03fafc..e351c98e284bc 100644 --- a/drivers/usb/udc/udc_sam0.c +++ b/drivers/usb/udc/udc_sam0.c @@ -693,7 +693,7 @@ static void sam0_isr_handler(const struct device *dev) base->INTFLAG.reg = intflag; if (intflag & USB_DEVICE_INTFLAG_SOF) { - udc_submit_event(dev, UDC_EVT_SOF, 0); + udc_submit_sof_event(dev); } if (intflag & USB_DEVICE_INTFLAG_EORST) { diff --git a/drivers/usb/udc/udc_skeleton.c b/drivers/usb/udc/udc_skeleton.c index c808cc98ad85d..2c9be371dec29 100644 --- a/drivers/usb/udc/udc_skeleton.c +++ b/drivers/usb/udc/udc_skeleton.c @@ -233,6 +233,10 @@ static int udc_skeleton_init(const struct device *dev) return -EIO; } + if (IS_ENABLED(CONFIG_UDC_ENABLE_SOF)) { + LOG_INF("Enable SOF interrupt"); + } + return 0; } diff --git a/drivers/usb/udc/udc_stm32.c b/drivers/usb/udc/udc_stm32.c index 6cc8c4add1c7f..f773a1c641dbd 100644 --- a/drivers/usb/udc/udc_stm32.c +++ b/drivers/usb/udc/udc_stm32.c @@ -182,7 +182,7 @@ void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) { struct udc_stm32_data *priv = hpcd2data(hpcd); - udc_submit_event(priv->dev, UDC_EVT_SOF, 0); + udc_submit_sof_event(priv->dev); } static int usbd_ctrl_feed_dout(const struct device *dev, const size_t length) diff --git a/subsys/usb/device_next/class/Kconfig.uac2 b/subsys/usb/device_next/class/Kconfig.uac2 index ad6fb54b38a81..5c19e0542c3e3 100644 --- a/subsys/usb/device_next/class/Kconfig.uac2 +++ b/subsys/usb/device_next/class/Kconfig.uac2 @@ -4,6 +4,7 @@ config USBD_AUDIO2_CLASS bool "USB Audio 2 class support [EXPERIMENTAL]" + select UDC_ENABLE_SOF help USB Audio 2 device class support. diff --git a/tests/drivers/udc/prj.conf b/tests/drivers/udc/prj.conf index 380d5e74b9963..975887e579c19 100644 --- a/tests/drivers/udc/prj.conf +++ b/tests/drivers/udc/prj.conf @@ -5,6 +5,7 @@ CONFIG_LOG=y CONFIG_ZTEST=y CONFIG_UDC_DRIVER=y +CONFIG_UDC_ENABLE_SOF=y CONFIG_UDC_BUF_COUNT=16 CONFIG_UDC_BUF_POOL_SIZE=16384 CONFIG_UDC_DRIVER_LOG_LEVEL_INF=y diff --git a/tests/subsys/usb/device_next/prj.conf b/tests/subsys/usb/device_next/prj.conf index 54321edc95239..05fc7b0b02872 100644 --- a/tests/subsys/usb/device_next/prj.conf +++ b/tests/subsys/usb/device_next/prj.conf @@ -6,6 +6,7 @@ CONFIG_ZTEST=y CONFIG_USB_DEVICE_STACK_NEXT=y CONFIG_USBD_LOOPBACK_CLASS=y +CONFIG_UDC_ENABLE_SOF=y CONFIG_UHC_DRIVER=y CONFIG_USB_HOST_STACK=y