esp_hal/clock/clocks_ll/
esp32c2.rs

1use crate::{
2    clock::{ApbClock, Clock, CpuClock, PllClock, XtalClock},
3    peripherals::{APB_CTRL, I2C_ANA_MST, LPWR, MODEM_CLKRST, SYSTEM},
4    rom::{regi2c_write, regi2c_write_mask},
5};
6
7const I2C_BBPLL: u32 = 0x66;
8const I2C_BBPLL_HOSTID: u32 = 0;
9
10const I2C_BBPLL_MODE_HF: u32 = 4;
11
12const I2C_BBPLL_OC_REF_DIV: u32 = 2;
13const I2C_BBPLL_OC_DCHGP_LSB: u32 = 4;
14const I2C_BBPLL_OC_DIV_7_0: u32 = 3;
15
16const I2C_BBPLL_OC_DR1: u32 = 5;
17const I2C_BBPLL_OC_DR1_MSB: u32 = 2;
18const I2C_BBPLL_OC_DR1_LSB: u32 = 0;
19
20const I2C_BBPLL_OC_DR3: u32 = 5;
21const I2C_BBPLL_OC_DR3_MSB: u32 = 6;
22const I2C_BBPLL_OC_DR3_LSB: u32 = 4;
23
24const I2C_BBPLL_OC_DCUR: u32 = 6;
25
26const I2C_BBPLL_OC_VCO_DBIAS: u32 = 9;
27const I2C_BBPLL_OC_VCO_DBIAS_MSB: u32 = 1;
28const I2C_BBPLL_OC_VCO_DBIAS_LSB: u32 = 0;
29
30const I2C_BBPLL_OC_DHREF_SEL_LSB: u32 = 4;
31
32const I2C_BBPLL_OC_DLREF_SEL_LSB: u32 = 6;
33
34pub(crate) fn esp32c2_rtc_bbpll_configure(xtal_freq: XtalClock, _pll_freq: PllClock) {
35    let div_ref: u32;
36    let div7_0: u32;
37    let dr1: u32;
38    let dr3: u32;
39    let dchgp: u32;
40    let dcur: u32;
41    let dbias: u32;
42
43    // Set this register to let the digital part know 480M PLL is used
44    SYSTEM::regs()
45        .cpu_per_conf()
46        .modify(|_, w| w.pll_freq_sel().set_bit());
47
48    I2C_ANA_MST::regs().ana_conf0().modify(|_, w| {
49        w.bbpll_stop_force_high().clear_bit();
50        w.bbpll_stop_force_low().set_bit()
51    });
52
53    // Configure 480M PLL
54    match xtal_freq {
55        XtalClock::_26M => {
56            div_ref = 12;
57            div7_0 = 236;
58            dr1 = 4;
59            dr3 = 4;
60            dchgp = 0;
61            dcur = 0;
62            dbias = 2;
63        }
64        XtalClock::_40M | XtalClock::Other(_) => {
65            div_ref = 0;
66            div7_0 = 8;
67            dr1 = 0;
68            dr3 = 0;
69            dchgp = 5;
70            dcur = 3;
71            dbias = 2;
72        }
73    }
74
75    regi2c_write!(I2C_BBPLL, I2C_BBPLL_MODE_HF, 0x6b);
76
77    let i2c_bbpll_lref = (dchgp << I2C_BBPLL_OC_DCHGP_LSB) | div_ref;
78    let i2c_bbpll_div_7_0 = div7_0;
79    let i2c_bbpll_dcur =
80        (1 << I2C_BBPLL_OC_DLREF_SEL_LSB) | (3 << I2C_BBPLL_OC_DHREF_SEL_LSB) | dcur;
81
82    regi2c_write!(I2C_BBPLL, I2C_BBPLL_OC_REF_DIV, i2c_bbpll_lref);
83
84    regi2c_write!(I2C_BBPLL, I2C_BBPLL_OC_DIV_7_0, i2c_bbpll_div_7_0);
85
86    regi2c_write_mask!(I2C_BBPLL, I2C_BBPLL_OC_DR1, dr1);
87
88    regi2c_write_mask!(I2C_BBPLL, I2C_BBPLL_OC_DR3, dr3);
89
90    regi2c_write!(I2C_BBPLL, I2C_BBPLL_OC_DCUR, i2c_bbpll_dcur);
91
92    regi2c_write_mask!(I2C_BBPLL, I2C_BBPLL_OC_VCO_DBIAS, dbias);
93
94    // WAIT CALIBRATION DONE
95    while I2C_ANA_MST::regs()
96        .ana_conf0()
97        .read()
98        .bbpll_cal_done()
99        .bit_is_clear()
100    {}
101
102    // workaround bbpll calibration might stop early
103    crate::rom::ets_delay_us(10);
104
105    // Stop BBPLL self-calibration
106    I2C_ANA_MST::regs().ana_conf0().modify(|_, w| {
107        w.bbpll_stop_force_high().set_bit();
108        w.bbpll_stop_force_low().clear_bit()
109    });
110}
111
112pub(crate) fn esp32c2_rtc_bbpll_enable() {
113    LPWR::regs().options0().modify(|_, w| {
114        w.bb_i2c_force_pd().clear_bit();
115        w.bbpll_force_pd().clear_bit();
116        w.bbpll_i2c_force_pd().clear_bit()
117    });
118}
119
120pub(crate) fn esp32c2_rtc_update_to_xtal(freq: XtalClock, div: u32) {
121    crate::rom::ets_update_cpu_frequency_rom(freq.mhz());
122
123    // Set divider from XTAL to APB clock. Need to set divider to 1 (reg. value 0)
124    // first.
125    SYSTEM::regs().sysclk_conf().modify(|_, w| unsafe {
126        w.pre_div_cnt().bits(0);
127        w.pre_div_cnt().bits((div - 1) as u16)
128    });
129
130    // No need to adjust the REF_TICK
131
132    // Switch clock source
133    SYSTEM::regs()
134        .sysclk_conf()
135        .modify(|_, w| unsafe { w.soc_clk_sel().bits(0) });
136}
137
138pub(crate) fn esp32c2_rtc_freq_to_pll_mhz(cpu_clock_speed: CpuClock) {
139    SYSTEM::regs().sysclk_conf().modify(|_, w| unsafe {
140        w.pre_div_cnt().bits(0);
141        w.soc_clk_sel().bits(1)
142    });
143    SYSTEM::regs().cpu_per_conf().modify(|_, w| unsafe {
144        w.cpuperiod_sel().bits(match cpu_clock_speed {
145            CpuClock::_80MHz => 0,
146            CpuClock::_120MHz => 1,
147        })
148    });
149
150    crate::rom::ets_update_cpu_frequency_rom(cpu_clock_speed.mhz());
151}
152
153pub(crate) fn esp32c2_rtc_apb_freq_update(apb_freq: ApbClock) {
154    let value = ((apb_freq.hz() >> 12) & u16::MAX as u32)
155        | (((apb_freq.hz() >> 12) & u16::MAX as u32) << 16);
156
157    LPWR::regs()
158        .store5()
159        .modify(|_, w| unsafe { w.scratch5().bits(value) });
160}
161
162// Mask for clock bits used by both WIFI and Bluetooth, 0, 1, 2, 3, 7, 8, 9, 10,
163// 19, 20, 21, 22, 23
164const SYSTEM_WIFI_CLK_WIFI_BT_COMMON_M: u32 = 0x78078F;
165// SYSTEM_WIFI_CLK_EN : R/W ;bitpos:[31:0] ;default: 32'hfffce030
166const SYSTEM_WIFI_CLK_EN: u32 = 0x00FB9FCF;
167
168pub(super) fn enable_phy(enable: bool) {
169    // `periph_ll_wifi_bt_module_enable_clk_clear_rst`
170    // `periph_ll_wifi_bt_module_disable_clk_set_rst`
171    APB_CTRL::regs().wifi_clk_en().modify(|r, w| unsafe {
172        if enable {
173            w.bits(r.bits() | SYSTEM_WIFI_CLK_WIFI_BT_COMMON_M)
174        } else {
175            w.bits(r.bits() & !SYSTEM_WIFI_CLK_WIFI_BT_COMMON_M)
176        }
177    });
178}
179
180pub(super) fn enable_bt(_: bool) {
181    // `periph_ll_wifi_module_enable_clk_clear_rst`, no-op
182    // `periph_ll_wifi_module_disable_clk_clear_rst`, no-op
183}
184
185pub(super) fn enable_wifi(_: bool) {
186    // `periph_ll_wifi_module_enable_clk_clear_rst`, no-op
187    // `periph_ll_wifi_module_disable_clk_clear_rst`, no-op
188}
189
190pub(super) fn reset_mac() {
191    APB_CTRL::regs()
192        .wifi_rst_en()
193        .modify(|_, w| w.mac_rst().set_bit());
194    APB_CTRL::regs()
195        .wifi_rst_en()
196        .modify(|_, w| w.mac_rst().clear_bit());
197}
198
199pub(super) fn init_clocks() {
200    // from `esp_perip_clk_init`
201    const SYSTEM_WIFI_CLK_UNUSED_BIT5: u32 = 1 << 5;
202    const SYSTEM_WIFI_CLK_UNUSED_BIT12: u32 = 1 << 12;
203    const WIFI_BT_SDIO_CLK: u32 = SYSTEM_WIFI_CLK_UNUSED_BIT5 | SYSTEM_WIFI_CLK_UNUSED_BIT12;
204
205    APB_CTRL::regs()
206        .wifi_clk_en()
207        .modify(|r, w| unsafe { w.bits(r.bits() & !WIFI_BT_SDIO_CLK | SYSTEM_WIFI_CLK_EN) });
208}
209
210pub(super) fn ble_rtc_clk_init() {
211    MODEM_CLKRST::regs().modem_lp_timer_conf().modify(|_, w| {
212        w.lp_timer_sel_xtal32k().clear_bit();
213        w.lp_timer_sel_xtal().set_bit();
214        w.lp_timer_sel_8m().clear_bit();
215        w.lp_timer_sel_rtc_slow().clear_bit()
216    });
217
218    // assume 40MHz xtal
219    MODEM_CLKRST::regs()
220        .modem_lp_timer_conf()
221        .modify(|_, w| unsafe { w.lp_timer_clk_div_num().bits(249) });
222
223    MODEM_CLKRST::regs().etm_clk_conf().modify(|_, w| {
224        w.etm_clk_active().set_bit();
225        w.etm_clk_sel().clear_bit()
226    });
227}
228
229pub(super) fn reset_rpa() {
230    APB_CTRL::regs()
231        .wifi_rst_en()
232        .modify(|_, w| w.ble_rpa_rst().set_bit());
233    APB_CTRL::regs()
234        .wifi_rst_en()
235        .modify(|_, w| w.ble_rpa_rst().clear_bit());
236}