From 18fb3f9a329ade44495983206a5263f7aa2a84a4 Mon Sep 17 00:00:00 2001 From: Aleksander Strzebonski Date: Fri, 6 Sep 2024 17:23:04 +0200 Subject: [PATCH] usb: dwc2: Allow for enabling USB if the cable is disconnected Adds CONFIG_UDC_DWC2_USBHS_VBUS_READY_TIMEOUT_MS that allows for waiting for a USBHS VBUS ready event for a specified amount of time. Earlier it waited forever and because of that, the udc_enable() was blocked forever if the USB cable was disconnected. Now the function returns error on timeout. Signed-off-by: Aleksander Strzebonski --- drivers/usb/udc/Kconfig.dwc2 | 10 ++++++++++ drivers/usb/udc/udc_dwc2_vendor_quirks.h | 14 ++++++++++++-- include/zephyr/drivers/usb/udc.h | 1 + 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/drivers/usb/udc/Kconfig.dwc2 b/drivers/usb/udc/Kconfig.dwc2 index 4c023cfb04d85c..2f40c8f71a283d 100644 --- a/drivers/usb/udc/Kconfig.dwc2 +++ b/drivers/usb/udc/Kconfig.dwc2 @@ -38,3 +38,13 @@ config UDC_DWC2_THREAD_PRIORITY default 8 help DWC2 driver thread priority. + +config UDC_DWC2_USBHS_VBUS_READY_TIMEOUT + int "UDC DWC2 USBHS VBUS ready event timeout in ms" + depends on UDC_DWC2 + depends on NRFS_HAS_VBUS_DETECTOR_SERVICE + default 0 + help + UDC DWC2 USBHS VBUS ready event timeout. If the VBUS is not ready + and the Nordic USBHS controller is used, the udc_enable() is + blocked for this amount of time. Set it to zero to wait forever. diff --git a/drivers/usb/udc/udc_dwc2_vendor_quirks.h b/drivers/usb/udc/udc_dwc2_vendor_quirks.h index 84d912f9fdb668..d12d64ef848c07 100644 --- a/drivers/usb/udc/udc_dwc2_vendor_quirks.h +++ b/drivers/usb/udc/udc_dwc2_vendor_quirks.h @@ -121,7 +121,8 @@ DT_INST_FOREACH_STATUS_OKAY(QUIRK_STM32F4_FSOTG_DEFINE) * On USBHS, we cannot access the DWC2 register until VBUS is detected and * valid. If the user tries to force usbd_enable() and the corresponding * udc_enable() without a "VBUS ready" notification, the event wait will block - * until a valid VBUS signal is detected. + * until a valid VBUS signal is detected or until the + * CONFIG_UDC_DWC2_USBHS_VBUS_READY_TIMEOUT timeout expires. */ static K_EVENT_DEFINE(usbhs_events); #define USBHS_VBUS_READY BIT(0) @@ -182,10 +183,19 @@ static inline int usbhs_enable_nrfs_service(const struct device *dev) static inline int usbhs_enable_core(const struct device *dev) { NRF_USBHS_Type *wrapper = USBHS_DT_WRAPPER_REG_ADDR(0); + k_timeout_t timeout = K_FOREVER; + + #if CONFIG_NRFS_HAS_VBUS_DETECTOR_SERVICE + if (CONFIG_UDC_DWC2_USBHS_VBUS_READY_TIMEOUT) { + timeout = K_MSEC(CONFIG_UDC_DWC2_USBHS_VBUS_READY_TIMEOUT); + } + #endif if (!k_event_wait(&usbhs_events, USBHS_VBUS_READY, false, K_NO_WAIT)) { LOG_WRN("VBUS is not ready, block udc_enable()"); - k_event_wait(&usbhs_events, USBHS_VBUS_READY, false, K_FOREVER); + if (!k_event_wait(&usbhs_events, USBHS_VBUS_READY, false, timeout)) { + return -ETIMEDOUT; + } } wrapper->ENABLE = USBHS_ENABLE_PHY_Msk | USBHS_ENABLE_CORE_Msk; diff --git a/include/zephyr/drivers/usb/udc.h b/include/zephyr/drivers/usb/udc.h index 7910d8cfd8ff57..15b99cf525137d 100644 --- a/include/zephyr/drivers/usb/udc.h +++ b/include/zephyr/drivers/usb/udc.h @@ -371,6 +371,7 @@ int udc_init(const struct device *dev, * @return 0 on success, all other values should be treated as error. * @retval -EPERM controller is not initialized * @retval -EALREADY already enabled + * @retval -ETIMEDOUT enable operation timed out */ int udc_enable(const struct device *dev);