-
Notifications
You must be signed in to change notification settings - Fork 8.4k
drivers: usb: udc: stm32: move power configuration to common code #100519
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| add_subdirectory_ifdef(CONFIG_HAS_NRFX nrf_usbd_common) | ||
| add_subdirectory_ifdef(CONFIG_SOC_FAMILY_STM32 stm32) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,5 +4,6 @@ | |
| menu "USB common" | ||
|
|
||
| rsource "nrf_usbd_common/Kconfig" | ||
| rsource "stm32/Kconfig" | ||
|
|
||
| endmenu | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| # Copyright (c) 2025 STMicroelectronics | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| if(CONFIG_STM32_USB_COMMON) | ||
| zephyr_library() | ||
|
|
||
| zephyr_include_directories(.) | ||
|
|
||
| zephyr_library_sources(stm32_usb_pwr.c) | ||
| endif() |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| # Copyright (c) 2025 STMicroelectronics | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| if SOC_FAMILY_STM32 | ||
|
|
||
| config STM32_USB_COMMON | ||
| bool | ||
| help | ||
| Enable compilation of STM32 USB common code. | ||
|
|
||
| This option is selected by the USB drivers when appropriate. | ||
|
|
||
| module = STM32_USB_COMMON | ||
| module-str = STM32 USB common code | ||
| source "subsys/logging/Kconfig.template.log_config" | ||
|
|
||
| endif # SOC_FAMILY_STM32 | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| /* | ||
| * Copyright (c) 2025 STMicroelectronics | ||
| * | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
tmon-nordic marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| #ifndef ZEPHYR_DRIVERS_USB_COMMON_STM32_STM32_USB_COMMON_H_ | ||
| #define ZEPHYR_DRIVERS_USB_COMMON_STM32_STM32_USB_COMMON_H_ | ||
|
|
||
| /** | ||
| * @brief Configures the Power Controller as necessary | ||
| * for proper operation of the USB controllers | ||
| */ | ||
| int stm32_usb_pwr_enable(void); | ||
|
|
||
| /** | ||
| * @brief Configures the Power Controller to disable | ||
| * USB-related regulators/etc if no controller is | ||
| * still active (refcounted). | ||
| */ | ||
| int stm32_usb_pwr_disable(void); | ||
|
|
||
| #endif /* ZEPHYR_DRIVERS_USB_COMMON_STM32_STM32_USB_COMMON_H_ */ | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
But it is not shared. You just moved the code from UDC driver. It is not worth it to touch legacy driver at this point. What is the reason to move the code? If there is stm32_usb_pwr_enable(void), then you need also stm32_usb_pwr_disable(). stm32_usb_pwr.c actually looks like regulator driver. Why not use regulator API and implement a regulator driver? What you would need to implement is just static DEVICE_API(regulator, api) = {
.enable = stm32_usbreg_enable,
.disable = stm32_usbreg_disable,
};
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
It is not shared for now, but would become shared when/if an STM32 UHC driver is implemented.
What do you mean by
I did not implement
...good remark - and this solves refcounting issues. I'll try implementing as a regulator driver.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. After a quick and dirty implementation, I don't think a regulator driver will be an acceptable solution. Turning this code into a regulator driver (and thus enabling the regulator subsystem!) adds an unjustified ~1K to the ROM footprint (on our smallest product with USB support, that's 2% of ROM size!) Would you be OK if the code was in
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Just FYI, UHC shim driver for DWC2 controller would not be acceptable.
From the commit message it is not clear where it would be shared, so I have to guess.
But why move still "not yet" shared code and keep it half-backed?
AFAIK there is no regulator subsystem and the increased footprint sounds acceptable to me, we should stimulate the market, but I do not insist on it. Please add stm32_usb_pwr_disable().
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
ST's USB controller also supports Host mode. (not that this matters anyways - regardless of which driver controls the IP, it will have to enable power the same way, hence the move to common code)
I want to avoid functional changes as much as possible while implementing multi-instance support. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,171 @@ | ||
| /* | ||
| * Copyright (c) 2025 STMicroelectronics | ||
| * | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| #include <soc.h> | ||
| #include <stm32_ll_bus.h> | ||
| #include <stm32_ll_pwr.h> | ||
| #include <stm32_ll_rcc.h> | ||
| #include <stm32_ll_system.h> | ||
| #include <string.h> | ||
| #include <zephyr/kernel.h> | ||
| #include <zephyr/sys/atomic.h> | ||
| #include <zephyr/sys/util.h> | ||
|
|
||
| #include <zephyr/logging/log.h> | ||
| LOG_MODULE_REGISTER(stm32_usb_pwr, CONFIG_STM32_USB_COMMON_LOG_LEVEL); | ||
|
|
||
| /* | ||
| * Keep track of whether power is already | ||
| * enabled here to simplify the USB drivers. | ||
| */ | ||
| static atomic_t usb_pwr_refcount = ATOMIC_INIT(0); | ||
|
|
||
| int stm32_usb_pwr_enable(void) | ||
| { | ||
| atomic_val_t old = atomic_inc(&usb_pwr_refcount); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should it be incremented if the function exits with |
||
|
|
||
| if (old > 0) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you need old? Can it be |
||
| /* Already enabled - nothing to do */ | ||
| return 0; | ||
| } | ||
|
|
||
| #if defined(CONFIG_SOC_SERIES_STM32H7X) | ||
| LL_PWR_EnableUSBVoltageDetector(); | ||
|
|
||
| /* Per AN2606: USBREGEN not supported when running in FS mode. */ | ||
| LL_PWR_DisableUSBReg(); | ||
| while (!LL_PWR_IsActiveFlag_USB()) { | ||
| LOG_INF("PWR not active yet"); | ||
| k_msleep(100); | ||
| } | ||
| #elif defined(CONFIG_SOC_SERIES_STM32U5X) | ||
| /* Sequence to enable the power of the OTG HS on a stm32U5 serie : Enable VDDUSB */ | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| __ASSERT_NO_MSG(LL_AHB3_GRP1_IsEnabledClock(LL_AHB3_GRP1_PERIPH_PWR)); | ||
|
|
||
| /* Check that power range is 1 or 2 */ | ||
| if (LL_PWR_GetRegulVoltageScaling() < LL_PWR_REGU_VOLTAGE_SCALE2) { | ||
| LOG_ERR("Wrong Power range to use USB OTG HS"); | ||
| return -EIO; | ||
| } | ||
|
|
||
| LL_PWR_EnableVddUSB(); | ||
|
|
||
| #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_otghs) | ||
| /* Configure VOSR register of USB HSTransceiverSupply(); */ | ||
| LL_PWR_EnableUSBPowerSupply(); | ||
| LL_PWR_EnableUSBEPODBooster(); | ||
| while (LL_PWR_IsActiveFlag_USBBOOST() != 1) { | ||
| /* Wait for USB EPOD BOOST ready */ | ||
| } | ||
| #endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32_otghs) */ | ||
|
Comment on lines
+56
to
+63
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We usually do not indent blocks inside #if/#endif. |
||
| #elif defined(CONFIG_SOC_SERIES_STM32N6X) | ||
| /* Enable Vdd33USB voltage monitoring */ | ||
| LL_PWR_EnableVddUSBMonitoring(); | ||
| while (!LL_PWR_IsActiveFlag_USB33RDY()) { | ||
| /* Wait for Vdd33USB ready */ | ||
| } | ||
|
|
||
| /* Enable VDDUSB */ | ||
| LL_PWR_EnableVddUSB(); | ||
| #elif defined(CONFIG_SOC_SERIES_STM32WBAX) | ||
| /* Remove VDDUSB power isolation */ | ||
| LL_PWR_EnableVddUSB(); | ||
|
|
||
| /* Make sure that voltage scaling is Range 1 */ | ||
| __ASSERT_NO_MSG(LL_PWR_GetRegulCurrentVOS() == LL_PWR_REGU_VOLTAGE_SCALE1); | ||
|
|
||
| /* Enable VDD11USB */ | ||
| LL_PWR_EnableVdd11USB(); | ||
|
|
||
| /* Enable USB OTG internal power */ | ||
| LL_PWR_EnableUSBPWR(); | ||
|
|
||
| while (!LL_PWR_IsActiveFlag_VDD11USBRDY()) { | ||
| /* Wait for VDD11USB supply to be ready */ | ||
| } | ||
|
|
||
| /* Enable USB OTG booster */ | ||
| LL_PWR_EnableUSBBooster(); | ||
|
|
||
| while (!LL_PWR_IsActiveFlag_USBBOOSTRDY()) { | ||
| /* Wait for USB OTG booster to be ready */ | ||
| } | ||
| #elif defined(PWR_USBSCR_USB33SV) || defined(PWR_SVMCR_USV) | ||
| /* | ||
| * VDDUSB independent USB supply (PWR clock is on) | ||
| * with LL_PWR_EnableVDDUSB function (higher case) | ||
| */ | ||
| LL_PWR_EnableVDDUSB(); | ||
| #elif defined(PWR_CR2_USV) | ||
| /*cd | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| * Required for at least STM32L4 devices as they electrically | ||
| * isolate USB features from VDDUSB. It must be enabled before | ||
| * USB can function. Refer to section 5.1.3 in DM00083560 or | ||
| * DM00310109. | ||
| */ | ||
| LL_PWR_EnableVddUSB(); | ||
| #endif | ||
| return 0; | ||
| } | ||
|
|
||
| int stm32_usb_pwr_disable(void) | ||
| { | ||
| atomic_val_t old = atomic_dec(&usb_pwr_refcount); | ||
|
|
||
| if (old > 1) { | ||
| /* There are other users - don't disable now */ | ||
| return 0; | ||
| } | ||
|
|
||
| #if defined(CONFIG_SOC_SERIES_STM32H7X) | ||
| LL_PWR_DisableUSBVoltageDetector(); | ||
| #elif defined(CONFIG_SOC_SERIES_STM32U5X) | ||
| #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_otghs) | ||
| LL_PWR_DisableUSBEPODBooster(); | ||
| while (LL_PWR_IsActiveFlag_USBBOOST() != 0) { | ||
| /* Wait for USB EPOD BOOST off */ | ||
| } | ||
|
|
||
| LL_PWR_DisableUSBPowerSupply(); | ||
| #endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32_otghs) */ | ||
|
|
||
| LL_PWR_DisableVddUSB(); | ||
| #elif defined(CONFIG_SOC_SERIES_STM32N6X) | ||
| /* Disable Vdd33USB voltage monitoring */ | ||
| LL_PWR_DisableVddUSBMonitoring(); | ||
|
|
||
| /* Disable VDDUSB */ | ||
| LL_PWR_DisableVddUSB(); | ||
| #elif defined(CONFIG_SOC_SERIES_STM32WBAX) | ||
| /* Disable USB OTG booster */ | ||
| LL_PWR_DisableUSBBooster(); | ||
|
|
||
| while (LL_PWR_IsActiveFlag_USBBOOSTRDY()) { | ||
| /* Wait until USB OTG booster is off */ | ||
| } | ||
|
|
||
| /* Disable USB OTG internal power */ | ||
| LL_PWR_DisableUSBPWR(); | ||
|
|
||
| /* Disable VDD11USB */ | ||
| LL_PWR_DisableVdd11USB(); | ||
|
|
||
| while (LL_PWR_IsActiveFlag_VDD11USBRDY()) { | ||
| /* Wait until VDD11USB supply is off */ | ||
| } | ||
|
|
||
| /* Enable VDDUSB power isolation */ | ||
| LL_PWR_DisableVddUSB(); | ||
| #elif defined(PWR_USBSCR_USB33SV) || defined(PWR_SVMCR_USV) | ||
| /* Enable VDDUSB power isolation */ | ||
| LL_PWR_DisableVDDUSB(); | ||
| #elif defined(PWR_CR2_USV) | ||
| /* Enable VDDUSB power isolation */ | ||
| LL_PWR_DisableVddUSB(); | ||
| #endif | ||
|
|
||
| return 0; | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remove this empty line.