esp_hal/clock/clocks_ll/
esp32.rsuse crate::{
clock::{Clock, PllClock, XtalClock},
peripherals::{APB_CTRL, DPORT, EFUSE, LPWR},
rom::regi2c_write,
};
const REF_CLK_FREQ: u32 = 1000000;
const MHZ: u32 = 1000000;
const UINT16_MAX: u32 = 0xffff;
const RTC_CNTL_DBIAS_1V10: u32 = 4;
const RTC_CNTL_DBIAS_1V25: u32 = 7;
const DIG_DBIAS_80M_160M: u32 = RTC_CNTL_DBIAS_1V10;
const DIG_DBIAS_XTAL: u32 = RTC_CNTL_DBIAS_1V10;
const I2C_BBPLL: u32 = 0x66;
const I2C_BBPLL_HOSTID: u32 = 4;
const I2C_BBPLL_IR_CAL_DELAY: u32 = 0;
const I2C_BBPLL_IR_CAL_EXT_CAP: u32 = 1;
const I2C_BBPLL_OC_ENB_FCAL: u32 = 4;
const I2C_BBPLL_OC_ENB_VCON: u32 = 10;
const I2C_BBPLL_BBADC_CAL_7_0: u32 = 12;
const BBPLL_IR_CAL_DELAY_VAL: u32 = 0x18;
const BBPLL_IR_CAL_EXT_CAP_VAL: u32 = 0x20;
const BBPLL_OC_ENB_FCAL_VAL: u32 = 0x9a;
const BBPLL_OC_ENB_VCON_VAL: u32 = 0x00;
const BBPLL_BBADC_CAL_7_0_VAL: u32 = 0x00;
const I2C_BBPLL_ENDIV5: u32 = 11;
const BBPLL_ENDIV5_VAL_320M: u32 = 0x43;
const BBPLL_BBADC_DSMP_VAL_320M: u32 = 0x84;
const BBPLL_ENDIV5_VAL_480M: u32 = 0xc3;
const BBPLL_BBADC_DSMP_VAL_480M: u32 = 0x74;
const I2C_BBPLL_BBADC_DSMP: u32 = 9;
const I2C_BBPLL_OC_LREF: u32 = 2;
const I2C_BBPLL_OC_DIV_7_0: u32 = 3;
const I2C_BBPLL_OC_DCUR: u32 = 5;
pub(crate) fn esp32_rtc_bbpll_configure(xtal_freq: XtalClock, pll_freq: PllClock) {
let rtc_cntl_dbias_hp_volt: u32 = RTC_CNTL_DBIAS_1V25
- EFUSE::regs()
.blk0_rdata5()
.read()
.rd_vol_level_hp_inv()
.bits() as u32;
let dig_dbias_240_m: u32 = rtc_cntl_dbias_hp_volt;
let div_ref: u32;
let div7_0: u32;
let div10_8: u32;
let lref: u32;
let dcur: u32;
let bw: u32;
if matches!(pll_freq, PllClock::Pll320MHz) {
LPWR::regs()
.reg()
.modify(|_, w| unsafe { w.dig_dbias_wak().bits(DIG_DBIAS_80M_160M as u8) });
match xtal_freq {
XtalClock::_40M => {
div_ref = 0;
div7_0 = 32;
div10_8 = 0;
lref = 0;
dcur = 6;
bw = 3;
}
XtalClock::_26M => {
div_ref = 12;
div7_0 = 224;
div10_8 = 4;
lref = 1;
dcur = 0;
bw = 1;
}
XtalClock::Other(_) => {
div_ref = 12;
div7_0 = 224;
div10_8 = 4;
lref = 0;
dcur = 0;
bw = 0;
}
}
regi2c_write!(I2C_BBPLL, I2C_BBPLL_ENDIV5, BBPLL_ENDIV5_VAL_320M);
regi2c_write!(I2C_BBPLL, I2C_BBPLL_BBADC_DSMP, BBPLL_BBADC_DSMP_VAL_320M);
} else {
LPWR::regs()
.reg()
.modify(|_, w| unsafe { w.dig_dbias_wak().bits(dig_dbias_240_m as u8) });
match xtal_freq {
XtalClock::_40M => {
div_ref = 0;
div7_0 = 28;
div10_8 = 0;
lref = 0;
dcur = 6;
bw = 3;
}
XtalClock::_26M => {
div_ref = 12;
div7_0 = 144;
div10_8 = 4;
lref = 1;
dcur = 0;
bw = 1;
}
XtalClock::Other(_) => {
div_ref = 12;
div7_0 = 224;
div10_8 = 4;
lref = 0;
dcur = 0;
bw = 0;
}
}
regi2c_write!(I2C_BBPLL, I2C_BBPLL_ENDIV5, BBPLL_ENDIV5_VAL_480M);
regi2c_write!(I2C_BBPLL, I2C_BBPLL_BBADC_DSMP, BBPLL_BBADC_DSMP_VAL_480M);
}
let i2c_bbpll_lref = (lref << 7) | (div10_8 << 4) | (div_ref);
let i2c_bbpll_div_7_0 = div7_0;
let i2c_bbpll_dcur = (bw << 6) | dcur;
regi2c_write!(I2C_BBPLL, I2C_BBPLL_OC_LREF, i2c_bbpll_lref);
regi2c_write!(I2C_BBPLL, I2C_BBPLL_OC_DIV_7_0, i2c_bbpll_div_7_0);
regi2c_write!(I2C_BBPLL, I2C_BBPLL_OC_DCUR, i2c_bbpll_dcur);
}
pub(crate) fn esp32_rtc_bbpll_enable() {
LPWR::regs().options0().modify(|_, w| {
w.bias_i2c_force_pd().clear_bit();
w.bb_i2c_force_pd().clear_bit();
w.bbpll_force_pd().clear_bit();
w.bbpll_i2c_force_pd().clear_bit()
});
regi2c_write!(I2C_BBPLL, I2C_BBPLL_IR_CAL_DELAY, BBPLL_IR_CAL_DELAY_VAL);
regi2c_write!(
I2C_BBPLL,
I2C_BBPLL_IR_CAL_EXT_CAP,
BBPLL_IR_CAL_EXT_CAP_VAL
);
regi2c_write!(I2C_BBPLL, I2C_BBPLL_OC_ENB_FCAL, BBPLL_OC_ENB_FCAL_VAL);
regi2c_write!(I2C_BBPLL, I2C_BBPLL_OC_ENB_VCON, BBPLL_OC_ENB_VCON_VAL);
regi2c_write!(I2C_BBPLL, I2C_BBPLL_BBADC_CAL_7_0, BBPLL_BBADC_CAL_7_0_VAL);
}
pub(crate) fn esp32_rtc_update_to_xtal(freq: XtalClock, _div: u32) {
let value = ((freq.hz() >> 12) & UINT16_MAX) | (((freq.hz() >> 12) & UINT16_MAX) << 16);
esp32_update_cpu_freq(freq.hz());
APB_CTRL::regs().sysclk_conf().modify(|_, w| unsafe {
w.pre_div_cnt()
.bits(((freq.hz()) / REF_CLK_FREQ - 1) as u16)
});
APB_CTRL::regs().xtal_tick_conf().modify(|_, w| unsafe {
w.xtal_tick_num()
.bits(((freq.hz()) / REF_CLK_FREQ - 1) as u8)
});
LPWR::regs()
.clk_conf()
.modify(|_, w| w.soc_clk_sel().xtal());
LPWR::regs()
.store5()
.modify(|_, w| unsafe { w.scratch5().bits(value) });
LPWR::regs()
.reg()
.modify(|_, w| unsafe { w.dig_dbias_wak().bits(DIG_DBIAS_XTAL as u8) });
}
pub(crate) fn set_cpu_freq(cpu_freq_mhz: crate::clock::CpuClock) {
let rtc_cntl_dbias_hp_volt: u32 = RTC_CNTL_DBIAS_1V25
- EFUSE::regs()
.blk0_rdata5()
.read()
.rd_vol_level_hp_inv()
.bits() as u32;
let dig_dbias_240_m: u32 = rtc_cntl_dbias_hp_volt;
const CPU_80M: u32 = 0;
const CPU_160M: u32 = 1;
const CPU_240M: u32 = 2;
let mut dbias = DIG_DBIAS_80M_160M;
let per_conf;
match cpu_freq_mhz {
crate::clock::CpuClock::_160MHz => {
per_conf = CPU_160M;
}
crate::clock::CpuClock::_240MHz => {
dbias = dig_dbias_240_m;
per_conf = CPU_240M;
}
crate::clock::CpuClock::_80MHz => {
per_conf = CPU_80M;
}
}
let value = (((80 * MHZ) >> 12) & UINT16_MAX) | ((((80 * MHZ) >> 12) & UINT16_MAX) << 16);
DPORT::regs()
.cpu_per_conf()
.write(|w| unsafe { w.cpuperiod_sel().bits(per_conf as u8) });
LPWR::regs()
.reg()
.modify(|_, w| unsafe { w.dig_dbias_wak().bits(dbias as u8) });
LPWR::regs().clk_conf().modify(|_, w| w.soc_clk_sel().pll());
LPWR::regs()
.store5()
.modify(|_, w| unsafe { w.scratch5().bits(value) });
esp32_update_cpu_freq(cpu_freq_mhz.mhz());
}
fn esp32_update_cpu_freq(mhz: u32) {
const G_TICKS_PER_US_PRO: u32 = 0x3ffe01e0;
unsafe {
(G_TICKS_PER_US_PRO as *mut u32).write_volatile(mhz);
}
}
const DPORT_WIFI_CLK_WIFI_BT_COMMON_M: u32 = 0x000003c9;
const DPORT_WIFI_CLK_WIFI_EN_M: u32 = 0x00000406;
const DPORT_WIFI_CLK_BT_EN_M: u32 = 0x00030800;
pub(super) fn enable_phy(enable: bool) {
DPORT::regs().wifi_clk_en().modify(|r, w| unsafe {
if enable {
w.bits(r.bits() | DPORT_WIFI_CLK_WIFI_BT_COMMON_M)
} else {
w.bits(r.bits() & !DPORT_WIFI_CLK_WIFI_BT_COMMON_M)
}
});
}
pub(super) fn enable_bt(enable: bool) {
DPORT::regs().wifi_clk_en().modify(|r, w| unsafe {
if enable {
w.bits(r.bits() | DPORT_WIFI_CLK_BT_EN_M)
} else {
w.bits(r.bits() & !DPORT_WIFI_CLK_BT_EN_M)
}
});
}
pub(super) fn enable_wifi(enable: bool) {
DPORT::regs().wifi_clk_en().modify(|r, w| unsafe {
if enable {
w.bits(r.bits() | DPORT_WIFI_CLK_WIFI_EN_M)
} else {
w.bits(r.bits() & !DPORT_WIFI_CLK_WIFI_EN_M)
}
});
}
pub(super) fn reset_mac() {
DPORT::regs()
.wifi_rst_en()
.modify(|_, w| w.mac_rst().set_bit());
DPORT::regs()
.wifi_rst_en()
.modify(|_, w| w.mac_rst().clear_bit());
}
pub(super) fn init_clocks() {
DPORT::regs()
.wifi_clk_en()
.write(|w| unsafe { w.bits(u32::MAX) });
}
pub(super) fn ble_rtc_clk_init() {
}
pub(super) fn reset_rpa() {
}