Skip to content

Commit 51c1f86

Browse files
drivers: usb: udc: stm32: move power configuration to common code
Create infrastructure for shared USB common code on STM32 family, and move the Power Controller configuration logic to common code. Signed-off-by: Mathieu Choplain <[email protected]>
1 parent ab09c94 commit 51c1f86

File tree

8 files changed

+170
-89
lines changed

8 files changed

+170
-89
lines changed

drivers/usb/common/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
# SPDX-License-Identifier: Apache-2.0
22

33
add_subdirectory_ifdef(CONFIG_HAS_NRFX nrf_usbd_common)
4+
add_subdirectory_ifdef(CONFIG_SOC_FAMILY_STM32 stm32)

drivers/usb/common/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@
44
menu "USB common"
55

66
rsource "nrf_usbd_common/Kconfig"
7+
rsource "stm32/Kconfig"
78

89
endmenu
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Copyright (c) 2025 STMicroelectronics
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
if(CONFIG_STM32_USB_COMMON)
5+
zephyr_library()
6+
7+
zephyr_include_directories(.)
8+
9+
zephyr_library_sources(stm32_usb_pwr.c)
10+
endif()

drivers/usb/common/stm32/Kconfig

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Copyright (c) 2025 STMicroelectronics
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
if SOC_FAMILY_STM32
5+
6+
config STM32_USB_COMMON
7+
bool
8+
help
9+
Enable compilation of STM32 USB common code.
10+
11+
This option is selected by the USB drivers when appropriate.
12+
13+
module = STM32_USB_COMMON
14+
module-str = STM32 USB common code
15+
source "subsys/logging/Kconfig.template.log_config"
16+
17+
endif # SOC_FAMILY_STM32
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/*
2+
* Copyright (c) 2025 STMicroelectronics
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#ifndef ZEPHYR_DRIVERS_USB_COMMON_STM32_STM32_USB_COMMON_H_
8+
#define ZEPHYR_DRIVERS_USB_COMMON_STM32_STM32_USB_COMMON_H_
9+
10+
/**
11+
* @brief Configures the Power Controller as necessary
12+
* for proper operation of the USB controllers
13+
*/
14+
int stm32_usb_pwr_enable(void);
15+
16+
#endif /* ZEPHYR_DRIVERS_USB_COMMON_STM32_STM32_USB_COMMON_H_ */
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/*
2+
* Copyright (c) 2025 STMicroelectronics
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <soc.h>
8+
#include <stm32_ll_bus.h>
9+
#include <stm32_ll_pwr.h>
10+
#include <stm32_ll_rcc.h>
11+
#include <stm32_ll_system.h>
12+
#include <string.h>
13+
#include <zephyr/kernel.h>
14+
#include <zephyr/sys/util.h>
15+
16+
#include <zephyr/logging/log.h>
17+
LOG_MODULE_REGISTER(stm32_usb_pwr, CONFIG_STM32_USB_COMMON_LOG_LEVEL);
18+
19+
static bool pwr_enabled;
20+
21+
int stm32_usb_pwr_enable(void)
22+
{
23+
/*
24+
* Keep track of whether this has already been called
25+
* to avoid repeating the sequence. The bookkeeping is
26+
* done here to simplify the USB drivers, which can
27+
* call this function as part of the instance init
28+
* function without any prior check.
29+
*
30+
* NOTE: no mutex mechanism is implemented as this
31+
* function is expected to be called during device
32+
* initialization (at boot), which already ensures
33+
* only one device at a time is initialized.
34+
*/
35+
if (pwr_enabled) {
36+
return 0;
37+
}
38+
39+
pwr_enabled = true;
40+
#if defined(CONFIG_SOC_SERIES_STM32H7X)
41+
LL_PWR_EnableUSBVoltageDetector();
42+
43+
/* Per AN2606: USBREGEN not supported when running in FS mode. */
44+
LL_PWR_DisableUSBReg();
45+
while (!LL_PWR_IsActiveFlag_USB()) {
46+
LOG_INF("PWR not active yet");
47+
k_msleep(100);
48+
}
49+
#elif defined(CONFIG_SOC_SERIES_STM32U5X)
50+
/* Sequence to enable the power of the OTG HS on a stm32U5 serie : Enable VDDUSB */
51+
__ASSERT_NO_MSG(LL_AHB3_GRP1_IsEnabledClock(LL_AHB3_GRP1_PERIPH_PWR));
52+
53+
/* Check that power range is 1 or 2 */
54+
if (LL_PWR_GetRegulVoltageScaling() < LL_PWR_REGU_VOLTAGE_SCALE2) {
55+
LOG_ERR("Wrong Power range to use USB OTG HS");
56+
return -EIO;
57+
}
58+
59+
LL_PWR_EnableVddUSB();
60+
61+
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_otghs)
62+
/* Configure VOSR register of USB HSTransceiverSupply(); */
63+
LL_PWR_EnableUSBPowerSupply();
64+
LL_PWR_EnableUSBEPODBooster();
65+
while (LL_PWR_IsActiveFlag_USBBOOST() != 1) {
66+
/* Wait for USB EPOD BOOST ready */
67+
}
68+
#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32_otghs) */
69+
#elif defined(CONFIG_SOC_SERIES_STM32N6X)
70+
/* Enable Vdd33USB voltage monitoring */
71+
LL_PWR_EnableVddUSBMonitoring();
72+
while (!LL_PWR_IsActiveFlag_USB33RDY()) {
73+
/* Wait for Vdd33USB ready */
74+
}
75+
76+
/* Enable VDDUSB */
77+
LL_PWR_EnableVddUSB();
78+
#elif defined(CONFIG_SOC_SERIES_STM32WBAX)
79+
/* Remove VDDUSB power isolation */
80+
LL_PWR_EnableVddUSB();
81+
82+
/* Make sure that voltage scaling is Range 1 */
83+
__ASSERT_NO_MSG(LL_PWR_GetRegulCurrentVOS() == LL_PWR_REGU_VOLTAGE_SCALE1);
84+
85+
/* Enable VDD11USB */
86+
LL_PWR_EnableVdd11USB();
87+
88+
/* Enable USB OTG internal power */
89+
LL_PWR_EnableUSBPWR();
90+
91+
while (!LL_PWR_IsActiveFlag_VDD11USBRDY()) {
92+
/* Wait for VDD11USB supply to be ready */
93+
}
94+
95+
/* Enable USB OTG booster */
96+
LL_PWR_EnableUSBBooster();
97+
98+
while (!LL_PWR_IsActiveFlag_USBBOOSTRDY()) {
99+
/* Wait for USB OTG booster to be ready */
100+
}
101+
#elif defined(PWR_USBSCR_USB33SV) || defined(PWR_SVMCR_USV)
102+
/*
103+
* VDDUSB independent USB supply (PWR clock is on)
104+
* with LL_PWR_EnableVDDUSB function (higher case)
105+
*/
106+
LL_PWR_EnableVDDUSB();
107+
#elif defined(PWR_CR2_USV)
108+
/*cd
109+
* Required for at least STM32L4 devices as they electrically
110+
* isolate USB features from VDDUSB. It must be enabled before
111+
* USB can function. Refer to section 5.1.3 in DM00083560 or
112+
* DM00310109.
113+
*/
114+
LL_PWR_EnableVddUSB();
115+
#endif
116+
return 0;
117+
}

drivers/usb/udc/Kconfig.stm32

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ config UDC_STM32
1010
select USE_STM32_HAL_PCD
1111
select USE_STM32_HAL_PCD_EX
1212
select UDC_DRIVER_HAS_HIGH_SPEED_SUPPORT
13+
select STM32_USB_COMMON
1314
select PINCTRL
1415
default y
1516
help

drivers/usb/udc/udc_stm32.c

Lines changed: 7 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <zephyr/sys/util.h>
2323

2424
#include "udc_common.h"
25+
#include <stm32_usb_common.h>
2526

2627
#include <zephyr/logging/log.h>
2728
LOG_MODULE_REGISTER(udc_stm32, CONFIG_UDC_DRIVER_LOG_LEVEL);
@@ -1296,76 +1297,6 @@ static int udc_stm32_clock_enable(const struct device *dev)
12961297
return -ENODEV;
12971298
}
12981299

1299-
/* Power configuration */
1300-
#if defined(CONFIG_SOC_SERIES_STM32H7X)
1301-
LL_PWR_EnableUSBVoltageDetector();
1302-
1303-
/* Per AN2606: USBREGEN not supported when running in FS mode. */
1304-
LL_PWR_DisableUSBReg();
1305-
while (!LL_PWR_IsActiveFlag_USB()) {
1306-
LOG_INF("PWR not active yet");
1307-
k_msleep(100);
1308-
}
1309-
#elif defined(CONFIG_SOC_SERIES_STM32U5X)
1310-
/* Sequence to enable the power of the OTG HS on a stm32U5 serie : Enable VDDUSB */
1311-
__ASSERT_NO_MSG(LL_AHB3_GRP1_IsEnabledClock(LL_AHB3_GRP1_PERIPH_PWR));
1312-
1313-
/* Check that power range is 1 or 2 */
1314-
if (LL_PWR_GetRegulVoltageScaling() < LL_PWR_REGU_VOLTAGE_SCALE2) {
1315-
LOG_ERR("Wrong Power range to use USB OTG HS");
1316-
return -EIO;
1317-
}
1318-
1319-
LL_PWR_EnableVddUSB();
1320-
1321-
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_otghs)
1322-
/* Configure VOSR register of USB HSTransceiverSupply(); */
1323-
LL_PWR_EnableUSBPowerSupply();
1324-
LL_PWR_EnableUSBEPODBooster();
1325-
while (LL_PWR_IsActiveFlag_USBBOOST() != 1) {
1326-
/* Wait for USB EPOD BOOST ready */
1327-
}
1328-
#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32_otghs) */
1329-
#elif defined(CONFIG_SOC_SERIES_STM32N6X)
1330-
/* Enable Vdd33USB voltage monitoring */
1331-
LL_PWR_EnableVddUSBMonitoring();
1332-
while (!LL_PWR_IsActiveFlag_USB33RDY()) {
1333-
/* Wait for Vdd33USB ready */
1334-
}
1335-
1336-
/* Enable VDDUSB */
1337-
LL_PWR_EnableVddUSB();
1338-
#elif defined(CONFIG_SOC_SERIES_STM32WBAX)
1339-
/* Remove VDDUSB power isolation */
1340-
LL_PWR_EnableVddUSB();
1341-
1342-
/* Make sure that voltage scaling is Range 1 */
1343-
__ASSERT_NO_MSG(LL_PWR_GetRegulCurrentVOS() == LL_PWR_REGU_VOLTAGE_SCALE1);
1344-
1345-
/* Enable VDD11USB */
1346-
LL_PWR_EnableVdd11USB();
1347-
1348-
/* Enable USB OTG internal power */
1349-
LL_PWR_EnableUSBPWR();
1350-
1351-
while (!LL_PWR_IsActiveFlag_VDD11USBRDY()) {
1352-
/* Wait for VDD11USB supply to be ready */
1353-
}
1354-
1355-
/* Enable USB OTG booster */
1356-
LL_PWR_EnableUSBBooster();
1357-
1358-
while (!LL_PWR_IsActiveFlag_USBBOOSTRDY()) {
1359-
/* Wait for USB OTG booster to be ready */
1360-
}
1361-
#elif defined(PWR_USBSCR_USB33SV) || defined(PWR_SVMCR_USV)
1362-
/*
1363-
* VDDUSB independent USB supply (PWR clock is on)
1364-
* with LL_PWR_EnableVDDUSB function (higher case)
1365-
*/
1366-
LL_PWR_EnableVDDUSB();
1367-
#endif
1368-
13691300
if (cfg->num_clocks > 1) {
13701301
if (clock_control_configure(clk, &cfg->pclken[1], NULL) != 0) {
13711302
LOG_ERR("Could not select USB domain clock");
@@ -1618,25 +1549,12 @@ static int udc_stm32_driver_init0(const struct device *dev)
16181549
}
16191550
}
16201551

1621-
/*cd
1622-
* Required for at least STM32L4 devices as they electrically
1623-
* isolate USB features from VDDUSB. It must be enabled before
1624-
* USB can function. Refer to section 5.1.3 in DM00083560 or
1625-
* DM00310109.
1626-
*/
1627-
#ifdef PWR_CR2_USV
1628-
#if defined(LL_APB1_GRP1_PERIPH_PWR)
1629-
if (LL_APB1_GRP1_IsEnabledClock(LL_APB1_GRP1_PERIPH_PWR)) {
1630-
LL_PWR_EnableVddUSB();
1631-
} else {
1632-
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR);
1633-
LL_PWR_EnableVddUSB();
1634-
LL_APB1_GRP1_DisableClock(LL_APB1_GRP1_PERIPH_PWR);
1635-
}
1636-
#else
1637-
LL_PWR_EnableVddUSB();
1638-
#endif /* defined(LL_APB1_GRP1_PERIPH_PWR) */
1639-
#endif /* PWR_CR2_USV */
1552+
/* Configure Power Controller as necessary for USB */
1553+
err = stm32_usb_pwr_enable();
1554+
if (err < 0) {
1555+
LOG_ERR("Failed USB power configuration: %d", err);
1556+
return err;
1557+
}
16401558

16411559
return 0;
16421560
}

0 commit comments

Comments
 (0)