1use crate::{
2 clock::{ApbClock, Clock, CpuClock, PllClock, XtalClock},
3 peripherals::{I2C_ANA_MST, LP_AON, MODEM_LPCON, MODEM_SYSCON, PCR, PMU},
4 rtc_cntl::rtc::CpuClockSource,
5};
6
7const I2C_BBPLL: u8 = 0x66;
8const I2C_BBPLL_HOSTID: u8 = 0;
9
10const I2C_BBPLL_OC_REF_DIV: u8 = 2;
11const I2C_BBPLL_OC_DCHGP_LSB: u32 = 4;
12
13const I2C_BBPLL_OC_DIV_7_0: u8 = 3;
14
15const I2C_BBPLL_OC_DR1: u8 = 5;
16const I2C_BBPLL_OC_DR1_MSB: u8 = 2;
17const I2C_BBPLL_OC_DR1_LSB: u8 = 0;
18
19const I2C_BBPLL_OC_DR3: u8 = 5;
20const I2C_BBPLL_OC_DR3_MSB: u8 = 6;
21const I2C_BBPLL_OC_DR3_LSB: u8 = 4;
22
23const I2C_BBPLL_OC_DCUR: u8 = 6;
24
25const I2C_BBPLL_OC_DHREF_SEL_LSB: u32 = 4;
26
27const I2C_BBPLL_OC_DLREF_SEL_LSB: u32 = 6;
28
29const I2C_BBPLL_OC_VCO_DBIAS: u8 = 9;
30const I2C_BBPLL_OC_VCO_DBIAS_MSB: u8 = 1;
31const I2C_BBPLL_OC_VCO_DBIAS_LSB: u8 = 0;
32
33pub(crate) fn esp32c6_rtc_bbpll_configure(xtal_freq: XtalClock, pll_freq: PllClock) {
35 esp32c6_rtc_bbpll_configure_raw(xtal_freq.mhz(), pll_freq.mhz())
36}
37
38pub(crate) fn esp32c6_rtc_bbpll_configure_raw(_xtal_freq: u32, pll_freq: u32) {
39 debug_assert!(pll_freq == 480);
43
44 critical_section::with(|_| {
45 let was_i2c_mst_en = MODEM_LPCON::regs().clk_conf().read().clk_i2c_mst_en().bit();
47 MODEM_LPCON::regs()
48 .clk_conf()
49 .modify(|_, w| w.clk_i2c_mst_en().set_bit());
50
51 MODEM_LPCON::regs()
52 .i2c_mst_clk_conf()
53 .modify(|_, w| w.clk_i2c_mst_sel_160m().set_bit());
54
55 I2C_ANA_MST::regs().ana_conf0().modify(|_, w| {
57 w.bbpll_stop_force_high().clear_bit();
58 w.bbpll_stop_force_low().set_bit()
59 });
60
61 let div_ref = 0;
62 let div7_0 = 8;
63 let dr1 = 0;
64 let dr3 = 0;
65 let dchgp = 5;
66 let dcur = 3;
67 let dbias = 2;
68
69 let i2c_bbpll_lref = (dchgp << I2C_BBPLL_OC_DCHGP_LSB) | div_ref;
70 let i2c_bbpll_div_7_0 = div7_0;
71 let i2c_bbpll_dcur =
72 (1 << I2C_BBPLL_OC_DLREF_SEL_LSB) | (3 << I2C_BBPLL_OC_DHREF_SEL_LSB) | dcur;
73
74 regi2c_write(
75 I2C_BBPLL,
76 I2C_BBPLL_HOSTID,
77 I2C_BBPLL_OC_REF_DIV,
78 i2c_bbpll_lref,
79 );
80 regi2c_write(
81 I2C_BBPLL,
82 I2C_BBPLL_HOSTID,
83 I2C_BBPLL_OC_DIV_7_0,
84 i2c_bbpll_div_7_0,
85 );
86 regi2c_write_mask(
87 I2C_BBPLL,
88 I2C_BBPLL_HOSTID,
89 I2C_BBPLL_OC_DR1,
90 I2C_BBPLL_OC_DR1_MSB,
91 I2C_BBPLL_OC_DR1_LSB,
92 dr1,
93 );
94 regi2c_write_mask(
95 I2C_BBPLL,
96 I2C_BBPLL_HOSTID,
97 I2C_BBPLL_OC_DR3,
98 I2C_BBPLL_OC_DR3_MSB,
99 I2C_BBPLL_OC_DR3_LSB,
100 dr3,
101 );
102 regi2c_write(
103 I2C_BBPLL,
104 I2C_BBPLL_HOSTID,
105 I2C_BBPLL_OC_DCUR,
106 i2c_bbpll_dcur,
107 );
108 regi2c_write_mask(
109 I2C_BBPLL,
110 I2C_BBPLL_HOSTID,
111 I2C_BBPLL_OC_VCO_DBIAS,
112 I2C_BBPLL_OC_VCO_DBIAS_MSB,
113 I2C_BBPLL_OC_VCO_DBIAS_LSB,
114 dbias,
115 );
116
117 while I2C_ANA_MST::regs()
119 .ana_conf0()
120 .read()
121 .cal_done()
122 .bit_is_clear()
123 {}
124
125 crate::rom::ets_delay_us(10);
127
128 I2C_ANA_MST::regs().ana_conf0().modify(|_, w| {
130 w.bbpll_stop_force_high().set_bit();
131 w.bbpll_stop_force_low().clear_bit()
132 });
133
134 MODEM_LPCON::regs()
135 .clk_conf()
136 .modify(|_, w| w.clk_i2c_mst_en().bit(was_i2c_mst_en));
137 });
138}
139
140pub(crate) fn esp32c6_rtc_bbpll_enable() {
141 PMU::regs().imm_hp_ck_power().modify(|_, w| {
142 w.tie_high_xpd_bb_i2c().set_bit();
143 w.tie_high_xpd_bbpll().set_bit();
144 w.tie_high_xpd_bbpll_i2c().set_bit()
145 });
146
147 PMU::regs()
148 .imm_hp_ck_power()
149 .modify(|_, w| w.tie_high_global_bbpll_icg().set_bit());
150}
151
152pub(crate) fn esp32c6_rtc_update_to_xtal(freq: XtalClock, div: u8) {
153 esp32c6_rtc_update_to_xtal_raw(freq.mhz(), div)
154}
155
156pub(crate) fn esp32c6_rtc_update_to_xtal_raw(freq_mhz: u32, div: u8) {
157 esp32c6_ahb_set_ls_divider(div);
158 esp32c6_cpu_set_ls_divider(div);
159
160 CpuClockSource::Xtal.select();
161
162 crate::rom::ets_update_cpu_frequency_rom(freq_mhz);
163}
164
165pub(crate) fn esp32c6_rtc_update_to_8m() {
166 esp32c6_ahb_set_ls_divider(1);
167 esp32c6_cpu_set_ls_divider(1);
168
169 CpuClockSource::RcFast.select();
170
171 crate::rom::ets_update_cpu_frequency_rom(20);
172}
173
174pub(crate) fn esp32c6_rtc_freq_to_pll_mhz(cpu_clock_speed: CpuClock) {
175 esp32c6_rtc_freq_to_pll_mhz_raw(cpu_clock_speed.mhz());
176}
177
178pub(crate) fn esp32c6_rtc_freq_to_pll_mhz_raw(cpu_clock_speed_mhz: u32) {
179 clk_ll_mspi_fast_set_hs_divider(6);
184
185 PCR::regs().cpu_freq_conf().modify(|_, w| unsafe {
186 w.cpu_hs_div_num()
187 .bits(((480 / cpu_clock_speed_mhz / 3) - 1) as u8);
188 w.cpu_hs_120m_force().clear_bit()
189 });
190
191 PCR::regs()
192 .cpu_freq_conf()
193 .modify(|_, w| w.cpu_hs_120m_force().clear_bit());
194
195 CpuClockSource::Pll.select();
196
197 crate::rom::ets_update_cpu_frequency_rom(cpu_clock_speed_mhz);
198}
199
200pub(crate) fn esp32c6_rtc_apb_freq_update(apb_freq: ApbClock) {
201 let value = ((apb_freq.hz() >> 12) & u16::MAX as u32)
202 | (((apb_freq.hz() >> 12) & u16::MAX as u32) << 16);
203
204 LP_AON::regs()
205 .store5()
206 .modify(|_, w| unsafe { w.lp_aon_store5().bits(value) });
207}
208
209fn clk_ll_mspi_fast_set_hs_divider(divider: u32) {
210 let div_num = match divider {
214 4..=6 => divider as u8 - 1,
215 _ => panic!("Unsupported HS MSPI_FAST divider"),
216 };
217
218 PCR::regs()
219 .mspi_clk_conf()
220 .modify(|_, w| unsafe { w.mspi_fast_hs_div_num().bits(div_num) });
221}
222
223const REGI2C_BBPLL: u8 = 0x66;
224const REGI2C_BIAS: u8 = 0x6a;
225const REGI2C_DIG_REG: u8 = 0x6d;
226const REGI2C_ULP_CAL: u8 = 0x61;
227const REGI2C_SAR_I2C: u8 = 0x69;
228
229const I2C_MST_ANA_CONF1_M: u32 = 0x00FFFFFF;
230
231fn regi2c_enable_block(block: u8) -> usize {
232 MODEM_LPCON::regs()
233 .clk_conf()
234 .modify(|_, w| w.clk_i2c_mst_en().set_bit());
235
236 let i2c_sel_bits = I2C_ANA_MST::regs().ana_conf2().read();
238 let i2c_sel = match block {
239 v if v == REGI2C_BBPLL => i2c_sel_bits.bbpll_mst_sel().bit_is_set(),
240 v if v == REGI2C_BIAS => i2c_sel_bits.bias_mst_sel().bit_is_set(),
241 v if v == REGI2C_DIG_REG => i2c_sel_bits.dig_reg_mst_sel().bit_is_set(),
242 v if v == REGI2C_ULP_CAL => i2c_sel_bits.ulp_cal_mst_sel().bit_is_set(),
243 v if v == REGI2C_SAR_I2C => i2c_sel_bits.sar_i2c_mst_sel().bit_is_set(),
244 _ => unreachable!(),
245 };
246 I2C_ANA_MST::regs().ana_conf1().write(|w| unsafe {
247 w.bits(I2C_MST_ANA_CONF1_M);
248 match block {
249 v if v == REGI2C_BBPLL => w.bbpll_rd().clear_bit(),
250 v if v == REGI2C_BIAS => w.bias_rd().clear_bit(),
251 v if v == REGI2C_DIG_REG => w.dig_reg_rd().clear_bit(),
252 v if v == REGI2C_ULP_CAL => w.ulp_cal_rd().clear_bit(),
253 v if v == REGI2C_SAR_I2C => w.sar_i2c_rd().clear_bit(),
254 _ => unreachable!(),
255 }
256 });
257
258 if i2c_sel {
259 0
260 } else {
261 1
262 }
263}
264
265pub(crate) fn regi2c_write(block: u8, _host_id: u8, reg_add: u8, data: u8) {
266 let master = regi2c_enable_block(block);
267
268 I2C_ANA_MST::regs().i2c_ctrl(master).write(|w| unsafe {
269 w.slave_addr().bits(block);
270 w.slave_reg_addr().bits(reg_add);
271 w.read_write().set_bit();
272 w.data().bits(data)
273 });
274
275 while I2C_ANA_MST::regs().i2c_ctrl(master).read().busy().bit() {}
276}
277
278pub(crate) fn regi2c_write_mask(block: u8, _host_id: u8, reg_add: u8, msb: u8, lsb: u8, data: u8) {
279 assert!(msb < 8 + lsb);
280 let master = regi2c_enable_block(block);
281
282 I2C_ANA_MST::regs().i2c_ctrl(master).write(|w| unsafe {
284 w.slave_addr().bits(block);
285 w.slave_reg_addr().bits(reg_add)
286 });
287
288 while I2C_ANA_MST::regs().i2c_ctrl(master).read().busy().bit() {}
289
290 let unwritten_bits = (!(u32::MAX << lsb) | (u32::MAX << (msb + 1))) as u8;
295 let data_mask = !(u32::MAX << (msb - lsb + 1)) as u8;
296 let data_bits = (data & data_mask) << lsb;
297
298 I2C_ANA_MST::regs().i2c_ctrl(master).modify(|r, w| unsafe {
299 w.slave_addr().bits(block);
300 w.slave_reg_addr().bits(reg_add);
301 w.read_write().set_bit();
302 w.data()
303 .bits((r.data().bits() & unwritten_bits) | data_bits)
304 });
305
306 while I2C_ANA_MST::regs().i2c_ctrl(master).read().busy().bit() {}
307}
308
309fn esp32c6_ahb_set_ls_divider(div: u8) {
311 PCR::regs()
312 .ahb_freq_conf()
313 .modify(|_, w| unsafe { w.ahb_ls_div_num().bits(div - 1) });
314}
315
316fn esp32c6_cpu_set_ls_divider(div: u8) {
318 PCR::regs()
319 .cpu_freq_conf()
320 .modify(|_, w| unsafe { w.cpu_ls_div_num().bits(div - 1) });
321}
322
323pub(crate) fn esp32c6_cpu_get_ls_divider() -> u8 {
325 let cpu_ls_div = PCR::regs().cpu_freq_conf().read().cpu_ls_div_num().bits();
326 let hp_root_ls_div = PCR::regs().sysclk_conf().read().ls_div_num().bits();
327 (hp_root_ls_div + 1) * (cpu_ls_div + 1)
328}
329
330pub(crate) fn esp32c6_cpu_get_hs_divider() -> u8 {
332 let force_120m = PCR::regs().cpu_freq_conf().read().cpu_hs_120m_force().bit();
333 let cpu_hs_div = PCR::regs().cpu_freq_conf().read().cpu_hs_div_num().bits();
334 if cpu_hs_div == 0 && force_120m {
335 return 4;
336 }
337 let hp_root_hs_div = PCR::regs().sysclk_conf().read().hs_div_num().bits();
338 (hp_root_hs_div + 1) * (cpu_hs_div + 1)
339}
340
341pub(crate) fn esp32c6_bbpll_get_freq_mhz() -> u32 {
343 const CLK_LL_PLL_480M_FREQ_MHZ: u32 = 480;
345
346 CLK_LL_PLL_480M_FREQ_MHZ
347}
348
349pub(super) fn enable_phy(en: bool) {
350 MODEM_LPCON::regs()
351 .clk_conf()
352 .modify(|_, w| w.clk_i2c_mst_en().bit(en));
353 MODEM_LPCON::regs()
354 .i2c_mst_clk_conf()
355 .modify(|_, w| w.clk_i2c_mst_sel_160m().bit(en));
356}
357
358pub(super) fn enable_wifi(en: bool) {
359 MODEM_SYSCON::regs().clk_conf1().modify(|_, w| {
360 w.clk_wifi_apb_en().bit(en);
361 w.clk_wifimac_en().bit(en);
362 w.clk_fe_apb_en().bit(en);
363 w.clk_fe_cal_160m_en().bit(en);
364 w.clk_fe_160m_en().bit(en);
365 w.clk_fe_80m_en().bit(en);
366 w.clk_wifibb_160x1_en().bit(en);
367 w.clk_wifibb_80x1_en().bit(en);
368 w.clk_wifibb_40x1_en().bit(en);
369 w.clk_wifibb_80x_en().bit(en);
370 w.clk_wifibb_40x_en().bit(en);
371 w.clk_wifibb_80m_en().bit(en);
372 w.clk_wifibb_44m_en().bit(en);
373 w.clk_wifibb_40m_en().bit(en);
374 w.clk_wifibb_22m_en().bit(en)
375 });
376
377 MODEM_LPCON::regs().clk_conf().modify(|_, w| {
378 w.clk_wifipwr_en().bit(en);
379 w.clk_coex_en().bit(en)
380 });
381}
382
383pub(super) fn enable_ieee802154(en: bool) {
384 MODEM_SYSCON::regs().clk_conf().modify(|_, w| {
385 w.clk_zb_apb_en().bit(en);
386 w.clk_zb_mac_en().bit(en)
387 });
388
389 MODEM_SYSCON::regs().clk_conf1().modify(|_, w| {
390 w.clk_fe_apb_en().bit(en);
391 w.clk_fe_cal_160m_en().bit(en);
392 w.clk_fe_160m_en().bit(en);
393 w.clk_fe_80m_en().bit(en);
394 w.clk_bt_apb_en().bit(en);
395 w.clk_bt_en().bit(en);
396 w.clk_wifibb_160x1_en().bit(en);
397 w.clk_wifibb_80x1_en().bit(en);
398 w.clk_wifibb_40x1_en().bit(en);
399 w.clk_wifibb_80x_en().bit(en);
400 w.clk_wifibb_40x_en().bit(en);
401 w.clk_wifibb_80m_en().bit(en);
402 w.clk_wifibb_44m_en().bit(en);
403 w.clk_wifibb_40m_en().bit(en);
404 w.clk_wifibb_22m_en().bit(en)
405 });
406
407 MODEM_LPCON::regs()
408 .clk_conf()
409 .modify(|_, w| w.clk_coex_en().set_bit());
410}
411
412pub(super) fn enable_bt(en: bool) {
413 MODEM_SYSCON::regs().clk_conf().modify(|_, w| {
414 w.clk_etm_en().bit(en);
415 w.clk_modem_sec_en().bit(en);
416 w.clk_modem_sec_ecb_en().bit(en);
417 w.clk_modem_sec_ccm_en().bit(en);
418 w.clk_modem_sec_bah_en().bit(en);
419 w.clk_modem_sec_apb_en().bit(en);
420 w.clk_ble_timer_en().bit(en)
421 });
422
423 MODEM_SYSCON::regs().clk_conf1().modify(|_, w| {
424 w.clk_fe_apb_en().bit(en);
425 w.clk_fe_cal_160m_en().bit(en);
426 w.clk_fe_160m_en().bit(en);
427 w.clk_fe_80m_en().bit(en);
428 w.clk_bt_apb_en().bit(en);
429 w.clk_bt_en().bit(en)
430 });
431
432 MODEM_LPCON::regs()
433 .clk_conf()
434 .modify(|_, w| w.clk_coex_en().bit(en));
435}
436
437pub(super) fn reset_mac() {
438 }
440
441pub(super) fn init_clocks() {
442 unsafe {
443 PMU::regs()
444 .hp_sleep_icg_modem()
445 .modify(|_, w| w.hp_sleep_dig_icg_modem_code().bits(0));
446 PMU::regs()
447 .hp_modem_icg_modem()
448 .modify(|_, w| w.hp_modem_dig_icg_modem_code().bits(1));
449 PMU::regs()
450 .hp_active_icg_modem()
451 .modify(|_, w| w.hp_active_dig_icg_modem_code().bits(2));
452 PMU::regs()
453 .imm_modem_icg()
454 .write(|w| w.update_dig_icg_modem_en().set_bit());
455 PMU::regs()
456 .imm_sleep_sysclk()
457 .write(|w| w.update_dig_icg_switch().set_bit());
458
459 MODEM_SYSCON::regs().clk_conf_power_st().modify(|_, w| {
460 w.clk_modem_apb_st_map().bits(6);
461 w.clk_modem_peri_st_map().bits(4);
462 w.clk_wifi_st_map().bits(6);
463 w.clk_bt_st_map().bits(6);
464 w.clk_fe_st_map().bits(6);
465 w.clk_zb_st_map().bits(6)
466 });
467
468 MODEM_LPCON::regs().clk_conf_power_st().modify(|_, w| {
469 w.clk_lp_apb_st_map().bits(6);
470 w.clk_i2c_mst_st_map().bits(6);
471 w.clk_coex_st_map().bits(6);
472 w.clk_wifipwr_st_map().bits(6)
473 });
474
475 MODEM_LPCON::regs().wifi_lp_clk_conf().modify(|_, w| {
476 w.clk_wifipwr_lp_sel_osc_slow().set_bit();
477 w.clk_wifipwr_lp_sel_osc_fast().set_bit();
478 w.clk_wifipwr_lp_sel_xtal32k().set_bit();
479 w.clk_wifipwr_lp_sel_xtal().set_bit()
480 });
481
482 MODEM_LPCON::regs()
483 .wifi_lp_clk_conf()
484 .modify(|_, w| w.clk_wifipwr_lp_div_num().bits(0));
485
486 MODEM_LPCON::regs()
487 .clk_conf()
488 .modify(|_, w| w.clk_wifipwr_en().set_bit());
489 }
490}
491
492pub(super) fn ble_rtc_clk_init() {
493 }
495
496pub(super) fn reset_rpa() {
497 }