|
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}; |
255 | 2 |
|
256 | 3 | pub(super) fn enable_phy(en: bool) { |
257 | 4 | MODEM_LPCON::regs() |
|
0 commit comments