esp_hal/clock/clocks_ll/
esp32h2.rs

1use crate::{
2    clock::{ApbClock, Clock, CpuClock, PllClock, XtalClock},
3    peripherals::{I2C_ANA_MST, LP_AON, MODEM_LPCON, MODEM_SYSCON, PCR, PMU},
4};
5
6const I2C_BBPLL: u8 = 0x66;
7const I2C_BBPLL_HOSTID: u8 = 0;
8const I2C_BBPLL_OC_REF_DIV: u8 = 2;
9const I2C_BBPLL_OC_REF_DIV_MSB: u8 = 3;
10const I2C_BBPLL_OC_REF_DIV_LSB: u8 = 0;
11
12const I2C_BBPLL_OC_DIV: u8 = 3;
13const I2C_BBPLL_OC_DIV_MSB: u8 = 5;
14const I2C_BBPLL_OC_DIV_LSB: u8 = 0;
15
16const I2C_BBPLL_OC_DHREF_SEL: u8 = 5;
17const I2C_BBPLL_OC_DHREF_SEL_MSB: u8 = 5;
18const I2C_BBPLL_OC_DHREF_SEL_LSB: u8 = 4;
19
20const I2C_BBPLL_OC_DLREF_SEL: u8 = 5;
21const I2C_BBPLL_OC_DLREF_SEL_MSB: u8 = 7;
22const I2C_BBPLL_OC_DLREF_SEL_LSB: u8 = 6;
23
24// May be needed for enabling I2C clock
25const MODEM_LPCON_CLK_I2C_SEL_96M: u32 = 1 << 0;
26
27const REGI2C_BBPLL: u8 = 0x66;
28const REGI2C_BIAS: u8 = 0x6a;
29const REGI2C_PMU: u8 = 0x6d;
30const REGI2C_ULP_CAL: u8 = 0x61;
31const REGI2C_SAR_I2C: u8 = 0x69;
32
33const I2C_MST_ANA_CONF1_M: u32 = 0x00FFFFFF;
34
35pub(crate) fn esp32h2_rtc_bbpll_configure(_xtal_freq: XtalClock, _pll_freq: PllClock) {
36    // Enable I2C master clock
37    MODEM_LPCON::regs()
38        .clk_conf_force_on()
39        .modify(|_, w| w.clk_i2c_mst_fo().set_bit());
40
41    // Set I2C clock to 96MHz
42    MODEM_LPCON::regs()
43        .clk_conf()
44        .modify(|r, w| unsafe { w.bits(r.bits() | MODEM_LPCON_CLK_I2C_SEL_96M) });
45
46    // BPPLL calibration start
47    I2C_ANA_MST::regs().ana_conf0().modify(|_, w| {
48        w.bbpll_stop_force_high().clear_bit();
49        w.bbpll_stop_force_low().set_bit()
50    });
51
52    let oc_ref_div = 0;
53    let oc_div = 1;
54    let oc_dhref_sel = 3;
55    let oc_dlref_sel = 1;
56
57    regi2c_write_mask(
58        I2C_BBPLL,
59        I2C_BBPLL_HOSTID,
60        I2C_BBPLL_OC_REF_DIV,
61        I2C_BBPLL_OC_REF_DIV_MSB,
62        I2C_BBPLL_OC_REF_DIV_LSB,
63        oc_ref_div,
64    );
65
66    regi2c_write_mask(
67        I2C_BBPLL,
68        I2C_BBPLL_HOSTID,
69        I2C_BBPLL_OC_DIV,
70        I2C_BBPLL_OC_DIV_MSB,
71        I2C_BBPLL_OC_DIV_LSB,
72        oc_div,
73    );
74
75    regi2c_write_mask(
76        I2C_BBPLL,
77        I2C_BBPLL_HOSTID,
78        I2C_BBPLL_OC_DHREF_SEL,
79        I2C_BBPLL_OC_DHREF_SEL_MSB,
80        I2C_BBPLL_OC_DHREF_SEL_LSB,
81        oc_dhref_sel,
82    );
83
84    regi2c_write_mask(
85        I2C_BBPLL,
86        I2C_BBPLL_HOSTID,
87        I2C_BBPLL_OC_DLREF_SEL,
88        I2C_BBPLL_OC_DLREF_SEL_MSB,
89        I2C_BBPLL_OC_DLREF_SEL_LSB,
90        oc_dlref_sel,
91    );
92
93    // WAIT CALIBRATION DONE
94    while I2C_ANA_MST::regs()
95        .ana_conf0()
96        .read()
97        .cal_done()
98        .bit_is_clear()
99    {}
100
101    // workaround bbpll calibration might stop early
102    crate::rom::ets_delay_us(10);
103
104    // BBPLL CALIBRATION STOP
105    I2C_ANA_MST::regs().ana_conf0().modify(|_, w| {
106        w.bbpll_stop_force_high().set_bit();
107        w.bbpll_stop_force_low().clear_bit()
108    });
109}
110
111pub(crate) fn esp32h2_rtc_bbpll_enable() {
112    PMU::regs().imm_hp_ck_power().modify(|_, w| {
113        w.tie_high_xpd_bb_i2c().set_bit();
114        w.tie_high_xpd_bbpll().set_bit();
115        w.tie_high_xpd_bbpll_i2c().set_bit()
116    });
117
118    PMU::regs()
119        .imm_hp_ck_power()
120        .modify(|_, w| w.tie_high_global_bbpll_icg().set_bit());
121}
122
123pub(crate) fn esp32h2_rtc_update_to_xtal(freq: XtalClock, div: u8) {
124    crate::rom::ets_update_cpu_frequency_rom(freq.mhz());
125    // Set divider from XTAL to APB clock. Need to set divider to 1 (reg. value 0)
126    // first.
127    clk_ll_ahb_set_divider(div as u32);
128
129    PCR::regs()
130        .cpu_freq_conf()
131        .modify(|_, w| unsafe { w.cpu_div_num().bits(div - 1) });
132    // Switch clock source
133    PCR::regs()
134        .sysclk_conf()
135        .modify(|_, w| unsafe { w.soc_clk_sel().bits(0) });
136
137    clk_ll_bus_update();
138}
139
140pub(crate) fn esp32h2_rtc_freq_to_pll_mhz(cpu_clock_speed: CpuClock) {
141    let cpu_divider = 96 / cpu_clock_speed.mhz();
142    clk_ll_cpu_set_divider(cpu_divider);
143    let ahb_divider = match cpu_divider {
144        1 | 2 => cpu_divider + 2,
145        _ => cpu_divider,
146    };
147    clk_ll_ahb_set_divider(ahb_divider);
148
149    PCR::regs()
150        .sysclk_conf()
151        .modify(|_, w| unsafe { w.soc_clk_sel().bits(1) });
152
153    clk_ll_bus_update();
154
155    crate::rom::ets_update_cpu_frequency_rom(cpu_clock_speed.mhz());
156}
157
158pub(crate) fn esp32h2_rtc_apb_freq_update(apb_freq: ApbClock) {
159    let value = ((apb_freq.hz() >> 12) & u16::MAX as u32)
160        | (((apb_freq.hz() >> 12) & u16::MAX as u32) << 16);
161
162    LP_AON::regs()
163        .store5()
164        .modify(|_, w| unsafe { w.lp_aon_store5().bits(value) });
165}
166
167fn clk_ll_cpu_set_divider(divider: u32) {
168    assert!(divider >= 1);
169
170    PCR::regs()
171        .cpu_freq_conf()
172        .modify(|_, w| unsafe { w.cpu_div_num().bits((divider - 1) as u8) });
173}
174
175fn clk_ll_ahb_set_divider(divider: u32) {
176    assert!(divider >= 1);
177
178    PCR::regs()
179        .ahb_freq_conf()
180        .modify(|_, w| unsafe { w.ahb_div_num().bits((divider - 1) as u8) });
181}
182
183fn clk_ll_bus_update() {
184    PCR::regs()
185        .bus_clk_update()
186        .modify(|_, w| w.bus_clock_update().bit(true));
187
188    // reg_get_bit
189    while PCR::regs()
190        .bus_clk_update()
191        .read()
192        .bus_clock_update()
193        .bit_is_set()
194    {}
195}
196
197fn regi2c_enable_block(block: u8) -> usize {
198    MODEM_LPCON::regs()
199        .clk_conf()
200        .modify(|_, w| w.clk_i2c_mst_en().set_bit());
201
202    // Before config I2C register, enable corresponding slave.
203    let i2c_sel_bits = I2C_ANA_MST::regs().ana_conf2().read();
204    let i2c_sel = match block {
205        v if v == REGI2C_BBPLL => i2c_sel_bits.bbpll_mst_sel().bit_is_set(),
206        v if v == REGI2C_BIAS => i2c_sel_bits.bias_mst_sel().bit_is_set(),
207        v if v == REGI2C_PMU => i2c_sel_bits.dig_reg_mst_sel().bit_is_set(),
208        v if v == REGI2C_ULP_CAL => i2c_sel_bits.ulp_cal_mst_sel().bit_is_set(),
209        v if v == REGI2C_SAR_I2C => i2c_sel_bits.sar_i2c_mst_sel().bit_is_set(),
210        _ => unreachable!(),
211    };
212    I2C_ANA_MST::regs().ana_conf1().write(|w| unsafe {
213        w.bits(I2C_MST_ANA_CONF1_M);
214        match block {
215            v if v == REGI2C_BBPLL => w.bbpll_rd().clear_bit(),
216            v if v == REGI2C_BIAS => w.bias_rd().clear_bit(),
217            v if v == REGI2C_PMU => w.dig_reg_rd().clear_bit(),
218            v if v == REGI2C_ULP_CAL => w.ulp_cal_rd().clear_bit(),
219            v if v == REGI2C_SAR_I2C => w.sar_i2c_rd().clear_bit(),
220            _ => unreachable!(),
221        }
222    });
223
224    if i2c_sel {
225        0
226    } else {
227        1
228    }
229}
230
231pub(crate) fn regi2c_write_mask(block: u8, _host_id: u8, reg_add: u8, msb: u8, lsb: u8, data: u8) {
232    assert!(msb < 8 + lsb);
233    let master = regi2c_enable_block(block);
234
235    // Read the i2c bus register
236    I2C_ANA_MST::regs().i2c_ctrl(master).write(|w| unsafe {
237        w.slave_addr().bits(block);
238        w.slave_reg_addr().bits(reg_add)
239    });
240
241    while I2C_ANA_MST::regs().i2c_ctrl(master).read().busy().bit() {}
242
243    // Example: LSB=2, MSB = 5
244    // unwritten_bits = 1100 0011
245    // data_mask      = 0000 1111
246    // data_bits      = 00xx xx00
247    let unwritten_bits = (!(u32::MAX << lsb) | (u32::MAX << (msb + 1))) as u8;
248    let data_mask = !(u32::MAX << (msb - lsb + 1)) as u8;
249    let data_bits = (data & data_mask) << lsb;
250
251    I2C_ANA_MST::regs().i2c_ctrl(master).modify(|r, w| unsafe {
252        w.slave_addr().bits(block);
253        w.slave_reg_addr().bits(reg_add);
254        w.read_write().set_bit();
255        w.data()
256            .bits((r.data().bits() & unwritten_bits) | data_bits)
257    });
258
259    while I2C_ANA_MST::regs().i2c_ctrl(master).read().busy().bit() {}
260}
261
262pub(super) fn enable_phy(en: bool) {
263    MODEM_LPCON::regs()
264        .clk_conf()
265        .modify(|_, w| w.clk_i2c_mst_en().bit(en));
266}
267
268fn ble_ieee802154_clock_enable(en: bool) {
269    MODEM_SYSCON::regs().clk_conf().modify(|_, w| {
270        w.clk_zb_apb_en().bit(en);
271        w.clk_zb_mac_en().bit(en)
272    });
273
274    MODEM_SYSCON::regs().clk_conf1().modify(|_, w| {
275        w.clk_bt_apb_en().bit(en);
276        w.clk_bt_en().bit(en);
277        w.clk_fe_16m_en().bit(en);
278        w.clk_fe_32m_en().bit(en);
279        w.clk_fe_adc_en().bit(en);
280        w.clk_fe_apb_en().bit(en);
281        w.clk_fe_sdm_en().bit(en)
282    });
283
284    MODEM_LPCON::regs()
285        .clk_conf()
286        .modify(|_, w| w.clk_coex_en().bit(en));
287}
288
289pub(super) fn enable_bt(en: bool) {
290    ble_ieee802154_clock_enable(en);
291}
292
293pub(super) fn enable_ieee802154(en: bool) {
294    ble_ieee802154_clock_enable(en);
295}
296
297pub(super) fn reset_mac() {
298    // empty
299}
300
301pub(super) fn init_clocks() {
302    PMU::regs()
303        .hp_sleep_icg_modem()
304        .modify(|_, w| unsafe { w.hp_sleep_dig_icg_modem_code().bits(0) });
305    PMU::regs()
306        .hp_modem_icg_modem()
307        .modify(|_, w| unsafe { w.hp_modem_dig_icg_modem_code().bits(1) });
308    PMU::regs()
309        .hp_active_icg_modem()
310        .modify(|_, w| unsafe { w.hp_active_dig_icg_modem_code().bits(2) });
311    PMU::regs()
312        .imm_modem_icg()
313        .write(|w| w.update_dig_icg_modem_en().set_bit());
314    PMU::regs()
315        .imm_sleep_sysclk()
316        .write(|w| w.update_dig_icg_switch().set_bit());
317
318    MODEM_LPCON::regs().clk_conf().modify(|_, w| {
319        w.clk_i2c_mst_en().set_bit();
320        w.clk_coex_en().set_bit();
321        w.clk_fe_mem_en().set_bit()
322    });
323}
324
325pub(super) fn ble_rtc_clk_init() {
326    // nothing for this target (yet)
327}
328
329pub(super) fn reset_rpa() {
330    // nothing for this target (yet)
331}