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.rs69
1 files changed, 62 insertions, 7 deletions
diff --git a/src/clocks/mod.rs b/src/clocks/mod.rs
index c86ed1cd5..ad48a9cf2 100644
--- a/src/clocks/mod.rs
+++ b/src/clocks/mod.rs
@@ -6,10 +6,7 @@ use mcxa_pac::scg0::{
6}; 6};
7 7
8use crate::pac; 8use crate::pac;
9 9pub mod periph_helpers;
10pub trait SPConfHelper {
11 fn post_enable_config(&self, clocks: &Clocks) -> Result<u32, ClockError>;
12}
13 10
14// /// Trait describing an AHB clock gate that can be toggled through MRCC. 11// /// Trait describing an AHB clock gate that can be toggled through MRCC.
15// pub trait Gate { 12// pub trait Gate {
@@ -198,10 +195,22 @@ pub struct Clock {
198 195
199#[derive(Debug, Clone, Copy)] 196#[derive(Debug, Clone, Copy)]
200pub enum PoweredClock { 197pub enum PoweredClock {
201 HighPowerOnly, 198 NormalEnabledDeepSleepDisabled,
202 AlwaysEnabled, 199 AlwaysEnabled,
203} 200}
204 201
202impl PoweredClock {
203 /// Does THIS clock meet the power requirements of the OTHER clock?
204 pub fn meets_requirement_of(&self, other: &Self) -> bool {
205 match (self, other) {
206 (PoweredClock::NormalEnabledDeepSleepDisabled, PoweredClock::AlwaysEnabled) => false,
207 (PoweredClock::NormalEnabledDeepSleepDisabled, PoweredClock::NormalEnabledDeepSleepDisabled) => true,
208 (PoweredClock::AlwaysEnabled, PoweredClock::NormalEnabledDeepSleepDisabled) => true,
209 (PoweredClock::AlwaysEnabled, PoweredClock::AlwaysEnabled) => true,
210 }
211 }
212}
213
205/// ```text 214/// ```text
206/// ┌─────────────────────────────────────────────────────────┐ 215/// ┌─────────────────────────────────────────────────────────┐
207/// │ │ 216/// │ │
@@ -341,6 +350,7 @@ static CLOCKS: critical_section::Mutex<Option<Clocks>> = critical_section::Mutex
341pub enum ClockError { 350pub enum ClockError {
342 AlreadyInitialized, 351 AlreadyInitialized,
343 BadConfig { clock: &'static str, reason: &'static str }, 352 BadConfig { clock: &'static str, reason: &'static str },
353 NotImplemented { clock: &'static str },
344} 354}
345 355
346struct ClockOperator<'a> { 356struct ClockOperator<'a> {
@@ -417,7 +427,7 @@ impl ClockOperator<'_> {
417 427
418 // When is the FRO enabled? 428 // When is the FRO enabled?
419 let pow_set = match power { 429 let pow_set = match power {
420 PoweredClock::HighPowerOnly => Fircsten::DisabledInStopModes, 430 PoweredClock::NormalEnabledDeepSleepDisabled => Fircsten::DisabledInStopModes,
421 PoweredClock::AlwaysEnabled => Fircsten::EnabledInStopModes, 431 PoweredClock::AlwaysEnabled => Fircsten::EnabledInStopModes,
422 }; 432 };
423 433
@@ -505,7 +515,7 @@ impl ClockOperator<'_> {
505 }); 515 });
506 516
507 let deep = match power { 517 let deep = match power {
508 PoweredClock::HighPowerOnly => Sircsten::Disabled, 518 PoweredClock::NormalEnabledDeepSleepDisabled => Sircsten::Disabled,
509 PoweredClock::AlwaysEnabled => Sircsten::Enabled, 519 PoweredClock::AlwaysEnabled => Sircsten::Enabled,
510 }; 520 };
511 let pclk = if *fro_12m_enabled { 521 let pclk = if *fro_12m_enabled {
@@ -615,3 +625,48 @@ pub fn with_clocks<R: 'static, F: FnOnce(&Clocks) -> R>(f: F) -> Option<R> {
615 Some(f(c)) 625 Some(f(c))
616 }) 626 })
617} 627}
628
629impl Clocks {
630 pub fn ensure_fro_lf_div_active(&self, at_level: &PoweredClock) -> Result<u32, ClockError> {
631 let Some(clk) = self.fro_lf_div.as_ref() else {
632 return Err(ClockError::BadConfig { clock: "fro_lf_div", reason: "required but not active" });
633 };
634 if !clk.power.meets_requirement_of(at_level) {
635 return Err(ClockError::BadConfig { clock: "fro_lf_div", reason: "not low power active" });
636 }
637 Ok(clk.frequency)
638 }
639
640 pub fn ensure_fro_hf_div_active(&self, at_level: &PoweredClock) -> Result<u32, ClockError> {
641 let Some(clk) = self.fro_hf_div.as_ref() else {
642 return Err(ClockError::BadConfig { clock: "fro_hf_div", reason: "required but not active" });
643 };
644 if !clk.power.meets_requirement_of(at_level) {
645 return Err(ClockError::BadConfig { clock: "fro_hf_div", reason: "not low power active" });
646 }
647 Ok(clk.frequency)
648 }
649
650 pub fn ensure_clk_in_active(&self, _at_level: &PoweredClock) -> Result<u32, ClockError> {
651 Err(ClockError::NotImplemented { clock: "clk_in" })
652 }
653
654 pub fn ensure_clk_16k_active(&self, _at_level: &PoweredClock) -> Result<u32, ClockError> {
655 Err(ClockError::NotImplemented { clock: "clk_16k" })
656 }
657
658 pub fn ensure_clk_1m_active(&self, at_level: &PoweredClock) -> Result<u32, ClockError> {
659 let Some(clk) = self.clk_1m.as_ref() else {
660 return Err(ClockError::BadConfig { clock: "clk_1m", reason: "required but not active" });
661 };
662 if !clk.power.meets_requirement_of(at_level) {
663 return Err(ClockError::BadConfig { clock: "clk_1m", reason: "not low power active" });
664 }
665 Ok(clk.frequency)
666 }
667
668 pub fn ensure_pll1_clk_div_active(&self, _at_level: &PoweredClock) -> Result<u32, ClockError> {
669 Err(ClockError::NotImplemented { clock: "pll1_clk_div" })
670 }
671
672}