diff options
Diffstat (limited to 'src/clocks')
| -rw-r--r-- | src/clocks/mod.rs | 9 | ||||
| -rw-r--r-- | src/clocks/periph_helpers.rs | 113 |
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 { | |||
| 904 | pub(crate) mod gate { | 904 | pub(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)] | ||
| 132 | pub 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)] | ||
| 154 | pub 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. | ||
| 166 | pub 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 | |||
| 178 | impl 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 | ||
