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
24const 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 MODEM_LPCON::regs()
38 .clk_conf_force_on()
39 .modify(|_, w| w.clk_i2c_mst_fo().set_bit());
40
41 MODEM_LPCON::regs()
43 .clk_conf()
44 .modify(|r, w| unsafe { w.bits(r.bits() | MODEM_LPCON_CLK_I2C_SEL_96M) });
45
46 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 while I2C_ANA_MST::regs()
95 .ana_conf0()
96 .read()
97 .cal_done()
98 .bit_is_clear()
99 {}
100
101 crate::rom::ets_delay_us(10);
103
104 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 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 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 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 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 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 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 }
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 }
328
329pub(super) fn reset_rpa() {
330 }