diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index aed9f7a46..c412e13d5 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -68,7 +68,7 @@ rand_core = "0.6.3"
 sdio-host = "0.5.0"
 critical-section = "1.1"
 #stm32-metapac = { version = "15" }
-stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-768b3e8e3199e03de0acd0d4590d06f51eebb7dd" }
+stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-3e3b53df78b4c90ae9c44a58b4f9f93c93a415b7" }
 vcell = "0.1.3"
 bxcan = "0.7.0"
 nb = "1.0.0"
@@ -89,7 +89,7 @@ critical-section = { version = "1.1", features = ["std"] }
 proc-macro2 = "1.0.36"
 quote = "1.0.15"
 #stm32-metapac = { version = "15", default-features = false, features = ["metadata"]}
-stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-768b3e8e3199e03de0acd0d4590d06f51eebb7dd", default-features = false, features = ["metadata"]}
+stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-3e3b53df78b4c90ae9c44a58b4f9f93c93a415b7", default-features = false, features = ["metadata"]}
 
 
 [features]
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs
index 74cc3f8b9..3885c5d18 100644
--- a/embassy-stm32/build.rs
+++ b/embassy-stm32/build.rs
@@ -461,6 +461,8 @@ fn main() {
     let force_refcount = HashSet::from(["usart"]);
     let mut refcount_statics = BTreeSet::new();
 
+    let mut clock_names = BTreeSet::new();
+
     for p in METADATA.peripherals {
         if !singletons.contains(&p.name.to_string()) {
             continue;
@@ -492,7 +494,6 @@ fn main() {
 
             let ptype = if let Some(reg) = &p.registers { reg.kind } else { "" };
             let pname = format_ident!("{}", p.name);
-            let clk = format_ident!("{}", rcc.clock);
             let en_reg = format_ident!("{}", en.register);
             let set_en_field = format_ident!("set_{}", en.field);
 
@@ -522,14 +523,7 @@ fn main() {
                 (TokenStream::new(), TokenStream::new())
             };
 
-            let mux_supported = HashSet::from(["c0", "h5", "h50", "h7", "h7ab", "h7rm0433", "g0", "g4", "l4"])
-                .contains(rcc_registers.version);
             let mux_for = |mux: Option<&'static PeripheralRccRegister>| {
-                // restrict mux implementation to supported versions
-                if !mux_supported {
-                    return None;
-                }
-
                 let mux = mux?;
                 let fieldset = rcc_enum_map.get(mux.register)?;
                 let enumm = fieldset.get(mux.field)?;
@@ -550,15 +544,9 @@ fn main() {
                         .map(|v| {
                             let variant_name = format_ident!("{}", v.name);
                             let clock_name = format_ident!("{}", v.name.to_ascii_lowercase());
-
-                            if v.name.starts_with("HCLK") || v.name.starts_with("PCLK") || v.name == "SYS" {
-                                quote! {
-                                    #enum_name::#variant_name => unsafe { crate::rcc::get_freqs().#clock_name },
-                                }
-                            } else {
-                                quote! {
-                                    #enum_name::#variant_name => unsafe { crate::rcc::get_freqs().#clock_name.unwrap() },
-                                }
+                            clock_names.insert(v.name.to_ascii_lowercase());
+                            quote! {
+                                #enum_name::#variant_name => unsafe { crate::rcc::get_freqs().#clock_name.unwrap() },
                             }
                         })
                         .collect();
@@ -569,19 +557,21 @@ fn main() {
                         #[allow(unreachable_patterns)]
                         match crate::pac::RCC.#fieldset_name().read().#field_name() {
                             #match_arms
-
                             _ => unreachable!(),
                         }
                     }
                 }
-                None => quote! {
-                    unsafe { crate::rcc::get_freqs().#clk }
-                },
+                None => {
+                    let clock_name = format_ident!("{}", rcc.clock);
+                    clock_names.insert(rcc.clock.to_string());
+                    quote! {
+                        unsafe { crate::rcc::get_freqs().#clock_name.unwrap() }
+                    }
+                }
             };
 
             /*
                 A refcount leak can result if the same field is shared by peripherals with different stop modes
-
                 This condition should be checked in stm32-data
             */
             let stop_refcount = match rcc.stop_mode {
@@ -628,6 +618,39 @@ fn main() {
         }
     }
 
+    // Generate RCC
+    clock_names.insert("sys".to_string());
+    clock_names.insert("rtc".to_string());
+    let clock_idents: Vec<_> = clock_names.iter().map(|n| format_ident!("{}", n)).collect();
+    g.extend(quote! {
+        #[derive(Clone, Copy, Debug)]
+        #[cfg_attr(feature = "defmt", derive(defmt::Format))]
+        pub struct Clocks {
+            #(
+                pub #clock_idents: Option<crate::time::Hertz>,
+            )*
+        }
+    });
+
+    let clocks_macro = quote!(
+        macro_rules! set_clocks {
+            ($($(#[$m:meta])* $k:ident: $v:expr,)*) => {
+                {
+                    #[allow(unused)]
+                    struct Temp {
+                        $($(#[$m])* $k: Option<crate::time::Hertz>,)*
+                    }
+                    let all = Temp {
+                        $($(#[$m])* $k: $v,)*
+                    };
+                    crate::rcc::set_freqs(crate::rcc::Clocks {
+                        #( #clock_idents: all.#clock_idents, )*
+                    });
+                }
+            };
+        }
+    );
+
     let refcount_mod: TokenStream = refcount_statics
         .iter()
         .map(|refcount_static| {
@@ -1349,7 +1372,7 @@ fn main() {
         }
     }
 
-    let mut m = String::new();
+    let mut m = clocks_macro.to_string();
 
     // DO NOT ADD more macros like these.
     // These turned to be a bad idea!
diff --git a/embassy-stm32/src/adc/f1.rs b/embassy-stm32/src/adc/f1.rs
index fb27bb87b..c896d8e3a 100644
--- a/embassy-stm32/src/adc/f1.rs
+++ b/embassy-stm32/src/adc/f1.rs
@@ -6,7 +6,6 @@ use embassy_hal_internal::into_ref;
 use embedded_hal_02::blocking::delay::DelayUs;
 
 use crate::adc::{Adc, AdcPin, Instance, SampleTime};
-use crate::rcc::get_freqs;
 use crate::time::Hertz;
 use crate::{interrupt, Peripheral};
 
@@ -80,7 +79,7 @@ impl<'d, T: Instance> Adc<'d, T> {
     }
 
     fn freq() -> Hertz {
-        unsafe { get_freqs() }.adc.unwrap()
+        T::frequency()
     }
 
     pub fn sample_time_for_us(&self, us: u32) -> SampleTime {
diff --git a/embassy-stm32/src/adc/f3.rs b/embassy-stm32/src/adc/f3.rs
index 6f59c230f..6606a2b9c 100644
--- a/embassy-stm32/src/adc/f3.rs
+++ b/embassy-stm32/src/adc/f3.rs
@@ -102,7 +102,7 @@ impl<'d, T: Instance> Adc<'d, T> {
     }
 
     fn freq() -> Hertz {
-        <T as crate::adc::sealed::Instance>::frequency()
+        <T as crate::rcc::sealed::RccPeripheral>::frequency()
     }
 
     pub fn sample_time_for_us(&self, us: u32) -> SampleTime {
diff --git a/embassy-stm32/src/adc/mod.rs b/embassy-stm32/src/adc/mod.rs
index e4dd35c34..d21c3053f 100644
--- a/embassy-stm32/src/adc/mod.rs
+++ b/embassy-stm32/src/adc/mod.rs
@@ -61,8 +61,6 @@ pub(crate) mod sealed {
         fn regs() -> crate::pac::adc::Adc;
         #[cfg(not(any(adc_f1, adc_v1, adc_f3_v2, adc_f3_v1_1, adc_g0)))]
         fn common_regs() -> crate::pac::adccommon::AdcCommon;
-        #[cfg(adc_f3)]
-        fn frequency() -> crate::time::Hertz;
         #[cfg(any(adc_f1, adc_f3, adc_v1, adc_f3_v1_1))]
         fn state() -> &'static State;
     }
@@ -103,11 +101,6 @@ foreach_adc!(
                 return crate::pac::$common_inst
             }
 
-            #[cfg(adc_f3)]
-            fn frequency() -> crate::time::Hertz {
-                unsafe { crate::rcc::get_freqs() }.$clock.unwrap()
-            }
-
             #[cfg(any(adc_f1, adc_f3, adc_v1, adc_f3_v1_1))]
             fn state() -> &'static sealed::State {
                 static STATE: sealed::State = sealed::State::new();
diff --git a/embassy-stm32/src/eth/mod.rs b/embassy-stm32/src/eth/mod.rs
index fbcdd7fae..71fe09c3f 100644
--- a/embassy-stm32/src/eth/mod.rs
+++ b/embassy-stm32/src/eth/mod.rs
@@ -13,6 +13,7 @@ use embassy_net_driver::{Capabilities, HardwareAddress, LinkState};
 use embassy_sync::waitqueue::AtomicWaker;
 
 pub use self::_version::{InterruptHandler, *};
+use crate::rcc::RccPeripheral;
 
 #[allow(unused)]
 const MTU: usize = 1514;
@@ -183,7 +184,7 @@ pub(crate) mod sealed {
 }
 
 /// Ethernet instance.
-pub trait Instance: sealed::Instance + Send + 'static {}
+pub trait Instance: sealed::Instance + RccPeripheral + Send + 'static {}
 
 impl sealed::Instance for crate::peripherals::ETH {
     fn regs() -> crate::pac::eth::Eth {
diff --git a/embassy-stm32/src/eth/v1/mod.rs b/embassy-stm32/src/eth/v1/mod.rs
index 2ce5b3927..e5b7b0452 100644
--- a/embassy-stm32/src/eth/v1/mod.rs
+++ b/embassy-stm32/src/eth/v1/mod.rs
@@ -20,6 +20,7 @@ use crate::pac::AFIO;
 #[cfg(any(eth_v1b, eth_v1c))]
 use crate::pac::SYSCFG;
 use crate::pac::{ETH, RCC};
+use crate::rcc::sealed::RccPeripheral;
 use crate::{interrupt, Peripheral};
 
 /// Interrupt handler.
@@ -191,8 +192,7 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
 
         // TODO MTU size setting not found for v1 ethernet, check if correct
 
-        // NOTE(unsafe) We got the peripheral singleton, which means that `rcc::init` was called
-        let hclk = unsafe { crate::rcc::get_freqs() }.hclk1;
+        let hclk = <T as RccPeripheral>::frequency();
         let hclk_mhz = hclk.0 / 1_000_000;
 
         // Set the MDC clock frequency in the range 1MHz - 2.5MHz
diff --git a/embassy-stm32/src/eth/v2/mod.rs b/embassy-stm32/src/eth/v2/mod.rs
index 4b22d1d21..8d69561d4 100644
--- a/embassy-stm32/src/eth/v2/mod.rs
+++ b/embassy-stm32/src/eth/v2/mod.rs
@@ -11,6 +11,7 @@ use crate::gpio::sealed::{AFType, Pin as _};
 use crate::gpio::{AnyPin, Speed};
 use crate::interrupt::InterruptExt;
 use crate::pac::ETH;
+use crate::rcc::sealed::RccPeripheral;
 use crate::{interrupt, Peripheral};
 
 /// Interrupt handler.
@@ -264,8 +265,7 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
             w.set_rbsz(RX_BUFFER_SIZE as u16);
         });
 
-        // NOTE(unsafe) We got the peripheral singleton, which means that `rcc::init` was called
-        let hclk = unsafe { crate::rcc::get_freqs() }.hclk1;
+        let hclk = <T as RccPeripheral>::frequency();
         let hclk_mhz = hclk.0 / 1_000_000;
 
         // Set the MDC clock frequency in the range 1MHz - 2.5MHz
diff --git a/embassy-stm32/src/hrtim/mod.rs b/embassy-stm32/src/hrtim/mod.rs
index faefaabbc..3ec646fc3 100644
--- a/embassy-stm32/src/hrtim/mod.rs
+++ b/embassy-stm32/src/hrtim/mod.rs
@@ -10,8 +10,6 @@ pub use traits::Instance;
 #[allow(unused_imports)]
 use crate::gpio::sealed::{AFType, Pin};
 use crate::gpio::AnyPin;
-#[cfg(stm32f334)]
-use crate::rcc::get_freqs;
 use crate::time::Hertz;
 use crate::Peripheral;
 
@@ -182,7 +180,7 @@ impl<'d, T: Instance> AdvancedPwm<'d, T> {
         T::enable_and_reset();
 
         #[cfg(stm32f334)]
-        if unsafe { get_freqs() }.hrtim.is_some() {
+        if crate::pac::RCC.cfgr3().read().hrtim1sw() == crate::pac::rcc::vals::Timsw::PLL1_P {
             // Enable and and stabilize the DLL
             T::regs().dllcr().modify(|w| {
                 w.set_cal(true);
diff --git a/embassy-stm32/src/hrtim/traits.rs b/embassy-stm32/src/hrtim/traits.rs
index cfd31c47c..dcc2b9ef4 100644
--- a/embassy-stm32/src/hrtim/traits.rs
+++ b/embassy-stm32/src/hrtim/traits.rs
@@ -80,10 +80,12 @@ pub(crate) mod sealed {
 
         fn set_master_frequency(frequency: Hertz) {
             let f = frequency.0;
-            #[cfg(not(stm32f334))]
+
+            // TODO: wire up HRTIM to the RCC mux infra.
+            //#[cfg(stm32f334)]
+            //let timer_f = unsafe { crate::rcc::get_freqs() }.hrtim.unwrap_or(Self::frequency()).0;
+            //#[cfg(not(stm32f334))]
             let timer_f = Self::frequency().0;
-            #[cfg(stm32f334)]
-            let timer_f = unsafe { crate::rcc::get_freqs() }.hrtim.unwrap_or(Self::frequency()).0;
 
             let psc_min = (timer_f / f) / (u16::MAX as u32 / 32);
             let psc = if Self::regs().isr().read().dllrdy() {
@@ -103,10 +105,12 @@ pub(crate) mod sealed {
 
         fn set_channel_frequency(channel: usize, frequency: Hertz) {
             let f = frequency.0;
-            #[cfg(not(stm32f334))]
+
+            // TODO: wire up HRTIM to the RCC mux infra.
+            //#[cfg(stm32f334)]
+            //let timer_f = unsafe { crate::rcc::get_freqs() }.hrtim.unwrap_or(Self::frequency()).0;
+            //#[cfg(not(stm32f334))]
             let timer_f = Self::frequency().0;
-            #[cfg(stm32f334)]
-            let timer_f = unsafe { crate::rcc::get_freqs() }.hrtim.unwrap_or(Self::frequency()).0;
 
             let psc_min = (timer_f / f) / (u16::MAX as u32 / 32);
             let psc = if Self::regs().isr().read().dllrdy() {
diff --git a/embassy-stm32/src/i2s.rs b/embassy-stm32/src/i2s.rs
index 1f85c0bc5..e9065dce6 100644
--- a/embassy-stm32/src/i2s.rs
+++ b/embassy-stm32/src/i2s.rs
@@ -4,7 +4,6 @@ use embassy_hal_internal::into_ref;
 use crate::gpio::sealed::{AFType, Pin as _};
 use crate::gpio::AnyPin;
 use crate::pac::spi::vals;
-use crate::rcc::get_freqs;
 use crate::spi::{Config as SpiConfig, *};
 use crate::time::Hertz;
 use crate::{Peripheral, PeripheralRef};
@@ -193,10 +192,10 @@ impl<'d, T: Instance, Tx, Rx> I2S<'d, T, Tx, Rx> {
         spi_cfg.frequency = freq;
         let spi = Spi::new_internal(peri, txdma, rxdma, spi_cfg);
 
-        #[cfg(all(rcc_f4, not(stm32f410)))]
-        let pclk = unsafe { get_freqs() }.plli2s1_q.unwrap();
-
-        #[cfg(stm32f410)]
+        // TODO move i2s to the new mux infra.
+        //#[cfg(all(rcc_f4, not(stm32f410)))]
+        //let pclk = unsafe { get_freqs() }.plli2s1_q.unwrap();
+        //#[cfg(stm32f410)]
         let pclk = T::frequency();
 
         let (odd, div) = compute_baud_rate(pclk, freq, config.master_clock, config.format);
diff --git a/embassy-stm32/src/rcc/c0.rs b/embassy-stm32/src/rcc/c0.rs
index 68f029ca0..ca1222185 100644
--- a/embassy-stm32/src/rcc/c0.rs
+++ b/embassy-stm32/src/rcc/c0.rs
@@ -2,7 +2,6 @@ use crate::pac::flash::vals::Latency;
 use crate::pac::rcc::vals::Sw;
 pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Hsidiv as HSIPrescaler, Ppre as APBPrescaler};
 use crate::pac::{FLASH, RCC};
-use crate::rcc::{set_freqs, Clocks};
 use crate::time::Hertz;
 
 /// HSI speed
@@ -133,13 +132,13 @@ pub(crate) unsafe fn init(config: Config) {
         }
     };
 
-    set_freqs(Clocks {
+    set_clocks!(
         hsi: None,
         lse: None,
-        sys: sys_clk,
-        hclk1: ahb_freq,
-        pclk1: apb_freq,
-        pclk1_tim: apb_tim_freq,
-        rtc,
-    });
+        sys: Some(sys_clk),
+        hclk1: Some(ahb_freq),
+        pclk1: Some(apb_freq),
+        pclk1_tim: Some(apb_tim_freq),
+        rtc: rtc,
+    );
 }
diff --git a/embassy-stm32/src/rcc/f.rs b/embassy-stm32/src/rcc/f.rs
index 36d9f178f..e306d478d 100644
--- a/embassy-stm32/src/rcc/f.rs
+++ b/embassy-stm32/src/rcc/f.rs
@@ -7,7 +7,6 @@ pub use crate::pac::rcc::vals::{
 #[cfg(any(stm32f4, stm32f7))]
 use crate::pac::PWR;
 use crate::pac::{FLASH, RCC};
-use crate::rcc::{set_freqs, Clocks};
 use crate::time::Hertz;
 
 // TODO: on some F4s, PLLM is shared between all PLLs. Enforce that.
@@ -183,9 +182,9 @@ pub(crate) unsafe fn init(config: Config) {
     };
     let pll = init_pll(PllInstance::Pll, config.pll, &pll_input);
     #[cfg(any(stm32f2, all(stm32f4, not(stm32f410)), stm32f7))]
-    let _plli2s = init_pll(PllInstance::Plli2s, config.plli2s, &pll_input);
+    let plli2s = init_pll(PllInstance::Plli2s, config.plli2s, &pll_input);
     #[cfg(any(stm32f446, stm32f427, stm32f437, stm32f4x9, stm32f7))]
-    let _pllsai = init_pll(PllInstance::Pllsai, config.pllsai, &pll_input);
+    let pllsai = init_pll(PllInstance::Pllsai, config.pllsai, &pll_input);
 
     // Configure sysclk
     let sys = match config.sys {
@@ -257,27 +256,41 @@ pub(crate) unsafe fn init(config: Config) {
     });
     while RCC.cfgr().read().sws() != config.sys {}
 
-    set_freqs(Clocks {
-        sys,
-        hclk1: hclk,
-        hclk2: hclk,
-        hclk3: hclk,
-        pclk1,
-        pclk2,
-        pclk1_tim,
-        pclk2_tim,
-        rtc,
+    set_clocks!(
+        hsi: hsi,
+        hse: hse,
+        lse: None, // TODO
+        lsi: None, // TODO
+        sys: Some(sys),
+        hclk1: Some(hclk),
+        hclk2: Some(hclk),
+        hclk3: Some(hclk),
+        pclk1: Some(pclk1),
+        pclk2: Some(pclk2),
+        pclk1_tim: Some(pclk1_tim),
+        pclk2_tim: Some(pclk2_tim),
+        rtc: rtc,
         pll1_q: pll.q,
-        #[cfg(all(rcc_f4, not(stm32f410)))]
-        plli2s1_q: _plli2s.q,
-        #[cfg(all(rcc_f4, not(stm32f410)))]
-        plli2s1_r: _plli2s.r,
 
-        #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
-        pllsai1_q: _pllsai.q,
-        #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
-        pllsai1_r: _pllsai.r,
-    });
+        #[cfg(any(stm32f2, all(stm32f4, not(stm32f410)), stm32f7))]
+        plli2s1_p: plli2s.p,
+        #[cfg(any(stm32f2, all(stm32f4, not(stm32f410)), stm32f7))]
+        plli2s1_q: plli2s.q,
+        #[cfg(any(stm32f2, all(stm32f4, not(stm32f410)), stm32f7))]
+        plli2s1_r: plli2s.r,
+
+        #[cfg(any(stm32f446, stm32f427, stm32f437, stm32f4x9, stm32f7))]
+        pllsai1_p: pllsai.p,
+        #[cfg(any(stm32f446, stm32f427, stm32f437, stm32f4x9, stm32f7))]
+        pllsai1_q: pllsai.q,
+        #[cfg(any(stm32f446, stm32f427, stm32f437, stm32f4x9, stm32f7))]
+        pllsai1_r: pllsai.r,
+
+        clk48: pll.q,
+
+        hsi_hse: None,
+        afif: None,
+    );
 }
 
 struct PllInput {
diff --git a/embassy-stm32/src/rcc/f0.rs b/embassy-stm32/src/rcc/f0.rs
index feaa2f4c0..a6b627887 100644
--- a/embassy-stm32/src/rcc/f0.rs
+++ b/embassy-stm32/src/rcc/f0.rs
@@ -1,6 +1,5 @@
 use stm32_metapac::flash::vals::Latency;
 
-use super::{set_freqs, Clocks};
 use crate::pac::rcc::vals::{Hpre, Pllmul, Pllsrc, Ppre, Sw, Usbsw};
 use crate::pac::{FLASH, RCC};
 use crate::time::Hertz;
@@ -160,13 +159,15 @@ pub(crate) unsafe fn init(config: Config) {
 
     let rtc = config.ls.init();
 
-    set_freqs(Clocks {
-        sys: Hertz(real_sysclk),
-        pclk1: Hertz(pclk),
-        pclk2: Hertz(pclk),
-        pclk1_tim: Hertz(pclk * timer_mul),
-        pclk2_tim: Hertz(pclk * timer_mul),
-        hclk1: Hertz(hclk),
-        rtc,
-    });
+    set_clocks!(
+        hsi: None,
+        lse: None,
+        sys: Some(Hertz(real_sysclk)),
+        pclk1: Some(Hertz(pclk)),
+        pclk2: Some(Hertz(pclk)),
+        pclk1_tim: Some(Hertz(pclk * timer_mul)),
+        pclk2_tim: Some(Hertz(pclk * timer_mul)),
+        hclk1: Some(Hertz(hclk)),
+        rtc: rtc,
+    );
 }
diff --git a/embassy-stm32/src/rcc/f1.rs b/embassy-stm32/src/rcc/f1.rs
index 169551e45..7f0adab27 100644
--- a/embassy-stm32/src/rcc/f1.rs
+++ b/embassy-stm32/src/rcc/f1.rs
@@ -1,6 +1,5 @@
 use core::convert::TryFrom;
 
-use super::{set_freqs, Clocks};
 use crate::pac::flash::vals::Latency;
 use crate::pac::rcc::vals::*;
 use crate::pac::{FLASH, RCC};
@@ -179,14 +178,14 @@ pub(crate) unsafe fn init(config: Config) {
 
     let rtc = config.ls.init();
 
-    set_freqs(Clocks {
-        sys: Hertz(real_sysclk),
-        pclk1: Hertz(pclk1),
-        pclk2: Hertz(pclk2),
-        pclk1_tim: Hertz(pclk1 * timer_mul1),
-        pclk2_tim: Hertz(pclk2 * timer_mul2),
-        hclk1: Hertz(hclk),
+    set_clocks!(
+        sys: Some(Hertz(real_sysclk)),
+        pclk1: Some(Hertz(pclk1)),
+        pclk2: Some(Hertz(pclk2)),
+        pclk1_tim: Some(Hertz(pclk1 * timer_mul1)),
+        pclk2_tim: Some(Hertz(pclk2 * timer_mul2)),
+        hclk1: Some(Hertz(hclk)),
         adc: Some(Hertz(adcclk)),
-        rtc,
-    });
+        rtc: rtc,
+    );
 }
diff --git a/embassy-stm32/src/rcc/f3.rs b/embassy-stm32/src/rcc/f3.rs
index bf035fd25..25866e446 100644
--- a/embassy-stm32/src/rcc/f3.rs
+++ b/embassy-stm32/src/rcc/f3.rs
@@ -4,7 +4,6 @@ use crate::pac::flash::vals::Latency;
 pub use crate::pac::rcc::vals::Adcpres;
 use crate::pac::rcc::vals::{Hpre, Pllmul, Pllsrc, Ppre, Prediv, Sw, Usbpre};
 use crate::pac::{FLASH, RCC};
-use crate::rcc::{set_freqs, Clocks};
 use crate::time::Hertz;
 
 /// HSI speed
@@ -279,13 +278,16 @@ pub(crate) unsafe fn init(config: Config) {
 
     let rtc = config.ls.init();
 
-    set_freqs(Clocks {
-        sys: sysclk,
-        pclk1: pclk1,
-        pclk2: pclk2,
-        pclk1_tim: pclk1 * timer_mul1,
-        pclk2_tim: pclk2 * timer_mul2,
-        hclk1: hclk,
+    set_clocks!(
+        hsi: None,
+        lse: None,
+        pll1_p: None,
+        sys: Some(sysclk),
+        pclk1: Some(pclk1),
+        pclk2: Some(pclk2),
+        pclk1_tim: Some(pclk1 * timer_mul1),
+        pclk2_tim: Some(pclk2 * timer_mul2),
+        hclk1: Some(hclk),
         #[cfg(rcc_f3)]
         adc: adc,
         #[cfg(all(rcc_f3, adc3_common))]
@@ -294,8 +296,8 @@ pub(crate) unsafe fn init(config: Config) {
         adc34: None,
         #[cfg(stm32f334)]
         hrtim: hrtim,
-        rtc,
-    });
+        rtc: rtc,
+    );
 }
 
 #[inline]
diff --git a/embassy-stm32/src/rcc/g0.rs b/embassy-stm32/src/rcc/g0.rs
index b38fe1dcc..e3cd46fb9 100644
--- a/embassy-stm32/src/rcc/g0.rs
+++ b/embassy-stm32/src/rcc/g0.rs
@@ -4,7 +4,6 @@ pub use crate::pac::rcc::vals::{
     Hpre as AHBPrescaler, Hsidiv as HSIPrescaler, Pllm, Plln, Pllp, Pllq, Pllr, Ppre as APBPrescaler,
 };
 use crate::pac::{FLASH, PWR, RCC};
-use crate::rcc::{set_freqs, Clocks};
 use crate::time::Hertz;
 
 /// HSI speed
@@ -352,11 +351,11 @@ pub(crate) unsafe fn init(config: Config) {
     #[cfg(not(any(stm32g0b1, stm32g0c1, stm32g0b0)))]
     let hsi48_freq: Option<Hertz> = None;
 
-    set_freqs(Clocks {
-        sys: sys_clk,
-        hclk1: ahb_freq,
-        pclk1: apb_freq,
-        pclk1_tim: apb_tim_freq,
+    set_clocks!(
+        sys: Some(sys_clk),
+        hclk1: Some(ahb_freq),
+        pclk1: Some(apb_freq),
+        pclk1_tim: Some(apb_tim_freq),
         hsi: hsi_freq,
         hsi48: hsi48_freq,
         hsi_div_8: hsi_div_8_freq,
@@ -365,6 +364,6 @@ pub(crate) unsafe fn init(config: Config) {
         lsi: lsi_freq,
         pll1_q: pll1_q_freq,
         pll1_p: pll1_p_freq,
-        rtc,
-    });
+        rtc: rtc,
+    );
 }
diff --git a/embassy-stm32/src/rcc/g4.rs b/embassy-stm32/src/rcc/g4.rs
index 891f0490b..3e20bf6af 100644
--- a/embassy-stm32/src/rcc/g4.rs
+++ b/embassy-stm32/src/rcc/g4.rs
@@ -7,7 +7,6 @@ pub use crate::pac::rcc::vals::{
     Pllp as PllP, Pllq as PllQ, Pllr as PllR, Ppre as APBPrescaler,
 };
 use crate::pac::{PWR, RCC};
-use crate::rcc::{set_freqs, Clocks};
 use crate::time::Hertz;
 
 /// HSI speed
@@ -307,20 +306,20 @@ pub(crate) unsafe fn init(config: Config) {
 
     let rtc = config.ls.init();
 
-    set_freqs(Clocks {
-        sys: sys_clk,
-        hclk1: ahb_freq,
-        hclk2: ahb_freq,
-        hclk3: ahb_freq,
-        pclk1: apb1_freq,
-        pclk1_tim: apb1_tim_freq,
-        pclk2: apb2_freq,
-        pclk2_tim: apb2_tim_freq,
+    set_clocks!(
+        sys: Some(sys_clk),
+        hclk1: Some(ahb_freq),
+        hclk2: Some(ahb_freq),
+        hclk3: Some(ahb_freq),
+        pclk1: Some(apb1_freq),
+        pclk1_tim: Some(apb1_tim_freq),
+        pclk2: Some(apb2_freq),
+        pclk2_tim: Some(apb2_tim_freq),
         adc: adc12_ck,
         adc34: adc345_ck,
         pll1_p: None,
         pll1_q: None, // TODO
         hse: None,    // TODO
-        rtc,
-    });
+        rtc: rtc,
+    );
 }
diff --git a/embassy-stm32/src/rcc/h.rs b/embassy-stm32/src/rcc/h.rs
index dcaf2dced..9ac2115f0 100644
--- a/embassy-stm32/src/rcc/h.rs
+++ b/embassy-stm32/src/rcc/h.rs
@@ -12,7 +12,6 @@ pub use crate::pac::rcc::vals::{
 };
 use crate::pac::rcc::vals::{Ckpersel, Pllrge, Pllvcosel, Timpre};
 use crate::pac::{FLASH, PWR, RCC};
-use crate::rcc::{set_freqs, Clocks};
 use crate::time::Hertz;
 
 /// HSI speed
@@ -430,7 +429,7 @@ pub(crate) unsafe fn init(config: Config) {
     };
 
     // Configure HSI48.
-    let _hsi48 = config.hsi48.map(super::init_hsi48);
+    let hsi48 = config.hsi48.map(super::init_hsi48);
 
     // Configure CSI.
     RCC.cr().modify(|w| w.set_csion(config.csi));
@@ -614,45 +613,33 @@ pub(crate) unsafe fn init(config: Config) {
         while !pac::SYSCFG.cccsr().read().ready() {}
     }
 
-    set_freqs(Clocks {
-        sys,
-        hclk1: hclk,
-        hclk2: hclk,
-        hclk3: hclk,
-        hclk4: hclk,
-        pclk1: apb1,
-        pclk2: apb2,
-        pclk3: apb3,
+    set_clocks!(
+        sys: Some(sys),
+        hclk1: Some(hclk),
+        hclk2: Some(hclk),
+        hclk3: Some(hclk),
+        hclk4: Some(hclk),
+        pclk1: Some(apb1),
+        pclk2: Some(apb2),
+        pclk3: Some(apb3),
         #[cfg(stm32h7)]
-        pclk4: apb4,
-        #[cfg(stm32h5)]
-        pclk4: Hertz(1),
-        pclk1_tim: apb1_tim,
-        pclk2_tim: apb2_tim,
-        adc,
-        rtc,
+        pclk4: Some(apb4),
+        pclk1_tim: Some(apb1_tim),
+        pclk2_tim: Some(apb2_tim),
+        adc: adc,
+        rtc: rtc,
 
-        #[cfg(any(stm32h5, stm32h7))]
-        hsi: None,
-        #[cfg(stm32h5)]
-        hsi48: None,
-        #[cfg(stm32h5)]
-        lsi: None,
-        #[cfg(any(stm32h5, stm32h7))]
-        csi: None,
+        hsi: hsi,
+        hsi48: hsi48,
+        csi: csi,
+        hse: hse,
 
-        #[cfg(any(stm32h5, stm32h7))]
         lse: None,
-        #[cfg(any(stm32h5, stm32h7))]
-        hse: None,
+        lsi: None,
 
-        #[cfg(any(stm32h5, stm32h7))]
         pll1_q: pll1.q,
-        #[cfg(any(stm32h5, stm32h7))]
         pll2_p: pll2.p,
-        #[cfg(any(stm32h5, stm32h7))]
         pll2_q: pll2.q,
-        #[cfg(any(stm32h5, stm32h7))]
         pll2_r: pll2.r,
         #[cfg(any(rcc_h5, stm32h7))]
         pll3_p: pll3.p,
@@ -670,12 +657,8 @@ pub(crate) unsafe fn init(config: Config) {
 
         #[cfg(stm32h5)]
         audioclk: None,
-        #[cfg(any(stm32h5, stm32h7))]
         per: None,
-
-        #[cfg(stm32h7)]
-        rcc_pclk_d3: None,
-    });
+    );
 }
 
 struct PllInput {
diff --git a/embassy-stm32/src/rcc/l.rs b/embassy-stm32/src/rcc/l.rs
index 257fd83fe..ab1681dd4 100644
--- a/embassy-stm32/src/rcc/l.rs
+++ b/embassy-stm32/src/rcc/l.rs
@@ -9,7 +9,6 @@ pub use crate::pac::rcc::vals::Clk48sel as Clk48Src;
 pub use crate::pac::rcc::vals::Hsepre as HsePrescaler;
 pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Msirange as MSIRange, Ppre as APBPrescaler, Sw as ClockSrc};
 use crate::pac::{FLASH, RCC};
-use crate::rcc::{set_freqs, Clocks};
 use crate::time::Hertz;
 
 /// HSI speed
@@ -262,7 +261,7 @@ pub(crate) unsafe fn init(config: Config) {
     #[cfg(any(stm32l4, stm32l5, stm32wb))]
     let pllsai1 = init_pll(PllInstance::Pllsai1, config.pllsai1, &pll_input);
     #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
-    let _pllsai2 = init_pll(PllInstance::Pllsai2, config.pllsai2, &pll_input);
+    let pllsai2 = init_pll(PllInstance::Pllsai2, config.pllsai2, &pll_input);
 
     let sys_clk = match config.mux {
         ClockSrc::HSE => hse.unwrap(),
@@ -274,12 +273,12 @@ pub(crate) unsafe fn init(config: Config) {
     #[cfg(any(rcc_l0_v2, stm32l4, stm32l5, stm32wb))]
     RCC.ccipr().modify(|w| w.set_clk48sel(config.clk48_src));
     #[cfg(any(rcc_l0_v2))]
-    let _clk48 = match config.clk48_src {
+    let clk48 = match config.clk48_src {
         Clk48Src::HSI48 => _hsi48,
         Clk48Src::PLL1_VCO_DIV_2 => pll.clk48,
     };
     #[cfg(any(stm32l4, stm32l5, stm32wb))]
-    let _clk48 = match config.clk48_src {
+    let clk48 = match config.clk48_src {
         Clk48Src::HSI48 => _hsi48,
         Clk48Src::MSI => msi,
         Clk48Src::PLLSAI1_Q => pllsai1.q,
@@ -376,37 +375,53 @@ pub(crate) unsafe fn init(config: Config) {
         while !RCC.extcfgr().read().c2hpref() {}
     }
 
-    set_freqs(Clocks {
-        sys: sys_clk,
-        hclk1,
+    set_clocks!(
+        sys: Some(sys_clk),
+        hclk1: Some(hclk1),
         #[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))]
-        hclk2,
+        hclk2: Some(hclk2),
         #[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))]
-        hclk3,
-        pclk1,
-        pclk2,
-        pclk1_tim,
-        pclk2_tim,
+        hclk3: Some(hclk3),
+        pclk1: Some(pclk1),
+        pclk2: Some(pclk2),
+        pclk1_tim: Some(pclk1_tim),
+        pclk2_tim: Some(pclk2_tim),
         #[cfg(stm32wl)]
-        pclk3: hclk3,
-        #[cfg(rcc_l4)]
-        hsi: None,
-        #[cfg(rcc_l4)]
-        lse: None,
-        #[cfg(rcc_l4)]
-        pllsai1_p: None,
-        #[cfg(rcc_l4)]
-        pllsai2_p: None,
-        #[cfg(rcc_l4)]
-        pll1_p: None,
-        #[cfg(rcc_l4)]
-        pll1_q: None,
-        #[cfg(rcc_l4)]
+        pclk3: Some(hclk3),
+        hsi: hsi,
+        hse: hse,
+        msi: msi,
+        #[cfg(any(rcc_l0_v2, stm32l4, stm32l5, stm32wb))]
+        clk48: clk48,
+
+        #[cfg(not(any(stm32l0, stm32l1)))]
+        pll1_p: pll.p,
+        #[cfg(not(any(stm32l0, stm32l1)))]
+        pll1_q: pll.q,
+        pll1_r: pll.r,
+
+        #[cfg(any(stm32l4, stm32l5, stm32wb))]
+        pllsai1_p: pllsai1.p,
+        #[cfg(any(stm32l4, stm32l5, stm32wb))]
+        pllsai1_q: pllsai1.q,
+        #[cfg(any(stm32l4, stm32l5, stm32wb))]
+        pllsai1_r: pllsai1.r,
+
+        #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
+        pllsai2_p: pllsai2.p,
+        #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
+        pllsai2_q: pllsai2.q,
+        #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
+        pllsai2_r: pllsai2.r,
+
+        rtc: rtc,
+
+        // TODO
         sai1_extclk: None,
-        #[cfg(rcc_l4)]
         sai2_extclk: None,
-        rtc,
-    });
+        lsi: None,
+        lse: None,
+    );
 }
 
 #[cfg(any(stm32l0, stm32l1))]
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs
index 240ffc6d2..280da7ae3 100644
--- a/embassy-stm32/src/rcc/mod.rs
+++ b/embassy-stm32/src/rcc/mod.rs
@@ -5,8 +5,6 @@
 
 use core::mem::MaybeUninit;
 
-use crate::time::Hertz;
-
 mod bd;
 mod mco;
 pub use bd::*;
@@ -32,162 +30,7 @@ mod _version;
 
 pub use _version::*;
 
-//  Model Clock Configuration
-//
-//  pub struct Clocks {
-//      hse: Option<Hertz>,
-//      hsi: bool,
-//      lse: Option<Hertz>,
-//      lsi: bool,
-//      rtc: RtcSource,
-//  }
-
-#[derive(Clone, Copy, Debug)]
-#[cfg_attr(feature = "defmt", derive(defmt::Format))]
-pub struct Clocks {
-    pub sys: Hertz,
-
-    // APB
-    pub pclk1: Hertz,
-    pub pclk1_tim: Hertz,
-    #[cfg(not(any(rcc_c0, rcc_g0)))]
-    pub pclk2: Hertz,
-    #[cfg(not(any(rcc_c0, rcc_g0)))]
-    pub pclk2_tim: Hertz,
-    #[cfg(any(rcc_wl5, rcc_wle, rcc_h5, rcc_h50, rcc_h7, rcc_h7rm0433, rcc_h7ab, rcc_u5))]
-    pub pclk3: Hertz,
-    #[cfg(any(rcc_h7, rcc_h7rm0433, rcc_h7ab, stm32h5))]
-    pub pclk4: Hertz,
-    #[cfg(any(rcc_wba))]
-    pub pclk7: Hertz,
-
-    // AHB
-    pub hclk1: Hertz,
-    #[cfg(any(
-        rcc_l4,
-        rcc_l4plus,
-        rcc_l5,
-        rcc_f2,
-        rcc_f4,
-        rcc_f410,
-        rcc_f7,
-        rcc_h5,
-        rcc_h50,
-        rcc_h7,
-        rcc_h7rm0433,
-        rcc_h7ab,
-        rcc_g4,
-        rcc_u5,
-        rcc_wb,
-        rcc_wba,
-        rcc_wl5,
-        rcc_wle
-    ))]
-    pub hclk2: Hertz,
-    #[cfg(any(
-        rcc_l4,
-        rcc_l4plus,
-        rcc_l5,
-        rcc_f2,
-        rcc_f4,
-        rcc_f410,
-        rcc_f7,
-        rcc_h5,
-        rcc_h50,
-        rcc_h7,
-        rcc_h7rm0433,
-        rcc_h7ab,
-        rcc_u5,
-        rcc_g4,
-        rcc_wb,
-        rcc_wl5,
-        rcc_wle
-    ))]
-    pub hclk3: Hertz,
-    #[cfg(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7rm0433, rcc_h7ab, rcc_wba))]
-    pub hclk4: Hertz,
-
-    #[cfg(all(rcc_f4, not(stm32f410)))]
-    pub plli2s1_q: Option<Hertz>,
-    #[cfg(all(rcc_f4, not(stm32f410)))]
-    pub plli2s1_r: Option<Hertz>,
-
-    #[cfg(rcc_l4)]
-    pub pllsai1_p: Option<Hertz>,
-    #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
-    pub pllsai1_q: Option<Hertz>,
-    #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
-    pub pllsai1_r: Option<Hertz>,
-    #[cfg(rcc_l4)]
-    pub pllsai2_p: Option<Hertz>,
-
-    #[cfg(any(stm32g0, stm32g4, rcc_l4))]
-    pub pll1_p: Option<Hertz>,
-    #[cfg(any(stm32h5, stm32h7, stm32f2, stm32f4, stm32f7, rcc_l4, stm32g0, stm32g4))]
-    pub pll1_q: Option<Hertz>,
-    #[cfg(any(stm32h5, stm32h7))]
-    pub pll2_p: Option<Hertz>,
-    #[cfg(any(stm32h5, stm32h7))]
-    pub pll2_q: Option<Hertz>,
-    #[cfg(any(stm32h5, stm32h7))]
-    pub pll2_r: Option<Hertz>,
-    #[cfg(any(stm32h5, stm32h7))]
-    pub pll3_p: Option<Hertz>,
-    #[cfg(any(stm32h5, stm32h7))]
-    pub pll3_q: Option<Hertz>,
-    #[cfg(any(stm32h5, stm32h7))]
-    pub pll3_r: Option<Hertz>,
-
-    #[cfg(any(
-        rcc_f1,
-        rcc_f100,
-        rcc_f1cl,
-        rcc_h5,
-        rcc_h50,
-        rcc_h7,
-        rcc_h7rm0433,
-        rcc_h7ab,
-        rcc_f3,
-        rcc_g4
-    ))]
-    pub adc: Option<Hertz>,
-
-    #[cfg(any(rcc_f3, rcc_g4))]
-    pub adc34: Option<Hertz>,
-
-    #[cfg(stm32f334)]
-    pub hrtim: Option<Hertz>,
-
-    pub rtc: Option<Hertz>,
-
-    #[cfg(any(stm32h5, stm32h7, rcc_l4, rcc_c0, stm32g0))]
-    pub hsi: Option<Hertz>,
-    #[cfg(any(stm32h5, stm32g0))]
-    pub hsi48: Option<Hertz>,
-    #[cfg(stm32g0)]
-    pub hsi_div_8: Option<Hertz>,
-    #[cfg(any(stm32g0, stm32h5))]
-    pub lsi: Option<Hertz>,
-    #[cfg(any(stm32h5, stm32h7))]
-    pub csi: Option<Hertz>,
-
-    #[cfg(any(stm32h5, stm32h7, rcc_l4, rcc_c0, stm32g0))]
-    pub lse: Option<Hertz>,
-    #[cfg(any(stm32h5, stm32h7, stm32g0, stm32g4))]
-    pub hse: Option<Hertz>,
-
-    #[cfg(stm32h5)]
-    pub audioclk: Option<Hertz>,
-    #[cfg(any(stm32h5, stm32h7))]
-    pub per: Option<Hertz>,
-
-    #[cfg(stm32h7)]
-    pub rcc_pclk_d3: Option<Hertz>,
-    #[cfg(rcc_l4)]
-    pub sai1_extclk: Option<Hertz>,
-    #[cfg(rcc_l4)]
-    pub sai2_extclk: Option<Hertz>,
-}
+pub use crate::_generated::Clocks;
 
 #[cfg(feature = "low-power")]
 /// Must be written within a critical section
diff --git a/embassy-stm32/src/rcc/u5.rs b/embassy-stm32/src/rcc/u5.rs
index dff08dc9b..9cec6c96c 100644
--- a/embassy-stm32/src/rcc/u5.rs
+++ b/embassy-stm32/src/rcc/u5.rs
@@ -1,7 +1,6 @@
 pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Msirange, Plldiv, Pllm, Plln, Ppre as APBPrescaler};
 use crate::pac::rcc::vals::{Msirgsel, Pllmboost, Pllrge, Pllsrc, Sw};
 use crate::pac::{FLASH, PWR, RCC};
-use crate::rcc::{set_freqs, Clocks};
 use crate::time::Hertz;
 
 /// HSI speed
@@ -338,7 +337,7 @@ pub(crate) unsafe fn init(config: Config) {
         }
     };
 
-    let _hsi48 = config.hsi48.map(super::init_hsi48);
+    let hsi48 = config.hsi48.map(super::init_hsi48);
 
     // The clock source is ready
     // Calculate and set the flash wait states
@@ -448,18 +447,37 @@ pub(crate) unsafe fn init(config: Config) {
 
     let rtc = config.ls.init();
 
-    set_freqs(Clocks {
-        sys: sys_clk,
-        hclk1: ahb_freq,
-        hclk2: ahb_freq,
-        hclk3: ahb_freq,
-        pclk1: apb1_freq,
-        pclk2: apb2_freq,
-        pclk3: apb3_freq,
-        pclk1_tim: apb1_tim_freq,
-        pclk2_tim: apb2_tim_freq,
-        rtc,
-    });
+    set_clocks!(
+        sys: Some(sys_clk),
+        hclk1: Some(ahb_freq),
+        hclk2: Some(ahb_freq),
+        hclk3: Some(ahb_freq),
+        pclk1: Some(apb1_freq),
+        pclk2: Some(apb2_freq),
+        pclk3: Some(apb3_freq),
+        pclk1_tim: Some(apb1_tim_freq),
+        pclk2_tim: Some(apb2_tim_freq),
+        hsi48: hsi48,
+        rtc: rtc,
+
+        // TODO
+        hse: None,
+        hsi: None,
+        audioclk: None,
+        hsi48_div_2: None,
+        lse: None,
+        lsi: None,
+        msik: None,
+        pll1_p: None,
+        pll1_q: None,
+        pll1_r: None,
+        pll2_p: None,
+        pll2_q: None,
+        pll2_r: None,
+        pll3_p: None,
+        pll3_q: None,
+        pll3_r: None,
+    );
 }
 
 fn msirange_to_hertz(range: Msirange) -> Hertz {
diff --git a/embassy-stm32/src/rcc/wba.rs b/embassy-stm32/src/rcc/wba.rs
index dfa236484..47ce4783c 100644
--- a/embassy-stm32/src/rcc/wba.rs
+++ b/embassy-stm32/src/rcc/wba.rs
@@ -4,7 +4,6 @@ pub use crate::pac::rcc::vals::{
     Adcsel as AdcClockSource, Hpre as AHBPrescaler, Hsepre as HsePrescaler, Ppre as APBPrescaler, Sw as ClockSrc,
 };
 use crate::pac::{FLASH, RCC};
-use crate::rcc::{set_freqs, Clocks};
 use crate::time::Hertz;
 
 /// HSI speed
@@ -155,16 +154,23 @@ pub(crate) unsafe fn init(config: Config) {
 
     RCC.ccipr3().modify(|w| w.set_adcsel(config.adc_clock_source));
 
-    set_freqs(Clocks {
-        sys: sys_clk,
-        hclk1,
-        hclk2,
-        hclk4,
-        pclk1,
-        pclk2,
-        pclk7,
-        pclk1_tim,
-        pclk2_tim,
-        rtc,
-    });
+    set_clocks!(
+        sys: Some(sys_clk),
+        hclk1: Some(hclk1),
+        hclk2: Some(hclk2),
+        hclk4: Some(hclk4),
+        pclk1: Some(pclk1),
+        pclk2: Some(pclk2),
+        pclk7: Some(pclk7),
+        pclk1_tim: Some(pclk1_tim),
+        pclk2_tim: Some(pclk2_tim),
+        rtc: rtc,
+        hse: hse,
+        hsi: hsi,
+
+        // TODO
+        lse: None,
+        lsi: None,
+        pll1_q: None,
+    );
 }
diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs
index debe26c88..61589a215 100644
--- a/embassy-stm32/src/sdmmc/mod.rs
+++ b/embassy-stm32/src/sdmmc/mod.rs
@@ -670,7 +670,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
             _ => panic!("Invalid Bus Width"),
         };
 
-        let ker_ck = T::kernel_clk();
+        let ker_ck = T::frequency();
         let (_bypass, clkdiv, new_clock) = clk_div(ker_ck, freq)?;
 
         // Enforce AHB and SDMMC_CK clock relation. See RM0433 Rev 7
@@ -1023,7 +1023,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
     /// specified frequency.
     pub async fn init_card(&mut self, freq: Hertz) -> Result<(), Error> {
         let regs = T::regs();
-        let ker_ck = T::kernel_clk();
+        let ker_ck = T::frequency();
 
         let bus_width = match self.d3.is_some() {
             true => BusWidth::Four,
@@ -1429,7 +1429,6 @@ pub(crate) mod sealed {
 
         fn regs() -> RegBlock;
         fn state() -> &'static AtomicWaker;
-        fn kernel_clk() -> Hertz;
     }
 
     pub trait Pins<T: Instance> {}
@@ -1461,61 +1460,6 @@ pub trait SdmmcDma<T: Instance> {}
 #[cfg(sdmmc_v2)]
 impl<T: Instance> SdmmcDma<T> for NoDma {}
 
-cfg_if::cfg_if! {
-    // TODO, these could not be implemented, because required clocks are not exposed in RCC:
-    // - H7 uses pll1_q_ck or pll2_r_ck depending on SDMMCSEL
-    // - L1 uses pll48
-    // - L4 uses clk48(pll48)
-    // - L4+, L5, U5 uses clk48(pll48) or PLLSAI3CLK(PLLP) depending on SDMMCSEL
-    if #[cfg(stm32f1)] {
-        // F1 uses AHB1(HCLK), which is correct in PAC
-        macro_rules! kernel_clk {
-            ($inst:ident) => {
-                <peripherals::$inst as crate::rcc::sealed::RccPeripheral>::frequency()
-            }
-        }
-    } else if #[cfg(any(stm32f2, stm32f4))] {
-        // F2, F4 always use pll48
-        macro_rules! kernel_clk {
-            ($inst:ident) => {
-                critical_section::with(|_| unsafe {
-                    unwrap!(crate::rcc::get_freqs().pll1_q)
-                })
-            }
-        }
-    } else if #[cfg(stm32f7)] {
-        macro_rules! kernel_clk {
-            (SDMMC1) => {
-                critical_section::with(|_| unsafe {
-                    let sdmmcsel = crate::pac::RCC.dckcfgr2().read().sdmmc1sel();
-                    if sdmmcsel == crate::pac::rcc::vals::Sdmmcsel::SYS {
-                        crate::rcc::get_freqs().sys
-                    } else {
-                        unwrap!(crate::rcc::get_freqs().pll1_q)
-                    }
-                })
-            };
-            (SDMMC2) => {
-                critical_section::with(|_| unsafe {
-                    let sdmmcsel = crate::pac::RCC.dckcfgr2().read().sdmmc2sel();
-                    if sdmmcsel == crate::pac::rcc::vals::Sdmmcsel::SYS {
-                        crate::rcc::get_freqs().sys
-                    } else {
-                        unwrap!(crate::rcc::get_freqs().pll1_q)
-                    }
-                })
-            };
-        }
-    } else {
-        // Use default peripheral clock and hope it works
-        macro_rules! kernel_clk {
-            ($inst:ident) => {
-                <peripherals::$inst as crate::rcc::sealed::RccPeripheral>::frequency()
-            }
-        }
-    }
-}
-
 foreach_peripheral!(
     (sdmmc, $inst:ident) => {
         impl sealed::Instance for peripherals::$inst {
@@ -1529,10 +1473,6 @@ foreach_peripheral!(
                 static WAKER: ::embassy_sync::waitqueue::AtomicWaker = ::embassy_sync::waitqueue::AtomicWaker::new();
                 &WAKER
             }
-
-            fn kernel_clk() -> Hertz {
-                kernel_clk!($inst)
-            }
         }
 
         impl Instance for peripherals::$inst {}
diff --git a/embassy-stm32/src/usb/usb.rs b/embassy-stm32/src/usb/usb.rs
index f39915906..34d6b52fd 100644
--- a/embassy-stm32/src/usb/usb.rs
+++ b/embassy-stm32/src/usb/usb.rs
@@ -280,7 +280,7 @@ impl<'d, T: Instance> Driver<'d, T> {
         #[cfg(time)]
         embassy_time::block_for(embassy_time::Duration::from_millis(100));
         #[cfg(not(time))]
-        cortex_m::asm::delay(unsafe { crate::rcc::get_freqs() }.sys.0 / 10);
+        cortex_m::asm::delay(unsafe { crate::rcc::get_freqs() }.sys.unwrap().0 / 10);
 
         #[cfg(not(usb_v4))]
         regs.btable().write(|w| w.set_btable(0));