-
Notifications
You must be signed in to change notification settings - Fork 37
[RFC] Clocks: Remove remaining hard coding, add partial NXP fsl_power library support #512
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
3b1ef51
906e6c3
8fb7976
172e50c
f3f7b40
9e93e45
6cd5fc2
5d31062
f70ac0b
5a75c04
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,11 +1,11 @@ | ||||||||||||||||||
| //! Clock configuration for the `RT6xx` | ||||||||||||||||||
| use core::sync::atomic::{AtomicU8, AtomicU32, Ordering}; | ||||||||||||||||||
| use core::sync::atomic::{AtomicU32, Ordering}; | ||||||||||||||||||
|
|
||||||||||||||||||
| #[cfg(feature = "defmt")] | ||||||||||||||||||
| use defmt; | ||||||||||||||||||
| use paste::paste; | ||||||||||||||||||
|
|
||||||||||||||||||
| use crate::pac; | ||||||||||||||||||
| use crate::{fsl_power, pac}; | ||||||||||||||||||
|
|
||||||||||||||||||
| /// Clock configuration; | ||||||||||||||||||
| #[derive(Clone, Copy, Debug, PartialEq, Eq)] | ||||||||||||||||||
|
|
@@ -39,11 +39,11 @@ pub enum Clocks { | |||||||||||||||||
| pub struct ClockConfig { | ||||||||||||||||||
| /// low-power oscillator config | ||||||||||||||||||
| pub lposc: LposcConfig, | ||||||||||||||||||
| /// 16Mhz internal oscillator config | ||||||||||||||||||
| /// 16MHz internal oscillator config | ||||||||||||||||||
| pub sfro: SfroConfig, | ||||||||||||||||||
| /// Real Time Clock config | ||||||||||||||||||
| pub rtc: RtcClkConfig, | ||||||||||||||||||
| /// 48/60 Mhz internal oscillator config | ||||||||||||||||||
| /// 48/60 MHz internal oscillator config | ||||||||||||||||||
| pub ffro: FfroConfig, | ||||||||||||||||||
| // pub pll: Option<PllPfdConfig>, //potentially covered in main pll clk | ||||||||||||||||||
| /// External Clock-In config | ||||||||||||||||||
|
|
@@ -58,6 +58,8 @@ pub struct ClockConfig { | |||||||||||||||||
| pub sys_clk: SysClkConfig, | ||||||||||||||||||
| /// System Oscillator Config | ||||||||||||||||||
| pub sys_osc: SysOscConfig, | ||||||||||||||||||
| /// Flag to adjust VDDCORE on init based on main clock frequency, can save power | ||||||||||||||||||
| pub vddcore_adjust: bool, | ||||||||||||||||||
| // todo: move ADC here | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
|
|
@@ -68,6 +70,7 @@ impl ClockConfig { | |||||||||||||||||
| const CORE_CPU_FREQ: u32 = 500_000_000; | ||||||||||||||||||
| const PLL_CLK_FREQ: u32 = 528_000_000; | ||||||||||||||||||
| const SYS_CLK_FREQ: u32 = CORE_CPU_FREQ / 2; | ||||||||||||||||||
|
|
||||||||||||||||||
| Self { | ||||||||||||||||||
| lposc: LposcConfig { | ||||||||||||||||||
| state: State::Enabled, | ||||||||||||||||||
|
|
@@ -101,9 +104,9 @@ impl ClockConfig { | |||||||||||||||||
| }, | ||||||||||||||||||
| main_pll_clk: MainPllClkConfig { | ||||||||||||||||||
| state: State::Enabled, | ||||||||||||||||||
| src: MainPllClkSrc::SFRO, | ||||||||||||||||||
| src: MainPllClkSrc::FFRO, | ||||||||||||||||||
| freq: AtomicU32::new(PLL_CLK_FREQ), | ||||||||||||||||||
| mult: AtomicU8::new(16), | ||||||||||||||||||
| mult: MainPllClkMult::Mult22, | ||||||||||||||||||
| pfd0: 19, // | ||||||||||||||||||
| pfd1: 0, // future field | ||||||||||||||||||
| pfd2: 19, // 0x13 | ||||||||||||||||||
|
|
@@ -115,11 +118,18 @@ impl ClockConfig { | |||||||||||||||||
| sysclkfreq: AtomicU32::new(SYS_CLK_FREQ), | ||||||||||||||||||
| }, | ||||||||||||||||||
| sys_osc: SysOscConfig { state: State::Enabled }, | ||||||||||||||||||
| vddcore_adjust: false, | ||||||||||||||||||
| //adc: Some(AdcConfig {}), // TODO: add config | ||||||||||||||||||
| } | ||||||||||||||||||
| } | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| impl Default for ClockConfig { | ||||||||||||||||||
| fn default() -> Self { | ||||||||||||||||||
| Self::crystal() | ||||||||||||||||||
| } | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| #[derive(Clone, Copy, Debug, PartialEq, Eq)] | ||||||||||||||||||
| #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||||||||||||||||||
| /// Clock state enum | ||||||||||||||||||
|
|
@@ -240,7 +250,7 @@ pub struct RtcClkConfig { | |||||||||||||||||
|
|
||||||||||||||||||
| /// Valid FFRO Frequencies | ||||||||||||||||||
| pub enum FfroFreq { | ||||||||||||||||||
| /// 48 Mhz Internal Oscillator | ||||||||||||||||||
| /// 48 MHz Internal Oscillator | ||||||||||||||||||
| Ffro48m, | ||||||||||||||||||
| /// 60 `MHz` Internal Oscillator | ||||||||||||||||||
| Ffro60m, | ||||||||||||||||||
|
|
@@ -309,6 +319,25 @@ impl TryFrom<Clocks> for MainPllClkSrc { | |||||||||||||||||
| } | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| #[repr(u8)] | ||||||||||||||||||
| /// Main PLL Clock multiplication factors | ||||||||||||||||||
| /// These are the only valid multipliers for the main PLL on RT6xx | ||||||||||||||||||
| #[derive(Clone, Copy, Debug, PartialEq, Eq)] | ||||||||||||||||||
| pub enum MainPllClkMult { | ||||||||||||||||||
| /// Multiply by 16 | ||||||||||||||||||
| Mult16 = 16, | ||||||||||||||||||
| /// Multiply by 17 | ||||||||||||||||||
| Mult17 = 17, | ||||||||||||||||||
| /// Multiply by 20 | ||||||||||||||||||
| Mult20 = 20, | ||||||||||||||||||
| /// Multiply by 22 | ||||||||||||||||||
| Mult22 = 22, | ||||||||||||||||||
| /// Multiply by 27 | ||||||||||||||||||
| Mult27 = 27, | ||||||||||||||||||
| /// Multiply by 33 | ||||||||||||||||||
| Mult33 = 33, | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| /// PLL configuration. | ||||||||||||||||||
| pub struct MainPllClkConfig { | ||||||||||||||||||
| /// Clock active state | ||||||||||||||||||
|
|
@@ -319,7 +348,7 @@ pub struct MainPllClkConfig { | |||||||||||||||||
| pub freq: AtomicU32, | ||||||||||||||||||
| //TODO: numerator and denominator not used but present in register | ||||||||||||||||||
| /// Multiplication factor. | ||||||||||||||||||
| pub mult: AtomicU8, | ||||||||||||||||||
| pub mult: MainPllClkMult, | ||||||||||||||||||
| // the following are actually 6-bits not 8 | ||||||||||||||||||
| /// Fractional divider 0, main pll clock | ||||||||||||||||||
| pub pfd0: u8, | ||||||||||||||||||
|
|
@@ -440,6 +469,8 @@ pub enum ClockError { | |||||||||||||||||
| InvalidDiv, | ||||||||||||||||||
| /// Error due to attempting to modify a clock output with an invalid multiplier | ||||||||||||||||||
| InvalidMult, | ||||||||||||||||||
| /// Error due to attempting to set VDDCORE for an invalid frequency | ||||||||||||||||||
| VoltageSettingFailed, | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| /// Trait to configure one of the clocks | ||||||||||||||||||
|
|
@@ -688,7 +719,7 @@ impl MultiSourceClock for MainPllClkConfig { | |||||||||||||||||
|
|
||||||||||||||||||
| impl ConfigurableClock for MainPllClkConfig { | ||||||||||||||||||
| fn enable_and_reset(&self) -> Result<(), ClockError> { | ||||||||||||||||||
| MainPllClkConfig::init_syspll(); | ||||||||||||||||||
| self.init_syspll(); | ||||||||||||||||||
|
|
||||||||||||||||||
| MainPllClkConfig::init_syspll_pfd0(self.pfd0); | ||||||||||||||||||
|
|
||||||||||||||||||
|
|
@@ -766,27 +797,47 @@ impl ConfigurableClock for MainPllClkConfig { | |||||||||||||||||
| clkctl0.syspll0num().write(|w| unsafe { w.num().bits(0b0) }); | ||||||||||||||||||
| clkctl0.syspll0denom().write(|w| unsafe { w.denom().bits(0b1) }); | ||||||||||||||||||
| delay_loop_clocks(30, desired_freq); | ||||||||||||||||||
| self.mult.store(mult, Ordering::Relaxed); | ||||||||||||||||||
|
|
||||||||||||||||||
| match mult { | ||||||||||||||||||
| 16 => { | ||||||||||||||||||
| clkctl0.syspll0ctl0().modify(|_r, w| w.mult().div_16()); | ||||||||||||||||||
| self.mult = MainPllClkMult::Mult16; | ||||||||||||||||||
| } | ||||||||||||||||||
| 17 => { | ||||||||||||||||||
| clkctl0.syspll0ctl0().modify(|_r, w| w.mult().div_17()); | ||||||||||||||||||
| self.mult = MainPllClkMult::Mult17; | ||||||||||||||||||
| } | ||||||||||||||||||
| 20 => { | ||||||||||||||||||
| clkctl0.syspll0ctl0().modify(|_r, w| w.mult().div_20()); | ||||||||||||||||||
| self.mult = MainPllClkMult::Mult20; | ||||||||||||||||||
| } | ||||||||||||||||||
| 22 => { | ||||||||||||||||||
| clkctl0.syspll0ctl0().modify(|_r, w| w.mult().div_22()); | ||||||||||||||||||
| self.mult = MainPllClkMult::Mult22; | ||||||||||||||||||
| } | ||||||||||||||||||
| 27 => { | ||||||||||||||||||
| clkctl0.syspll0ctl0().modify(|_r, w| w.mult().div_27()); | ||||||||||||||||||
| self.mult = MainPllClkMult::Mult27; | ||||||||||||||||||
| } | ||||||||||||||||||
| 33 => { | ||||||||||||||||||
| clkctl0.syspll0ctl0().modify(|_r, w| w.mult().div_33()); | ||||||||||||||||||
| self.mult = MainPllClkMult::Mult33; | ||||||||||||||||||
| } | ||||||||||||||||||
| _ => { | ||||||||||||||||||
| warn!( | ||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is reasonable to panic here as the value input should be constrained by the enum in the configuration struct.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Or better yet, make |
||||||||||||||||||
| "Setting clock rate of {}Hz failed due to Invalid mult value for Main PLL: {}. A valid combo of parameters must be used.", | ||||||||||||||||||
| freq, mult | ||||||||||||||||||
| ); | ||||||||||||||||||
| // make sure to power syspll back up before returning the error | ||||||||||||||||||
| // Clear System PLL reset | ||||||||||||||||||
| clkctl0.syspll0ctl0().write(|w| w.reset().normal()); | ||||||||||||||||||
| // Power up SYSPLL | ||||||||||||||||||
| sysctl0 | ||||||||||||||||||
| .pdruncfg0_clr() | ||||||||||||||||||
| .write(|w| w.syspllana_pd().clr_pdruncfg0().syspllldo_pd().clr_pdruncfg0()); | ||||||||||||||||||
|
|
||||||||||||||||||
| return Err(ClockError::InvalidMult); | ||||||||||||||||||
| } | ||||||||||||||||||
| _ => return Err(ClockError::InvalidMult), | ||||||||||||||||||
| } | ||||||||||||||||||
| // Clear System PLL reset | ||||||||||||||||||
| clkctl0.syspll0ctl0().modify(|_r, w| w.reset().normal()); | ||||||||||||||||||
|
|
@@ -851,7 +902,7 @@ impl MainPllClkConfig { | |||||||||||||||||
| } | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| pub(self) fn init_syspll() { | ||||||||||||||||||
| pub(self) fn init_syspll(&self) { | ||||||||||||||||||
| // SAFETY: unsafe needed to take pointers to Sysctl0 and Clkctl0 | ||||||||||||||||||
| let clkctl0 = unsafe { crate::pac::Clkctl0::steal() }; | ||||||||||||||||||
| let sysctl0 = unsafe { crate::pac::Sysctl0::steal() }; | ||||||||||||||||||
|
|
@@ -861,13 +912,33 @@ impl MainPllClkConfig { | |||||||||||||||||
| .pdruncfg0_set() | ||||||||||||||||||
| .write(|w| w.syspllldo_pd().set_pdruncfg0().syspllana_pd().set_pdruncfg0()); | ||||||||||||||||||
|
|
||||||||||||||||||
| clkctl0.syspll0clksel().write(|w| w.sel().ffro_div_2()); | ||||||||||||||||||
| match self.src { | ||||||||||||||||||
madeleyneVaca marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||
| MainPllClkSrc::ClkIn => { | ||||||||||||||||||
| clkctl0.syspll0clksel().write(|w| w.sel().sysxtal_clk()); | ||||||||||||||||||
| } | ||||||||||||||||||
| MainPllClkSrc::FFRO => { | ||||||||||||||||||
| // FFRO Clock is divided by 2 | ||||||||||||||||||
| clkctl0.syspll0clksel().write(|w| w.sel().ffro_div_2()); | ||||||||||||||||||
| } | ||||||||||||||||||
| MainPllClkSrc::SFRO => { | ||||||||||||||||||
| clkctl0.syspll0clksel().write(|w| w.sel().sfro_clk()); | ||||||||||||||||||
| } | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| // SAFETY: unsafe needed to write the bits for both num and denom | ||||||||||||||||||
| clkctl0.syspll0num().write(|w| unsafe { w.num().bits(0x0) }); | ||||||||||||||||||
| clkctl0.syspll0denom().write(|w| unsafe { w.denom().bits(0x1) }); | ||||||||||||||||||
|
|
||||||||||||||||||
| // kCLOCK_SysPllMult22 | ||||||||||||||||||
| clkctl0.syspll0ctl0().modify(|_, w| w.mult().div_22()); | ||||||||||||||||||
| // kCLOCK_SetSysPll<Mult> | ||||||||||||||||||
| // Use the mult defined in main pll config | ||||||||||||||||||
| match self.mult { | ||||||||||||||||||
| MainPllClkMult::Mult16 => clkctl0.syspll0ctl0().modify(|_, w| w.mult().div_16()), | ||||||||||||||||||
| MainPllClkMult::Mult17 => clkctl0.syspll0ctl0().modify(|_, w| w.mult().div_17()), | ||||||||||||||||||
| MainPllClkMult::Mult20 => clkctl0.syspll0ctl0().modify(|_, w| w.mult().div_20()), | ||||||||||||||||||
| MainPllClkMult::Mult22 => clkctl0.syspll0ctl0().modify(|_, w| w.mult().div_22()), | ||||||||||||||||||
| MainPllClkMult::Mult27 => clkctl0.syspll0ctl0().modify(|_, w| w.mult().div_27()), | ||||||||||||||||||
| MainPllClkMult::Mult33 => clkctl0.syspll0ctl0().modify(|_, w| w.mult().div_33()), | ||||||||||||||||||
| }; | ||||||||||||||||||
|
|
||||||||||||||||||
| // Clear System PLL reset | ||||||||||||||||||
| clkctl0.syspll0ctl0().modify(|_, w| w.reset().normal()); | ||||||||||||||||||
|
|
@@ -890,7 +961,7 @@ impl MainPllClkConfig { | |||||||||||||||||
| /// enables default settings for pfd2 bits | ||||||||||||||||||
| pub(self) fn init_syspll_pfd2(config_bits: u8) { | ||||||||||||||||||
| // SAFETY: unsafe needed to take pointer to Clkctl0 and write specific bits | ||||||||||||||||||
| // needed to change the output of pfd0 | ||||||||||||||||||
| // needed to change the output of pfd2 | ||||||||||||||||||
| let clkctl0 = unsafe { crate::pac::Clkctl0::steal() }; | ||||||||||||||||||
|
|
||||||||||||||||||
| // Disable the clock output first. | ||||||||||||||||||
|
|
@@ -1537,6 +1608,46 @@ fn init_clock_hw(config: ClockConfig) -> Result<(), ClockError> { | |||||||||||||||||
| // Increase divisor to safe value. | ||||||||||||||||||
| init_syscpuahb_clk(256); | ||||||||||||||||||
|
|
||||||||||||||||||
| const SYSPLL_MULTIPLIER_FOR_PFDS: u32 = 18; | ||||||||||||||||||
| // These calculations will not overflow and panic since that'd require a freq in the GHz range which is not supported by the hardware | ||||||||||||||||||
| let true_main_clk_freq: u32 = (config.main_pll_clk.freq.load(Ordering::Relaxed) / config.main_pll_clk.pfd0 as u32) | ||||||||||||||||||
| * SYSPLL_MULTIPLIER_FOR_PFDS; | ||||||||||||||||||
|
Comment on lines
+1613
to
+1614
|
||||||||||||||||||
| let true_main_clk_freq: u32 = (config.main_pll_clk.freq.load(Ordering::Relaxed) / config.main_pll_clk.pfd0 as u32) | |
| * SYSPLL_MULTIPLIER_FOR_PFDS; | |
| let pfd0 = config.main_pll_clk.pfd0 as u32; | |
| if pfd0 == 0 { | |
| panic!("config.main_pll_clk.pfd0 must be non-zero to avoid divide-by-zero in main clock frequency calculation"); | |
| } | |
| let true_main_clk_freq: u32 = | |
| (config.main_pll_clk.freq.load(Ordering::Relaxed) / pfd0) * SYSPLL_MULTIPLIER_FOR_PFDS; |
madeleyneVaca marked this conversation as resolved.
Show resolved
Hide resolved
Copilot
AI
Jan 7, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The temperature range is hardcoded to TempRange::TempN20CtoP85C (-20°C to 85°C). This may not be appropriate for all use cases, particularly if the hardware is rated for the narrower 0°C to 85°C range (TempRange::Temp0Cto85C). Using the wider temperature range when not needed could result in conservative (higher) voltage settings that waste power. Consider making the temperature range configurable via the ClockConfig struct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo in comment: "demon" should be "denom" (short for denominator).