aboutsummaryrefslogtreecommitdiff
path: root/src/clocks/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/clocks/mod.rs')
-rw-r--r--src/clocks/mod.rs43
1 files changed, 41 insertions, 2 deletions
diff --git a/src/clocks/mod.rs b/src/clocks/mod.rs
index 0b4535dc4..948355079 100644
--- a/src/clocks/mod.rs
+++ b/src/clocks/mod.rs
@@ -91,8 +91,11 @@ pub fn init(settings: ClocksConfig) -> Result<(), ClockError> {
91 // For now, just use FIRC as the main/cpu clock, which should already be 91 // For now, just use FIRC as the main/cpu clock, which should already be
92 // the case on reset 92 // the case on reset
93 assert!(operator.scg0.rccr().read().scs().is_firc()); 93 assert!(operator.scg0.rccr().read().scs().is_firc());
94 let input = operator.clocks.fro_hf_root.clone().unwrap();
95 operator.clocks.main_clk = Some(input.clone());
96 // We can also assume cpu/system clk == fro_hf because div is /1.
94 assert_eq!(operator.syscon.ahbclkdiv().read().div().bits(), 0); 97 assert_eq!(operator.syscon.ahbclkdiv().read().div().bits(), 0);
95 operator.clocks.main_clk = Some(operator.clocks.fro_hf_root.clone().unwrap()); 98 operator.clocks.cpu_system_clk = Some(input);
96 99
97 critical_section::with(|cs| { 100 critical_section::with(|cs| {
98 let mut clks = CLOCKS.borrow_ref_mut(cs); 101 let mut clks = CLOCKS.borrow_ref_mut(cs);
@@ -189,6 +192,9 @@ pub struct Clocks {
189 /// peripherals. 192 /// peripherals.
190 pub main_clk: Option<Clock>, 193 pub main_clk: Option<Clock>,
191 194
195 /// `CPU_CLK` or `SYSTEM_CLK` is the output of `main_clk`, run through the `AHBCLKDIV`
196 pub cpu_system_clk: Option<Clock>,
197
192 /// `pll1_clk` is the output of the main system PLL, `pll1`. 198 /// `pll1_clk` is the output of the main system PLL, `pll1`.
193 pub pll1_clk: Option<Clock>, 199 pub pll1_clk: Option<Clock>,
194} 200}
@@ -522,10 +528,43 @@ impl Clocks {
522 Ok(clk.frequency) 528 Ok(clk.frequency)
523 } 529 }
524 530
531 /// Ensure the `pll1_clk` clock is active and valid at the given power state.
532 pub fn ensure_pll1_clk_active(&self, _at_level: &PoweredClock) -> Result<u32, ClockError> {
533 Err(ClockError::NotImplemented { clock: "pll1_clk" })
534 }
535
525 /// Ensure the `pll1_clk_div` clock is active and valid at the given power state. 536 /// Ensure the `pll1_clk_div` clock is active and valid at the given power state.
526 pub fn ensure_pll1_clk_div_active(&self, _at_level: &PoweredClock) -> Result<u32, ClockError> { 537 pub fn ensure_pll1_clk_div_active(&self, _at_level: &PoweredClock) -> Result<u32, ClockError> {
527 Err(ClockError::NotImplemented { clock: "pll1_clk_div" }) 538 Err(ClockError::NotImplemented { clock: "pll1_clk_div" })
528 } 539 }
540
541 /// Ensure the `CPU_CLK` or `SYSTEM_CLK` is active
542 pub fn ensure_cpu_system_clk_active(&self, at_level: &PoweredClock) -> Result<u32, ClockError> {
543 let Some(clk) = self.cpu_system_clk.as_ref() else {
544 return Err(ClockError::BadConfig {
545 clock: "cpu_system_clk",
546 reason: "required but not active",
547 });
548 };
549 // Can the main_clk ever be active in deep sleep? I think it is gated?
550 match at_level {
551 PoweredClock::NormalEnabledDeepSleepDisabled => {}
552 PoweredClock::AlwaysEnabled => {
553 return Err(ClockError::BadConfig {
554 clock: "main_clk",
555 reason: "not low power active",
556 })
557 }
558 }
559
560 Ok(clk.frequency)
561 }
562
563 pub fn ensure_slow_clk_active(&self, at_level: &PoweredClock) -> Result<u32, ClockError> {
564 let freq = self.ensure_cpu_system_clk_active(at_level)?;
565
566 Ok(freq / 6)
567 }
529} 568}
530 569
531impl PoweredClock { 570impl PoweredClock {
@@ -749,7 +788,7 @@ impl ClockOperator<'_> {
749 w 788 w
750 }); 789 });
751 // Then unhalt it, and reset it 790 // Then unhalt it, and reset it
752 self.syscon.frolfdiv().write(|w| { 791 self.syscon.frolfdiv().modify(|_r, w| {
753 w.halt().run(); 792 w.halt().run();
754 w.reset().released(); 793 w.reset().released();
755 w 794 w