From c3b121bc64ee3af581495d66410f1af122387c28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Mon, 24 Aug 2026 16:38:29 +0200 Subject: [PATCH] Correctly model MEM_CLK and SYS_CLK --- esp-hal/src/soc/esp32s31/clocks.rs | 34 ++- .../src/_build_script_utils.rs | 12 +- .../src/_generated_esp32s31.rs | 213 +++++++++++++----- esp-metadata/devices/esp32p4/clocks.toml | 2 +- esp-metadata/devices/esp32s31/clocks.toml | 7 +- 5 files changed, 200 insertions(+), 68 deletions(-) diff --git a/esp-hal/src/soc/esp32s31/clocks.rs b/esp-hal/src/soc/esp32s31/clocks.rs index bc2159d7e3f..3224f922ff4 100644 --- a/esp-hal/src/soc/esp32s31/clocks.rs +++ b/esp-hal/src/soc/esp32s31/clocks.rs @@ -41,8 +41,9 @@ impl CpuClock { const PRESET_160: ClockConfig = ClockConfig { cpu_root_clk: Some(CpuRootClkConfig::Cpll), cpu_clk: Some(CpuClkConfig::new(1)), - ahb_clk: Some(AhbClkConfig::new(1)), - apb_clk: Some(ApbClkConfig::new(1)), + mem_clk: Some(MemClkConfig::new(0)), // Max 160 MHz + sys_clk: Some(SysClkConfig::new(1)), // Max ~320/3 MHz + apb_clk: Some(ApbClkConfig::new(1)), // MAX ~320/6MHz lp_fast_clk: Some(LpFastClkConfig::RcFast), lp_slow_clk: Some(xtal32k::default_lp_slow_clk()), iomux_function_clock: Some(IomuxFunctionClockConfig::new( @@ -54,8 +55,9 @@ impl CpuClock { const PRESET_240: ClockConfig = ClockConfig { cpu_root_clk: Some(CpuRootClkConfig::PllF240m), cpu_clk: Some(CpuClkConfig::new(0)), - ahb_clk: Some(AhbClkConfig::new(2)), - apb_clk: Some(ApbClkConfig::new(1)), + mem_clk: Some(MemClkConfig::new(1)), // Max 160 MHz + sys_clk: Some(SysClkConfig::new(2)), // Max ~320/3 MHz + apb_clk: Some(ApbClkConfig::new(1)), // MAX ~320/6MHz lp_fast_clk: Some(LpFastClkConfig::RcFast), lp_slow_clk: Some(xtal32k::default_lp_slow_clk()), iomux_function_clock: Some(IomuxFunctionClockConfig::new( @@ -67,8 +69,9 @@ impl CpuClock { const PRESET_320: ClockConfig = ClockConfig { cpu_root_clk: Some(CpuRootClkConfig::Cpll), cpu_clk: Some(CpuClkConfig::new(0)), - ahb_clk: Some(AhbClkConfig::new(2)), - apb_clk: Some(ApbClkConfig::new(1)), + mem_clk: Some(MemClkConfig::new(1)), // Max 160 MHz + sys_clk: Some(SysClkConfig::new(2)), // Max ~320/3 MHz + apb_clk: Some(ApbClkConfig::new(1)), // MAX ~320/6MHz lp_fast_clk: Some(LpFastClkConfig::RcFast), lp_slow_clk: Some(xtal32k::default_lp_slow_clk()), iomux_function_clock: Some(IomuxFunctionClockConfig::new( @@ -420,11 +423,26 @@ fn configure_cpu_clk_impl(_clocks: &mut ClockTree, _old: Option, n } } -fn enable_ahb_clk_impl(_clocks: &mut ClockTree, _en: bool) { +// MEM_CLK + +fn enable_mem_clk_impl(_clocks: &mut ClockTree, _en: bool) { + // Nothing to do here +} + +fn configure_mem_clk_impl(_clocks: &mut ClockTree, _old: Option, new: MemClkConfig) { + HP_SYS_CLKRST::regs() + .mem_freq_ctrl0() + .modify(|_, w| w.mem_clk_div_num().bit(new.divisor() == 1)); + update_bus_clocks(); +} + +// SYS_CLK + +fn enable_sys_clk_impl(_clocks: &mut ClockTree, _en: bool) { // Nothing to do here } -fn configure_ahb_clk_impl(_clocks: &mut ClockTree, _old: Option, new: AhbClkConfig) { +fn configure_sys_clk_impl(_clocks: &mut ClockTree, _old: Option, new: SysClkConfig) { HP_SYS_CLKRST::regs() .sys_freq_ctrl0() .modify(|_, w| unsafe { diff --git a/esp-metadata-generated/src/_build_script_utils.rs b/esp-metadata-generated/src/_build_script_utils.rs index f4a24c28ac5..bac1bfb3953 100644 --- a/esp-metadata-generated/src/_build_script_utils.rs +++ b/esp-metadata-generated/src/_build_script_utils.rs @@ -8157,8 +8157,10 @@ impl Chip { "soc_clock_node_cpu_root_clk_is_configurable", "soc_has_clock_node_cpu_clk", "soc_clock_node_cpu_clk_is_configurable", - "soc_has_clock_node_ahb_clk", - "soc_clock_node_ahb_clk_is_configurable", + "soc_has_clock_node_mem_clk", + "soc_clock_node_mem_clk_is_configurable", + "soc_has_clock_node_sys_clk", + "soc_clock_node_sys_clk_is_configurable", "soc_has_clock_node_apb_clk", "soc_clock_node_apb_clk_is_configurable", "soc_has_clock_node_lp_fast_clk", @@ -8446,8 +8448,10 @@ impl Chip { "cargo:rustc-cfg=soc_clock_node_cpu_root_clk_is_configurable", "cargo:rustc-cfg=soc_has_clock_node_cpu_clk", "cargo:rustc-cfg=soc_clock_node_cpu_clk_is_configurable", - "cargo:rustc-cfg=soc_has_clock_node_ahb_clk", - "cargo:rustc-cfg=soc_clock_node_ahb_clk_is_configurable", + "cargo:rustc-cfg=soc_has_clock_node_mem_clk", + "cargo:rustc-cfg=soc_clock_node_mem_clk_is_configurable", + "cargo:rustc-cfg=soc_has_clock_node_sys_clk", + "cargo:rustc-cfg=soc_clock_node_sys_clk_is_configurable", "cargo:rustc-cfg=soc_has_clock_node_apb_clk", "cargo:rustc-cfg=soc_clock_node_apb_clk_is_configurable", "cargo:rustc-cfg=soc_has_clock_node_lp_fast_clk", diff --git a/esp-metadata-generated/src/_generated_esp32s31.rs b/esp-metadata-generated/src/_generated_esp32s31.rs index d6048b5537d..8ebec15e7be 100644 --- a/esp-metadata-generated/src/_generated_esp32s31.rs +++ b/esp-metadata-generated/src/_generated_esp32s31.rs @@ -454,7 +454,10 @@ macro_rules! property { ("clock_tree.cpu_clk.divisor") => { (0, 255) }; - ("clock_tree.ahb_clk.divisor") => { + ("clock_tree.mem_clk.divisor") => { + (0, 1) + }; + ("clock_tree.sys_clk.divisor") => { (0, 255) }; ("clock_tree.apb_clk.divisor") => { @@ -1409,16 +1412,30 @@ macro_rules! for_each_sw_interrupt { /// todo!() /// } /// -/// // AHB_CLK +/// // MEM_CLK /// -/// fn enable_ahb_clk_impl(_clocks: &mut ClockTree, _en: bool) { +/// fn enable_mem_clk_impl(_clocks: &mut ClockTree, _en: bool) { /// todo!() /// } /// -/// fn configure_ahb_clk_impl( +/// fn configure_mem_clk_impl( /// _clocks: &mut ClockTree, -/// _old_config: Option, -/// _new_config: AhbClkConfig, +/// _old_config: Option, +/// _new_config: MemClkConfig, +/// ) { +/// todo!() +/// } +/// +/// // SYS_CLK +/// +/// fn enable_sys_clk_impl(_clocks: &mut ClockTree, _en: bool) { +/// todo!() +/// } +/// +/// fn configure_sys_clk_impl( +/// _clocks: &mut ClockTree, +/// _old_config: Option, +/// _new_config: SysClkConfig, /// ) { /// todo!() /// } @@ -1707,16 +1724,42 @@ macro_rules! define_clock_tree_types { self.divisor as u32 } } - /// Configures the `AHB_CLK` clock node. + /// Configures the `MEM_CLK` clock node. + /// + /// The output is calculated as `OUTPUT = CPU_CLK / (divisor + 1)`. + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] + pub struct MemClkConfig { + divisor: u32, + } + impl MemClkConfig { + /// Creates a new configuration for the MEM_CLK clock node. + /// + /// ## Panics + /// + /// Panics if the divisor value is outside the + /// valid range (0 ..= 1). + pub const fn new(divisor: u32) -> Self { + ::core::assert!( + divisor <= 1, + "`MEM_CLK` divisor must be between 0 and 1 (inclusive)." + ); + Self { divisor } + } + pub(crate) fn divisor(self) -> u32 { + self.divisor as u32 + } + } + /// Configures the `SYS_CLK` clock node. /// /// The output is calculated as `OUTPUT = CPU_CLK / (divisor + 1)`. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] - pub struct AhbClkConfig { + pub struct SysClkConfig { divisor: u32, } - impl AhbClkConfig { - /// Creates a new configuration for the AHB_CLK clock node. + impl SysClkConfig { + /// Creates a new configuration for the SYS_CLK clock node. /// /// ## Panics /// @@ -1725,7 +1768,7 @@ macro_rules! define_clock_tree_types { pub const fn new(divisor: u32) -> Self { ::core::assert!( divisor <= 255, - "`AHB_CLK` divisor must be between 0 and 255 (inclusive)." + "`SYS_CLK` divisor must be between 0 and 255 (inclusive)." ); Self { divisor } } @@ -1735,7 +1778,7 @@ macro_rules! define_clock_tree_types { } /// Configures the `APB_CLK` clock node. /// - /// The output is calculated as `OUTPUT = AHB_CLK / (divisor + 1)`. + /// The output is calculated as `OUTPUT = SYS_CLK / (divisor + 1)`. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct ApbClkConfig { @@ -2012,7 +2055,8 @@ macro_rules! define_clock_tree_types { pub struct ClockTree { cpu_root_clk: Option, cpu_clk: Option, - ahb_clk: Option, + mem_clk: Option, + sys_clk: Option, apb_clk: Option, lp_fast_clk: Option, lp_slow_clk: Option, @@ -2039,6 +2083,8 @@ macro_rules! define_clock_tree_types { pll_f25m_refcount: u32, pll_f50m_refcount: u32, xtal_d2_clk_refcount: u32, + cpu_clk_refcount: u32, + mem_clk_refcount: u32, lp_fast_clk_refcount: u32, lp_slow_clk_refcount: u32, timg_calibration_clock_refcount: u32, @@ -2066,9 +2112,13 @@ macro_rules! define_clock_tree_types { pub fn cpu_clk(&self) -> Option { self.cpu_clk } - /// Returns the current configuration of the AHB_CLK clock tree node - pub fn ahb_clk(&self) -> Option { - self.ahb_clk + /// Returns the current configuration of the MEM_CLK clock tree node + pub fn mem_clk(&self) -> Option { + self.mem_clk + } + /// Returns the current configuration of the SYS_CLK clock tree node + pub fn sys_clk(&self) -> Option { + self.sys_clk } /// Returns the current configuration of the APB_CLK clock tree node pub fn apb_clk(&self) -> Option { @@ -2167,7 +2217,8 @@ macro_rules! define_clock_tree_types { ::esp_sync::NonReentrantMutex::new(ClockTree { cpu_root_clk: None, cpu_clk: None, - ahb_clk: None, + mem_clk: None, + sys_clk: None, apb_clk: None, lp_fast_clk: None, lp_slow_clk: None, @@ -2194,6 +2245,8 @@ macro_rules! define_clock_tree_types { pll_f25m_refcount: 0, pll_f50m_refcount: 0, xtal_d2_clk_refcount: 0, + cpu_clk_refcount: 0, + mem_clk_refcount: 0, lp_fast_clk_refcount: 0, lp_slow_clk_refcount: 0, timg_calibration_clock_refcount: 0, @@ -2212,7 +2265,9 @@ macro_rules! define_clock_tree_types { ::core::sync::atomic::AtomicU32::new(0); static CPU_CLK_FREQ_CACHE: ::core::sync::atomic::AtomicU32 = ::core::sync::atomic::AtomicU32::new(0); - static AHB_CLK_FREQ_CACHE: ::core::sync::atomic::AtomicU32 = + static MEM_CLK_FREQ_CACHE: ::core::sync::atomic::AtomicU32 = + ::core::sync::atomic::AtomicU32::new(0); + static SYS_CLK_FREQ_CACHE: ::core::sync::atomic::AtomicU32 = ::core::sync::atomic::AtomicU32::new(0); static APB_CLK_FREQ_CACHE: ::core::sync::atomic::AtomicU32 = ::core::sync::atomic::AtomicU32::new(0); @@ -2611,15 +2666,19 @@ macro_rules! define_clock_tree_types { } pub fn request_cpu_clk(clocks: &mut ClockTree) { trace!("Requesting CPU_CLK"); - trace!("Enabling CPU_CLK"); - request_cpu_root_clk(clocks); - enable_cpu_clk_impl(clocks, true); + if increment_reference_count(&mut clocks.cpu_clk_refcount) { + trace!("Enabling CPU_CLK"); + request_cpu_root_clk(clocks); + enable_cpu_clk_impl(clocks, true); + } } pub fn release_cpu_clk(clocks: &mut ClockTree) { trace!("Releasing CPU_CLK"); - trace!("Disabling CPU_CLK"); - enable_cpu_clk_impl(clocks, false); - release_cpu_root_clk(clocks); + if decrement_reference_count(&mut clocks.cpu_clk_refcount) { + trace!("Disabling CPU_CLK"); + enable_cpu_clk_impl(clocks, false); + release_cpu_root_clk(clocks); + } } #[allow(unused_variables)] pub fn cpu_clk_config_frequency(clocks: &mut ClockTree, config: CpuClkConfig) -> u32 { @@ -2631,34 +2690,68 @@ macro_rules! define_clock_tree_types { pub fn cpu_clk_source_frequency() -> u32 { cpu_root_clk_frequency() } - pub fn configure_ahb_clk(clocks: &mut ClockTree, config: AhbClkConfig) { - let old_config = clocks.ahb_clk.replace(config); - refresh_ahb_clk_downstream(clocks); - configure_ahb_clk_impl(clocks, old_config, config); + pub fn configure_mem_clk(clocks: &mut ClockTree, config: MemClkConfig) { + let old_config = clocks.mem_clk.replace(config); + refresh_mem_clk_downstream(clocks); + configure_mem_clk_impl(clocks, old_config, config); + } + pub fn mem_clk_config(clocks: &mut ClockTree) -> Option { + clocks.mem_clk + } + pub fn request_mem_clk(clocks: &mut ClockTree) { + trace!("Requesting MEM_CLK"); + if increment_reference_count(&mut clocks.mem_clk_refcount) { + trace!("Enabling MEM_CLK"); + request_cpu_clk(clocks); + enable_mem_clk_impl(clocks, true); + } } - pub fn ahb_clk_config(clocks: &mut ClockTree) -> Option { - clocks.ahb_clk + pub fn release_mem_clk(clocks: &mut ClockTree) { + trace!("Releasing MEM_CLK"); + if decrement_reference_count(&mut clocks.mem_clk_refcount) { + trace!("Disabling MEM_CLK"); + enable_mem_clk_impl(clocks, false); + release_cpu_clk(clocks); + } } - pub fn request_ahb_clk(clocks: &mut ClockTree) { - trace!("Requesting AHB_CLK"); - trace!("Enabling AHB_CLK"); + #[allow(unused_variables)] + pub fn mem_clk_config_frequency(clocks: &mut ClockTree, config: MemClkConfig) -> u32 { + (cpu_clk_frequency() / (config.divisor() + 1)) + } + pub fn mem_clk_frequency() -> u32 { + MEM_CLK_FREQ_CACHE.load(::core::sync::atomic::Ordering::Acquire) + } + pub fn mem_clk_source_frequency() -> u32 { + cpu_clk_frequency() + } + pub fn configure_sys_clk(clocks: &mut ClockTree, config: SysClkConfig) { + let old_config = clocks.sys_clk.replace(config); + refresh_sys_clk_downstream(clocks); + configure_sys_clk_impl(clocks, old_config, config); + } + pub fn sys_clk_config(clocks: &mut ClockTree) -> Option { + clocks.sys_clk + } + pub fn request_sys_clk(clocks: &mut ClockTree) { + trace!("Requesting SYS_CLK"); + trace!("Enabling SYS_CLK"); request_cpu_clk(clocks); - enable_ahb_clk_impl(clocks, true); + enable_sys_clk_impl(clocks, true); } - pub fn release_ahb_clk(clocks: &mut ClockTree) { - trace!("Releasing AHB_CLK"); - trace!("Disabling AHB_CLK"); - enable_ahb_clk_impl(clocks, false); + pub fn release_sys_clk(clocks: &mut ClockTree) { + trace!("Releasing SYS_CLK"); + trace!("Disabling SYS_CLK"); + enable_sys_clk_impl(clocks, false); release_cpu_clk(clocks); } #[allow(unused_variables)] - pub fn ahb_clk_config_frequency(clocks: &mut ClockTree, config: AhbClkConfig) -> u32 { + pub fn sys_clk_config_frequency(clocks: &mut ClockTree, config: SysClkConfig) -> u32 { (cpu_clk_frequency() / (config.divisor() + 1)) } - pub fn ahb_clk_frequency() -> u32 { - AHB_CLK_FREQ_CACHE.load(::core::sync::atomic::Ordering::Acquire) + pub fn sys_clk_frequency() -> u32 { + SYS_CLK_FREQ_CACHE.load(::core::sync::atomic::Ordering::Acquire) } - pub fn ahb_clk_source_frequency() -> u32 { + pub fn sys_clk_source_frequency() -> u32 { cpu_clk_frequency() } pub fn configure_apb_clk(clocks: &mut ClockTree, config: ApbClkConfig) { @@ -2673,13 +2766,13 @@ macro_rules! define_clock_tree_types { fn release_apb_clk(_clocks: &mut ClockTree) {} #[allow(unused_variables)] pub fn apb_clk_config_frequency(clocks: &mut ClockTree, config: ApbClkConfig) -> u32 { - (ahb_clk_frequency() / (config.divisor() + 1)) + (sys_clk_frequency() / (config.divisor() + 1)) } pub fn apb_clk_frequency() -> u32 { APB_CLK_FREQ_CACHE.load(::core::sync::atomic::Ordering::Acquire) } pub fn apb_clk_source_frequency() -> u32 { - ahb_clk_frequency() + sys_clk_frequency() } pub fn configure_lp_fast_clk(clocks: &mut ClockTree, new_selector: LpFastClkConfig) { let old_selector = clocks.lp_fast_clk.replace(new_selector); @@ -3587,8 +3680,10 @@ macro_rules! define_clock_tree_types { pub cpu_root_clk: Option, /// `CPU_CLK` configuration. pub cpu_clk: Option, - /// `AHB_CLK` configuration. - pub ahb_clk: Option, + /// `MEM_CLK` configuration. + pub mem_clk: Option, + /// `SYS_CLK` configuration. + pub sys_clk: Option, /// `APB_CLK` configuration. pub apb_clk: Option, /// `LP_FAST_CLK` configuration. @@ -3608,8 +3703,11 @@ macro_rules! define_clock_tree_types { if let Some(config) = self.cpu_clk { configure_cpu_clk(clocks, config); } - if let Some(config) = self.ahb_clk { - configure_ahb_clk(clocks, config); + if let Some(config) = self.mem_clk { + configure_mem_clk(clocks, config); + } + if let Some(config) = self.sys_clk { + configure_sys_clk(clocks, config); } if let Some(config) = self.apb_clk { configure_apb_clk(clocks, config); @@ -3654,12 +3752,21 @@ macro_rules! define_clock_tree_types { ::core::sync::atomic::Ordering::Release, ); } - refresh_ahb_clk_downstream(clocks); + refresh_mem_clk_downstream(clocks); + refresh_sys_clk_downstream(clocks); + } + fn refresh_mem_clk_downstream(clocks: &mut ClockTree) { + if let Some(config) = clocks.mem_clk { + MEM_CLK_FREQ_CACHE.store( + mem_clk_config_frequency(clocks, config), + ::core::sync::atomic::Ordering::Release, + ); + } } - fn refresh_ahb_clk_downstream(clocks: &mut ClockTree) { - if let Some(config) = clocks.ahb_clk { - AHB_CLK_FREQ_CACHE.store( - ahb_clk_config_frequency(clocks, config), + fn refresh_sys_clk_downstream(clocks: &mut ClockTree) { + if let Some(config) = clocks.sys_clk { + SYS_CLK_FREQ_CACHE.store( + sys_clk_config_frequency(clocks, config), ::core::sync::atomic::Ordering::Release, ); } diff --git a/esp-metadata/devices/esp32p4/clocks.toml b/esp-metadata/devices/esp32p4/clocks.toml index 47f354f2228..b31ab6d0da9 100644 --- a/esp-metadata/devices/esp32p4/clocks.toml +++ b/esp-metadata/devices/esp32p4/clocks.toml @@ -45,7 +45,7 @@ system_clocks = { clock_tree = [ ] }, # TODO: model fractional divider parameters - # CPU_CLK divider (HP_SYS_CLKRST.root_clk_ctrl0.cpu_clk_div_num) + # CPU_CLK divider { name = "CPU_CLK", type = "generic", params = { divisor = "0..256" }, output = "CPU_ROOT_CLK / (divisor + 1)" }, # MEM_CLK divider { name = "MEM_CLK", type = "generic", params = { divisor = "0..256" }, output = "CPU_CLK / (divisor + 1)" }, diff --git a/esp-metadata/devices/esp32s31/clocks.toml b/esp-metadata/devices/esp32s31/clocks.toml index cd162c0840f..4c5b5edd217 100644 --- a/esp-metadata/devices/esp32s31/clocks.toml +++ b/esp-metadata/devices/esp32s31/clocks.toml @@ -32,9 +32,12 @@ system_clocks = { clock_tree = [ ] }, { name = "CPU_CLK", type = "generic", params = { divisor = "0..256" }, output = "CPU_ROOT_CLK / (divisor + 1)" }, - { name = "AHB_CLK", type = "generic", params = { divisor = "0..256" }, output = "CPU_CLK / (divisor + 1)" }, + # MEM_CLK divider + { name = "MEM_CLK", type = "generic", params = { divisor = "0..2" }, output = "CPU_CLK / (divisor + 1)" }, + # SYS_CLK divider + { name = "SYS_CLK", type = "generic", params = { divisor = "0..256" }, output = "CPU_CLK / (divisor + 1)" }, # APB is a core system bus and must not be released with a peripheral clock. - { name = "APB_CLK", type = "generic", params = { divisor = "0..256" }, output = "AHB_CLK / (divisor + 1)", always_on = true }, + { name = "APB_CLK", type = "generic", params = { divisor = "0..256" }, output = "SYS_CLK / (divisor + 1)", always_on = true }, # LP clocks { name = "LP_FAST_CLK", type = "mux", variants = [