stm32/rcc: make h7 rm0399 power supply configurable

This commit is contained in:
Badr Bouslikhin 2023-12-01 15:05:31 +01:00
parent fe8c46bce3
commit c97f65ac60
No known key found for this signature in database

View File

@ -117,6 +117,57 @@ impl From<TimerPrescaler> for Timpre {
}
}
/// Power supply configuration
/// See RM0433 Rev 4 7.4
#[cfg(pwr_h7rm0399)]
pub enum SupplyConfig {
/// Default power supply configuration.
/// V CORE Power Domains are supplied from the LDO according to VOS.
/// SMPS step-down converter enabled at 1.2V, may be used to supply the LDO.
Default,
/// Power supply configuration using the LDO.
/// V CORE Power Domains are supplied from the LDO according to VOS.
/// LDO power mode (Main, LP, Off) will follow system low-power modes.
/// SMPS step-down converter disabled.
LDO,
/// Power supply configuration directly from the SMPS step-down converter.
/// V CORE Power Domains are supplied from SMPS step-down converter according to VOS.
/// LDO bypassed.
/// SMPS step-down converter power mode (MR, LP, Off) will follow system low-power modes.
DirectSMPS,
/// Power supply configuration from the SMPS step-down converter, that supplies the LDO.
/// V CORE Power Domains are supplied from the LDO according to VOS
/// LDO power mode (Main, LP, Off) will follow system low-power modes.
/// SMPS step-down converter enabled according to SDLEVEL, and supplies the LDO.
/// SMPS step-down converter power mode (MR, LP, Off) will follow system low-power modes.
SMPSLDO,
/// Power supply configuration from SMPS supplying external circuits and potentially the LDO.
/// V CORE Power Domains are supplied from voltage regulator according to VOS
/// LDO power mode (Main, LP, Off) will follow system low-power modes.
/// SMPS step-down converter enabled according to SDLEVEL used to supply external circuits and may supply the LDO.
/// SMPS step-down converter forced ON in MR mode.
SMPSExternalLDO,
/// Power supply configuration from SMPS supplying external circuits and bypassing the LDO.
/// V CORE supplied from external source
/// SMPS step-down converter enabled according to SDLEVEL used to supply external circuits and may supply the external source for V CORE .
/// SMPS step-down converter forced ON in MR mode.
SMPSExternalLDOBypass,
}
/// SMPS step-down converter voltage output level.
/// This is only used in certain power supply configurations:
/// SMPSLDO, SMPSExternalLDO, SMPSExternalLDOBypass.
#[cfg(pwr_h7rm0399)]
pub enum SMPSSupplyVoltage {
V1_8,
V2_5,
}
/// Configuration of the core clocks
#[non_exhaustive]
pub struct Config {
@ -144,6 +195,10 @@ pub struct Config {
pub timer_prescaler: TimerPrescaler,
pub voltage_scale: VoltageScale,
pub ls: super::LsConfig,
#[cfg(pwr_h7rm0399)]
pub supply_config: SupplyConfig,
pub smps_supply_voltage: Option<SMPSSupplyVoltage>,
}
impl Default for Config {
@ -177,6 +232,10 @@ impl Default for Config {
timer_prescaler: TimerPrescaler::DefaultX2,
voltage_scale: VoltageScale::Scale0,
ls: Default::default(),
#[cfg(pwr_h7rm0399)]
supply_config: SupplyConfig::Default,
smps_supply_voltage: None,
}
}
}
@ -194,7 +253,7 @@ pub(crate) unsafe fn init(config: Config) {
w.set_bypass(false);
});
#[cfg(any(pwr_h7rm0399, pwr_h7rm0455, pwr_h7rm0468))]
#[cfg(any(pwr_h7rm0455, pwr_h7rm0468))]
PWR.cr3().modify(|w| {
// hardcode "Direct SPMS" for now, this is what works on nucleos with the
// default solderbridge configuration.
@ -202,6 +261,93 @@ pub(crate) unsafe fn init(config: Config) {
w.set_ldoen(false);
});
#[cfg(pwr_h7rm0399)]
{
match config.supply_config {
SupplyConfig::Default => {
PWR.cr3().modify(|w| {
w.set_sdlevel(0b00);
w.set_sdexthp(false);
w.set_sden(true);
w.set_ldoen(true);
w.set_bypass(false);
});
}
SupplyConfig::LDO => {
PWR.cr3().modify(|w| {
w.set_sden(false);
w.set_ldoen(true);
w.set_bypass(false);
});
}
SupplyConfig::DirectSMPS => {
PWR.cr3().modify(|w| {
w.set_sdexthp(false);
w.set_sden(true);
w.set_ldoen(false);
w.set_bypass(false);
});
}
SupplyConfig::SMPSLDO => {
PWR.cr3().modify(|w| {
match config.smps_supply_voltage {
Some(SMPSSupplyVoltage::V1_8) => {
PWR.cr3().modify(|w| w.set_sdlevel(0b01));
}
Some(SMPSSupplyVoltage::V2_5) => {
PWR.cr3().modify(|w| w.set_sdlevel(0b10));
}
None => {
panic!("Supply configuration SMPSLDO requires a supply voltage to be set.");
}
}
w.set_sdexthp(false);
w.set_sden(true);
w.set_ldoen(true);
w.set_bypass(false);
});
}
SupplyConfig::SMPSExternalLDO => {
PWR.cr3().modify(|w| {
match config.smps_supply_voltage {
Some(SMPSSupplyVoltage::V1_8) => {
PWR.cr3().modify(|w| w.set_sdlevel(0b01));
}
Some(SMPSSupplyVoltage::V2_5) => {
PWR.cr3().modify(|w| w.set_sdlevel(0b10));
}
None => {
panic!("Supply configuration SMPSExternalLDO requires a supply voltage to be set.");
}
}
w.set_sdexthp(true);
w.set_sden(true);
w.set_ldoen(true);
w.set_bypass(false);
});
}
SupplyConfig::SMPSExternalLDOBypass => {
PWR.cr3().modify(|w| {
match config.smps_supply_voltage {
Some(SMPSSupplyVoltage::V1_8) => {
PWR.cr3().modify(|w| w.set_sdlevel(0b01));
}
Some(SMPSSupplyVoltage::V2_5) => {
PWR.cr3().modify(|w| w.set_sdlevel(0b10));
}
None => {
panic!("Supply configuration SMPSExternalLDOBypass requires a supply voltage to be set.");
}
}
w.set_sdexthp(true);
w.set_sden(true);
w.set_ldoen(false);
w.set_bypass(true);
});
}
}
}
// Validate the supply configuration. If you are stuck here, it is
// because the voltages on your board do not match those specified
// in the D3CR.VOS and CR3.SDLEVEL fields. By default after reset