Skip to content

Commit f72ef5c

Browse files
mniestrojAdrian Chadd
authored andcommitted
drivers: usb: stm32: fix support of STM32U5 OTG_HS with embedded PHY
Introduce new binding "st,stm32u5-otghs-phy" for OTG_HS PHY. This allows to configure clock source and handle STM32U5 specific OTG_HS PHY behavior in driver implementation in a more readable way. Move OTG_HS PHY clock selection (previously <&rcc STM32_SRC_HSI48 ICKLK_SEL(0)>) from OTG_HS node to OTG_HS PHY node. Rename USBPHYC_SEL -> OTGHS_SEL which matches the definition in the stm32u5 CCIPR2 register (RM0456 Rev 5, Section 11.8.47). Support enabling OTG_HS PHY clock, which is bit 15 (OTGHSPHYEN) in RCC_AHB2ENR1. Change OTG_HS clock to be bit 14 (OTGEN). Calculate in runtime OTG_HS PHY clock source frequency. Try to match that to supported (16, 19.2, 20, 24, 26, 32 MHz) frequencies and select proper option with HAL_SYSCFG_SetOTGPHYReferenceClockSelection() API (instead of hardcoded 16 MHz selection). Co-authored-by: Adrian Chadd <[email protected]> Signed-off-by: Adrian Chadd <[email protected]> Signed-off-by: Marcin Niestroj <[email protected]>
1 parent fafaa58 commit f72ef5c

File tree

5 files changed

+141
-16
lines changed

5 files changed

+141
-16
lines changed

drivers/usb/device/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ config USB_DC_STM32
6262
config USB_DC_STM32_CLOCK_CHECK
6363
bool "Runtime USB 48MHz clock check"
6464
depends on USB_DC_STM32
65-
default y if !(SOC_SERIES_STM32F1X || SOC_SERIES_STM32F3X)
65+
default y if !(SOC_SERIES_STM32F1X || SOC_SERIES_STM32F3X || SOC_SERIES_STM32U5X)
6666
help
6767
Enable USB clock 48MHz configuration runtime check.
6868
In specific cases, this check might provide wrong verdict and should

drivers/usb/device/usb_dc_stm32.c

Lines changed: 99 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -208,16 +208,67 @@ void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
208208
}
209209
#endif
210210

211-
static int usb_dc_stm32_clock_enable(void)
211+
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32u5_otghs_phy)
212+
213+
static const struct stm32_pclken phy_pclken[] = STM32_DT_CLOCKS(DT_INST_PHANDLE(0, phys));
214+
215+
static int usb_dc_stm32u5_phy_clock_select(const struct device *const clk)
212216
{
213-
const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE);
217+
static const struct {
218+
uint32_t freq;
219+
uint32_t ref_clk;
220+
} clk_select[] = {
221+
{ MHZ(16), SYSCFG_OTG_HS_PHY_CLK_SELECT_1 },
222+
{ KHZ(19200), SYSCFG_OTG_HS_PHY_CLK_SELECT_2 },
223+
{ MHZ(20), SYSCFG_OTG_HS_PHY_CLK_SELECT_3 },
224+
{ MHZ(24), SYSCFG_OTG_HS_PHY_CLK_SELECT_4 },
225+
{ MHZ(26), SYSCFG_OTG_HS_PHY_CLK_SELECT_5 },
226+
{ MHZ(32), SYSCFG_OTG_HS_PHY_CLK_SELECT_6 },
227+
};
228+
uint32_t freq;
229+
230+
if (clock_control_get_rate(clk,
231+
(clock_control_subsys_t)&phy_pclken[1],
232+
&freq) != 0) {
233+
LOG_ERR("Failed to get USB_PHY clock source rate");
234+
return -EIO;
235+
}
214236

215-
if (!device_is_ready(clk)) {
216-
LOG_ERR("clock control device not ready");
217-
return -ENODEV;
237+
for (size_t i = 0; ARRAY_SIZE(clk_select); i++) {
238+
if (clk_select[i].freq == freq) {
239+
HAL_SYSCFG_SetOTGPHYReferenceClockSelection(clk_select[i].ref_clk);
240+
return 0;
241+
}
218242
}
219243

220-
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_otghs) && defined(CONFIG_SOC_SERIES_STM32U5X)
244+
LOG_ERR("Unsupported PHY clock source frequency (%"PRIu32")", freq);
245+
246+
return -EINVAL;
247+
}
248+
249+
static int usb_dc_stm32u5_phy_clock_enable(const struct device *const clk)
250+
{
251+
int err;
252+
253+
err = clock_control_configure(clk, (clock_control_subsys_t)&phy_pclken[1], NULL);
254+
if (err) {
255+
LOG_ERR("Could not select USB_PHY clock source");
256+
return -EIO;
257+
}
258+
259+
err = clock_control_on(clk, (clock_control_subsys_t)&phy_pclken[0]);
260+
if (err) {
261+
LOG_ERR("Unable to enable USB_PHY clock");
262+
return -EIO;
263+
}
264+
265+
return usb_dc_stm32u5_phy_clock_select(clk);
266+
}
267+
268+
static int usb_dc_stm32_phy_specific_clock_enable(const struct device *const clk)
269+
{
270+
int err;
271+
221272
/* Sequence to enable the power of the OTG HS on a stm32U5 serie : Enable VDDUSB */
222273
bool pwr_clk = LL_AHB3_GRP1_IsEnabledClock(LL_AHB3_GRP1_PERIPH_PWR);
223274

@@ -246,10 +297,28 @@ static int usb_dc_stm32_clock_enable(void)
246297

247298
/* Set the OTG PHY reference clock selection (through SYSCFG) block */
248299
LL_APB3_GRP1_EnableClock(LL_APB3_GRP1_PERIPH_SYSCFG);
249-
HAL_SYSCFG_SetOTGPHYReferenceClockSelection(SYSCFG_OTG_HS_PHY_CLK_SELECT_1);
300+
301+
err = usb_dc_stm32u5_phy_clock_enable(clk);
302+
if (err) {
303+
return err;
304+
}
305+
250306
/* Configuring the SYSCFG registers OTG_HS PHY : OTG_HS PHY enable*/
251307
HAL_SYSCFG_EnableOTGPHY(SYSCFG_OTG_HS_PHY_ENABLE);
252-
#elif defined(PWR_USBSCR_USB33SV) || defined(PWR_SVMCR_USV)
308+
309+
if (clock_control_on(clk, (clock_control_subsys_t)&pclken[0]) != 0) {
310+
LOG_ERR("Unable to enable USB clock");
311+
return -EIO;
312+
}
313+
314+
return 0;
315+
}
316+
317+
#else /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32u5_otghs_phy) */
318+
319+
static int usb_dc_stm32_phy_specific_clock_enable(const struct device *const clk)
320+
{
321+
#if defined(PWR_USBSCR_USB33SV) || defined(PWR_SVMCR_USV)
253322
/*
254323
* VDDUSB independent USB supply (PWR clock is on)
255324
* with LL_PWR_EnableVDDUSB function (higher case)
@@ -286,6 +355,26 @@ static int usb_dc_stm32_clock_enable(void)
286355
}
287356
}
288357

358+
return 0;
359+
}
360+
361+
#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32u5_otghs_phy) */
362+
363+
static int usb_dc_stm32_clock_enable(void)
364+
{
365+
const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE);
366+
int err;
367+
368+
if (!device_is_ready(clk)) {
369+
LOG_ERR("clock control device not ready");
370+
return -ENODEV;
371+
}
372+
373+
err = usb_dc_stm32_phy_specific_clock_enable(clk);
374+
if (err) {
375+
return err;
376+
}
377+
289378
/* Previous check won't work in case of F1/F3. Add build time check */
290379
#if defined(RCC_CFGR_OTGFSPRE) || defined(RCC_CFGR_USBPRE)
291380

@@ -333,8 +422,8 @@ static int usb_dc_stm32_clock_disable(void)
333422
LOG_ERR("Unable to disable USB clock");
334423
return -EIO;
335424
}
336-
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_otghs) && defined(CONFIG_SOC_SERIES_STM32U5X)
337-
LL_AHB2_GRP1_DisableClock(LL_AHB2_GRP1_PERIPH_USBPHY);
425+
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32u5_otghs_phy)
426+
clock_control_off(clk, (clock_control_subsys_t)&phy_pclken[0]);
338427
#endif
339428

340429
return 0;

dts/arm/st/u5/stm32u595.dtsi

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,16 +106,16 @@
106106
num-bidir-endpoints = <9>;
107107
ram-size = <4096>;
108108
maximum-speed = "high-speed";
109-
clocks = <&rcc STM32_CLOCK(AHB2, 15U)>,
110-
<&rcc STM32_SRC_HSI48 ICKLK_SEL(0)>;
109+
clocks = <&rcc STM32_CLOCK(AHB2, 14U)>;
111110
phys = <&otghs_phy>;
112111
status = "disabled";
113112
};
114113
};
115114

116115
otghs_phy: otghs_phy {
117-
/* Clock source defined by USBPHYC_SEL in */
118-
compatible = "usb-nop-xceiv";
116+
compatible = "st,stm32u5-otghs-phy";
117+
clocks = <&rcc STM32_CLOCK(AHB2, 15U)>,
118+
<&rcc STM32_SRC_HSE OTGHS_SEL(0)>;
119119
#phy-cells = <0>;
120120
};
121121

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Copyright (c) 2024 Marcin Niestroj
2+
# Copyright (c) 2024 Meta
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
description: |
6+
This binding is to be used by the STM32U5xx transceivers which are built-in
7+
with USB HS PHY IP and a configurable HSE clock source.
8+
9+
compatible: "st,stm32u5-otghs-phy"
10+
11+
include: phy-controller.yaml
12+
13+
properties:
14+
"#phy-cells":
15+
const: 0
16+
17+
clocks:
18+
required: true
19+
description: |
20+
Supported configurations:
21+
22+
/* HSE */
23+
clocks = <&rcc STM32_CLOCK(AHB2, 15U)>,
24+
<&rcc STM32_SRC_HSE OTGHS_SEL(0)>;
25+
26+
/* HSE/2 */
27+
clocks = <&rcc STM32_CLOCK(AHB2, 15U)>,
28+
<&rcc (STM32_SRC_HSE | STM32_CLOCK_DIV(2)) OTGHS_SEL(2)>;
29+
30+
/* PLL1_P_CK */
31+
clocks = <&rcc STM32_CLOCK(AHB2, 15U)>,
32+
<&rcc STM32_SRC_PLL1_P OTGHS_SEL(1)>;
33+
34+
/* PLL1_P_CK/2 */
35+
clocks = <&rcc STM32_CLOCK(AHB2, 15U)>,
36+
<&rcc (STM32_SRC_PLL1_P | STM32_CLOCK_DIV(2)) OTGHS_SEL(3)>;

include/zephyr/dt-bindings/clock/stm32u5_clock.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@
122122
#define HSPI_SEL(val) STM32_DOMAIN_CLOCK(val, 3, 22, CCIPR2_REG)
123123
#define I2C5_SEL(val) STM32_DOMAIN_CLOCK(val, 3, 24, CCIPR2_REG)
124124
#define I2C6_SEL(val) STM32_DOMAIN_CLOCK(val, 3, 26, CCIPR2_REG)
125-
#define USBPHYC_SEL(val) STM32_DOMAIN_CLOCK(val, 3, 30, CCIPR2_REG)
125+
#define OTGHS_SEL(val) STM32_DOMAIN_CLOCK(val, 3, 30, CCIPR2_REG)
126126
/** CCIPR3 devices */
127127
#define LPUART1_SEL(val) STM32_DOMAIN_CLOCK(val, 7, 0, CCIPR3_REG)
128128
#define SPI3_SEL(val) STM32_DOMAIN_CLOCK(val, 3, 3, CCIPR3_REG)

0 commit comments

Comments
 (0)