Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions doc/releases/release-notes-4.4.rst
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,12 @@ New APIs and options
* :kconfig:option:`CONFIG_NVMEM_FLASH`
* :kconfig:option:`CONFIG_NVMEM_FLASH_WRITE`

* Power

* The new ``voltage-scale`` property of :dtcompatible:`st,stm32u5-pwr` can be used to
select the voltage scale manually on STM32U5 series via Devicetree. This notably
enables usage of the USB controller at lower system clock frequencies.

* Settings

* :kconfig:option:`CONFIG_SETTINGS_SAVE_SINGLE_SUBTREE_WITHOUT_MODIFICATION`
Expand Down
53 changes: 47 additions & 6 deletions drivers/clock_control/clock_stm32_ll_u5.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,17 @@
#define PLL2_ID 2
#define PLL3_ID 3

/* Shorthand for Power Controller node */
#define PWR_NODE DT_NODELABEL(pwr)

/* Dummy value to use automatic voltage scale selection */
#define VOLTAGE_SCALE_AUTOMATIC 0xFFFFFFFFu

#define SELECTED_VOLTAGE_SCALE \
COND_CODE_1(DT_NODE_HAS_PROP(PWR_NODE, voltage_scale), \
(CONCAT(LL_PWR_REGU_VOLTAGE_SCALE, DT_PROP(PWR_NODE, voltage_scale))), \
(VOLTAGE_SCALE_AUTOMATIC))

static uint32_t get_bus_clock(uint32_t clock, uint32_t prescaler)
{
return clock / prescaler;
Expand Down Expand Up @@ -430,17 +441,35 @@ static int get_vco_input_range(uint32_t m_div, uint32_t *range, size_t pll_id)
return 0;
}

static void set_regu_voltage(uint32_t hclk_freq)
static void set_regu_voltage(uint32_t hclk_freq, uint32_t wanted_scale)
{
uint32_t minimal_scale, scale_to_apply;

if (hclk_freq < MHZ(25)) {
LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE4);
minimal_scale = LL_PWR_REGU_VOLTAGE_SCALE4;
} else if (hclk_freq < MHZ(55)) {
LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE3);
minimal_scale = LL_PWR_REGU_VOLTAGE_SCALE3;
} else if (hclk_freq < MHZ(110)) {
LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE2);
minimal_scale = LL_PWR_REGU_VOLTAGE_SCALE2;
} else {
LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1);
minimal_scale = LL_PWR_REGU_VOLTAGE_SCALE1;
}

if (wanted_scale == VOLTAGE_SCALE_AUTOMATIC) {
scale_to_apply = minimal_scale;
} else if (wanted_scale < minimal_scale) {
/*
* This ought to never happen thanks to the
* compile-time checks, but better safe than
* sorry. Ideally, an error message should be
* logged if this ever occurs...
*/
scale_to_apply = minimal_scale;
} else {
scale_to_apply = wanted_scale;
}

LL_PWR_SetRegulVoltageScaling(scale_to_apply);
while (LL_PWR_IsActiveFlag_VOS() == 0) {
}
}
Expand Down Expand Up @@ -855,7 +884,7 @@ int stm32_clock_control_init(const struct device *dev)
old_hclk_freq = __LL_RCC_CALC_HCLK_FREQ(get_startup_frequency(), LL_RCC_GetAHBPrescaler());

/* Set voltage regulator to comply with targeted system frequency */
set_regu_voltage(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC);
set_regu_voltage(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC, SELECTED_VOLTAGE_SCALE);

/* Set flash latency */
/* If freq increases, set flash latency before any clock setting */
Expand Down Expand Up @@ -928,6 +957,18 @@ int stm32_clock_control_init(const struct device *dev)
return 0;
}

/* Asserts fSYSCLK < `freq_mhz` if `vos` is selected on PWR node */
#define ASSERT_VALID_VOS(vos, freq_mhz) \
BUILD_ASSERT(DT_PROP_OR(PWR_NODE, voltage_scale, 0) != (vos) \
|| CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC <= MHZ(freq_mhz), \
"Maximal system clock frequency in voltage scale " #vos \
" is " #freq_mhz " MHz.");

ASSERT_VALID_VOS(4, 25);
ASSERT_VALID_VOS(3, 55);
ASSERT_VALID_VOS(2, 110);
ASSERT_VALID_VOS(1, 160);

/**
* @brief RCC device, note that priority is intentionally set to 1 so
* that the device init runs just after SOC init
Expand Down
2 changes: 1 addition & 1 deletion dts/arm/st/u5/stm32u5.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -927,7 +927,7 @@
};

pwr: power@46020800 {
compatible = "st,stm32-dualreg-pwr", "st,stm32-pwr";
compatible = "st,stm32u5-pwr", "st,stm32-dualreg-pwr", "st,stm32-pwr";
reg = <0x46020800 0x400>; /* PWR register bank */
status = "disabled";

Expand Down
58 changes: 58 additions & 0 deletions dts/bindings/power/st,stm32u5-pwr.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Copyright (c) 2025 STMicroelectronics
# SPDX-License-Identifier: Apache-2.0

title: STM32U5 power controller

description: |
Power controller of STM32U5 series

Controls two voltage regulators which can output one voltage
among four different voltage scales, depending on use case.

include: "st,stm32-dualreg-pwr.yaml"

properties:
voltage-scale:
type: int
description: |
Voltage regulator scale selection

If present, this property can be used to indicate the desired
voltage regulator scale to use. This choice affects several
aspects of the system:
* power consumption
* memory and flash wait states
* maximal system clock frequency
* availability of certain peripherals
* ...

The following values can be selected:
+---------+----------------+-----------------------------------+
| Scale # | Max. frequency | Notes |
+---------+----------------+-----------------------------------+
| 1 | 160 MHz | Highest power consumption |
+---------+----------------+-----------------------------------+
| 2 | 110 MHz | |
+---------+----------------+-----------------------------------+
| 3 | 55 MHz | [1] |
+---------+----------------+-----------------------------------+
| 4 | 25 MHz | [1][2]; lowest power consumption |
+---------+----------------+-----------------------------------+

[1] OTG_HS cannot be used when this voltage scale is selected.
[2] OTG_FS / USB cannot be used when this voltage scale is selected.

When this property is not present, the lowest voltage scale compatible
with the system's clock configuration is selected automatically: for
example, voltage scale 3 would be used if the system was configured
to operate with a system clock frequency of 40 MHz.

Note that the same behavior is observed if the property is provided but
the selected voltage scale is not compatible with the system's clock
configuration; in this case, clock configuration takes precedence and
the value of this property is ignored.
enum:
- 1
- 2
- 3
- 4