aboutsummaryrefslogtreecommitdiff
path: root/src/clocks
diff options
context:
space:
mode:
Diffstat (limited to 'src/clocks')
-rw-r--r--src/clocks/mod.rs9
-rw-r--r--src/clocks/periph_helpers.rs113
2 files changed, 120 insertions, 2 deletions
diff --git a/src/clocks/mod.rs b/src/clocks/mod.rs
index cd6318c4b..9c9e6ef3d 100644
--- a/src/clocks/mod.rs
+++ b/src/clocks/mod.rs
@@ -553,7 +553,7 @@ impl Clocks {
553 return Err(ClockError::BadConfig { 553 return Err(ClockError::BadConfig {
554 clock: "main_clk", 554 clock: "main_clk",
555 reason: "not low power active", 555 reason: "not low power active",
556 }) 556 });
557 } 557 }
558 } 558 }
559 559
@@ -904,7 +904,7 @@ macro_rules! impl_cc_gate {
904pub(crate) mod gate { 904pub(crate) mod gate {
905 #[cfg(not(feature = "time"))] 905 #[cfg(not(feature = "time"))]
906 use super::periph_helpers::OsTimerConfig; 906 use super::periph_helpers::OsTimerConfig;
907 use super::periph_helpers::{AdcConfig, LpuartConfig, NoConfig}; 907 use super::periph_helpers::{AdcConfig, Lpi2cConfig, LpuartConfig, NoConfig};
908 use super::*; 908 use super::*;
909 909
910 // These peripherals have no additional upstream clocks or configuration required 910 // These peripherals have no additional upstream clocks or configuration required
@@ -928,6 +928,11 @@ pub(crate) mod gate {
928 #[cfg(not(feature = "time"))] 928 #[cfg(not(feature = "time"))]
929 impl_cc_gate!(OSTIMER0, mrcc_glb_cc1, mrcc_glb_rst1, ostimer0, OsTimerConfig); 929 impl_cc_gate!(OSTIMER0, mrcc_glb_cc1, mrcc_glb_rst1, ostimer0, OsTimerConfig);
930 930
931 impl_cc_gate!(LPI2C0, mrcc_glb_cc0, mrcc_glb_rst0, lpi2c0, Lpi2cConfig);
932 impl_cc_gate!(LPI2C1, mrcc_glb_cc0, mrcc_glb_rst0, lpi2c1, Lpi2cConfig);
933 impl_cc_gate!(LPI2C2, mrcc_glb_cc1, mrcc_glb_rst1, lpi2c2, Lpi2cConfig);
934 impl_cc_gate!(LPI2C3, mrcc_glb_cc1, mrcc_glb_rst1, lpi2c3, Lpi2cConfig);
935
931 impl_cc_gate!(LPUART0, mrcc_glb_cc0, mrcc_glb_rst0, lpuart0, LpuartConfig); 936 impl_cc_gate!(LPUART0, mrcc_glb_cc0, mrcc_glb_rst0, lpuart0, LpuartConfig);
932 impl_cc_gate!(LPUART1, mrcc_glb_cc0, mrcc_glb_rst0, lpuart1, LpuartConfig); 937 impl_cc_gate!(LPUART1, mrcc_glb_cc0, mrcc_glb_rst0, lpuart1, LpuartConfig);
933 impl_cc_gate!(LPUART2, mrcc_glb_cc0, mrcc_glb_rst0, lpuart2, LpuartConfig); 938 impl_cc_gate!(LPUART2, mrcc_glb_cc0, mrcc_glb_rst0, lpuart2, LpuartConfig);
diff --git a/src/clocks/periph_helpers.rs b/src/clocks/periph_helpers.rs
index eac3ef8dd..24d074e8a 100644
--- a/src/clocks/periph_helpers.rs
+++ b/src/clocks/periph_helpers.rs
@@ -124,6 +124,119 @@ impl SPConfHelper for NoConfig {
124} 124}
125 125
126// 126//
127// LPI2c
128//
129
130/// Selectable clocks for `Lpi2c` peripherals
131#[derive(Debug, Clone, Copy)]
132pub enum Lpi2cClockSel {
133 /// FRO12M/FRO_LF/SIRC clock source, passed through divider
134 /// "fro_lf_div"
135 FroLfDiv,
136 /// FRO180M/FRO_HF/FIRC clock source, passed through divider
137 /// "fro_hf_div"
138 FroHfDiv,
139 /// SOSC/XTAL/EXTAL clock source
140 ClkIn,
141 /// clk_1m/FRO_LF divided by 12
142 Clk1M,
143 /// Output of PLL1, passed through clock divider,
144 /// "pll1_clk_div", maybe "pll1_lf_div"?
145 Pll1ClkDiv,
146 /// Disabled
147 None,
148}
149
150/// Which instance of the `Lpi2c` is this?
151///
152/// Should not be directly selectable by end-users.
153#[derive(Copy, Clone, Debug, PartialEq, Eq)]
154pub enum Lpi2cInstance {
155 /// Instance 0
156 Lpi2c0,
157 /// Instance 1
158 Lpi2c1,
159 /// Instance 2
160 Lpi2c2,
161 /// Instance 3
162 Lpi2c3,
163}
164
165/// Top level configuration for `Lpi2c` instances.
166pub struct Lpi2cConfig {
167 /// Power state required for this peripheral
168 pub power: PoweredClock,
169 /// Clock source
170 pub source: Lpi2cClockSel,
171 /// Clock divisor
172 pub div: Div4,
173 /// Which instance is this?
174 // NOTE: should not be user settable
175 pub(crate) instance: Lpi2cInstance,
176}
177
178impl SPConfHelper for Lpi2cConfig {
179 fn post_enable_config(&self, clocks: &Clocks) -> Result<u32, ClockError> {
180 // check that source is suitable
181 let mrcc0 = unsafe { pac::Mrcc0::steal() };
182 use mcxa_pac::mrcc0::mrcc_lpi2c0_clksel::Mux;
183
184 let (clkdiv, clksel) = match self.instance {
185 Lpi2cInstance::Lpi2c0 => (mrcc0.mrcc_lpi2c0_clkdiv(), mrcc0.mrcc_lpi2c0_clksel()),
186 Lpi2cInstance::Lpi2c1 => (mrcc0.mrcc_lpi2c1_clkdiv(), mrcc0.mrcc_lpi2c1_clksel()),
187 Lpi2cInstance::Lpi2c2 => (mrcc0.mrcc_lpi2c2_clkdiv(), mrcc0.mrcc_lpi2c2_clksel()),
188 Lpi2cInstance::Lpi2c3 => (mrcc0.mrcc_lpi2c3_clkdiv(), mrcc0.mrcc_lpi2c3_clksel()),
189 };
190
191 let (freq, variant) = match self.source {
192 Lpi2cClockSel::FroLfDiv => {
193 let freq = clocks.ensure_fro_lf_div_active(&self.power)?;
194 (freq, Mux::ClkrootFunc0)
195 }
196 Lpi2cClockSel::FroHfDiv => {
197 let freq = clocks.ensure_fro_hf_div_active(&self.power)?;
198 (freq, Mux::ClkrootFunc2)
199 }
200 Lpi2cClockSel::ClkIn => {
201 let freq = clocks.ensure_clk_in_active(&self.power)?;
202 (freq, Mux::ClkrootFunc3)
203 }
204 Lpi2cClockSel::Clk1M => {
205 let freq = clocks.ensure_clk_1m_active(&self.power)?;
206 (freq, Mux::ClkrootFunc5)
207 }
208 Lpi2cClockSel::Pll1ClkDiv => {
209 let freq = clocks.ensure_pll1_clk_div_active(&self.power)?;
210 (freq, Mux::ClkrootFunc6)
211 }
212 Lpi2cClockSel::None => unsafe {
213 // no ClkrootFunc7, just write manually for now
214 clksel.write(|w| w.bits(0b111));
215 clkdiv.modify(|_r, w| w.reset().asserted().halt().asserted());
216 return Ok(0);
217 },
218 };
219
220 // set clksel
221 clksel.modify(|_r, w| w.mux().variant(variant));
222
223 // Set up clkdiv
224 clkdiv.modify(|_r, w| {
225 unsafe { w.div().bits(self.div.into_bits()) }
226 .halt()
227 .asserted()
228 .reset()
229 .asserted()
230 });
231 clkdiv.modify(|_r, w| w.halt().deasserted().reset().deasserted());
232
233 while clkdiv.read().unstab().is_unstable() {}
234
235 Ok(freq / self.div.into_divisor())
236 }
237}
238
239//
127// LPUart 240// LPUart
128// 241//
129 242