Skip to content

Commit 9605b11

Browse files
committed
Rework H2 clocktree
1 parent f7c17f3 commit 9605b11

File tree

12 files changed

+1597
-417
lines changed

12 files changed

+1597
-417
lines changed

esp-hal/src/clock/clocks_ll/esp32h2.rs

Lines changed: 1 addition & 254 deletions
Original file line numberDiff line numberDiff line change
@@ -1,257 +1,4 @@
1-
use crate::{
2-
clock::{ApbClock, Clock, CpuClock, PllClock, XtalClock},
3-
peripherals::{I2C_ANA_MST, LP_AON, MODEM_LPCON, MODEM_SYSCON, PCR, PMU},
4-
};
5-
6-
const I2C_BBPLL: u8 = 0x66;
7-
const I2C_BBPLL_HOSTID: u8 = 0;
8-
const I2C_BBPLL_OC_REF_DIV: u8 = 2;
9-
const I2C_BBPLL_OC_REF_DIV_MSB: u8 = 3;
10-
const I2C_BBPLL_OC_REF_DIV_LSB: u8 = 0;
11-
12-
const I2C_BBPLL_OC_DIV: u8 = 3;
13-
const I2C_BBPLL_OC_DIV_MSB: u8 = 5;
14-
const I2C_BBPLL_OC_DIV_LSB: u8 = 0;
15-
16-
const I2C_BBPLL_OC_DHREF_SEL: u8 = 5;
17-
const I2C_BBPLL_OC_DHREF_SEL_MSB: u8 = 5;
18-
const I2C_BBPLL_OC_DHREF_SEL_LSB: u8 = 4;
19-
20-
const I2C_BBPLL_OC_DLREF_SEL: u8 = 5;
21-
const I2C_BBPLL_OC_DLREF_SEL_MSB: u8 = 7;
22-
const I2C_BBPLL_OC_DLREF_SEL_LSB: u8 = 6;
23-
24-
// May be needed for enabling I2C clock
25-
const MODEM_LPCON_CLK_I2C_SEL_96M: u32 = 1 << 0;
26-
27-
const REGI2C_BBPLL: u8 = 0x66;
28-
const REGI2C_BIAS: u8 = 0x6a;
29-
const REGI2C_PMU: u8 = 0x6d;
30-
const REGI2C_ULP_CAL: u8 = 0x61;
31-
const REGI2C_SAR_I2C: u8 = 0x69;
32-
33-
const I2C_MST_ANA_CONF1_M: u32 = 0x00FFFFFF;
34-
35-
pub(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-
111-
pub(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-
123-
pub(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_cpu_set_divider(div as u32);
128-
clk_ll_ahb_set_divider(div as u32);
129-
130-
// Switch clock source
131-
PCR::regs()
132-
.sysclk_conf()
133-
.modify(|_, w| unsafe { w.soc_clk_sel().bits(0) });
134-
135-
clk_ll_bus_update();
136-
}
137-
138-
pub(crate) fn esp32h2_rtc_freq_to_pll_mhz(cpu_clock_speed: CpuClock) {
139-
let cpu_divider = 96 / cpu_clock_speed.mhz();
140-
clk_ll_cpu_set_divider(cpu_divider);
141-
let ahb_divider = match cpu_divider {
142-
1 | 2 => cpu_divider + 2,
143-
_ => cpu_divider,
144-
};
145-
clk_ll_ahb_set_divider(ahb_divider);
146-
147-
PCR::regs()
148-
.sysclk_conf()
149-
.modify(|_, w| unsafe { w.soc_clk_sel().bits(1) });
150-
151-
clk_ll_bus_update();
152-
153-
crate::rom::ets_update_cpu_frequency_rom(cpu_clock_speed.mhz());
154-
}
155-
156-
pub(crate) fn esp32h2_rtc_apb_freq_update(apb_freq: ApbClock) {
157-
let value = ((apb_freq.hz() >> 12) & u16::MAX as u32)
158-
| (((apb_freq.hz() >> 12) & u16::MAX as u32) << 16);
159-
160-
LP_AON::regs()
161-
.store5()
162-
.modify(|_, w| unsafe { w.data().bits(value) });
163-
}
164-
165-
fn clk_ll_cpu_set_divider(divider: u32) {
166-
assert!(divider >= 1);
167-
168-
PCR::regs()
169-
.cpu_freq_conf()
170-
.modify(|_, w| unsafe { w.cpu_div_num().bits((divider - 1) as u8) });
171-
}
172-
173-
fn clk_ll_ahb_set_divider(divider: u32) {
174-
assert!(divider >= 1);
175-
176-
PCR::regs()
177-
.ahb_freq_conf()
178-
.modify(|_, w| unsafe { w.ahb_div_num().bits((divider - 1) as u8) });
179-
}
180-
181-
fn clk_ll_bus_update() {
182-
PCR::regs()
183-
.bus_clk_update()
184-
.modify(|_, w| w.bus_clock_update().bit(true));
185-
186-
// reg_get_bit
187-
while PCR::regs()
188-
.bus_clk_update()
189-
.read()
190-
.bus_clock_update()
191-
.bit_is_set()
192-
{}
193-
}
194-
195-
fn regi2c_enable_block(block: u8) -> usize {
196-
MODEM_LPCON::regs()
197-
.clk_conf()
198-
.modify(|_, w| w.clk_i2c_mst_en().set_bit());
199-
200-
// Before config I2C register, enable corresponding slave.
201-
let i2c_sel_bits = I2C_ANA_MST::regs().ana_conf2().read();
202-
let i2c_sel = match block {
203-
v if v == REGI2C_BBPLL => i2c_sel_bits.bbpll_mst_sel().bit_is_set(),
204-
v if v == REGI2C_BIAS => i2c_sel_bits.bias_mst_sel().bit_is_set(),
205-
v if v == REGI2C_PMU => i2c_sel_bits.dig_reg_mst_sel().bit_is_set(),
206-
v if v == REGI2C_ULP_CAL => i2c_sel_bits.ulp_cal_mst_sel().bit_is_set(),
207-
v if v == REGI2C_SAR_I2C => i2c_sel_bits.sar_i2c_mst_sel().bit_is_set(),
208-
_ => unreachable!(),
209-
};
210-
I2C_ANA_MST::regs().ana_conf1().write(|w| unsafe {
211-
w.bits(I2C_MST_ANA_CONF1_M);
212-
match block {
213-
v if v == REGI2C_BBPLL => w.bbpll_rd().clear_bit(),
214-
v if v == REGI2C_BIAS => w.bias_rd().clear_bit(),
215-
v if v == REGI2C_PMU => w.dig_reg_rd().clear_bit(),
216-
v if v == REGI2C_ULP_CAL => w.ulp_cal_rd().clear_bit(),
217-
v if v == REGI2C_SAR_I2C => w.sar_i2c_rd().clear_bit(),
218-
_ => unreachable!(),
219-
}
220-
});
221-
222-
if i2c_sel { 0 } else { 1 }
223-
}
224-
225-
pub(crate) fn regi2c_write_mask(block: u8, _host_id: u8, reg_add: u8, msb: u8, lsb: u8, data: u8) {
226-
assert!(msb < 8 + lsb);
227-
let master = regi2c_enable_block(block);
228-
229-
// Read the i2c bus register
230-
I2C_ANA_MST::regs().i2c_ctrl(master).write(|w| unsafe {
231-
w.slave_addr().bits(block);
232-
w.slave_reg_addr().bits(reg_add)
233-
});
234-
235-
while I2C_ANA_MST::regs().i2c_ctrl(master).read().busy().bit() {}
236-
237-
// Example: LSB=2, MSB = 5
238-
// unwritten_bits = 1100 0011
239-
// data_mask = 0000 1111
240-
// data_bits = 00xx xx00
241-
let unwritten_bits = (!(u32::MAX << lsb) | (u32::MAX << (msb + 1))) as u8;
242-
let data_mask = !(u32::MAX << (msb - lsb + 1)) as u8;
243-
let data_bits = (data & data_mask) << lsb;
244-
245-
I2C_ANA_MST::regs().i2c_ctrl(master).modify(|r, w| unsafe {
246-
w.slave_addr().bits(block);
247-
w.slave_reg_addr().bits(reg_add);
248-
w.read_write().set_bit();
249-
w.data()
250-
.bits((r.data().bits() & unwritten_bits) | data_bits)
251-
});
252-
253-
while I2C_ANA_MST::regs().i2c_ctrl(master).read().busy().bit() {}
254-
}
1+
use crate::peripherals::{MODEM_LPCON, MODEM_SYSCON, PMU};
2552

2563
pub(super) fn enable_phy(en: bool) {
2574
MODEM_LPCON::regs()

esp-hal/src/clock/mod.rs

Lines changed: 11 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,14 +1073,6 @@ pub struct Clocks {
10731073
/// Crypto clock frequency
10741074
#[cfg(any(esp32c6, esp32h2))]
10751075
pub crypto_clock: Rate,
1076-
1077-
/// PLL 48M clock frequency (fixed)
1078-
#[cfg(esp32h2)]
1079-
pub pll_48m_clock: Rate,
1080-
1081-
/// PLL 96M clock frequency (fixed)
1082-
#[cfg(esp32h2)]
1083-
pub pll_96m_clock: Rate,
10841076
}
10851077

10861078
static mut ACTIVE_CLOCKS: Option<Clocks> = None;
@@ -1256,34 +1248,20 @@ impl Clocks {
12561248
impl Clocks {
12571249
/// Configure the CPU clock speed.
12581250
pub(crate) fn configure(cpu_clock_speed: CpuClock) -> Self {
1259-
let xtal_freq = Self::measure_xtal_frequency();
1251+
use crate::soc::clocks::ClockTree;
12601252

1261-
let apb_freq;
1262-
if cpu_clock_speed != CpuClock::default() {
1263-
if cpu_clock_speed.mhz() <= xtal_freq.mhz() {
1264-
apb_freq = ApbClock::ApbFreqOther(cpu_clock_speed.mhz());
1265-
clocks_ll::esp32h2_rtc_update_to_xtal(xtal_freq, 1);
1266-
clocks_ll::esp32h2_rtc_apb_freq_update(apb_freq);
1267-
} else {
1268-
let pll_freq = PllClock::Pll96MHz;
1269-
apb_freq = ApbClock::ApbFreq32MHz;
1270-
clocks_ll::esp32h2_rtc_bbpll_enable();
1271-
clocks_ll::esp32h2_rtc_bbpll_configure(xtal_freq, pll_freq);
1272-
clocks_ll::esp32h2_rtc_freq_to_pll_mhz(cpu_clock_speed);
1273-
clocks_ll::esp32h2_rtc_apb_freq_update(apb_freq);
1274-
}
1275-
} else {
1276-
apb_freq = ApbClock::ApbFreq32MHz;
1253+
// TODO: expose the whole new enum for custom options
1254+
match cpu_clock_speed {
1255+
CpuClock::_96MHz => crate::soc::clocks::CpuClock::_96MHz,
12771256
}
1257+
.configure();
12781258

1279-
Self {
1280-
cpu_clock: cpu_clock_speed.frequency(),
1281-
apb_clock: apb_freq.frequency(),
1282-
xtal_clock: xtal_freq.frequency(),
1283-
pll_48m_clock: Rate::from_mhz(48),
1284-
crypto_clock: Rate::from_mhz(96),
1285-
pll_96m_clock: Rate::from_mhz(96),
1286-
}
1259+
ClockTree::with(|clocks| Self {
1260+
cpu_clock: Rate::from_hz(crate::soc::clocks::cpu_clk_frequency(clocks)),
1261+
apb_clock: Rate::from_hz(crate::soc::clocks::apb_clk_frequency(clocks)),
1262+
xtal_clock: Rate::from_hz(crate::soc::clocks::xtal_clk_frequency(clocks)),
1263+
crypto_clock: Rate::from_hz(crate::soc::clocks::hp_root_clk_frequency(clocks)),
1264+
})
12871265
}
12881266
}
12891267

0 commit comments

Comments
 (0)