1use strum::FromRepr;
6
7use crate::{
8    clock::{
9        Clock,
10        RtcClock,
11        RtcFastClock,
12        RtcSlowClock,
13        clocks_ll::{
14            esp32c6_bbpll_get_freq_mhz,
15            esp32c6_cpu_get_hs_divider,
16            esp32c6_cpu_get_ls_divider,
17            esp32c6_rtc_bbpll_configure_raw,
18            esp32c6_rtc_freq_to_pll_mhz_raw,
19            esp32c6_rtc_update_to_8m,
20            esp32c6_rtc_update_to_xtal_raw,
21        },
22    },
23    peripherals::{LP_AON, LP_CLKRST, MODEM_LPCON, MODEM_SYSCON, PCR, PMU},
24    rtc_cntl::RtcCalSel,
25    soc::regi2c,
26};
27
28fn pmu_power_domain_force_default() {
29    PMU::regs().power_pd_top_cntl().modify(|_, w| {
33        w.force_top_reset().bit(false); w.force_top_iso().bit(false); w.force_top_pu().bit(false); w.force_top_no_reset().bit(false); w.force_top_no_iso().bit(false); w.force_top_pd().bit(false) });
40
41    PMU::regs().power_pd_hpaon_cntl().modify(|_, w| {
43        w.force_hp_aon_reset().bit(false); w.force_hp_aon_iso().bit(false); w.force_hp_aon_pu().bit(false); w.force_hp_aon_no_reset().bit(false); w.force_hp_aon_no_iso().bit(false); w.force_hp_aon_pd().bit(false) });
50
51    PMU::regs().power_pd_hpcpu_cntl().modify(|_, w| {
53        w.force_hp_cpu_reset().bit(false); w.force_hp_cpu_iso().bit(false); w.force_hp_cpu_pu().bit(false); w.force_hp_cpu_no_reset().bit(false); w.force_hp_cpu_no_iso().bit(false); w.force_hp_cpu_pd().bit(false) });
60
61    PMU::regs().power_pd_hpwifi_cntl().modify(|_, w| {
63        w.force_hp_wifi_reset().bit(false); w.force_hp_wifi_iso().bit(false); w.force_hp_wifi_pu().bit(false); w.force_hp_wifi_no_reset().bit(false); w.force_hp_wifi_no_iso().bit(false); w.force_hp_wifi_pd().bit(false) });
70
71    PMU::regs().power_pd_mem_cntl().modify(|_, w| unsafe {
74        w.force_hp_mem_no_iso().bits(0) });
76
77    PMU::regs().power_pd_lpperi_cntl().modify(|_, w| {
78        w.force_lp_peri_reset().bit(false); w.force_lp_peri_iso().bit(false); w.force_lp_peri_pu().bit(false); w.force_lp_peri_no_reset().bit(false); w.force_lp_peri_no_iso().bit(false); w.force_lp_peri_pd().bit(false) });
85}
86
87fn modem_clock_domain_power_state_icg_map_init() {
88    const ICG_NOGATING_MODEM: u8 = 1 << 1;
92    const ICG_NOGATING_ACTIVE: u8 = 1 << 2;
93
94    const ICG_NOGATING_ACTIVE_MODEM: u8 = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM;
95
96    MODEM_SYSCON::regs()
99        .clk_conf_power_st()
100        .modify(|_, w| unsafe {
101            w.clk_modem_apb_st_map().bits(ICG_NOGATING_ACTIVE_MODEM); w.clk_modem_peri_st_map().bits(ICG_NOGATING_ACTIVE); w.clk_wifi_st_map().bits(ICG_NOGATING_ACTIVE_MODEM); w.clk_bt_st_map().bits(ICG_NOGATING_ACTIVE_MODEM); w.clk_fe_st_map().bits(ICG_NOGATING_ACTIVE_MODEM); w.clk_zb_st_map().bits(ICG_NOGATING_ACTIVE_MODEM) });
108
109    MODEM_LPCON::regs()
110        .clk_conf_power_st()
111        .modify(|_, w| unsafe {
112            w.clk_lp_apb_st_map().bits(ICG_NOGATING_ACTIVE_MODEM); w.clk_i2c_mst_st_map().bits(ICG_NOGATING_ACTIVE_MODEM); w.clk_coex_st_map().bits(ICG_NOGATING_ACTIVE_MODEM); w.clk_wifipwr_st_map().bits(ICG_NOGATING_ACTIVE_MODEM) });
117}
118
119enum RtcSlowClockSource {
120    RcSlow  = 0,
122
123    XTAL32K = 1,
125
126    RC32K   = 2,
128
129    OscSlow = 3,
131
132    Invalid,
134}
135
136impl RtcSlowClockSource {
137    fn current() -> Self {
138        match LP_CLKRST::regs().lp_clk_conf().read().slow_clk_sel().bits() {
140            0 => Self::RcSlow,
141            1 => Self::XTAL32K,
142            2 => Self::RC32K,
143            3 => Self::OscSlow,
144            _ => Self::Invalid,
145        }
146    }
147}
148
149#[allow(unused)]
150enum ModemClockLpclkSource {
151    RcSlow = 0,
152    RcFast,
153    MainXtal,
154    RC32K,
155    XTAL32K,
156    EXT32K,
157}
158
159impl From<RtcSlowClockSource> for ModemClockLpclkSource {
160    fn from(src: RtcSlowClockSource) -> Self {
161        match src {
162            RtcSlowClockSource::RcSlow => Self::RcSlow,
163            RtcSlowClockSource::XTAL32K => Self::XTAL32K,
164            RtcSlowClockSource::RC32K => Self::RC32K,
165            RtcSlowClockSource::OscSlow => Self::EXT32K,
166            _ => Self::RcSlow,
167        }
168    }
169}
170
171fn modem_clock_hal_deselect_all_wifi_lpclk_source() {
172    MODEM_LPCON::regs().wifi_lp_clk_conf().modify(|_, w| {
173        w.clk_wifipwr_lp_sel_osc_slow().clear_bit();
174        w.clk_wifipwr_lp_sel_osc_fast().clear_bit();
175        w.clk_wifipwr_lp_sel_xtal32k().clear_bit();
176        w.clk_wifipwr_lp_sel_xtal().clear_bit()
177    });
178}
179
180fn modem_clock_hal_select_wifi_lpclk_source(src: ModemClockLpclkSource) {
181    MODEM_LPCON::regs()
182        .wifi_lp_clk_conf()
183        .modify(|_, w| match src {
184            ModemClockLpclkSource::RcSlow => w.clk_wifipwr_lp_sel_osc_slow().set_bit(),
185            ModemClockLpclkSource::RcFast => w.clk_wifipwr_lp_sel_osc_fast().set_bit(),
186            ModemClockLpclkSource::MainXtal => w.clk_wifipwr_lp_sel_xtal().set_bit(),
187
188            ModemClockLpclkSource::RC32K
189            | ModemClockLpclkSource::XTAL32K
190            | ModemClockLpclkSource::EXT32K => w.clk_wifipwr_lp_sel_xtal32k().set_bit(),
191        });
192
193    MODEM_LPCON::regs()
194        .modem_32k_clk_conf()
195        .modify(|_, w| unsafe {
196            match src {
197                ModemClockLpclkSource::RcSlow
198                | ModemClockLpclkSource::RcFast
199                | ModemClockLpclkSource::MainXtal => w,
200
201                ModemClockLpclkSource::RC32K => w.clk_modem_32k_sel().bits(1),
202                ModemClockLpclkSource::XTAL32K => w.clk_modem_32k_sel().bits(0),
203                ModemClockLpclkSource::EXT32K => w.clk_modem_32k_sel().bits(2),
204            }
205        });
206}
207
208fn modem_lpcon_ll_set_wifi_lpclk_divisor_value(divider: u16) {
209    MODEM_LPCON::regs()
210        .wifi_lp_clk_conf()
211        .modify(|_, w| unsafe { w.clk_wifipwr_lp_div_num().bits(divider) });
212}
213
214fn modem_clock_hal_enable_wifipwr_clock(enable: bool) {
215    MODEM_LPCON::regs()
216        .clk_conf()
217        .modify(|_, w| w.clk_wifipwr_en().bit(enable));
218}
219
220fn modem_clock_select_lp_clock_source_wifi(src: ModemClockLpclkSource, divider: u16) {
222    modem_clock_hal_deselect_all_wifi_lpclk_source();
223    modem_clock_hal_select_wifi_lpclk_source(src);
224    modem_lpcon_ll_set_wifi_lpclk_divisor_value(divider);
225    modem_clock_hal_enable_wifipwr_clock(true);
226}
227
228const fn hp_retention_regdma_config(dir: u8, entry: u8) -> u8 {
229    (((dir) << 2) | (entry & 0x3)) & 0x7
230}
231
232const HP_CALI_DBIAS: u8 = 25;
233const LP_CALI_DBIAS: u8 = 26;
234
235const ICG_MODEM_CODE_SLEEP: u8 = 0;
236const ICG_MODEM_CODE_MODEM: u8 = 1;
237const ICG_MODEM_CODE_ACTIVE: u8 = 2;
238
239const HP_SYSCLK_XTAL: u8 = 0;
240const HP_SYSCLK_PLL: u8 = 1;
241
242bitfield::bitfield! {
243    #[derive(Clone, Copy, Default)]
244    pub struct HpDigPower(u32);
246
247    pub bool, vdd_spi_pd_en, set_vdd_spi_pd_en: 21;
248    pub bool, mem_dslp     , set_mem_dslp     : 22;
249    pub u8,   mem_pd_en    , set_mem_pd_en    : 26, 23;
250    pub bool, wifi_pd_en   , set_wifi_pd_en   : 27;
251    pub bool, cpu_pd_en    , set_cpu_pd_en    : 29;
252    pub bool, aon_pd_en    , set_aon_pd_en    : 30;
253    pub bool, top_pd_en    , set_top_pd_en    : 31;
254}
255
256bitfield::bitfield! {
257    #[derive(Clone, Copy, Default)]
258    pub struct HpClkPower(u32);
260
261    pub bool, i2c_iso_en   , set_i2c_iso_en   : 26;
262    pub bool, i2c_retention, set_i2c_retention: 27;
263    pub bool, xpd_bb_i2c   , set_xpd_bb_i2c   : 28;
264    pub bool, xpd_bbpll_i2c, set_xpd_bbpll_i2c: 29;
265    pub bool, xpd_bbpll    , set_xpd_bbpll    : 30;
266}
267
268bitfield::bitfield! {
269    #[derive(Clone, Copy, Default)]
270    pub struct HpXtalPower(u32);
272
273    pub bool, xpd_xtal     , set_xpd_xtal     : 31;
274}
275
276#[derive(Clone, Copy, Default)]
277pub struct HpSysPower {
279    pub dig_power: HpDigPower,
282    pub clk: HpClkPower,
283    pub xtal: HpXtalPower,
284}
285
286bitfield::bitfield! {
287    #[derive(Clone, Copy, Default)]
288    pub struct HpSysCntlReg(u32);
290
291    pub bool, uart_wakeup_en , set_uart_wakeup_en : 24;
292    pub bool, lp_pad_hold_all, set_lp_pad_hold_all: 25;
293    pub bool, hp_pad_hold_all, set_hp_pad_hold_all: 26;
294    pub bool, dig_pad_slp_sel, set_dig_pad_slp_sel: 27;
295    pub bool, dig_pause_wdt  , set_dig_pause_wdt  : 28;
296    pub bool, dig_cpu_stall  , set_dig_cpu_stall  : 29;
297}
298
299bitfield::bitfield! {
300    #[derive(Clone, Copy, Default)]
301    pub struct HpIcgModem(u32);
303
304    pub u8, code, set_code: 31, 30;
305}
306
307bitfield::bitfield! {
308    #[derive(Clone, Copy, Default)]
309    pub struct HpSysclk(u32);
311
312    pub bool, dig_sysclk_nodiv , set_dig_sysclk_nodiv : 26;
313    pub bool, icg_sysclk_en    , set_icg_sysclk_en    : 27;
314    pub bool, sysclk_slp_sel   , set_sysclk_slp_sel   : 28;
315    pub bool, icg_slp_sel      , set_icg_slp_sel      : 29;
316    pub u8,   dig_sysclk_sel   , set_dig_sysclk_sel   : 31, 30;
317}
318
319#[derive(Clone, Copy, Default)]
321struct SystemClockParam {
322    icg_func: u32,
323    icg_apb: u32,
324    icg_modem: HpIcgModem,
325    sysclk: HpSysclk,
326}
327
328bitfield::bitfield! {
329    #[derive(Clone, Copy, Default)]
330    pub struct HpAnalogBias(u32);
332
333    pub bool, xpd_bias  , set_xpd_bias  : 25;
334    pub u8,   dbg_atten , set_dbg_atten : 29, 26;
335    pub bool, pd_cur    , set_pd_cur    : 30;
336    pub bool, bias_sleep, set_bias_sleep: 31;
337}
338
339bitfield::bitfield! {
340    #[derive(Clone, Copy, Default)]
341    pub struct HpAnalogRegulator0(u32);
343
344    pub u8,   lp_dbias_vol   , set_lp_dbias_vol   : 8, 4;
346    pub u8,   hp_dbias_vol   , set_hp_dbias_vol   : 13, 9;
348    pub bool, dbias_sel      , set_dbias_sel      : 14;
350    pub bool, dbias_init     , set_dbias_init     : 15;
352
353    pub bool, slp_mem_xpd    , set_slp_mem_xpd    : 16;
354    pub bool, slp_logic_xpd  , set_slp_logic_xpd  : 17;
355    pub bool, xpd            , set_xpd            : 18;
356    pub u8,   slp_mem_dbias  , set_slp_mem_dbias  : 22, 19;
357    pub u8,   slp_logic_dbias, set_slp_logic_dbias: 26, 23;
358    pub u8,   dbias          , set_dbias          : 31, 27;
359}
360
361bitfield::bitfield! {
362    #[derive(Clone, Copy, Default)]
363    pub struct HpAnalogRegulator1(u32);
365
366    pub u32, drv_b          , set_drv_b          : 31, 8;
367}
368
369#[derive(Clone, Copy, Default)]
370pub struct HpAnalog {
372    pub bias: HpAnalogBias,
373    pub regulator0: HpAnalogRegulator0,
374    pub regulator1: HpAnalogRegulator1,
375}
376
377bitfield::bitfield! {
378    #[derive(Clone, Copy, Default)]
379    pub struct HpActiveBackup(u32);
381
382    pub u8,   hp_sleep2active_backup_modem_clk_code, set_hp_sleep2active_backup_modem_clk_code: 5, 4;
383    pub u8,   hp_modem2active_backup_modem_clk_code, set_hp_modem2active_backup_modem_clk_code: 7, 6;
384    pub bool, hp_active_retention_mode             , set_hp_active_retention_mode             : 10;
385    pub bool, hp_sleep2active_retention_en         , set_hp_sleep2active_retention_en         : 11;
386    pub bool, hp_modem2active_retention_en         , set_hp_modem2active_retention_en         : 12;
387    pub u8,   hp_sleep2active_backup_clk_sel       , set_hp_sleep2active_backup_clk_sel       : 15, 14;
388    pub u8,   hp_modem2active_backup_clk_sel       , set_hp_modem2active_backup_clk_sel       : 17, 16;
389    pub u8,   hp_sleep2active_backup_mode          , set_hp_sleep2active_backup_mode          : 22, 20;
390    pub u8,   hp_modem2active_backup_mode          , set_hp_modem2active_backup_mode          : 25, 23;
391    pub bool, hp_sleep2active_backup_en            , set_hp_sleep2active_backup_en            : 29;
392    pub bool, hp_modem2active_backup_en            , set_hp_modem2active_backup_en            : 30;
393}
394
395bitfield::bitfield! {
396    #[derive(Clone, Copy, Default)]
397    pub struct HpModemBackup(u32);
399
400    pub u8,   hp_sleep2modem_backup_modem_clk_code , set_hp_sleep2modem_backup_modem_clk_code : 5, 4;
401    pub bool, hp_modem_retention_mode              , set_hp_modem_retention_mode              : 10;
402    pub bool, hp_sleep2modem_retention_en          , set_hp_sleep2modem_retention_en          : 11;
403    pub u8,   hp_sleep2modem_backup_clk_sel        , set_hp_sleep2modem_backup_clk_sel        : 15, 14;
404    pub u8,   hp_sleep2modem_backup_mode           , set_hp_sleep2modem_backup_mode           : 22, 20;
405    pub bool, hp_sleep2modem_backup_en             , set_hp_sleep2modem_backup_en             : 29;
406}
407
408bitfield::bitfield! {
409    #[derive(Clone, Copy, Default)]
410    pub struct HpSleepBackup(u32);
412
413    pub u8,   hp_modem2sleep_backup_modem_clk_code , set_hp_modem2sleep_backup_modem_clk_code : 7, 6;
414    pub u8,   hp_active2sleep_backup_modem_clk_code, set_hp_active2sleep_backup_modem_clk_code: 9, 8;
415    pub bool, hp_sleep_retention_mode              , set_hp_sleep_retention_mode              : 10;
416    pub bool, hp_modem2sleep_retention_en          , set_hp_modem2sleep_retention_en          : 12;
417    pub bool, hp_active2sleep_retention_en         , set_hp_active2sleep_retention_en         : 13;
418    pub u8,   hp_modem2sleep_backup_clk_sel        , set_hp_modem2sleep_backup_clk_sel        : 17, 16;
419    pub u8,   hp_active2sleep_backup_clk_sel       , set_hp_active2sleep_backup_clk_sel       : 19, 18;
420    pub u8,   hp_modem2sleep_backup_mode           , set_hp_modem2sleep_backup_mode           : 25, 23;
421    pub u8,   hp_active2sleep_backup_mode          , set_hp_active2sleep_backup_mode          : 28, 26;
422    pub bool, hp_modem2sleep_backup_en             , set_hp_modem2sleep_backup_en             : 30;
423    pub bool, hp_active2sleep_backup_en            , set_hp_active2sleep_backup_en            : 31;
424}
425
426bitfield::bitfield! {
427    #[derive(Clone, Copy, Default)]
428    pub struct HpBackupClk(u32);
430
431    pub bool, gdma        , set_gdma         : 0;
432    pub bool, spi2        , set_spi2         : 1;
433    pub bool, i2s_rx      , set_i2s_rx       : 2;
434    pub bool, uart0       , set_uart0        : 3;
435    pub bool, uart1       , set_uart1        : 4;
436    pub bool, uhci        , set_uhci         : 5;
437    pub bool, usb_device  , set_usb_device   : 6;
438    pub bool, i2s_tx      , set_i2s_tx       : 7;
439    pub bool, regdma      , set_regdma       : 8;
440    pub bool, retention   , set_retention    : 9;
441    pub bool, mem_monitor , set_mem_monitor  : 10;
442    pub bool, sdio_slave  , set_sdio_slave   : 11;
443    pub bool, tsens       , set_tsens        : 12;
444    pub bool, tg1         , set_tg1          : 13;
445    pub bool, tg0         , set_tg0          : 14;
446    pub bool, hpbus       , set_hpbus        : 15;
447    pub bool, soc_etm     , set_soc_etm      : 16;
448    pub bool, hpcore      , set_hpcore       : 17;
449    pub bool, systimer    , set_systimer     : 18;
450    pub bool, sec         , set_sec          : 19;
451    pub bool, saradc      , set_saradc       : 20;
452    pub bool, rmt         , set_rmt          : 21;
453    pub bool, pwm         , set_pwm          : 22;
454    pub bool, pvt_monitor , set_pvt_monitor  : 23;
455    pub bool, parl_tx     , set_parl_tx      : 24;
456    pub bool, parl_rx     , set_parl_rx      : 25;
457    pub bool, mspi        , set_mspi         : 26;
458    pub bool, ledc        , set_ledc         : 27;
459    pub bool, iomux       , set_iomux        : 28;
460    pub bool, i2c         , set_i2c          : 29;
461    pub bool, can1        , set_can1         : 30;
462    pub bool, can0        , set_can0         : 31;
463}
464
465macro_rules! hp_system_init {
466    ($state:ident => $s:ident) => {
467        paste::paste! {
468            unsafe {
469                PMU::regs().[<$state _dig_power >]().modify(|_, w| w.bits($s.power.dig_power.0));
471                PMU::regs().[<$state _hp_ck_power >]().modify(|_, w| w.bits($s.power.clk.0));
472                PMU::regs().[<$state _xtal >]().modify(|_, w| w
473                    .[<$state _xpd_xtal >]().bit($s.power.xtal.xpd_xtal())
474                );
475
476                PMU::regs().[<$state _icg_hp_func >]().write(|w| w.bits($s.clock.icg_func));
478                PMU::regs().[<$state _icg_hp_apb >]().write(|w| w.bits($s.clock.icg_apb));
479                PMU::regs().[<$state _icg_modem >]().write(|w| w
480                    .[<$state _dig_icg_modem_code >]().bits($s.clock.icg_modem.code())
481                );
482                PMU::regs().[<$state _sysclk >]().modify(|_, w| w
483                    .[<$state _dig_sys_clk_no_div >]().bit($s.clock.sysclk.dig_sysclk_nodiv())
484                    .[<$state _icg_sys_clock_en >]().bit($s.clock.sysclk.icg_sysclk_en())
485                    .[<$state _sys_clk_slp_sel >]().bit($s.clock.sysclk.sysclk_slp_sel())
486                    .[<$state _icg_slp_sel >]().bit($s.clock.sysclk.icg_slp_sel())
487                    .[<$state _dig_sys_clk_sel >]().bits($s.clock.sysclk.dig_sysclk_sel())
488                );
489
490                PMU::regs().[<$state _hp_sys_cntl >]().modify(|_, w| w
493                    .[<$state _uart_wakeup_en >]().bit($s.syscntl.uart_wakeup_en())
494                    .[<$state _lp_pad_hold_all >]().bit($s.syscntl.lp_pad_hold_all())
495                    .[<$state _hp_pad_hold_all >]().bit($s.syscntl.hp_pad_hold_all())
496                    .[<$state _dig_pad_slp_sel >]().bit($s.syscntl.dig_pad_slp_sel())
497                    .[<$state _dig_pause_wdt >]().bit($s.syscntl.dig_pause_wdt())
498                    .[<$state _dig_cpu_stall >]().bit($s.syscntl.dig_cpu_stall())
499                );
500
501                PMU::regs().[<$state _bias >]().modify(|_, w| w
504                    .[<$state _xpd_bias >]().bit($s.anlg.bias.xpd_bias())
505                    .[<$state _dbg_atten >]().bits($s.anlg.bias.dbg_atten())
506                    .[<$state _pd_cur >]().bit($s.anlg.bias.pd_cur())
507                    .sleep().bit($s.anlg.bias.bias_sleep())
508                );
509
510                PMU::regs().[<$state _hp_regulator0 >]().modify(|_, w| w
511                    .[<$state _hp_regulator_slp_mem_xpd >]().bit($s.anlg.regulator0.slp_mem_xpd())
512                    .[<$state _hp_regulator_slp_logic_xpd >]().bit($s.anlg.regulator0.slp_logic_xpd())
513                    .[<$state _hp_regulator_xpd >]().bit($s.anlg.regulator0.xpd())
514                    .[<$state _hp_regulator_slp_mem_dbias >]().bits($s.anlg.regulator0.slp_mem_dbias())
515                    .[<$state _hp_regulator_slp_logic_dbias >]().bits($s.anlg.regulator0.slp_logic_dbias())
516                    .[<$state _hp_regulator_dbias >]().bits($s.anlg.regulator0.dbias())
517                );
518
519                PMU::regs().[<$state _hp_regulator1 >]().modify(|_, w| w
520                    .[<$state _hp_regulator_drv_b >]().bits($s.anlg.regulator1.drv_b())
521                );
522
523                PMU::regs().[<$state _backup >]().write(|w| w.bits($s.retention));
526                PMU::regs().[<$state _backup_clk >]().write(|w| w.bits($s.backup_clk));
527            }
528        }
529    };
530}
531
532struct HpSystemInit {
533    power: HpSysPower,
534    clock: SystemClockParam,
535    syscntl: HpSysCntlReg,
536    anlg: HpAnalog,
537    retention: u32,
538    backup_clk: u32,
539}
540impl HpSystemInit {
541    fn active() -> Self {
542        let mut power = HpSysPower::default();
545        power.dig_power.set_vdd_spi_pd_en(false);
546        power.dig_power.set_wifi_pd_en(false);
547        power.dig_power.set_cpu_pd_en(false);
548        power.dig_power.set_aon_pd_en(false);
549        power.dig_power.set_top_pd_en(false);
550        power.dig_power.set_mem_pd_en(0);
551        power.dig_power.set_mem_dslp(false);
552
553        power.clk.set_i2c_iso_en(false);
554        power.clk.set_i2c_retention(false);
555        power.clk.set_xpd_bb_i2c(true);
556        power.clk.set_xpd_bbpll_i2c(true);
557        power.clk.set_xpd_bbpll(true);
558
559        power.xtal.set_xpd_xtal(true);
560
561        let mut clock = SystemClockParam {
562            icg_func: 0xffffffff,
563            icg_apb: 0xffffffff,
564            ..SystemClockParam::default()
565        };
566        clock.icg_modem.set_code(ICG_MODEM_CODE_ACTIVE);
567        clock.sysclk.set_dig_sysclk_nodiv(false);
568        clock.sysclk.set_icg_sysclk_en(true);
569        clock.sysclk.set_sysclk_slp_sel(false);
570        clock.sysclk.set_icg_slp_sel(false);
571        clock.sysclk.set_dig_sysclk_sel(HP_SYSCLK_XTAL);
572
573        let mut syscntl = HpSysCntlReg::default();
574        syscntl.set_uart_wakeup_en(false);
575        syscntl.set_lp_pad_hold_all(false);
576        syscntl.set_hp_pad_hold_all(false);
577        syscntl.set_dig_pad_slp_sel(false);
578        syscntl.set_dig_pause_wdt(false);
579        syscntl.set_dig_cpu_stall(false);
580
581        let mut anlg = HpAnalog::default();
583        anlg.bias.set_xpd_bias(true);
584        anlg.bias.set_dbg_atten(0x0);
585        anlg.bias.set_pd_cur(false);
586        anlg.bias.set_bias_sleep(false);
587
588        anlg.regulator0.set_lp_dbias_vol(0xD);
590        anlg.regulator0.set_hp_dbias_vol(0x1C);
591        anlg.regulator0.set_dbias_sel(true);
592        anlg.regulator0.set_dbias_init(true);
593
594        anlg.regulator0.set_slp_mem_xpd(false);
595        anlg.regulator0.set_slp_logic_xpd(false);
596        anlg.regulator0.set_xpd(true);
597        anlg.regulator0.set_slp_mem_dbias(0);
598        anlg.regulator0.set_slp_logic_dbias(0);
599        anlg.regulator0.set_dbias(HP_CALI_DBIAS);
600
601        anlg.regulator1.set_drv_b(0);
602
603        let mut retention = HpActiveBackup::default();
604        retention.set_hp_sleep2active_backup_modem_clk_code(2);
605        retention.set_hp_modem2active_backup_modem_clk_code(2);
606        retention.set_hp_active_retention_mode(false);
607        retention.set_hp_sleep2active_retention_en(false);
608        retention.set_hp_modem2active_retention_en(false);
609        retention.set_hp_sleep2active_backup_clk_sel(0);
610        retention.set_hp_modem2active_backup_clk_sel(1);
611        retention.set_hp_sleep2active_backup_mode(hp_retention_regdma_config(0, 0));
612        retention.set_hp_modem2active_backup_mode(hp_retention_regdma_config(0, 2));
613        retention.set_hp_sleep2active_backup_en(false);
614        retention.set_hp_modem2active_backup_en(false);
615
616        let mut backup_clk = HpBackupClk::default();
617        backup_clk.set_regdma(true);
618        backup_clk.set_tg0(true);
619        backup_clk.set_tg1(true);
620        backup_clk.set_hpbus(true);
621        backup_clk.set_mspi(true);
622        backup_clk.set_iomux(true);
623        backup_clk.set_spi2(true);
624        backup_clk.set_uart0(true);
625        backup_clk.set_systimer(true);
626
627        Self {
628            power,
629            clock,
630            syscntl,
631            anlg,
632            retention: retention.0,
633            backup_clk: backup_clk.0,
634        }
635    }
636
637    fn modem() -> Self {
638        let mut power = HpSysPower::default();
639        power.dig_power.set_vdd_spi_pd_en(false);
640        power.dig_power.set_wifi_pd_en(false);
641        power.dig_power.set_cpu_pd_en(true);
642        power.dig_power.set_aon_pd_en(false);
643        power.dig_power.set_top_pd_en(false);
644        power.dig_power.set_mem_pd_en(0);
645        power.dig_power.set_mem_dslp(false);
646
647        power.clk.set_xpd_bb_i2c(true);
648        power.clk.set_xpd_bbpll_i2c(true);
649        power.clk.set_xpd_bbpll(true);
650        power.clk.set_i2c_iso_en(false);
651        power.clk.set_i2c_retention(false);
652
653        power.xtal.set_xpd_xtal(true);
654
655        let mut clock = SystemClockParam {
656            icg_func: 0,
657            icg_apb: 0,
658            ..SystemClockParam::default()
659        };
660        clock.icg_modem.set_code(ICG_MODEM_CODE_MODEM);
661        clock.sysclk.set_dig_sysclk_nodiv(false);
662        clock.sysclk.set_icg_sysclk_en(true);
663        clock.sysclk.set_sysclk_slp_sel(true);
664        clock.sysclk.set_icg_slp_sel(true);
665        clock.sysclk.set_dig_sysclk_sel(HP_SYSCLK_PLL);
666
667        let mut syscntl = HpSysCntlReg::default();
668        syscntl.set_uart_wakeup_en(true);
669        syscntl.set_lp_pad_hold_all(false);
670        syscntl.set_hp_pad_hold_all(false);
671        syscntl.set_dig_pad_slp_sel(false);
672        syscntl.set_dig_pause_wdt(true);
673        syscntl.set_dig_cpu_stall(true);
674
675        let mut anlg = HpAnalog::default();
676        anlg.bias.set_xpd_bias(false);
677        anlg.bias.set_dbg_atten(0x0);
678        anlg.bias.set_pd_cur(false);
679        anlg.bias.set_bias_sleep(false);
680
681        anlg.regulator0.set_slp_mem_xpd(false);
682        anlg.regulator0.set_slp_logic_xpd(false);
683        anlg.regulator0.set_xpd(true);
684        anlg.regulator0.set_slp_mem_dbias(0);
685        anlg.regulator0.set_slp_logic_dbias(0);
686        anlg.regulator0.set_dbias(HP_CALI_DBIAS);
687
688        anlg.regulator1.set_drv_b(0);
689
690        let mut retention = HpModemBackup::default();
691        retention.set_hp_sleep2modem_backup_modem_clk_code(1);
692        retention.set_hp_modem_retention_mode(false);
693        retention.set_hp_sleep2modem_retention_en(false);
694        retention.set_hp_sleep2modem_backup_clk_sel(0);
695        retention.set_hp_sleep2modem_backup_mode(hp_retention_regdma_config(0, 1));
696        retention.set_hp_sleep2modem_backup_en(false);
697
698        let mut backup_clk = HpBackupClk::default();
699        backup_clk.set_regdma(true);
700        backup_clk.set_tg0(true);
701        backup_clk.set_tg1(true);
702        backup_clk.set_hpbus(true);
703        backup_clk.set_mspi(true);
704        backup_clk.set_iomux(true);
705        backup_clk.set_spi2(true);
706        backup_clk.set_uart0(true);
707        backup_clk.set_systimer(true);
708
709        Self {
710            power,
711            clock,
712            syscntl,
713            anlg,
714            retention: retention.0,
715            backup_clk: backup_clk.0,
716        }
717    }
718
719    fn sleep() -> Self {
720        let mut power = HpSysPower::default();
721        power.dig_power.set_vdd_spi_pd_en(true);
722        power.dig_power.set_mem_dslp(false);
723        power.dig_power.set_mem_pd_en(0);
724        power.dig_power.set_wifi_pd_en(true);
725        power.dig_power.set_cpu_pd_en(false);
726        power.dig_power.set_aon_pd_en(false);
727        power.dig_power.set_top_pd_en(false);
728
729        power.clk.set_i2c_iso_en(true);
730        power.clk.set_i2c_retention(true);
731        power.clk.set_xpd_bb_i2c(true);
732        power.clk.set_xpd_bbpll_i2c(false);
733        power.clk.set_xpd_bbpll(false);
734
735        power.xtal.set_xpd_xtal(false);
736
737        let mut clock = SystemClockParam {
738            icg_func: 0,
739            icg_apb: 0,
740            ..SystemClockParam::default()
741        };
742        clock.icg_modem.set_code(ICG_MODEM_CODE_SLEEP);
743        clock.sysclk.set_dig_sysclk_nodiv(false);
744        clock.sysclk.set_icg_sysclk_en(false);
745        clock.sysclk.set_sysclk_slp_sel(true);
746        clock.sysclk.set_icg_slp_sel(true);
747        clock.sysclk.set_dig_sysclk_sel(HP_SYSCLK_XTAL);
748
749        let mut anlg = HpAnalog::default();
750        anlg.bias.set_xpd_bias(false);
751        anlg.bias.set_dbg_atten(0x0);
752        anlg.bias.set_pd_cur(false);
753        anlg.bias.set_bias_sleep(false);
754
755        anlg.regulator0.set_slp_mem_xpd(false);
756        anlg.regulator0.set_slp_logic_xpd(false);
757        anlg.regulator0.set_xpd(true);
758        anlg.regulator0.set_slp_mem_dbias(0);
759        anlg.regulator0.set_slp_logic_dbias(0);
760        anlg.regulator0.set_dbias(1);
761
762        anlg.regulator1.set_drv_b(0);
763
764        let mut retention = HpSleepBackup::default();
765        retention.set_hp_modem2sleep_backup_modem_clk_code(0);
766        retention.set_hp_active2sleep_backup_modem_clk_code(2);
767        retention.set_hp_sleep_retention_mode(false);
768        retention.set_hp_modem2sleep_retention_en(false);
769        retention.set_hp_active2sleep_retention_en(false);
770        retention.set_hp_modem2sleep_backup_clk_sel(0);
771        retention.set_hp_active2sleep_backup_clk_sel(0);
772        retention.set_hp_modem2sleep_backup_mode(hp_retention_regdma_config(1, 1));
773        retention.set_hp_active2sleep_backup_mode(hp_retention_regdma_config(1, 0));
774        retention.set_hp_modem2sleep_backup_en(false);
775        retention.set_hp_active2sleep_backup_en(false);
776
777        let mut backup_clk = HpBackupClk::default();
778        backup_clk.set_regdma(true);
779        backup_clk.set_tg0(true);
780        backup_clk.set_tg1(true);
781        backup_clk.set_hpbus(true);
782        backup_clk.set_mspi(true);
783        backup_clk.set_iomux(true);
784        backup_clk.set_spi2(true);
785        backup_clk.set_uart0(true);
786        backup_clk.set_systimer(true);
787
788        let mut syscntl = HpSysCntlReg::default();
789        syscntl.set_uart_wakeup_en(true);
790        syscntl.set_lp_pad_hold_all(false);
791        syscntl.set_hp_pad_hold_all(false);
792        syscntl.set_dig_pad_slp_sel(true);
793        syscntl.set_dig_pause_wdt(true);
794        syscntl.set_dig_cpu_stall(true);
795
796        Self {
797            power,
798            clock,
799            syscntl,
800            anlg,
801            retention: retention.0,
802            backup_clk: backup_clk.0,
803        }
804    }
805
806    fn init_default() {
807        let active = Self::active();
808        let modem = Self::modem();
809        let sleep = Self::sleep();
810
811        hp_system_init!(hp_active => active);
812        hp_system_init!(hp_modem => modem);
813        hp_system_init!(hp_sleep => sleep);
814
815        unsafe {
816            PMU::regs()
818                .imm_modem_icg()
819                .write(|w| w.update_dig_icg_modem_en().bit(true));
820            PMU::regs()
821                .imm_sleep_sysclk()
822                .write(|w| w.update_dig_icg_switch().bit(true));
823
824            const PMU_SLEEP_PROTECT_HP_LP_SLEEP: u8 = 2;
825            PMU::regs()
826                .slp_wakeup_cntl3()
827                .modify(|_, w| w.sleep_prt_sel().bits(PMU_SLEEP_PROTECT_HP_LP_SLEEP));
828        }
829    }
830}
831
832bitfield::bitfield! {
833    #[derive(Clone, Copy, Default)]
834    pub struct LpDigPower(u32);
836
837    pub u32, mem_dslp  , set_mem_dslp  : 30;
838    pub u32, peri_pd_en, set_peri_pd_en: 31;
839
840}
841
842bitfield::bitfield! {
843    #[derive(Clone, Copy, Default)]
844    pub struct LpClkPower(u32);
846
847    pub u32, xpd_xtal32k, set_xpd_xtal32k: 28;
848    pub u32, xpd_rc32k  , set_xpd_rc32k  : 29;
849    pub u32, xpd_fosc   , set_xpd_fosc   : 30;
850    pub u32, pd_osc     , set_pd_osc     : 31;
851}
852
853bitfield::bitfield! {
854    #[derive(Clone, Copy, Default)]
855    pub struct LpXtalPower(u32);
857
858    pub bool, xpd_xtal     , set_xpd_xtal     : 31;
859}
860
861#[derive(Clone, Copy, Default)]
862pub struct LpSysPower {
864    pub dig_power: LpDigPower,
867    pub clk_power: LpClkPower,
868    pub xtal: LpXtalPower,
869}
870
871bitfield::bitfield! {
872    #[derive(Clone, Copy, Default)]
873    pub struct LpAnalogBias(u32);
875
876    pub bool, xpd_bias  , set_xpd_bias  : 25;
877    pub u8,   dbg_atten , set_dbg_atten : 29, 26;
878    pub bool, pd_cur    , set_pd_cur    : 30;
879    pub bool, bias_sleep, set_bias_sleep: 31;
880}
881
882bitfield::bitfield! {
883    #[derive(Clone, Copy, Default)]
884    pub struct LpAnalogRegulator0(u32);
886
887    pub bool, slp_xpd  , set_slp_xpd  : 21;
888    pub bool, xpd      , set_xpd      : 22;
889    pub u8,   slp_dbias, set_slp_dbias: 26, 23;
890    pub u8,   dbias    , set_dbias    : 31, 27;
891}
892
893bitfield::bitfield! {
894    #[derive(Clone, Copy, Default)]
895    pub struct LpAnalogRegulator1(u32);
897
898    pub u8, drv_b    , set_drv_b    : 31, 28;
899}
900
901#[derive(Clone, Copy, Default)]
902pub struct LpAnalog {
904    pub bias: LpAnalogBias,
905    pub regulator0: LpAnalogRegulator0,
906    pub regulator1: LpAnalogRegulator1,
907}
908
909macro_rules! lp_system_init {
910    ($state:ident => $s:ident) => {
911        paste::paste! {
912            unsafe {
913                PMU::regs().[< $state _dig_power >]().modify(|_, w| w.bits($s.dig_power.0));
915                PMU::regs().[< $state _ck_power >]().modify(|_, w| w.bits($s.clk_power.0));
916
917                PMU::regs().[< $state _regulator0 >]().modify(|_, w| w
919                    .[< $state _regulator_slp_xpd >]().bit($s.analog_regulator0.slp_xpd())
920                    .[< $state _regulator_xpd >]().bit($s.analog_regulator0.xpd())
921                    .[< $state _regulator_slp_dbias >]().bits($s.analog_regulator0.slp_dbias())
922                    .[< $state _regulator_dbias >]().bits($s.analog_regulator0.dbias())
923                );
924
925                PMU::regs().[< $state _regulator1 >]().modify(|_, w| w
926                    .[< $state _regulator_drv_b >]().bits($s.analog_regulator1.drv_b())
927                );
928            }
929        }
930    };
931}
932
933struct LpSystemInit {
934    dig_power: LpDigPower,
935    clk_power: LpClkPower,
936    xtal: LpXtalPower,
937    bias: LpAnalogBias,
938    analog_regulator0: LpAnalogRegulator0,
939    analog_regulator1: LpAnalogRegulator1,
940}
941impl LpSystemInit {
942    fn active() -> Self {
943        let mut dig_power = LpDigPower::default();
944        dig_power.set_peri_pd_en(false);
945        dig_power.set_mem_dslp(false);
946
947        let mut clk_power = LpClkPower::default();
948        clk_power.set_xpd_xtal32k(true);
949        clk_power.set_xpd_rc32k(true);
950        clk_power.set_xpd_fosc(true);
951
952        let mut analog_regulator0 = LpAnalogRegulator0::default();
953        analog_regulator0.set_slp_xpd(false);
954        analog_regulator0.set_xpd(true);
955        analog_regulator0.set_slp_dbias(0);
956        analog_regulator0.set_dbias(26);
957
958        let mut analog_regulator1 = LpAnalogRegulator1::default();
959        analog_regulator1.set_drv_b(0);
960
961        Self {
962            dig_power,
963            clk_power,
964            xtal: LpXtalPower::default(),
965            bias: LpAnalogBias::default(),
966            analog_regulator0,
967            analog_regulator1,
968        }
969    }
970
971    fn sleep() -> Self {
972        let mut dig_power = LpDigPower::default();
973        dig_power.set_mem_dslp(true);
974        dig_power.set_peri_pd_en(false);
975
976        let mut clk_power = LpClkPower::default();
977        clk_power.set_xpd_xtal32k(false);
978        clk_power.set_xpd_rc32k(false);
979        clk_power.set_xpd_fosc(false);
980        clk_power.set_pd_osc(false);
981
982        let mut xtal = LpXtalPower::default();
983        xtal.set_xpd_xtal(false);
984
985        let mut analog_bias = LpAnalogBias::default();
986        analog_bias.set_xpd_bias(false);
987        analog_bias.set_dbg_atten(0);
988        analog_bias.set_pd_cur(true);
989        analog_bias.set_bias_sleep(true);
990
991        let mut analog_regulator0 = LpAnalogRegulator0::default();
992        analog_regulator0.set_slp_xpd(false);
993        analog_regulator0.set_xpd(true);
994        analog_regulator0.set_slp_dbias(0);
995        analog_regulator0.set_dbias(12);
996
997        let mut analog_regulator1 = LpAnalogRegulator1::default();
998        analog_regulator1.set_drv_b(0);
999
1000        Self {
1001            dig_power,
1002            clk_power,
1003            xtal,
1004            bias: analog_bias,
1005            analog_regulator0,
1006            analog_regulator1,
1007        }
1008    }
1009
1010    fn init_default() {
1011        let active = Self::active();
1012        let sleep = Self::sleep();
1013
1014        lp_system_init!(hp_sleep_lp => active);
1015        lp_system_init!(lp_sleep_lp => sleep);
1016
1017        PMU::regs()
1018            .lp_sleep_xtal()
1019            .modify(|_, w| w.lp_sleep_xpd_xtal().bit(sleep.xtal.xpd_xtal()));
1020
1021        PMU::regs().lp_sleep_bias().modify(|_, w| unsafe {
1022            w.lp_sleep_xpd_bias().bit(sleep.bias.xpd_bias()); w.lp_sleep_dbg_atten().bits(sleep.bias.dbg_atten()); w.lp_sleep_pd_cur().bit(sleep.bias.pd_cur()); w.sleep().bit(sleep.bias.bias_sleep()) });
1027    }
1028}
1029
1030pub(crate) fn init() {
1031    PMU::regs()
1033        .rf_pwc()
1034        .modify(|_, w| w.perif_i2c_rstb().set_bit().xpd_perif_i2c().set_bit());
1035
1036    regi2c::I2C_DIG_REG_ENIF_RTC_DREG.write_field(1);
1037    regi2c::I2C_DIG_REG_ENIF_DIG_DREG.write_field(1);
1038    regi2c::I2C_DIG_REG_XPD_RTC_REG.write_field(0);
1039    regi2c::I2C_DIG_REG_XPD_DIG_REG.write_field(0);
1040
1041    HpSystemInit::init_default();
1042    LpSystemInit::init_default();
1043
1044    pmu_power_domain_force_default();
1045
1046    modem_clock_domain_power_state_icg_map_init();
1048
1049    let modem_lpclk_src = ModemClockLpclkSource::from(RtcSlowClockSource::current());
1058
1059    modem_clock_select_lp_clock_source_wifi(modem_lpclk_src, 0);
1060
1061    RtcClock::set_fast_freq(RtcFastClock::RcFast);
1062    RtcClock::set_slow_freq(RtcSlowClock::RcSlow);
1063}
1064
1065pub(crate) fn configure_clock() {
1066    let cal_val = loop {
1067        let res = RtcClock::calibrate(RtcCalSel::RtcMux, 1024);
1068        if res != 0 {
1069            break res;
1070        }
1071    };
1072
1073    LP_AON::regs()
1074        .store1()
1075        .modify(|_, w| unsafe { w.bits(cal_val) });
1076
1077    modem_clk_domain_active_state_icg_map_preinit();
1078}
1079
1080fn modem_clk_domain_active_state_icg_map_preinit() {
1081    unsafe {
1082        PMU::regs()
1084            .hp_active_icg_modem()
1085            .modify(|_, w| w.hp_active_dig_icg_modem_code().bits(ICG_MODEM_CODE_ACTIVE));
1086
1087        MODEM_SYSCON::regs()
1090            .clk_conf_power_st()
1091            .modify(|_, w| w.clk_modem_apb_st_map().bits(1 << ICG_MODEM_CODE_ACTIVE));
1092        MODEM_LPCON::regs().clk_conf_power_st().modify(|_, w| {
1093            w.clk_i2c_mst_st_map()
1094                .bits(1 << ICG_MODEM_CODE_ACTIVE)
1095                .clk_lp_apb_st_map()
1096                .bits(1 << ICG_MODEM_CODE_ACTIVE)
1097        });
1098
1099        PMU::regs()
1101            .imm_modem_icg()
1102            .write(|w| w.update_dig_icg_modem_en().set_bit());
1103        PMU::regs()
1104            .imm_sleep_sysclk()
1105            .write(|w| w.update_dig_icg_switch().set_bit());
1106
1107        LP_CLKRST::regs()
1110            .fosc_cntl()
1111            .modify(|_, w| w.fosc_dfreq().bits(100));
1112
1113        regi2c::I2C_DIG_REG_SCK_DCAP.write_reg(128);
1114
1115        LP_CLKRST::regs()
1116            .rc32k_cntl()
1117            .modify(|_, w| w.rc32k_dfreq().bits(700));
1118
1119        regi2c::I2C_DIG_REG_ENIF_RTC_DREG.write_field(1);
1120        regi2c::I2C_DIG_REG_ENIF_DIG_DREG.write_field(1);
1121
1122        PMU::regs()
1123            .hp_active_hp_regulator0()
1124            .modify(|_, w| w.hp_active_hp_regulator_dbias().bits(HP_CALI_DBIAS));
1125        PMU::regs()
1126            .hp_sleep_lp_regulator0()
1127            .modify(|_, w| w.hp_sleep_lp_regulator_dbias().bits(LP_CALI_DBIAS));
1128
1129        PCR::regs()
1131            .ctrl_tick_conf()
1132            .modify(|_, w| w.fosc_tick_num().bits(255));
1133    }
1134}
1135
1136#[derive(Debug, Clone, Copy, PartialEq, Eq, FromRepr)]
1146pub enum SocResetReason {
1147    ChipPowerOn   = 0x01,
1153    CoreSw        = 0x03,
1155    CoreDeepSleep = 0x05,
1157    CoreSDIO      = 0x06,
1159    CoreMwdt0     = 0x07,
1161    CoreMwdt1     = 0x08,
1163    CoreRtcWdt    = 0x09,
1165    Cpu0Mwdt0     = 0x0B,
1167    Cpu0Sw        = 0x0C,
1169    Cpu0RtcWdt    = 0x0D,
1171    SysBrownOut   = 0x0F,
1173    SysRtcWdt     = 0x10,
1175    Cpu0Mwdt1     = 0x11,
1177    SysSuperWdt   = 0x12,
1179    CoreEfuseCrc  = 0x14,
1181    CoreUsbUart   = 0x15,
1183    CoreUsbJtag   = 0x16,
1185    Cpu0JtagCpu   = 0x18,
1187}
1188
1189pub(crate) fn rtc_clk_cpu_freq_set_xtal() {
1190    let freq = RtcClock::xtal_freq().mhz();
1192
1193    esp32c6_rtc_update_to_xtal_raw(freq, 1);
1194
1195    rtc_clk_bbpll_disable();
1198    }
1200
1201#[derive(Clone, Copy, PartialEq, Debug)]
1202#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1203pub(crate) struct UnsupportedClockSource;
1204
1205#[derive(Clone, Copy, PartialEq, Debug)]
1206#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1207pub(crate) enum CpuClockSource {
1208    Xtal,
1209    Pll,
1210    RcFast,
1211}
1212
1213impl CpuClockSource {
1214    pub(crate) fn current() -> Result<Self, UnsupportedClockSource> {
1215        let source = match PCR::regs().sysclk_conf().read().soc_clk_sel().bits() {
1216            0 => CpuClockSource::Xtal,
1217            1 => CpuClockSource::Pll,
1218            2 => CpuClockSource::RcFast,
1219            _ => return Err(UnsupportedClockSource),
1220        };
1221
1222        Ok(source)
1223    }
1224
1225    pub(crate) fn select(self) {
1226        PCR::regs().sysclk_conf().modify(|_, w| unsafe {
1227            w.soc_clk_sel().bits(match self {
1228                CpuClockSource::Xtal => 0,
1229                CpuClockSource::Pll => 1,
1230                CpuClockSource::RcFast => 2,
1231            })
1232        });
1233    }
1234}
1235
1236#[derive(Clone, Copy)]
1237pub(crate) struct SavedClockConfig {
1238    pub source: CpuClockSource,
1240
1241    pub source_freq_mhz: u32,
1243
1244    pub div: u8,
1246}
1247
1248impl SavedClockConfig {
1249    pub(crate) fn save() -> Self {
1250        let source = unwrap!(CpuClockSource::current());
1251
1252        let div;
1253        let source_freq_mhz;
1254        match source {
1255            CpuClockSource::Xtal => {
1256                div = esp32c6_cpu_get_ls_divider();
1257                source_freq_mhz = RtcClock::xtal_freq().mhz();
1258            }
1259            CpuClockSource::Pll => {
1260                div = esp32c6_cpu_get_hs_divider();
1261                source_freq_mhz = esp32c6_bbpll_get_freq_mhz();
1262            }
1263            CpuClockSource::RcFast => {
1264                div = esp32c6_cpu_get_ls_divider();
1265                source_freq_mhz = 20;
1266            }
1267        }
1268
1269        SavedClockConfig {
1270            source,
1271            source_freq_mhz,
1272            div,
1273        }
1274    }
1275
1276    fn freq_mhz(&self) -> u32 {
1277        self.source_freq_mhz / self.div as u32
1278    }
1279
1280    pub(crate) fn restore(self) {
1282        let old_source = unwrap!(CpuClockSource::current());
1283
1284        match self.source {
1285            CpuClockSource::Xtal => esp32c6_rtc_update_to_xtal_raw(self.freq_mhz(), self.div),
1286            CpuClockSource::RcFast => esp32c6_rtc_update_to_8m(),
1287            CpuClockSource::Pll => {
1288                if old_source != CpuClockSource::Pll {
1289                    rtc_clk_bbpll_enable();
1290                    esp32c6_rtc_bbpll_configure_raw(
1291                        RtcClock::xtal_freq().mhz(),
1292                        self.source_freq_mhz,
1293                    );
1294                }
1295                esp32c6_rtc_freq_to_pll_mhz_raw(self.freq_mhz());
1296            }
1297        }
1298
1299        if old_source == CpuClockSource::Pll && self.source != CpuClockSource::Pll
1300        {
1302            rtc_clk_bbpll_disable();
1304        }
1305    }
1306}
1307
1308fn rtc_clk_bbpll_enable() {
1309    PMU::regs().imm_hp_ck_power().modify(|_, w| {
1310        w.tie_high_xpd_bb_i2c().set_bit();
1311        w.tie_high_xpd_bbpll().set_bit();
1312        w.tie_high_xpd_bbpll_i2c().set_bit()
1313    });
1314    PMU::regs()
1315        .imm_hp_ck_power()
1316        .modify(|_, w| w.tie_high_global_bbpll_icg().set_bit());
1317}
1318
1319fn rtc_clk_bbpll_disable() {
1320    PMU::regs()
1321        .imm_hp_ck_power()
1322        .modify(|_, w| w.tie_low_global_bbpll_icg().set_bit());
1323
1324    PMU::regs().imm_hp_ck_power().modify(|_, w| {
1325        w.tie_low_xpd_bbpll().set_bit();
1326        w.tie_low_xpd_bbpll_i2c().set_bit()
1327    });
1328}