Clean up clocks_ll (#3101)

This commit is contained in:
Dániel Buga 2025-02-06 17:48:41 +01:00 committed by GitHub
parent 477e1d6521
commit dc4daa9217
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 550 additions and 797 deletions

View File

@ -57,13 +57,13 @@ ufmt-write = "0.1.0"
# IMPORTANT:
# Each supported device MUST have its PAC included below along with a
# corresponding feature.
esp32 = { version = "0.35.0", features = ["critical-section", "rt"], git = "https://github.com/esp-rs/esp-pacs", rev = "cab435a", optional = true }
esp32c2 = { version = "0.24.0", features = ["critical-section", "rt"], git = "https://github.com/esp-rs/esp-pacs", rev = "cab435a", optional = true }
esp32c3 = { version = "0.27.0", features = ["critical-section", "rt"], git = "https://github.com/esp-rs/esp-pacs", rev = "cab435a", optional = true }
esp32c6 = { version = "0.18.0", features = ["critical-section", "rt"], git = "https://github.com/esp-rs/esp-pacs", rev = "cab435a", optional = true }
esp32h2 = { version = "0.14.0", features = ["critical-section", "rt"], git = "https://github.com/esp-rs/esp-pacs", rev = "cab435a", optional = true }
esp32s2 = { version = "0.26.0", features = ["critical-section", "rt"], git = "https://github.com/esp-rs/esp-pacs", rev = "cab435a", optional = true }
esp32s3 = { version = "0.30.0", features = ["critical-section", "rt"], git = "https://github.com/esp-rs/esp-pacs", rev = "cab435a", optional = true }
esp32 = { version = "0.35.0", features = ["critical-section", "rt"], git = "https://github.com/esp-rs/esp-pacs", rev = "0f3ea9f", optional = true }
esp32c2 = { version = "0.24.0", features = ["critical-section", "rt"], git = "https://github.com/esp-rs/esp-pacs", rev = "0f3ea9f", optional = true }
esp32c3 = { version = "0.27.0", features = ["critical-section", "rt"], git = "https://github.com/esp-rs/esp-pacs", rev = "0f3ea9f", optional = true }
esp32c6 = { version = "0.18.0", features = ["critical-section", "rt"], git = "https://github.com/esp-rs/esp-pacs", rev = "0f3ea9f", optional = true }
esp32h2 = { version = "0.14.0", features = ["critical-section", "rt"], git = "https://github.com/esp-rs/esp-pacs", rev = "0f3ea9f", optional = true }
esp32s2 = { version = "0.26.0", features = ["critical-section", "rt"], git = "https://github.com/esp-rs/esp-pacs", rev = "0f3ea9f", optional = true }
esp32s3 = { version = "0.30.0", features = ["critical-section", "rt"], git = "https://github.com/esp-rs/esp-pacs", rev = "0f3ea9f", optional = true }
[target.'cfg(target_arch = "riscv32")'.dependencies]
riscv = { version = "0.12.1" }

View File

@ -1,6 +1,6 @@
use crate::{
clock::{Clock, PllClock, XtalClock},
peripherals::DPORT,
peripherals::{APB_CTRL, DPORT, EFUSE, LPWR},
rom::regi2c_write,
};
@ -43,11 +43,12 @@ 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 efuse = crate::peripherals::EFUSE::regs();
let rtc_cntl = crate::peripherals::LPWR::regs();
let rtc_cntl_dbias_hp_volt: u32 =
RTC_CNTL_DBIAS_1V25 - efuse.blk0_rdata5().read().rd_vol_level_hp_inv().bits() as u32;
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;
@ -59,7 +60,7 @@ pub(crate) fn esp32_rtc_bbpll_configure(xtal_freq: XtalClock, pll_freq: PllClock
if matches!(pll_freq, PllClock::Pll320MHz) {
// Raise the voltage, if needed
rtc_cntl
LPWR::regs()
.reg()
.modify(|_, w| unsafe { w.dig_dbias_wak().bits(DIG_DBIAS_80M_160M as u8) });
@ -97,7 +98,7 @@ pub(crate) fn esp32_rtc_bbpll_configure(xtal_freq: XtalClock, pll_freq: PllClock
regi2c_write!(I2C_BBPLL, I2C_BBPLL_BBADC_DSMP, BBPLL_BBADC_DSMP_VAL_320M);
} else {
// Raise the voltage
rtc_cntl
LPWR::regs()
.reg()
.modify(|_, w| unsafe { w.dig_dbias_wak().bits(dig_dbias_240_m as u8) });
@ -145,15 +146,11 @@ pub(crate) fn esp32_rtc_bbpll_configure(xtal_freq: XtalClock, pll_freq: PllClock
}
pub(crate) fn esp32_rtc_bbpll_enable() {
crate::peripherals::LPWR::regs().options0().modify(|_, w| {
w.bias_i2c_force_pd()
.clear_bit()
.bb_i2c_force_pd()
.clear_bit()
.bbpll_force_pd()
.clear_bit()
.bbpll_i2c_force_pd()
.clear_bit()
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()
});
// reset BBPLL configuration
@ -169,80 +166,77 @@ pub(crate) fn esp32_rtc_bbpll_enable() {
}
pub(crate) fn esp32_rtc_update_to_xtal(freq: XtalClock, _div: u32) {
let apb_cntl = crate::peripherals::APB_CTRL::regs();
let rtc_cntl = crate::peripherals::LPWR::regs();
let value = ((freq.hz() >> 12) & UINT16_MAX) | (((freq.hz() >> 12) & UINT16_MAX) << 16);
esp32_update_cpu_freq(freq.hz());
unsafe {
let value = (((freq.hz()) >> 12) & UINT16_MAX) | ((((freq.hz()) >> 12) & UINT16_MAX) << 16);
esp32_update_cpu_freq(freq.hz());
// set divider from XTAL to APB clock
APB_CTRL::regs().sysclk_conf().modify(|_, w| unsafe {
w.pre_div_cnt()
.bits(((freq.hz()) / REF_CLK_FREQ - 1) as u16)
});
// set divider from XTAL to APB clock
apb_cntl.sysclk_conf().modify(|_, w| {
w.pre_div_cnt()
.bits(((freq.hz()) / REF_CLK_FREQ - 1) as u16)
});
// adjust ref_tick
APB_CTRL::regs().xtal_tick_conf().modify(|_, w| unsafe {
w.xtal_tick_num()
.bits(((freq.hz()) / REF_CLK_FREQ - 1) as u8)
});
// adjust ref_tick
apb_cntl.xtal_tick_conf().modify(|_, w| {
w.xtal_tick_num()
.bits(((freq.hz()) / REF_CLK_FREQ - 1) as u8)
});
// switch clock source
LPWR::regs()
.clk_conf()
.modify(|_, w| w.soc_clk_sel().xtal());
LPWR::regs()
.store5()
.modify(|_, w| unsafe { w.scratch5().bits(value) });
// switch clock source
rtc_cntl.clk_conf().modify(|_, w| w.soc_clk_sel().xtal());
rtc_cntl.store5().modify(|_, w| w.scratch5().bits(value));
// lower the voltage
rtc_cntl
.reg()
.modify(|_, w| w.dig_dbias_wak().bits(DIG_DBIAS_XTAL as u8));
}
// lower the voltage
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 efuse = crate::peripherals::EFUSE::regs();
let dport = crate::peripherals::DPORT::regs();
let rtc_cntl = crate::peripherals::LPWR::regs();
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;
unsafe {
const RTC_CNTL_DBIAS_1V25: u32 = 7;
const CPU_80M: u32 = 0;
const CPU_160M: u32 = 1;
const CPU_240M: u32 = 2;
let rtc_cntl_dbias_hp_volt: u32 =
RTC_CNTL_DBIAS_1V25 - efuse.blk0_rdata5().read().rd_vol_level_hp_inv().bits() as u32;
let dig_dbias_240_m: u32 = rtc_cntl_dbias_hp_volt;
let mut dbias = DIG_DBIAS_80M_160M;
let per_conf;
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;
}
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
.cpu_per_conf()
.write(|w| w.cpuperiod_sel().bits(per_conf as u8));
rtc_cntl
.reg()
.modify(|_, w| w.dig_dbias_wak().bits(dbias as u8));
rtc_cntl.clk_conf().modify(|_, w| w.soc_clk_sel().pll());
rtc_cntl.store5().modify(|_, w| w.scratch5().bits(value));
esp32_update_cpu_freq(cpu_freq_mhz.mhz());
}
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());
}
/// Pass the CPU clock in MHz so that ets_delay_us
@ -294,13 +288,12 @@ pub(super) fn enable_wifi(enable: bool) {
}
pub(super) fn reset_mac() {
const SYSTEM_MAC_RST: u8 = 1 << 2;
DPORT::regs()
.core_rst_en()
.modify(|r, w| unsafe { w.core_rst().bits(r.core_rst().bits() | SYSTEM_MAC_RST) });
.wifi_rst_en()
.modify(|_, w| w.mac_rst().set_bit());
DPORT::regs()
.core_rst_en()
.modify(|r, w| unsafe { w.core_rst().bits(r.core_rst().bits() & !SYSTEM_MAC_RST) });
.wifi_rst_en()
.modify(|_, w| w.mac_rst().clear_bit());
}
pub(super) fn init_clocks() {

View File

@ -1,6 +1,6 @@
use crate::{
clock::{ApbClock, Clock, CpuClock, PllClock, XtalClock},
peripherals::{APB_CTRL, MODEM_CLKRST},
peripherals::{APB_CTRL, I2C_ANA_MST, LPWR, MODEM_CLKRST, SYSTEM},
rom::{regi2c_write, regi2c_write_mask},
};
@ -31,13 +31,7 @@ const I2C_BBPLL_OC_DHREF_SEL_LSB: u32 = 4;
const I2C_BBPLL_OC_DLREF_SEL_LSB: u32 = 6;
const I2C_MST_ANA_CONF0_REG: u32 = 0x6004_E840;
const I2C_MST_BBPLL_STOP_FORCE_HIGH: u32 = 1 << 2;
const I2C_MST_BBPLL_STOP_FORCE_LOW: u32 = 1 << 3;
pub(crate) fn esp32c2_rtc_bbpll_configure(xtal_freq: XtalClock, _pll_freq: PllClock) {
let system = crate::peripherals::SYSTEM::regs();
let div_ref: u32;
let div7_0: u32;
let dr1: u32;
@ -46,23 +40,16 @@ pub(crate) fn esp32c2_rtc_bbpll_configure(xtal_freq: XtalClock, _pll_freq: PllCl
let dcur: u32;
let dbias: u32;
unsafe {
let clear_reg_mask = |reg, mask: u32| {
(reg as *mut u32).write_volatile((reg as *mut u32).read_volatile() & !mask)
};
let set_reg_mask = |reg, mask: u32| {
(reg as *mut u32).write_volatile((reg as *mut u32).read_volatile() | mask)
};
clear_reg_mask(I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_HIGH);
set_reg_mask(I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_LOW);
}
// Set this register to let the digital part know 480M PLL is used
system
SYSTEM::regs()
.cpu_per_conf()
.modify(|_, w| w.pll_freq_sel().set_bit());
I2C_ANA_MST::regs().ana_conf0().modify(|_, w| {
w.bbpll_stop_force_high().clear_bit();
w.bbpll_stop_force_low().set_bit()
});
// Configure 480M PLL
match xtal_freq {
XtalClock::_26M => {
@ -103,69 +90,71 @@ pub(crate) fn esp32c2_rtc_bbpll_configure(xtal_freq: XtalClock, _pll_freq: PllCl
regi2c_write!(I2C_BBPLL, I2C_BBPLL_OC_DCUR, i2c_bbpll_dcur);
regi2c_write_mask!(I2C_BBPLL, I2C_BBPLL_OC_VCO_DBIAS, dbias);
}
pub(crate) fn esp32c2_rtc_bbpll_enable() {
let rtc_cntl = crate::peripherals::LPWR::regs();
// WAIT CALIBRATION DONE
while I2C_ANA_MST::regs()
.ana_conf0()
.read()
.bbpll_cal_done()
.bit_is_clear()
{}
rtc_cntl.options0().modify(|_, w| {
w.bb_i2c_force_pd()
.clear_bit()
.bbpll_force_pd()
.clear_bit()
.bbpll_i2c_force_pd()
.clear_bit()
// workaround bbpll calibration might stop early
crate::rom::ets_delay_us(10);
// Stop BBPLL self-calibration
I2C_ANA_MST::regs().ana_conf0().modify(|_, w| {
w.bbpll_stop_force_high().set_bit();
w.bbpll_stop_force_low().clear_bit()
});
}
pub(crate) fn esp32c2_rtc_update_to_xtal(freq: XtalClock, _div: u32) {
pub(crate) fn esp32c2_rtc_bbpll_enable() {
LPWR::regs().options0().modify(|_, w| {
w.bb_i2c_force_pd().clear_bit();
w.bbpll_force_pd().clear_bit();
w.bbpll_i2c_force_pd().clear_bit()
});
}
pub(crate) fn esp32c2_rtc_update_to_xtal(freq: XtalClock, div: u32) {
crate::rom::ets_update_cpu_frequency_rom(freq.mhz());
let system_control = crate::peripherals::SYSTEM::regs();
unsafe {
// Set divider from XTAL to APB clock. Need to set divider to 1 (reg. value 0)
// first.
system_control.sysclk_conf().modify(|_, w| {
w.pre_div_cnt()
.bits(0)
.pre_div_cnt()
.bits((_div - 1) as u16)
});
// Set divider from XTAL to APB clock. Need to set divider to 1 (reg. value 0)
// first.
SYSTEM::regs().sysclk_conf().modify(|_, w| unsafe {
w.pre_div_cnt().bits(0);
w.pre_div_cnt().bits((div - 1) as u16)
});
// No need to adjust the REF_TICK
// No need to adjust the REF_TICK
// Switch clock source
system_control
.sysclk_conf()
.modify(|_, w| w.soc_clk_sel().bits(0));
}
// Switch clock source
SYSTEM::regs()
.sysclk_conf()
.modify(|_, w| unsafe { w.soc_clk_sel().bits(0) });
}
pub(crate) fn esp32c2_rtc_freq_to_pll_mhz(cpu_clock_speed: CpuClock) {
let system_control = crate::peripherals::SYSTEM::regs();
unsafe {
system_control
.sysclk_conf()
.modify(|_, w| w.pre_div_cnt().bits(0).soc_clk_sel().bits(1));
system_control.cpu_per_conf().modify(|_, w| {
w.cpuperiod_sel().bits(match cpu_clock_speed {
CpuClock::_80MHz => 0,
CpuClock::_120MHz => 1,
})
});
}
SYSTEM::regs().sysclk_conf().modify(|_, w| unsafe {
w.pre_div_cnt().bits(0);
w.soc_clk_sel().bits(1)
});
SYSTEM::regs().cpu_per_conf().modify(|_, w| unsafe {
w.cpuperiod_sel().bits(match cpu_clock_speed {
CpuClock::_80MHz => 0,
CpuClock::_120MHz => 1,
})
});
crate::rom::ets_update_cpu_frequency_rom(cpu_clock_speed.mhz());
}
pub(crate) fn esp32c2_rtc_apb_freq_update(apb_freq: ApbClock) {
let rtc_cntl = crate::peripherals::LPWR::regs();
let value = ((apb_freq.hz() >> 12) & u16::MAX as u32)
| (((apb_freq.hz() >> 12) & u16::MAX as u32) << 16);
rtc_cntl
LPWR::regs()
.store5()
.modify(|_, w| unsafe { w.scratch5().bits(value) });
}
@ -199,13 +188,12 @@ pub(super) fn enable_wifi(_: bool) {
}
pub(super) fn reset_mac() {
const SYSTEM_MAC_RST: u32 = 1 << 2;
APB_CTRL::regs()
.wifi_rst_en()
.modify(|r, w| unsafe { w.wifi_rst().bits(r.wifi_rst().bits() | SYSTEM_MAC_RST) });
.modify(|_, w| w.mac_rst().set_bit());
APB_CTRL::regs()
.wifi_rst_en()
.modify(|r, w| unsafe { w.wifi_rst().bits(r.wifi_rst().bits() & !SYSTEM_MAC_RST) });
.modify(|_, w| w.mac_rst().clear_bit());
}
pub(super) fn init_clocks() {
@ -220,39 +208,29 @@ pub(super) fn init_clocks() {
}
pub(super) fn ble_rtc_clk_init() {
let modem_clkrst = MODEM_CLKRST::regs();
modem_clkrst
.modem_lp_timer_conf()
.modify(|_, w| w.lp_timer_sel_xtal32k().clear_bit());
modem_clkrst
.modem_lp_timer_conf()
.modify(|_, w| w.lp_timer_sel_xtal().set_bit());
modem_clkrst
.modem_lp_timer_conf()
.modify(|_, w| w.lp_timer_sel_8m().clear_bit());
modem_clkrst
.modem_lp_timer_conf()
.modify(|_, w| w.lp_timer_sel_rtc_slow().clear_bit());
MODEM_CLKRST::regs().modem_lp_timer_conf().modify(|_, w| {
w.lp_timer_sel_xtal32k().clear_bit();
w.lp_timer_sel_xtal().set_bit();
w.lp_timer_sel_8m().clear_bit();
w.lp_timer_sel_rtc_slow().clear_bit()
});
// assume 40MHz xtal
modem_clkrst
MODEM_CLKRST::regs()
.modem_lp_timer_conf()
.modify(|_, w| unsafe { w.lp_timer_clk_div_num().bits(249) });
modem_clkrst
.etm_clk_conf()
.modify(|_, w| w.etm_clk_active().set_bit());
modem_clkrst
.etm_clk_conf()
.modify(|_, w| w.etm_clk_sel().clear_bit());
MODEM_CLKRST::regs().etm_clk_conf().modify(|_, w| {
w.etm_clk_active().set_bit();
w.etm_clk_sel().clear_bit()
});
}
pub(super) fn reset_rpa() {
const BLE_RPA_REST_BIT: u32 = 1 << 27;
APB_CTRL::regs()
.wifi_rst_en()
.modify(|r, w| unsafe { w.bits(r.bits() | BLE_RPA_REST_BIT) });
.modify(|_, w| w.ble_rpa_rst().set_bit());
APB_CTRL::regs()
.wifi_rst_en()
.modify(|r, w| unsafe { w.bits(r.bits() & !BLE_RPA_REST_BIT) });
.modify(|_, w| w.ble_rpa_rst().clear_bit());
}

View File

@ -1,6 +1,6 @@
use crate::{
clock::{ApbClock, Clock, CpuClock, PllClock, XtalClock},
peripherals::{APB_CTRL, LPWR},
peripherals::{APB_CTRL, I2C_ANA_MST, LPWR, SYSTEM},
rom::{regi2c_write, regi2c_write_mask},
};
@ -35,13 +35,7 @@ const I2C_BBPLL_OC_DLREF_SEL: u32 = 6;
const I2C_BBPLL_OC_DLREF_SEL_MSB: u32 = 7;
const I2C_BBPLL_OC_DLREF_SEL_LSB: u32 = 6;
const I2C_MST_ANA_CONF0_REG: u32 = 0x6000_e040;
const I2C_MST_BBPLL_STOP_FORCE_HIGH: u32 = 1 << 3;
const I2C_MST_BBPLL_STOP_FORCE_LOW: u32 = 1 << 2;
pub(crate) fn esp32c3_rtc_bbpll_configure(xtal_freq: XtalClock, pll_freq: PllClock) {
let system = crate::peripherals::SYSTEM::regs();
let div_ref: u32;
let div7_0: u32;
let dr1: u32;
@ -50,24 +44,18 @@ pub(crate) fn esp32c3_rtc_bbpll_configure(xtal_freq: XtalClock, pll_freq: PllClo
let dcur: u32;
let dbias: u32;
unsafe {
let clear_reg_mask = |reg, mask: u32| {
(reg as *mut u32).write_volatile((reg as *mut u32).read_volatile() & !mask)
};
let set_reg_mask = |reg, mask: u32| {
(reg as *mut u32).write_volatile((reg as *mut u32).read_volatile() | mask)
};
// Set this register to let the digital part know 480M PLL is used
SYSTEM::regs().cpu_per_conf().modify(|_, w| {
w.pll_freq_sel()
.bit(matches!(pll_freq, PllClock::Pll480MHz))
});
clear_reg_mask(I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_HIGH);
set_reg_mask(I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_LOW);
}
I2C_ANA_MST::regs().ana_conf0().modify(|_, w| {
w.bbpll_stop_force_high().clear_bit();
w.bbpll_stop_force_low().set_bit()
});
if matches!(pll_freq, PllClock::Pll480MHz) {
// Set this register to let the digital part know 480M PLL is used
system
.cpu_per_conf()
.modify(|_, w| w.pll_freq_sel().set_bit());
// Configure 480M PLL
match xtal_freq {
XtalClock::_40M => {
@ -103,11 +91,6 @@ pub(crate) fn esp32c3_rtc_bbpll_configure(xtal_freq: XtalClock, pll_freq: PllClo
regi2c_write!(I2C_BBPLL, I2C_BBPLL_MODE_HF, 0x6b);
} else {
// Clear this register to let the digital part know 320M PLL is used
system
.cpu_per_conf()
.modify(|_, w| w.pll_freq_sel().clear_bit());
// Configure 320M PLL
match xtal_freq {
XtalClock::_40M => {
@ -167,65 +150,51 @@ pub(crate) fn esp32c3_rtc_bbpll_configure(xtal_freq: XtalClock, pll_freq: PllClo
}
pub(crate) fn esp32c3_rtc_bbpll_enable() {
let rtc_cntl = crate::peripherals::LPWR::regs();
rtc_cntl.options0().modify(|_, w| {
w.bb_i2c_force_pd()
.clear_bit()
.bbpll_force_pd()
.clear_bit()
.bbpll_i2c_force_pd()
.clear_bit()
LPWR::regs().options0().modify(|_, w| {
w.bb_i2c_force_pd().clear_bit();
w.bbpll_force_pd().clear_bit();
w.bbpll_i2c_force_pd().clear_bit()
});
}
pub(crate) fn esp32c3_rtc_update_to_xtal(freq: XtalClock, _div: u32) {
crate::rom::ets_update_cpu_frequency_rom(freq.mhz());
let system_control = crate::peripherals::SYSTEM::regs();
unsafe {
// Set divider from XTAL to APB clock. Need to set divider to 1 (reg. value 0)
// first.
system_control.sysclk_conf().modify(|_, w| {
w.pre_div_cnt()
.bits(0)
.pre_div_cnt()
.bits((_div - 1) as u16)
});
// Set divider from XTAL to APB clock. Need to set divider to 1 (reg. value 0)
// first.
SYSTEM::regs().sysclk_conf().modify(|_, w| unsafe {
w.pre_div_cnt().bits(0);
w.pre_div_cnt().bits((_div - 1) as u16)
});
// No need to adjust the REF_TICK
// No need to adjust the REF_TICK
// Switch clock source
system_control
.sysclk_conf()
.modify(|_, w| w.soc_clk_sel().bits(0));
}
// Switch clock source
SYSTEM::regs()
.sysclk_conf()
.modify(|_, w| unsafe { w.soc_clk_sel().bits(0) });
}
pub(crate) fn esp32c3_rtc_freq_to_pll_mhz(cpu_clock_speed: CpuClock) {
let system_control = crate::peripherals::SYSTEM::regs();
unsafe {
system_control
.sysclk_conf()
.modify(|_, w| w.pre_div_cnt().bits(0).soc_clk_sel().bits(1));
system_control.cpu_per_conf().modify(|_, w| {
w.cpuperiod_sel().bits(match cpu_clock_speed {
CpuClock::_80MHz => 0,
CpuClock::_160MHz => 1,
})
});
}
SYSTEM::regs().sysclk_conf().modify(|_, w| unsafe {
w.pre_div_cnt().bits(0);
w.soc_clk_sel().bits(1)
});
SYSTEM::regs().cpu_per_conf().modify(|_, w| unsafe {
w.cpuperiod_sel().bits(match cpu_clock_speed {
CpuClock::_80MHz => 0,
CpuClock::_160MHz => 1,
})
});
crate::rom::ets_update_cpu_frequency_rom(cpu_clock_speed.mhz());
}
pub(crate) fn esp32c3_rtc_apb_freq_update(apb_freq: ApbClock) {
let rtc_cntl = crate::peripherals::LPWR::regs();
let value = ((apb_freq.hz() >> 12) & u16::MAX as u32)
| (((apb_freq.hz() >> 12) & u16::MAX as u32) << 16);
rtc_cntl
LPWR::regs()
.store5()
.modify(|_, w| unsafe { w.scratch5().bits(value) });
}
@ -259,24 +228,25 @@ pub(super) fn enable_bt(_: bool) {
}
pub(super) fn reset_mac() {
const SYSTEM_MAC_RST: u32 = 1 << 2;
APB_CTRL::regs()
.wifi_rst_en()
.modify(|r, w| unsafe { w.wifi_rst().bits(r.wifi_rst().bits() | SYSTEM_MAC_RST) });
.modify(|_, w| w.mac_rst().set_bit());
APB_CTRL::regs()
.wifi_rst_en()
.modify(|r, w| unsafe { w.wifi_rst().bits(r.wifi_rst().bits() & !SYSTEM_MAC_RST) });
.modify(|_, w| w.mac_rst().clear_bit());
}
pub(super) fn init_clocks() {
// undo the power down in base_settings (esp32c3_sleep)
LPWR::regs()
.dig_iso()
.modify(|_, w| w.wifi_force_iso().clear_bit().bt_force_iso().clear_bit());
LPWR::regs().dig_iso().modify(|_, w| {
w.wifi_force_iso().clear_bit();
w.bt_force_iso().clear_bit()
});
LPWR::regs()
.dig_pwc()
.modify(|_, w| w.wifi_force_pd().clear_bit().bt_force_pd().clear_bit());
LPWR::regs().dig_pwc().modify(|_, w| {
w.wifi_force_pd().clear_bit();
w.bt_force_pd().clear_bit()
});
// from `esp_perip_clk_init`
const SYSTEM_WIFI_CLK_I2C_CLK_EN: u32 = 1 << 5;

View File

@ -1,6 +1,6 @@
use crate::{
clock::{ApbClock, Clock, CpuClock, PllClock, XtalClock},
peripherals::{MODEM_LPCON, MODEM_SYSCON, PMU},
peripherals::{I2C_ANA_MST, LP_AON, MODEM_LPCON, MODEM_SYSCON, PCR, PMU},
rtc_cntl::rtc::CpuClockSource,
};
@ -30,20 +30,6 @@ const I2C_BBPLL_OC_VCO_DBIAS: u8 = 9;
const I2C_BBPLL_OC_VCO_DBIAS_MSB: u8 = 1;
const I2C_BBPLL_OC_VCO_DBIAS_LSB: u8 = 0;
// Analog function control register
const I2C_MST_ANA_CONF0_REG: u32 = 0x600AF818;
const I2C_MST_BBPLL_STOP_FORCE_HIGH: u32 = 1 << 2;
const I2C_MST_BBPLL_STOP_FORCE_LOW: u32 = 1 << 3;
const I2C_MST_BBPLL_CAL_DONE: u32 = 1 << 24;
unsafe fn modem_lpcon<'a>() -> &'a esp32c6::modem_lpcon::RegisterBlock {
&*esp32c6::MODEM_LPCON::ptr()
}
unsafe fn pcr<'a>() -> &'a esp32c6::pcr::RegisterBlock {
&*esp32c6::PCR::ptr()
}
// rtc_clk_bbpll_configure
pub(crate) fn esp32c6_rtc_bbpll_configure(xtal_freq: XtalClock, pll_freq: PllClock) {
esp32c6_rtc_bbpll_configure_raw(xtal_freq.mhz(), pll_freq.mhz())
@ -55,33 +41,30 @@ pub(crate) fn esp32c6_rtc_bbpll_configure_raw(_xtal_freq: u32, pll_freq: u32) {
// Do nothing
debug_assert!(pll_freq == 480);
critical_section::with(|_| unsafe {
critical_section::with(|_| {
// enable i2c mst clk by force on (temporarily)
let was_i2c_mst_en = modem_lpcon().clk_conf().read().clk_i2c_mst_en().bit();
modem_lpcon()
let was_i2c_mst_en = MODEM_LPCON::regs().clk_conf().read().clk_i2c_mst_en().bit();
MODEM_LPCON::regs()
.clk_conf()
.modify(|_, w| w.clk_i2c_mst_en().set_bit());
modem_lpcon()
MODEM_LPCON::regs()
.i2c_mst_clk_conf()
.modify(|_, w| w.clk_i2c_mst_sel_160m().set_bit());
let i2c_mst_ana_conf0_reg_ptr = I2C_MST_ANA_CONF0_REG as *mut u32;
// BBPLL CALIBRATION START
i2c_mst_ana_conf0_reg_ptr.write_volatile(
i2c_mst_ana_conf0_reg_ptr.read_volatile() & !I2C_MST_BBPLL_STOP_FORCE_HIGH,
);
i2c_mst_ana_conf0_reg_ptr.write_volatile(
i2c_mst_ana_conf0_reg_ptr.read_volatile() | I2C_MST_BBPLL_STOP_FORCE_LOW,
);
I2C_ANA_MST::regs().ana_conf0().modify(|_, w| {
w.bbpll_stop_force_high().clear_bit();
w.bbpll_stop_force_low().set_bit()
});
let div_ref = 0u32;
let div7_0 = 8u32;
let dr1 = 0u32;
let dr3 = 0u32;
let dchgp = 5u32;
let dcur = 3u32;
let dbias = 2u32;
let div_ref = 0;
let div7_0 = 8;
let dr1 = 0;
let dr3 = 0;
let dchgp = 5;
let dcur = 3;
let dbias = 2;
let i2c_bbpll_lref = (dchgp << I2C_BBPLL_OC_DCHGP_LSB) | div_ref;
let i2c_bbpll_div_7_0 = div7_0;
@ -92,13 +75,13 @@ pub(crate) fn esp32c6_rtc_bbpll_configure_raw(_xtal_freq: u32, pll_freq: u32) {
I2C_BBPLL,
I2C_BBPLL_HOSTID,
I2C_BBPLL_OC_REF_DIV,
i2c_bbpll_lref as u8,
i2c_bbpll_lref,
);
regi2c_write(
I2C_BBPLL,
I2C_BBPLL_HOSTID,
I2C_BBPLL_OC_DIV_7_0,
i2c_bbpll_div_7_0 as u8,
i2c_bbpll_div_7_0,
);
regi2c_write_mask(
I2C_BBPLL,
@ -106,7 +89,7 @@ pub(crate) fn esp32c6_rtc_bbpll_configure_raw(_xtal_freq: u32, pll_freq: u32) {
I2C_BBPLL_OC_DR1,
I2C_BBPLL_OC_DR1_MSB,
I2C_BBPLL_OC_DR1_LSB,
dr1 as u8,
dr1,
);
regi2c_write_mask(
I2C_BBPLL,
@ -114,13 +97,13 @@ pub(crate) fn esp32c6_rtc_bbpll_configure_raw(_xtal_freq: u32, pll_freq: u32) {
I2C_BBPLL_OC_DR3,
I2C_BBPLL_OC_DR3_MSB,
I2C_BBPLL_OC_DR3_LSB,
dr3 as u8,
dr3,
);
regi2c_write(
I2C_BBPLL,
I2C_BBPLL_HOSTID,
I2C_BBPLL_OC_DCUR,
i2c_bbpll_dcur as u8,
i2c_bbpll_dcur,
);
regi2c_write_mask(
I2C_BBPLL,
@ -128,42 +111,41 @@ pub(crate) fn esp32c6_rtc_bbpll_configure_raw(_xtal_freq: u32, pll_freq: u32) {
I2C_BBPLL_OC_VCO_DBIAS,
I2C_BBPLL_OC_VCO_DBIAS_MSB,
I2C_BBPLL_OC_VCO_DBIAS_LSB,
dbias as u8,
dbias,
);
// WAIT CALIBRATION DONE
while (i2c_mst_ana_conf0_reg_ptr.read_volatile() & I2C_MST_BBPLL_CAL_DONE) == 0 {}
while I2C_ANA_MST::regs()
.ana_conf0()
.read()
.cal_done()
.bit_is_clear()
{}
// workaround bbpll calibration might stop early
crate::rom::ets_delay_us(10);
// BBPLL CALIBRATION STOP
i2c_mst_ana_conf0_reg_ptr.write_volatile(
i2c_mst_ana_conf0_reg_ptr.read_volatile() & !I2C_MST_BBPLL_STOP_FORCE_LOW,
);
i2c_mst_ana_conf0_reg_ptr.write_volatile(
i2c_mst_ana_conf0_reg_ptr.read_volatile() | I2C_MST_BBPLL_STOP_FORCE_HIGH,
);
I2C_ANA_MST::regs().ana_conf0().modify(|_, w| {
w.bbpll_stop_force_high().set_bit();
w.bbpll_stop_force_low().clear_bit()
});
modem_lpcon()
MODEM_LPCON::regs()
.clk_conf()
.modify(|_, w| w.clk_i2c_mst_en().bit(was_i2c_mst_en));
});
}
pub(crate) fn esp32c6_rtc_bbpll_enable() {
let pmu = crate::peripherals::PMU::regs();
pmu.imm_hp_ck_power().modify(|_, w| {
w.tie_high_xpd_bb_i2c()
.set_bit()
.tie_high_xpd_bbpll()
.set_bit()
.tie_high_xpd_bbpll_i2c()
.set_bit()
PMU::regs().imm_hp_ck_power().modify(|_, w| {
w.tie_high_xpd_bb_i2c().set_bit();
w.tie_high_xpd_bbpll().set_bit();
w.tie_high_xpd_bbpll_i2c().set_bit()
});
pmu.imm_hp_ck_power()
PMU::regs()
.imm_hp_ck_power()
.modify(|_, w| w.tie_high_global_bbpll_icg().set_bit());
}
@ -200,30 +182,26 @@ pub(crate) fn esp32c6_rtc_freq_to_pll_mhz_raw(cpu_clock_speed_mhz: u32) {
// 80MHz after the switch. PLL = 480MHz, so divider is 6.
clk_ll_mspi_fast_set_hs_divider(6);
let pcr = crate::peripherals::PCR::regs();
unsafe {
pcr.cpu_freq_conf().modify(|_, w| {
w.cpu_hs_div_num()
.bits(((480 / cpu_clock_speed_mhz / 3) - 1) as u8)
.cpu_hs_120m_force()
.clear_bit()
});
PCR::regs().cpu_freq_conf().modify(|_, w| unsafe {
w.cpu_hs_div_num()
.bits(((480 / cpu_clock_speed_mhz / 3) - 1) as u8);
w.cpu_hs_120m_force().clear_bit()
});
pcr.cpu_freq_conf()
.modify(|_, w| w.cpu_hs_120m_force().clear_bit());
PCR::regs()
.cpu_freq_conf()
.modify(|_, w| w.cpu_hs_120m_force().clear_bit());
CpuClockSource::Pll.select();
}
CpuClockSource::Pll.select();
crate::rom::ets_update_cpu_frequency_rom(cpu_clock_speed_mhz);
}
pub(crate) fn esp32c6_rtc_apb_freq_update(apb_freq: ApbClock) {
let lp_aon = crate::peripherals::LP_AON::regs();
let value = ((apb_freq.hz() >> 12) & u16::MAX as u32)
| (((apb_freq.hz() >> 12) & u16::MAX as u32) << 16);
lp_aon
LP_AON::regs()
.store5()
.modify(|_, w| unsafe { w.lp_aon_store5().bits(value) });
}
@ -231,214 +209,133 @@ pub(crate) fn esp32c6_rtc_apb_freq_update(apb_freq: ApbClock) {
fn clk_ll_mspi_fast_set_hs_divider(divider: u32) {
// SOC_ROOT_CLK ------> MSPI_FAST_CLK
// HS divider option: 4, 5, 6 (PCR_MSPI_FAST_HS_DIV_NUM=3, 4, 5)
let pcr = crate::peripherals::PCR::regs();
unsafe {
match divider {
4 => pcr
.mspi_clk_conf()
.modify(|_, w| w.mspi_fast_hs_div_num().bits(3)),
5 => pcr
.mspi_clk_conf()
.modify(|_, w| w.mspi_fast_hs_div_num().bits(4)),
6 => pcr
.mspi_clk_conf()
.modify(|_, w| w.mspi_fast_hs_div_num().bits(5)),
_ => panic!("Unsupported HS MSPI_FAST divider"),
};
}
let div_num = match divider {
4..=6 => divider as u8 - 1,
_ => panic!("Unsupported HS MSPI_FAST divider"),
};
PCR::regs()
.mspi_clk_conf()
.modify(|_, w| unsafe { w.mspi_fast_hs_div_num().bits(div_num) });
}
const REGI2C_BBPLL: u8 = 0x66;
const REGI2C_BIAS: u8 = 0x6a;
const REGI2C_DIG_REG: u8 = 0x6d;
const REGI2C_ULP_CAL: u8 = 0x61;
const REGI2C_SAR_I2C: u8 = 0x69;
const REGI2C_RTC_SLAVE_ID_V: u8 = 0xFF;
const REGI2C_RTC_SLAVE_ID_S: u8 = 0;
const REGI2C_RTC_ADDR_V: u8 = 0xFF;
const REGI2C_RTC_ADDR_S: u8 = 8;
const REGI2C_RTC_WR_CNTL_S: u8 = 24;
const REGI2C_RTC_DATA_V: u8 = 0xFF;
const REGI2C_RTC_DATA_S: u8 = 16;
const I2C_MST_ANA_CONF1_M: u32 = 0x00FFFFFF;
const REGI2C_BBPLL: u8 = 0x66;
const REGI2C_BBPLL_DEVICE_EN: u16 = 1 << 5;
const REGI2C_BIAS_DEVICE_EN: u16 = 1 << 4;
const REGI2C_DIG_REG_DEVICE_EN: u16 = 1 << 8;
const REGI2C_ULP_CAL_DEVICE_EN: u16 = 1 << 6;
const REGI2C_SAR_I2C_DEVICE_EN: u16 = 1 << 7;
fn regi2c_enable_block(block: u8) {
let modem_lpcon = crate::peripherals::MODEM_LPCON::regs();
let lp_i2c_ana = crate::peripherals::LP_I2C_ANA_MST::regs();
modem_lpcon
fn regi2c_enable_block(block: u8) -> usize {
MODEM_LPCON::regs()
.clk_conf()
.modify(|_, w| w.clk_i2c_mst_en().set_bit());
modem_lpcon
.i2c_mst_clk_conf()
.modify(|_, w| w.clk_i2c_mst_sel_160m().set_bit());
lp_i2c_ana
.date()
.modify(|_, w| w.lp_i2c_ana_mast_i2c_mat_clk_en().set_bit());
// Before config I2C register, enable corresponding slave.
let en_bit = match block {
v if v == REGI2C_BBPLL => REGI2C_BBPLL_DEVICE_EN,
v if v == REGI2C_BIAS => REGI2C_BIAS_DEVICE_EN,
v if v == REGI2C_DIG_REG => REGI2C_DIG_REG_DEVICE_EN,
v if v == REGI2C_ULP_CAL => REGI2C_ULP_CAL_DEVICE_EN,
v if v == REGI2C_SAR_I2C => REGI2C_SAR_I2C_DEVICE_EN,
_ => return,
let i2c_sel_bits = I2C_ANA_MST::regs().ana_conf2().read();
let i2c_sel = match block {
v if v == REGI2C_BBPLL => i2c_sel_bits.bbpll_mst_sel().bit_is_set(),
v if v == REGI2C_BIAS => i2c_sel_bits.bias_mst_sel().bit_is_set(),
v if v == REGI2C_DIG_REG => i2c_sel_bits.dig_reg_mst_sel().bit_is_set(),
v if v == REGI2C_ULP_CAL => i2c_sel_bits.ulp_cal_mst_sel().bit_is_set(),
v if v == REGI2C_SAR_I2C => i2c_sel_bits.sar_i2c_mst_sel().bit_is_set(),
_ => unreachable!(),
};
I2C_ANA_MST::regs().ana_conf1().write(|w| unsafe {
w.bits(I2C_MST_ANA_CONF1_M);
match block {
v if v == REGI2C_BBPLL => w.bbpll_rd().clear_bit(),
v if v == REGI2C_BIAS => w.bias_rd().clear_bit(),
v if v == REGI2C_DIG_REG => w.dig_reg_rd().clear_bit(),
v if v == REGI2C_ULP_CAL => w.ulp_cal_rd().clear_bit(),
v if v == REGI2C_SAR_I2C => w.sar_i2c_rd().clear_bit(),
_ => unreachable!(),
}
});
unsafe {
lp_i2c_ana.device_en().modify(|r, w| {
w.lp_i2c_ana_mast_i2c_device_en()
.bits(r.lp_i2c_ana_mast_i2c_device_en().bits() | en_bit)
});
}
}
fn regi2c_disable_block(block: u8) {
let en_bit = match block {
v if v == REGI2C_BBPLL => REGI2C_BBPLL_DEVICE_EN,
v if v == REGI2C_BIAS => REGI2C_BIAS_DEVICE_EN,
v if v == REGI2C_DIG_REG => REGI2C_DIG_REG_DEVICE_EN,
v if v == REGI2C_ULP_CAL => REGI2C_ULP_CAL_DEVICE_EN,
v if v == REGI2C_SAR_I2C => REGI2C_SAR_I2C_DEVICE_EN,
_ => return,
};
unsafe {
let lp_i2c_ana = crate::peripherals::LP_I2C_ANA_MST::regs();
lp_i2c_ana.device_en().modify(|r, w| {
w.lp_i2c_ana_mast_i2c_device_en()
.bits(r.lp_i2c_ana_mast_i2c_device_en().bits() & !en_bit)
});
if i2c_sel {
0
} else {
1
}
}
pub(crate) fn regi2c_write(block: u8, _host_id: u8, reg_add: u8, data: u8) {
regi2c_enable_block(block);
let lp_i2c_ana = crate::peripherals::LP_I2C_ANA_MST::regs();
let master = regi2c_enable_block(block);
let block_shifted = (block as u32 & REGI2C_RTC_SLAVE_ID_V as u32) << REGI2C_RTC_SLAVE_ID_S;
let reg_add_shifted = (reg_add as u32 & REGI2C_RTC_ADDR_V as u32) << REGI2C_RTC_ADDR_S;
let write_bit = 1u32 << REGI2C_RTC_WR_CNTL_S;
I2C_ANA_MST::regs().i2c_ctrl(master).write(|w| unsafe {
w.slave_addr().bits(block);
w.slave_reg_addr().bits(reg_add);
w.read_write().set_bit();
w.data().bits(data)
});
let new_value = (data as u32) << REGI2C_RTC_DATA_S;
lp_i2c_ana
.i2c0_ctrl()
.write(|w| unsafe { w.bits(block_shifted | reg_add_shifted | write_bit | new_value) });
while lp_i2c_ana
.i2c0_ctrl()
.read()
.lp_i2c_ana_mast_i2c0_busy()
.bit()
{}
regi2c_disable_block(block);
while I2C_ANA_MST::regs().i2c_ctrl(master).read().busy().bit() {}
}
pub(crate) fn regi2c_write_mask(block: u8, _host_id: u8, reg_add: u8, msb: u8, lsb: u8, data: u8) {
assert!(msb < 8 + lsb);
let lp_i2c_ana = crate::peripherals::LP_I2C_ANA_MST::regs();
regi2c_enable_block(block);
let master = regi2c_enable_block(block);
let block_shifted = (block as u32 & REGI2C_RTC_SLAVE_ID_V as u32) << REGI2C_RTC_SLAVE_ID_S;
let reg_add_shifted = (reg_add as u32 & REGI2C_RTC_ADDR_V as u32) << REGI2C_RTC_ADDR_S;
let write_bit = 1u32 << REGI2C_RTC_WR_CNTL_S;
// Read the i2c bus register
I2C_ANA_MST::regs().i2c_ctrl(master).write(|w| unsafe {
w.slave_addr().bits(block);
w.slave_reg_addr().bits(reg_add)
});
unsafe {
// Read the i2c bus register
lp_i2c_ana.i2c0_ctrl().write(|w| {
w.lp_i2c_ana_mast_i2c0_ctrl()
.bits(block_shifted | reg_add_shifted)
});
while I2C_ANA_MST::regs().i2c_ctrl(master).read().busy().bit() {}
while lp_i2c_ana
.i2c0_ctrl()
.read()
.lp_i2c_ana_mast_i2c0_busy()
.bit()
{}
// Example: LSB=2, MSB = 5
// unwritten_bits = 1100 0011
// data_mask = 0000 1111
// data_bits = 00xx xx00
let unwritten_bits = (!(u32::MAX << lsb) | (u32::MAX << (msb + 1))) as u8;
let data_mask = !(u32::MAX << (msb - lsb + 1)) as u8;
let data_bits = (data & data_mask) << lsb;
let mut temp = lp_i2c_ana
.i2c0_data()
.read()
.lp_i2c_ana_mast_i2c0_rdata()
.bits() as u32;
I2C_ANA_MST::regs().i2c_ctrl(master).modify(|r, w| unsafe {
w.slave_addr().bits(block);
w.slave_reg_addr().bits(reg_add);
w.read_write().set_bit();
w.data()
.bits((r.data().bits() & unwritten_bits) | data_bits)
});
// Mask the value field
temp &= (!(0xFFFFFFFF << lsb)) | (0xFFFFFFFF << (msb + 1));
// Write the value into the temporary
temp |= (data as u32 & (!(0xFFFFFFFF << (msb - lsb + 1)))) << lsb;
// Write the i2c bus register
let new_value = (temp & REGI2C_RTC_DATA_V as u32) << REGI2C_RTC_DATA_S;
lp_i2c_ana.i2c0_ctrl().write(|w| {
w.lp_i2c_ana_mast_i2c0_ctrl()
.bits(block_shifted | reg_add_shifted | write_bit | new_value)
});
while lp_i2c_ana
.i2c0_ctrl()
.read()
.lp_i2c_ana_mast_i2c0_busy()
.bit()
{}
regi2c_disable_block(block);
}
while I2C_ANA_MST::regs().i2c_ctrl(master).read().busy().bit() {}
}
// clk_ll_ahb_set_ls_divider
fn esp32c6_ahb_set_ls_divider(div: u8) {
unsafe {
pcr()
.ahb_freq_conf()
.modify(|_, w| w.ahb_ls_div_num().bits(div - 1));
}
PCR::regs()
.ahb_freq_conf()
.modify(|_, w| unsafe { w.ahb_ls_div_num().bits(div - 1) });
}
// clk_ll_cpu_set_ls_divider
fn esp32c6_cpu_set_ls_divider(div: u8) {
unsafe {
pcr()
.cpu_freq_conf()
.modify(|_, w| w.cpu_ls_div_num().bits(div - 1));
}
PCR::regs()
.cpu_freq_conf()
.modify(|_, w| unsafe { w.cpu_ls_div_num().bits(div - 1) });
}
// clk_ll_cpu_get_ls_divider
pub(crate) fn esp32c6_cpu_get_ls_divider() -> u8 {
unsafe {
let cpu_ls_div = pcr().cpu_freq_conf().read().cpu_ls_div_num().bits();
let hp_root_ls_div = pcr().sysclk_conf().read().ls_div_num().bits();
(hp_root_ls_div + 1) * (cpu_ls_div + 1)
}
let cpu_ls_div = PCR::regs().cpu_freq_conf().read().cpu_ls_div_num().bits();
let hp_root_ls_div = PCR::regs().sysclk_conf().read().ls_div_num().bits();
(hp_root_ls_div + 1) * (cpu_ls_div + 1)
}
// clk_ll_cpu_get_hs_divider
pub(crate) fn esp32c6_cpu_get_hs_divider() -> u8 {
unsafe {
let force_120m = pcr().cpu_freq_conf().read().cpu_hs_120m_force().bit();
let cpu_hs_div = pcr().cpu_freq_conf().read().cpu_hs_div_num().bits();
if cpu_hs_div == 0 && force_120m {
return 4;
}
let hp_root_hs_div = pcr().sysclk_conf().read().hs_div_num().bits();
(hp_root_hs_div + 1) * (cpu_hs_div + 1)
let force_120m = PCR::regs().cpu_freq_conf().read().cpu_hs_120m_force().bit();
let cpu_hs_div = PCR::regs().cpu_freq_conf().read().cpu_hs_div_num().bits();
if cpu_hs_div == 0 && force_120m {
return 4;
}
let hp_root_hs_div = PCR::regs().sysclk_conf().read().hs_div_num().bits();
(hp_root_hs_div + 1) * (cpu_hs_div + 1)
}
// clk_ll_bbpll_get_freq_mhz
@ -543,54 +440,43 @@ pub(super) fn reset_mac() {
pub(super) fn init_clocks() {
unsafe {
let pmu = PMU::regs();
pmu.hp_sleep_icg_modem()
PMU::regs()
.hp_sleep_icg_modem()
.modify(|_, w| w.hp_sleep_dig_icg_modem_code().bits(0));
pmu.hp_modem_icg_modem()
PMU::regs()
.hp_modem_icg_modem()
.modify(|_, w| w.hp_modem_dig_icg_modem_code().bits(1));
pmu.hp_active_icg_modem()
PMU::regs()
.hp_active_icg_modem()
.modify(|_, w| w.hp_active_dig_icg_modem_code().bits(2));
pmu.imm_modem_icg()
PMU::regs()
.imm_modem_icg()
.write(|w| w.update_dig_icg_modem_en().set_bit());
pmu.imm_sleep_sysclk()
PMU::regs()
.imm_sleep_sysclk()
.write(|w| w.update_dig_icg_switch().set_bit());
MODEM_SYSCON::regs().clk_conf_power_st().modify(|_, w| {
w.clk_modem_apb_st_map()
.bits(6)
.clk_modem_peri_st_map()
.bits(4)
.clk_wifi_st_map()
.bits(6)
.clk_bt_st_map()
.bits(6)
.clk_fe_st_map()
.bits(6)
.clk_zb_st_map()
.bits(6)
w.clk_modem_apb_st_map().bits(6);
w.clk_modem_peri_st_map().bits(4);
w.clk_wifi_st_map().bits(6);
w.clk_bt_st_map().bits(6);
w.clk_fe_st_map().bits(6);
w.clk_zb_st_map().bits(6)
});
MODEM_LPCON::regs().clk_conf_power_st().modify(|_, w| {
w.clk_lp_apb_st_map()
.bits(6)
.clk_i2c_mst_st_map()
.bits(6)
.clk_coex_st_map()
.bits(6)
.clk_wifipwr_st_map()
.bits(6)
w.clk_lp_apb_st_map().bits(6);
w.clk_i2c_mst_st_map().bits(6);
w.clk_coex_st_map().bits(6);
w.clk_wifipwr_st_map().bits(6)
});
MODEM_LPCON::regs().wifi_lp_clk_conf().modify(|_, w| {
w.clk_wifipwr_lp_sel_osc_slow()
.set_bit()
.clk_wifipwr_lp_sel_osc_fast()
.set_bit()
.clk_wifipwr_lp_sel_xtal32k()
.set_bit()
.clk_wifipwr_lp_sel_xtal()
.set_bit()
w.clk_wifipwr_lp_sel_osc_slow().set_bit();
w.clk_wifipwr_lp_sel_osc_fast().set_bit();
w.clk_wifipwr_lp_sel_xtal32k().set_bit();
w.clk_wifipwr_lp_sel_xtal().set_bit()
});
MODEM_LPCON::regs()

View File

@ -1,6 +1,6 @@
use crate::{
clock::{ApbClock, Clock, CpuClock, PllClock, XtalClock},
peripherals::{LP_AON, MODEM_LPCON, MODEM_SYSCON, PCR, PMU},
peripherals::{I2C_ANA_MST, LP_AON, MODEM_LPCON, MODEM_SYSCON, PCR, PMU},
};
const I2C_BBPLL: u8 = 0x66;
@ -21,20 +21,9 @@ const I2C_BBPLL_OC_DLREF_SEL: u8 = 5;
const I2C_BBPLL_OC_DLREF_SEL_MSB: u8 = 7;
const I2C_BBPLL_OC_DLREF_SEL_LSB: u8 = 6;
const I2C_MST_ANA_CONF0_REG: u32 = 0x600AD800 + 0x18;
const I2C_MST_BBPLL_STOP_FORCE_HIGH: u32 = 1 << 2;
const I2C_MST_BBPLL_STOP_FORCE_LOW: u32 = 1 << 3;
const I2C_MST_BBPLL_CAL_DONE: u32 = 1 << 24;
const MODEM_LPCON_CLK_CONF_FORCE_ON_REG: u32 = DR_REG_MODEM_LPCON_BASE + 0xc;
const MODEM_LPCON_CLK_I2C_MST_FO: u32 = 1 << 2;
// May be needed for enabling I2C clock
const MODEM_LPCON_I2C_CLK_CONF_REG: u32 = DR_REG_MODEM_LPCON_BASE + 0x8;
const MODEM_LPCON_CLK_I2C_SEL_96M: u32 = 1 << 0;
const DR_REG_MODEM_LPCON_BASE: u32 = 0x600AD000;
const REGI2C_BBPLL: u8 = 0x66;
const REGI2C_BIAS: u8 = 0x6a;
const REGI2C_PMU: u8 = 0x6d;
@ -42,101 +31,81 @@ const REGI2C_ULP_CAL: u8 = 0x61;
const REGI2C_SAR_I2C: u8 = 0x69;
const I2C_MST_ANA_CONF1_M: u32 = 0x00FFFFFF;
const I2C_MST_ANA_CONF1_REG: u32 = I2C_MST_I2C0_CTRL_REG + 0x1c;
const REGI2C_BBPLL_RD_MASK: u32 = !(1 << 7) & I2C_MST_ANA_CONF1_M;
const REGI2C_BIAS_RD_MASK: u32 = !(1 << 6) & I2C_MST_ANA_CONF1_M;
const REGI2C_DIG_REG_RD_MASK: u32 = !(1 << 10) & I2C_MST_ANA_CONF1_M;
const REGI2C_ULP_CAL_RD_MASK: u32 = !(1 << 8) & I2C_MST_ANA_CONF1_M;
const REGI2C_SAR_I2C_RD_MASK: u32 = !(1 << 9) & I2C_MST_ANA_CONF1_M;
const REGI2C_RTC_SLAVE_ID_V: u8 = 0xFF;
const REGI2C_RTC_SLAVE_ID_S: u8 = 0;
const REGI2C_RTC_ADDR_V: u8 = 0xFF;
const REGI2C_RTC_ADDR_S: u8 = 8;
const REGI2C_RTC_WR_CNTL_S: u8 = 24;
const REGI2C_RTC_DATA_V: u8 = 0xFF;
const REGI2C_RTC_DATA_S: u8 = 16;
const I2C_MST_I2C0_CTRL_REG: u32 = 0x600AD800;
const REGI2C_RTC_BUSY: u32 = 1 << 25;
pub(crate) fn esp32h2_rtc_bbpll_configure(_xtal_freq: XtalClock, _pll_freq: PllClock) {
unsafe {
// Enable I2C master clock
(MODEM_LPCON_CLK_CONF_FORCE_ON_REG as *mut u32).write_volatile(
(MODEM_LPCON_CLK_CONF_FORCE_ON_REG as *mut u32).read_volatile()
| MODEM_LPCON_CLK_I2C_MST_FO,
);
// Enable I2C master clock
MODEM_LPCON::regs()
.clk_conf_force_on()
.modify(|_, w| w.clk_i2c_mst_fo().set_bit());
// Set I2C clock to 96MHz
(MODEM_LPCON_I2C_CLK_CONF_REG as *mut u32).write_volatile(
(MODEM_LPCON_I2C_CLK_CONF_REG as *mut u32).read_volatile()
| MODEM_LPCON_CLK_I2C_SEL_96M,
);
// Set I2C clock to 96MHz
MODEM_LPCON::regs()
.clk_conf()
.modify(|r, w| unsafe { w.bits(r.bits() | MODEM_LPCON_CLK_I2C_SEL_96M) });
let i2c_mst_ana_conf0_reg_ptr = I2C_MST_ANA_CONF0_REG as *mut u32;
// BPPLL calibration start
I2C_ANA_MST::regs().ana_conf0().modify(|_, w| {
w.bbpll_stop_force_high().clear_bit();
w.bbpll_stop_force_low().set_bit()
});
// BPPLL calibration start
i2c_mst_ana_conf0_reg_ptr.write_volatile(
i2c_mst_ana_conf0_reg_ptr.read_volatile() & !I2C_MST_BBPLL_STOP_FORCE_HIGH,
);
i2c_mst_ana_conf0_reg_ptr.write_volatile(
i2c_mst_ana_conf0_reg_ptr.read_volatile() | I2C_MST_BBPLL_STOP_FORCE_LOW,
);
let oc_ref_div = 0;
let oc_div = 1;
let oc_dhref_sel = 3;
let oc_dlref_sel = 1;
let oc_ref_div = 0u32;
let oc_div = 1u32;
let oc_dhref_sel = 3u32;
let oc_dlref_sel = 1u32;
regi2c_write_mask(
I2C_BBPLL,
I2C_BBPLL_HOSTID,
I2C_BBPLL_OC_REF_DIV,
I2C_BBPLL_OC_REF_DIV_MSB,
I2C_BBPLL_OC_REF_DIV_LSB,
oc_ref_div,
);
regi2c_write_mask(
I2C_BBPLL,
I2C_BBPLL_HOSTID,
I2C_BBPLL_OC_REF_DIV,
I2C_BBPLL_OC_REF_DIV_MSB,
I2C_BBPLL_OC_REF_DIV_LSB,
oc_ref_div as u8,
);
regi2c_write_mask(
I2C_BBPLL,
I2C_BBPLL_HOSTID,
I2C_BBPLL_OC_DIV,
I2C_BBPLL_OC_DIV_MSB,
I2C_BBPLL_OC_DIV_LSB,
oc_div,
);
regi2c_write_mask(
I2C_BBPLL,
I2C_BBPLL_HOSTID,
I2C_BBPLL_OC_DIV,
I2C_BBPLL_OC_DIV_MSB,
I2C_BBPLL_OC_DIV_LSB,
oc_div as u8,
);
regi2c_write_mask(
I2C_BBPLL,
I2C_BBPLL_HOSTID,
I2C_BBPLL_OC_DHREF_SEL,
I2C_BBPLL_OC_DHREF_SEL_MSB,
I2C_BBPLL_OC_DHREF_SEL_LSB,
oc_dhref_sel,
);
regi2c_write_mask(
I2C_BBPLL,
I2C_BBPLL_HOSTID,
I2C_BBPLL_OC_DHREF_SEL,
I2C_BBPLL_OC_DHREF_SEL_MSB,
I2C_BBPLL_OC_DHREF_SEL_LSB,
oc_dhref_sel as u8,
);
regi2c_write_mask(
I2C_BBPLL,
I2C_BBPLL_HOSTID,
I2C_BBPLL_OC_DLREF_SEL,
I2C_BBPLL_OC_DLREF_SEL_MSB,
I2C_BBPLL_OC_DLREF_SEL_LSB,
oc_dlref_sel,
);
regi2c_write_mask(
I2C_BBPLL,
I2C_BBPLL_HOSTID,
I2C_BBPLL_OC_DLREF_SEL,
I2C_BBPLL_OC_DLREF_SEL_MSB,
I2C_BBPLL_OC_DLREF_SEL_LSB,
oc_dlref_sel as u8,
);
// WAIT CALIBRATION DONE
while I2C_ANA_MST::regs()
.ana_conf0()
.read()
.cal_done()
.bit_is_clear()
{}
// WAIT CALIBRATION DONE
while (i2c_mst_ana_conf0_reg_ptr.read_volatile() & I2C_MST_BBPLL_CAL_DONE) == 0 {}
// workaround bbpll calibration might stop early
crate::rom::ets_delay_us(10);
// BBPLL CALIBRATION STOP
i2c_mst_ana_conf0_reg_ptr.write_volatile(
i2c_mst_ana_conf0_reg_ptr.read_volatile() | I2C_MST_BBPLL_STOP_FORCE_HIGH,
);
i2c_mst_ana_conf0_reg_ptr.write_volatile(
i2c_mst_ana_conf0_reg_ptr.read_volatile() & !I2C_MST_BBPLL_STOP_FORCE_LOW,
);
}
// BBPLL CALIBRATION STOP
I2C_ANA_MST::regs().ana_conf0().modify(|_, w| {
w.bbpll_stop_force_high().set_bit();
w.bbpll_stop_force_low().clear_bit()
});
}
pub(crate) fn esp32h2_rtc_bbpll_enable() {
@ -151,21 +120,19 @@ pub(crate) fn esp32h2_rtc_bbpll_enable() {
.modify(|_, w| w.tie_high_global_bbpll_icg().set_bit());
}
pub(crate) fn esp32h2_rtc_update_to_xtal(freq: XtalClock, _div: u8) {
pub(crate) fn esp32h2_rtc_update_to_xtal(freq: XtalClock, div: u8) {
crate::rom::ets_update_cpu_frequency_rom(freq.mhz());
// Set divider from XTAL to APB clock. Need to set divider to 1 (reg. value 0)
// first.
clk_ll_ahb_set_divider(_div as u32);
clk_ll_ahb_set_divider(div as u32);
unsafe {
PCR::regs()
.cpu_freq_conf()
.modify(|_, w| w.cpu_div_num().bits(_div - 1));
// Switch clock source
PCR::regs()
.sysclk_conf()
.modify(|_, w| w.soc_clk_sel().bits(0));
}
PCR::regs()
.cpu_freq_conf()
.modify(|_, w| unsafe { w.cpu_div_num().bits(div - 1) });
// Switch clock source
PCR::regs()
.sysclk_conf()
.modify(|_, w| unsafe { w.soc_clk_sel().bits(0) });
clk_ll_bus_update();
}
@ -174,19 +141,16 @@ pub(crate) fn esp32h2_rtc_freq_to_pll_mhz(cpu_clock_speed: CpuClock) {
let cpu_divider = 96 / cpu_clock_speed.mhz();
clk_ll_cpu_set_divider(cpu_divider);
let ahb_divider = match cpu_divider {
1 => 3,
2 => 4,
1 | 2 => cpu_divider + 2,
_ => cpu_divider,
};
clk_ll_ahb_set_divider(ahb_divider);
unsafe {
PCR::regs()
.sysclk_conf()
.modify(|_, w| w.soc_clk_sel().bits(1));
PCR::regs()
.sysclk_conf()
.modify(|_, w| unsafe { w.soc_clk_sel().bits(1) });
clk_ll_bus_update();
}
clk_ll_bus_update();
crate::rom::ets_update_cpu_frequency_rom(cpu_clock_speed.mhz());
}
@ -203,21 +167,17 @@ pub(crate) fn esp32h2_rtc_apb_freq_update(apb_freq: ApbClock) {
fn clk_ll_cpu_set_divider(divider: u32) {
assert!(divider >= 1);
unsafe {
PCR::regs()
.cpu_freq_conf()
.modify(|_, w| w.cpu_div_num().bits((divider - 1) as u8));
}
PCR::regs()
.cpu_freq_conf()
.modify(|_, w| unsafe { w.cpu_div_num().bits((divider - 1) as u8) });
}
fn clk_ll_ahb_set_divider(divider: u32) {
assert!(divider >= 1);
unsafe {
PCR::regs()
.ahb_freq_conf()
.modify(|_, w| w.ahb_div_num().bits((divider - 1) as u8));
}
PCR::regs()
.ahb_freq_conf()
.modify(|_, w| unsafe { w.ahb_div_num().bits((divider - 1) as u8) });
}
fn clk_ll_bus_update() {
@ -234,95 +194,69 @@ fn clk_ll_bus_update() {
{}
}
fn regi2c_enable_block(block: u8) {
crate::peripherals::MODEM_LPCON::regs()
fn regi2c_enable_block(block: u8) -> usize {
MODEM_LPCON::regs()
.clk_conf()
.modify(|_, w| w.clk_i2c_mst_en().set_bit());
// Before config I2C register, enable corresponding slave.
let en_mask = match block {
v if v == REGI2C_BBPLL => REGI2C_BBPLL_RD_MASK,
v if v == REGI2C_BIAS => REGI2C_BIAS_RD_MASK,
v if v == REGI2C_PMU => REGI2C_DIG_REG_RD_MASK,
v if v == REGI2C_ULP_CAL => REGI2C_ULP_CAL_RD_MASK,
v if v == REGI2C_SAR_I2C => REGI2C_SAR_I2C_RD_MASK,
_ => return,
let i2c_sel_bits = I2C_ANA_MST::regs().ana_conf2().read();
let i2c_sel = match block {
v if v == REGI2C_BBPLL => i2c_sel_bits.bbpll_mst_sel().bit_is_set(),
v if v == REGI2C_BIAS => i2c_sel_bits.bias_mst_sel().bit_is_set(),
v if v == REGI2C_PMU => i2c_sel_bits.dig_reg_mst_sel().bit_is_set(),
v if v == REGI2C_ULP_CAL => i2c_sel_bits.ulp_cal_mst_sel().bit_is_set(),
v if v == REGI2C_SAR_I2C => i2c_sel_bits.sar_i2c_mst_sel().bit_is_set(),
_ => unreachable!(),
};
reg_set_bit(I2C_MST_ANA_CONF1_REG, en_mask)
}
I2C_ANA_MST::regs().ana_conf1().write(|w| unsafe {
w.bits(I2C_MST_ANA_CONF1_M);
match block {
v if v == REGI2C_BBPLL => w.bbpll_rd().clear_bit(),
v if v == REGI2C_BIAS => w.bias_rd().clear_bit(),
v if v == REGI2C_PMU => w.dig_reg_rd().clear_bit(),
v if v == REGI2C_ULP_CAL => w.ulp_cal_rd().clear_bit(),
v if v == REGI2C_SAR_I2C => w.sar_i2c_rd().clear_bit(),
_ => unreachable!(),
}
});
fn regi2c_disable_block(block: u8) {
let en_mask = match block {
v if v == REGI2C_BBPLL => REGI2C_BBPLL_RD_MASK,
v if v == REGI2C_BIAS => REGI2C_BIAS_RD_MASK,
v if v == REGI2C_PMU => REGI2C_DIG_REG_RD_MASK,
v if v == REGI2C_ULP_CAL => REGI2C_ULP_CAL_RD_MASK,
v if v == REGI2C_SAR_I2C => REGI2C_SAR_I2C_RD_MASK,
_ => return,
};
reg_clr_bit(I2C_MST_ANA_CONF1_REG, en_mask)
}
fn reg_set_bit(reg: u32, bit: u32) {
unsafe {
(reg as *mut u32).write_volatile((reg as *mut u32).read_volatile() | bit);
if i2c_sel {
0
} else {
1
}
}
fn reg_clr_bit(reg: u32, bit: u32) {
unsafe {
(reg as *mut u32).write_volatile((reg as *mut u32).read_volatile() & !bit);
}
}
fn reg_write(reg: u32, v: u32) {
unsafe {
(reg as *mut u32).write_volatile(v);
}
}
fn reg_get_bit(reg: u32, b: u32) -> u32 {
unsafe { (reg as *mut u32).read_volatile() & b }
}
fn reg_get_field(reg: u32, s: u32, v: u32) -> u32 {
unsafe { ((reg as *mut u32).read_volatile() >> s) & v }
}
pub(crate) fn regi2c_write_mask(block: u8, _host_id: u8, reg_add: u8, msb: u8, lsb: u8, data: u8) {
assert!(msb < 8 + lsb);
regi2c_enable_block(block);
let block_shifted = (block as u32 & REGI2C_RTC_SLAVE_ID_V as u32) << REGI2C_RTC_SLAVE_ID_S;
let reg_add_shifted = (reg_add as u32 & REGI2C_RTC_ADDR_V as u32) << REGI2C_RTC_ADDR_S;
let write_bit = 1u32 << REGI2C_RTC_WR_CNTL_S;
let master = regi2c_enable_block(block);
// Read the i2c bus register
while reg_get_bit(I2C_MST_I2C0_CTRL_REG, REGI2C_RTC_BUSY) != 0 {}
I2C_ANA_MST::regs().i2c_ctrl(master).write(|w| unsafe {
w.slave_addr().bits(block);
w.slave_reg_addr().bits(reg_add)
});
reg_write(I2C_MST_I2C0_CTRL_REG, block_shifted | reg_add_shifted);
while reg_get_bit(I2C_MST_I2C0_CTRL_REG, REGI2C_RTC_BUSY) != 0 {}
let mut temp = reg_get_field(
I2C_MST_I2C0_CTRL_REG,
REGI2C_RTC_DATA_S as u32,
REGI2C_RTC_DATA_V as u32,
);
while I2C_ANA_MST::regs().i2c_ctrl(master).read().busy().bit() {}
// Mask the value field
temp &= (!(0xFFFFFFFF << lsb)) | (0xFFFFFFFF << (msb + 1));
// Example: LSB=2, MSB = 5
// unwritten_bits = 1100 0011
// data_mask = 0000 1111
// data_bits = 00xx xx00
let unwritten_bits = (!(u32::MAX << lsb) | (u32::MAX << (msb + 1))) as u8;
let data_mask = !(u32::MAX << (msb - lsb + 1)) as u8;
let data_bits = (data & data_mask) << lsb;
// Write the value into the temporary
temp |= (data as u32 & (!(0xFFFFFFFF << (msb - lsb + 1)))) << lsb;
I2C_ANA_MST::regs().i2c_ctrl(master).modify(|r, w| unsafe {
w.slave_addr().bits(block);
w.slave_reg_addr().bits(reg_add);
w.read_write().set_bit();
w.data()
.bits((r.data().bits() & unwritten_bits) | data_bits)
});
let new_value = (temp & REGI2C_RTC_DATA_V as u32) << REGI2C_RTC_DATA_S;
reg_write(
I2C_MST_I2C0_CTRL_REG,
block_shifted | reg_add_shifted | write_bit | new_value,
);
while reg_get_bit(I2C_MST_I2C0_CTRL_REG, REGI2C_RTC_BUSY) != 0 {}
regi2c_disable_block(block);
while I2C_ANA_MST::regs().i2c_ctrl(master).read().busy().bit() {}
}
pub(super) fn enable_phy(en: bool) {
@ -365,29 +299,27 @@ pub(super) fn reset_mac() {
}
pub(super) fn init_clocks() {
unsafe {
let pmu = PMU::regs();
PMU::regs()
.hp_sleep_icg_modem()
.modify(|_, w| unsafe { w.hp_sleep_dig_icg_modem_code().bits(0) });
PMU::regs()
.hp_modem_icg_modem()
.modify(|_, w| unsafe { w.hp_modem_dig_icg_modem_code().bits(1) });
PMU::regs()
.hp_active_icg_modem()
.modify(|_, w| unsafe { w.hp_active_dig_icg_modem_code().bits(2) });
PMU::regs()
.imm_modem_icg()
.write(|w| w.update_dig_icg_modem_en().set_bit());
PMU::regs()
.imm_sleep_sysclk()
.write(|w| w.update_dig_icg_switch().set_bit());
pmu.hp_sleep_icg_modem()
.modify(|_, w| w.hp_sleep_dig_icg_modem_code().bits(0));
pmu.hp_modem_icg_modem()
.modify(|_, w| w.hp_modem_dig_icg_modem_code().bits(1));
pmu.hp_active_icg_modem()
.modify(|_, w| w.hp_active_dig_icg_modem_code().bits(2));
pmu.imm_modem_icg()
.write(|w| w.update_dig_icg_modem_en().set_bit());
pmu.imm_sleep_sysclk()
.write(|w| w.update_dig_icg_switch().set_bit());
MODEM_LPCON::regs().clk_conf().modify(|_, w| {
w.clk_i2c_mst_en()
.set_bit()
.clk_coex_en()
.set_bit()
.clk_fe_mem_en()
.set_bit()
});
}
MODEM_LPCON::regs().clk_conf().modify(|_, w| {
w.clk_i2c_mst_en().set_bit();
w.clk_coex_en().set_bit();
w.clk_fe_mem_en().set_bit()
});
}
pub(super) fn ble_rtc_clk_init() {

View File

@ -1,46 +1,44 @@
use crate::{clock::CpuClock, peripherals::SYSCON};
use crate::{
clock::CpuClock,
peripherals::{LPWR, SYSCON, SYSTEM},
};
const MHZ: u32 = 1000000;
const UINT16_MAX: u32 = 0xffff;
const RTC_CNTL_DBIAS_1V25: u32 = 7;
const RTC_CNTL_DBIAS_1V25: u8 = 7;
// when not running with 80MHz Flash frequency we could use RTC_CNTL_DBIAS_1V10
// for DIG_DBIAS_80M_160M - but RTC_CNTL_DBIAS_1V25 shouldn't hurt
const DIG_DBIAS_80M_160M: u32 = RTC_CNTL_DBIAS_1V25;
const DIG_DBIAS_240M: u32 = RTC_CNTL_DBIAS_1V25;
const DIG_DBIAS_80M_160M: u8 = RTC_CNTL_DBIAS_1V25;
const DIG_DBIAS_240M: u8 = RTC_CNTL_DBIAS_1V25;
pub(crate) fn set_cpu_clock(cpu_clock_speed: CpuClock) {
let system_control = crate::peripherals::SYSTEM::regs();
let rtc_cntl = crate::peripherals::LPWR::regs();
SYSTEM::regs()
.sysclk_conf()
.modify(|_, w| unsafe { w.soc_clk_sel().bits(1) });
SYSTEM::regs().cpu_per_conf().modify(|_, w| unsafe {
w.pll_freq_sel().set_bit();
w.cpuperiod_sel().bits(match cpu_clock_speed {
CpuClock::_80MHz => 0,
CpuClock::_160MHz => 1,
CpuClock::_240MHz => 2,
})
});
unsafe {
system_control
.sysclk_conf()
.modify(|_, w| w.soc_clk_sel().bits(1));
system_control.cpu_per_conf().modify(|_, w| {
w.pll_freq_sel()
.set_bit()
.cpuperiod_sel()
.bits(match cpu_clock_speed {
CpuClock::_80MHz => 0,
CpuClock::_160MHz => 1,
CpuClock::_240MHz => 2,
})
});
LPWR::regs().reg().modify(|_, w| unsafe {
w.dig_reg_dbias_wak().bits(match cpu_clock_speed {
CpuClock::_80MHz => DIG_DBIAS_80M_160M,
CpuClock::_160MHz => DIG_DBIAS_80M_160M,
CpuClock::_240MHz => DIG_DBIAS_240M,
})
});
rtc_cntl.reg().modify(|_, w| {
w.dig_reg_dbias_wak().bits(match cpu_clock_speed {
CpuClock::_80MHz => DIG_DBIAS_80M_160M,
CpuClock::_160MHz => DIG_DBIAS_80M_160M,
CpuClock::_240MHz => DIG_DBIAS_240M,
} as u8)
});
// FIXME untangle this
let value = (((80 * MHZ) >> 12) & UINT16_MAX) | ((((80 * MHZ) >> 12) & UINT16_MAX) << 16);
rtc_cntl.store5().modify(|_, w| w.scratch5().bits(value));
}
// FIXME untangle this
let value = (((80 * MHZ) >> 12) & UINT16_MAX) | ((((80 * MHZ) >> 12) & UINT16_MAX) << 16);
LPWR::regs()
.store5()
.modify(|_, w| unsafe { w.scratch5().bits(value) });
}
// Mask for clock bits used by both WIFI and Bluetooth, bit 0, 3, 6, 7, 8, 9
@ -72,13 +70,12 @@ pub(super) fn enable_wifi(enable: bool) {
}
pub(super) fn reset_mac() {
const SYSTEM_MAC_RST: u32 = 1 << 2;
SYSCON::regs()
.wifi_rst_en()
.modify(|r, w| unsafe { w.wifi_rst().bits(r.wifi_rst().bits() | SYSTEM_MAC_RST) });
.modify(|_, w| w.mac_rst().set_bit());
SYSCON::regs()
.wifi_rst_en()
.modify(|r, w| unsafe { w.wifi_rst().bits(r.wifi_rst().bits() & !SYSTEM_MAC_RST) });
.modify(|_, w| w.mac_rst().clear_bit());
}
pub(super) fn init_clocks() {

View File

@ -1,27 +1,21 @@
use crate::{
clock::{Clock, CpuClock},
peripherals::APB_CTRL,
peripherals::{APB_CTRL, SYSTEM},
rom,
};
pub(crate) fn set_cpu_clock(cpu_clock_speed: CpuClock) {
let system_control = crate::peripherals::SYSTEM::regs();
unsafe {
system_control
.sysclk_conf()
.modify(|_, w| w.soc_clk_sel().bits(1));
system_control.cpu_per_conf().modify(|_, w| {
w.pll_freq_sel()
.set_bit()
.cpuperiod_sel()
.bits(match cpu_clock_speed {
CpuClock::_80MHz => 0,
CpuClock::_160MHz => 1,
CpuClock::_240MHz => 2,
})
});
}
SYSTEM::regs()
.sysclk_conf()
.modify(|_, w| unsafe { w.soc_clk_sel().bits(1) });
SYSTEM::regs().cpu_per_conf().modify(|_, w| unsafe {
w.pll_freq_sel().set_bit();
w.cpuperiod_sel().bits(match cpu_clock_speed {
CpuClock::_80MHz => 0,
CpuClock::_160MHz => 1,
CpuClock::_240MHz => 2,
})
});
rom::ets_update_cpu_frequency_rom(cpu_clock_speed.frequency().as_mhz());
}
@ -57,13 +51,12 @@ pub(super) fn enable_wifi(_: bool) {
}
pub(super) fn reset_mac() {
const SYSTEM_MAC_RST: u32 = 1 << 2;
APB_CTRL::regs()
.wifi_rst_en()
.modify(|r, w| unsafe { w.bits(r.bits() | SYSTEM_MAC_RST) });
.modify(|_, w| w.mac_rst().set_bit());
APB_CTRL::regs()
.wifi_rst_en()
.modify(|r, w| unsafe { w.bits(r.bits() & !SYSTEM_MAC_RST) });
.modify(|_, w| w.mac_rst().clear_bit());
}
pub(super) fn init_clocks() {

View File

@ -35,6 +35,7 @@ crate::peripherals! {
EFUSE <= EFUSE,
EXTMEM <= EXTMEM,
GPIO <= GPIO,
I2C_ANA_MST <= I2C_ANA_MST,
INTERRUPT_CORE0 <= INTERRUPT_CORE0,
IO_MUX <= IO_MUX,
LEDC <= LEDC,

View File

@ -41,6 +41,7 @@ crate::peripherals! {
GPIO <= GPIO,
GPIO_SD <= GPIO_SD,
HMAC <= HMAC,
I2C_ANA_MST <= I2C_ANA_MST,
I2S0 <= I2S0 (I2S0),
INTERRUPT_CORE0 <= INTERRUPT_CORE0,
IO_MUX <= IO_MUX,

View File

@ -41,6 +41,7 @@ crate::peripherals! {
HMAC <= HMAC,
HP_APM <= HP_APM,
HP_SYS <= HP_SYS,
I2C_ANA_MST <= I2C_ANA_MST,
I2S0 <= I2S0 (I2S0),
IEEE802154 <= IEEE802154,
INTERRUPT_CORE0 <= INTERRUPT_CORE0,

View File

@ -39,6 +39,7 @@ crate::peripherals! {
HMAC <= HMAC,
HP_APM <= HP_APM,
HP_SYS <= HP_SYS,
I2C_ANA_MST <= I2C_ANA_MST,
I2S0 <= I2S0 (I2S0),
IEEE802154 <= IEEE802154,
INTERRUPT_CORE0 <= INTERRUPT_CORE0,