aboutsummaryrefslogtreecommitdiff
path: root/embassy-mcxa/src/clocks/mod.rs
diff options
context:
space:
mode:
authorJames Munns <[email protected]>2025-12-18 14:53:33 +0100
committerJames Munns <[email protected]>2025-12-18 15:02:24 +0100
commitb0cf9b4626e7fa99d1da82a5eb745e9ed14508de (patch)
tree8c8cdbf14561ac133d0fd377b9ebd57105495105 /embassy-mcxa/src/clocks/mod.rs
parentc94c09c72d16fd5cc9cb7c925386e7a2d6de1dcd (diff)
First basic test works
Diffstat (limited to 'embassy-mcxa/src/clocks/mod.rs')
-rw-r--r--embassy-mcxa/src/clocks/mod.rs83
1 files changed, 76 insertions, 7 deletions
diff --git a/embassy-mcxa/src/clocks/mod.rs b/embassy-mcxa/src/clocks/mod.rs
index 98f7075eb..866e78bf2 100644
--- a/embassy-mcxa/src/clocks/mod.rs
+++ b/embassy-mcxa/src/clocks/mod.rs
@@ -200,6 +200,9 @@ pub struct Clocks {
200 200
201 /// `pll1_clk` is the output of the main system PLL, `pll1`. 201 /// `pll1_clk` is the output of the main system PLL, `pll1`.
202 pub pll1_clk: Option<Clock>, 202 pub pll1_clk: Option<Clock>,
203
204 /// `pll1_clk_div` is a configurable frequency clock, sourced from `pll1_clk`
205 pub pll1_clk_div: Option<Clock>,
203} 206}
204 207
205/// `ClockError` is the main error returned when configuring or checking clock state 208/// `ClockError` is the main error returned when configuring or checking clock state
@@ -548,13 +551,37 @@ impl Clocks {
548 } 551 }
549 552
550 /// Ensure the `pll1_clk` clock is active and valid at the given power state. 553 /// Ensure the `pll1_clk` clock is active and valid at the given power state.
551 pub fn ensure_pll1_clk_active(&self, _at_level: &PoweredClock) -> Result<u32, ClockError> { 554 pub fn ensure_pll1_clk_active(&self, at_level: &PoweredClock) -> Result<u32, ClockError> {
552 Err(ClockError::NotImplemented { clock: "pll1_clk" }) 555 let Some(clk) = self.pll1_clk.as_ref() else {
556 return Err(ClockError::BadConfig {
557 clock: "spll",
558 reason: "required but not active",
559 });
560 };
561 if !clk.power.meets_requirement_of(at_level) {
562 return Err(ClockError::BadConfig {
563 clock: "spll",
564 reason: "not low power active",
565 });
566 }
567 Ok(clk.frequency)
553 } 568 }
554 569
555 /// Ensure the `pll1_clk_div` clock is active and valid at the given power state. 570 /// Ensure the `pll1_clk_div` clock is active and valid at the given power state.
556 pub fn ensure_pll1_clk_div_active(&self, _at_level: &PoweredClock) -> Result<u32, ClockError> { 571 pub fn ensure_pll1_clk_div_active(&self, at_level: &PoweredClock) -> Result<u32, ClockError> {
557 Err(ClockError::NotImplemented { clock: "pll1_clk_div" }) 572 let Some(clk) = self.pll1_clk_div.as_ref() else {
573 return Err(ClockError::BadConfig {
574 clock: "spll",
575 reason: "required but not active",
576 });
577 };
578 if !clk.power.meets_requirement_of(at_level) {
579 return Err(ClockError::BadConfig {
580 clock: "spll",
581 reason: "not low power active",
582 });
583 }
584 Ok(clk.frequency)
558 } 585 }
559 586
560 /// Ensure the `CPU_CLK` or `SYSTEM_CLK` is active 587 /// Ensure the `CPU_CLK` or `SYSTEM_CLK` is active
@@ -1031,7 +1058,10 @@ impl ClockOperator<'_> {
1031 reason: s, 1058 reason: s,
1032 })?; 1059 })?;
1033 if !clk.power.meets_requirement_of(&cfg.power) { 1060 if !clk.power.meets_requirement_of(&cfg.power) {
1034 return Err(ClockError::BadConfig { clock: "spll", reason: "needs low power source" }); 1061 return Err(ClockError::BadConfig {
1062 clock: "spll",
1063 reason: "needs low power source",
1064 });
1035 } 1065 }
1036 1066
1037 // Bandwidth calc 1067 // Bandwidth calc
@@ -1118,9 +1148,20 @@ impl ClockOperator<'_> {
1118 fout = (f_in / div).checked_mul(m_mult as u32); 1148 fout = (f_in / div).checked_mul(m_mult as u32);
1119 } 1149 }
1120 }; 1150 };
1151
1152 defmt::debug!("f_in: {:?}", f_in);
1153 defmt::debug!("bp_pre: {:?}", bp_pre);
1154 defmt::debug!("bp_post: {:?}", bp_post);
1155 defmt::debug!("bp_post2: {:?}", bp_post2);
1156 defmt::debug!("m: {:?}", m);
1157 defmt::debug!("p: {:?}", p);
1158 defmt::debug!("n: {:?}", n);
1159 defmt::debug!("fout: {:?}", fout);
1160 defmt::debug!("fcco: {:?}", fcco);
1161
1121 let fcco = fcco.ok_or(ClockError::BadConfig { 1162 let fcco = fcco.ok_or(ClockError::BadConfig {
1122 clock: "spll", 1163 clock: "spll",
1123 reason: "fcco invalid", 1164 reason: "fcco invalid1",
1124 })?; 1165 })?;
1125 let fout = fout.ok_or(ClockError::BadConfig { 1166 let fout = fout.ok_or(ClockError::BadConfig {
1126 clock: "spll", 1167 clock: "spll",
@@ -1130,7 +1171,7 @@ impl ClockOperator<'_> {
1130 if !(275_000_000..=550_000_000).contains(&fcco) { 1171 if !(275_000_000..=550_000_000).contains(&fcco) {
1131 return Err(ClockError::BadConfig { 1172 return Err(ClockError::BadConfig {
1132 clock: "spll", 1173 clock: "spll",
1133 reason: "fcco invalid", 1174 reason: "fcco invalid2",
1134 }); 1175 });
1135 } 1176 }
1136 // Fout: 4.3MHz to 2x Max CPU Frequency 1177 // Fout: 4.3MHz to 2x Max CPU Frequency
@@ -1149,6 +1190,7 @@ impl ClockOperator<'_> {
1149 assert!(m >= 1); 1190 assert!(m >= 1);
1150 if let Some(p) = p.as_ref() { 1191 if let Some(p) = p.as_ref() {
1151 assert!(*p >= 1); 1192 assert!(*p >= 1);
1193 assert!(*p <= 31);
1152 } 1194 }
1153 if let Some(n) = n.as_ref() { 1195 if let Some(n) = n.as_ref() {
1154 assert!(*n >= 1); 1196 assert!(*n >= 1);
@@ -1254,11 +1296,38 @@ impl ClockOperator<'_> {
1254 // Re-lock SPLL CSR 1296 // Re-lock SPLL CSR
1255 self.scg0.spllcsr().modify(|_r, w| w.lk().write_disabled()); 1297 self.scg0.spllcsr().modify(|_r, w| w.lk().write_disabled());
1256 1298
1299 // Store clock state
1257 self.clocks.pll1_clk = Some(Clock { 1300 self.clocks.pll1_clk = Some(Clock {
1258 frequency: fout, 1301 frequency: fout,
1259 power: cfg.power, 1302 power: cfg.power,
1260 }); 1303 });
1261 1304
1305 // Do we enable the `pll1_clk_div` output?
1306 if let Some(d) = cfg.pll1_clk_div.as_ref() {
1307 // Halt and reset the div; then set our desired div.
1308 self.syscon.pll1clkdiv().write(|w| {
1309 w.halt().halt();
1310 w.reset().asserted();
1311 unsafe { w.div().bits(d.into_bits()) };
1312 w
1313 });
1314 // Then unhalt it, and reset it
1315 self.syscon.pll1clkdiv().write(|w| {
1316 w.halt().run();
1317 w.reset().released();
1318 w
1319 });
1320
1321 // Wait for clock to stabilize
1322 while self.syscon.pll1clkdiv().read().unstab().is_ongoing() {}
1323
1324 // Store off the clock info
1325 self.clocks.pll1_clk_div = Some(Clock {
1326 frequency: fout / d.into_divisor(),
1327 power: cfg.power,
1328 });
1329 }
1330
1262 Ok(()) 1331 Ok(())
1263 } 1332 }
1264} 1333}