Skip to main content

esp_hal/rtc_cntl/rtc/
esp32c2.rs

1use strum::FromRepr;
2
3use crate::{
4    peripherals::{APB_CTRL, EXTMEM, LPWR, SPI0, SPI1, SYSTEM},
5    soc::{clocks::ClockConfig, regi2c},
6};
7
8pub(crate) fn init(_config: &ClockConfig) {
9    let rtc_cntl = LPWR::regs();
10
11    regi2c::I2C_DIG_REG_XPD_DIG_REG.write_field(0);
12    regi2c::I2C_DIG_REG_XPD_RTC_REG.write_field(0);
13
14    unsafe {
15        rtc_cntl.timer1().modify(|_, w| {
16            w.pll_buf_wait().bits(20u8);
17            w.ck8m_wait().bits(20u8)
18        });
19
20        rtc_cntl.timer5().modify(|_, w| w.min_slp_val().bits(2u8));
21    }
22
23    calibrate_ocode();
24
25    set_rtc_dig_dbias();
26
27    clock_control_init();
28
29    power_control_init();
30
31    unsafe {
32        rtc_cntl.int_ena().write(|w| w.bits(0));
33        rtc_cntl.int_clr().write(|w| w.bits(u32::MAX));
34    }
35
36    regi2c::I2C_ULP_IR_FORCE_XPD_CK.write_field(0);
37}
38
39// Trims the RTC bandgap using eFuse calibration data.
40//
41// See `set_ocode_by_efuse` in
42// <https://github.com/espressif/esp-idf/blob/v6.1/components/esp_hw_support/port/esp32c2/rtc_init.c>
43fn calibrate_ocode() {
44    super::calibrate_ocode(|| {
45        (crate::efuse::block_version() != (0, 0)).then(|| {
46            (crate::efuse::sign_magnitude(
47                crate::efuse::read_field_le::<u8>(crate::efuse::OCODE).into(),
48                6,
49            ) + 100) as u8
50        })
51    });
52}
53
54fn set_rtc_dig_dbias() {}
55
56/// Performs clock control related initialization.
57fn clock_control_init() {
58    let extmem = EXTMEM::regs();
59    let spi_mem_0 = SPI0::regs();
60    let spi_mem_1 = SPI1::regs();
61
62    // Clear CMMU clock force on
63    extmem
64        .cache_mmu_power_ctrl()
65        .modify(|_, w| w.cache_mmu_mem_force_on().clear_bit());
66
67    // Clear tag clock force on
68    extmem
69        .icache_tag_power_ctrl()
70        .modify(|_, w| w.icache_tag_mem_force_on().clear_bit());
71
72    // Clear register clock force on
73    spi_mem_0.clock_gate().modify(|_, w| w.clk_en().clear_bit());
74    spi_mem_1.clock_gate().modify(|_, w| w.clk_en().clear_bit());
75}
76
77/// Performs power control related initialization.
78fn power_control_init() {
79    let rtc_cntl = LPWR::regs();
80    let system = SYSTEM::regs();
81
82    rtc_cntl
83        .clk_conf()
84        .modify(|_, w| w.ck8m_force_pu().clear_bit());
85
86    // Cancel XTAL force PU if no need to force power up
87    // Cannot cancel XTAL force PU if PLL is force power on
88    rtc_cntl
89        .options0()
90        .modify(|_, w| w.xtl_force_pu().clear_bit());
91
92    // Force PD APLL
93    rtc_cntl.ana_conf().modify(|_, w| {
94        w.plla_force_pu().clear_bit();
95        w.plla_force_pd().set_bit();
96        // Open SAR_I2C protect function to avoid SAR_I2C
97        // Reset when rtc_ldo is low.
98        w.i2c_reset_por_force_pd().clear_bit()
99    });
100
101    // Cancel BBPLL force PU if setting no force power up
102    rtc_cntl.options0().modify(|_, w| {
103        w.bbpll_force_pu().clear_bit();
104        w.bbpll_i2c_force_pu().clear_bit();
105        w.bb_i2c_force_pu().clear_bit()
106    });
107
108    rtc_cntl
109        .rtc_cntl()
110        .modify(|_, w| w.regulator_force_pu().clear_bit());
111
112    // If this mask is enabled, all soc memories cannot enter power down mode.
113    // We should control soc memory power down mode from RTC,
114    // so we will not touch this register any more.
115    system
116        .mem_pd_mask()
117        .modify(|_, w| w.lslp_mem_pd_mask().clear_bit());
118
119    rtc_sleep_pu();
120
121    rtc_cntl
122        .dig_pwc()
123        .modify(|_, w| w.dg_wrap_force_pu().clear_bit());
124
125    rtc_cntl
126        .dig_iso()
127        .modify(|_, w| w.dg_wrap_force_noiso().clear_bit());
128
129    // Cancel digital PADS force no iso
130    system
131        .cpu_per_conf()
132        .modify(|_, w| w.cpu_wait_mode_force_on().clear_bit());
133
134    // If SYSTEM_CPU_WAIT_MODE_FORCE_ON == 0,
135    // the CPU clock will be closed when CPU enter WAITI mode.
136    rtc_cntl.dig_iso().modify(|_, w| {
137        w.dg_pad_force_unhold().clear_bit();
138        w.dg_pad_force_noiso().clear_bit()
139    });
140}
141
142/// Configures whether certain peripherals are powered down in deep sleep.
143fn rtc_sleep_pu() {
144    LPWR::regs()
145        .dig_pwc()
146        .modify(|_, w| w.lslp_mem_force_pu().clear_bit());
147
148    APB_CTRL::regs().front_end_mem_pd().modify(|_, w| {
149        w.dc_mem_force_pu().clear_bit();
150        w.pbus_mem_force_pu().clear_bit();
151        w.agc_mem_force_pu().clear_bit()
152    });
153    APB_CTRL::regs().mem_power_up().modify(|_, w| unsafe {
154        w.sram_power_up().bits(0u8);
155        w.rom_power_up().bits(0u8)
156    });
157}
158
159// Terminology:
160//
161// CPU Reset:    Reset CPU core only, once reset done, CPU will execute from
162//               reset vector
163// Core Reset:   Reset the whole digital system except RTC sub-system
164// System Reset: Reset the whole digital system, including RTC sub-system
165// Chip Reset:   Reset the whole chip, including the analog part
166
167#[derive(Debug, Clone, Copy, PartialEq, Eq, FromRepr)]
168/// SOC Reset Reason.
169pub enum SocResetReason {
170    /// Powers on reset.
171    ChipPowerOn   = 0x01,
172    /// Software resets the digital core by RTC_CNTL_SW_SYS_RST
173    CoreSw        = 0x03,
174    /// Deep sleep reset the digital core
175    CoreDeepSleep = 0x05,
176    /// Main watch dog 0 resets digital core
177    CoreMwdt0     = 0x07,
178    /// RTC watch dog resets digital core
179    CoreRtcWdt    = 0x09,
180    /// Main watch dog 0 resets CPU 0
181    Cpu0Mwdt0     = 0x0B,
182    /// Software resets CPU 0 by RTC_CNTL_SW_PROCPU_RST
183    Cpu0Sw        = 0x0C,
184    /// RTC watch dog resets CPU 0
185    Cpu0RtcWdt    = 0x0D,
186    /// VDD voltage is not stable and resets the digital core.
187    SysBrownOut   = 0x0F,
188    /// RTC watch dog resets digital core and rtc module
189    SysRtcWdt     = 0x10,
190    /// Super watch dog resets the digital core and rtc module
191    SysSuperWdt   = 0x12,
192    /// Glitch on clock resets the digital core and rtc module
193    SysClkGlitch  = 0x13,
194    /// eFuse CRC error resets the digital core
195    CoreEfuseCrc  = 0x14,
196    /// JTAG resets the CPU 0
197    Cpu0Jtag      = 0x18,
198}