#![allow(dead_code, reason = "Some of this is bound to be unused")]
#![allow(missing_docs, reason = "Experimental")]
use crate::{
peripherals::{I2C_ANA_MST, LP_CLKRST, PCR, PMU, TIMG0, UART0, UART1},
soc::regi2c,
};
define_clock_tree_types!();
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[allow(
clippy::enum_variant_names,
reason = "MHz suffix indicates physical unit."
)]
#[non_exhaustive]
pub enum CpuClock {
#[default]
_80MHz = 80,
_160MHz = 160,
}
impl CpuClock {
const PRESET_80: ClockConfig = ClockConfig {
xtal_clk: None,
soc_root_clk: Some(SocRootClkConfig::Pll),
cpu_hs_div: Some(CpuHsDivConfig::new(CpuHsDivDivisor::_1)),
cpu_ls_div: None, ahb_hs_div: Some(AhbHsDivConfig::new(AhbHsDivDivisor::_3)),
ahb_ls_div: None, mspi_fast_hs_clk: Some(MspiFastHsClkConfig::new(MspiFastHsClkDivisor::_5)),
mspi_fast_ls_clk: None, apb_clk: Some(ApbClkConfig::new(ApbClkDivisor::_0)),
ledc_sclk: Some(LedcSclkConfig::PllF80m),
lp_fast_clk: Some(LpFastClkConfig::RcFastClk),
lp_slow_clk: Some(LpSlowClkConfig::RcSlow),
timg_calibration_clock: None,
};
const PRESET_160: ClockConfig = ClockConfig {
xtal_clk: None,
soc_root_clk: Some(SocRootClkConfig::Pll),
cpu_hs_div: Some(CpuHsDivConfig::new(CpuHsDivDivisor::_0)),
cpu_ls_div: None, ahb_hs_div: Some(AhbHsDivConfig::new(AhbHsDivDivisor::_3)),
ahb_ls_div: None, mspi_fast_hs_clk: Some(MspiFastHsClkConfig::new(MspiFastHsClkDivisor::_5)),
mspi_fast_ls_clk: None, apb_clk: Some(ApbClkConfig::new(ApbClkDivisor::_0)),
ledc_sclk: Some(LedcSclkConfig::PllF80m),
lp_fast_clk: Some(LpFastClkConfig::RcFastClk),
lp_slow_clk: Some(LpSlowClkConfig::RcSlow),
timg_calibration_clock: None,
};
}
impl From<CpuClock> for ClockConfig {
fn from(value: CpuClock) -> ClockConfig {
match value {
CpuClock::_80MHz => CpuClock::PRESET_80,
CpuClock::_160MHz => CpuClock::PRESET_160,
}
}
}
impl Default for ClockConfig {
fn default() -> Self {
Self::from(CpuClock::default())
}
}
impl ClockConfig {
pub(crate) fn try_get_preset(self) -> Option<CpuClock> {
match self {
v if v == CpuClock::PRESET_80 => Some(CpuClock::_80MHz),
v if v == CpuClock::PRESET_160 => Some(CpuClock::_160MHz),
_ => None,
}
}
pub(crate) fn configure(mut self) {
if self.xtal_clk.is_none() {
self.xtal_clk = Some(XtalClkConfig::_40);
}
ClockTree::with(|clocks| {
configure_mspi_fast_hs_clk(clocks, MspiFastHsClkConfig::new(MspiFastHsClkDivisor::_5))
});
self.apply();
}
}
fn configure_xtal_clk_impl(
_clocks: &mut ClockTree,
_old_config: Option<XtalClkConfig>,
_config: XtalClkConfig,
) {
}
fn enable_pll_clk_impl(_clocks: &mut ClockTree, en: bool) {
if en {
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::regs()
.imm_hp_ck_power()
.modify(|_, w| w.tie_high_global_bbpll_icg().set_bit());
} else {
PMU::regs()
.imm_hp_ck_power()
.modify(|_, w| w.tie_low_global_bbpll_icg().set_bit());
PMU::regs().imm_hp_ck_power().modify(|_, w| {
w.tie_low_xpd_bb_i2c().set_bit();
w.tie_low_xpd_bbpll().set_bit();
w.tie_low_xpd_bbpll_i2c().set_bit()
});
return;
}
I2C_ANA_MST::regs().ana_conf0().modify(|_, w| {
w.bbpll_stop_force_high().clear_bit();
w.bbpll_stop_force_low().set_bit()
});
const DIV_REF: u8 = 0; const DCHGP: u8 = 5;
const DCUR: u8 = 3;
const I2C_BBPLL_OC_DCHGP_LSB: u32 = 4;
const I2C_BBPLL_OC_DHREF_SEL_LSB: u32 = 4;
const I2C_BBPLL_OC_DLREF_SEL_LSB: u32 = 6;
const I2C_BBPLL_LREF: u8 = (DCHGP << I2C_BBPLL_OC_DCHGP_LSB) | DIV_REF;
const I2C_BBPLL_DCUR: u8 =
(1 << I2C_BBPLL_OC_DLREF_SEL_LSB) | (3 << I2C_BBPLL_OC_DHREF_SEL_LSB) | DCUR;
regi2c::I2C_BBPLL_OC_REF.write_reg(I2C_BBPLL_LREF);
regi2c::I2C_BBPLL_OC_DIV_REG.write_reg(8); regi2c::I2C_BBPLL_OC_DR1.write_field(0);
regi2c::I2C_BBPLL_OC_DR3.write_field(0);
regi2c::I2C_BBPLL_REG6.write_reg(I2C_BBPLL_DCUR);
regi2c::I2C_BBPLL_OC_VCO_DBIAS.write_field(2);
while I2C_ANA_MST::regs()
.ana_conf0()
.read()
.cal_done()
.bit_is_clear()
{}
crate::rom::ets_delay_us(10);
I2C_ANA_MST::regs().ana_conf0().modify(|_, w| {
w.bbpll_stop_force_high().set_bit();
w.bbpll_stop_force_low().clear_bit()
});
}
fn enable_rc_fast_clk_impl(_clocks: &mut ClockTree, en: bool) {
PMU::regs()
.hp_sleep_lp_ck_power()
.modify(|_, w| w.hp_sleep_xpd_fosc_clk().bit(en));
LP_CLKRST::regs()
.clk_to_hp()
.modify(|_, w| w.icg_hp_fosc().bit(en));
crate::rom::ets_delay_us(5);
}
fn enable_xtal32k_clk_impl(_clocks: &mut ClockTree, en: bool) {
LP_CLKRST::regs().xtal32k().write(|w| unsafe {
w.dac_xtal32k().bits(3);
w.dres_xtal32k().bits(3);
w.dgm_xtal32k().bits(3);
w.dbuf_xtal32k().bit(true)
});
PMU::regs()
.hp_sleep_lp_ck_power()
.modify(|_, w| w.hp_sleep_xpd_xtal32k().bit(en));
LP_CLKRST::regs()
.clk_to_hp()
.modify(|_, w| w.icg_hp_xtal32k().bit(en));
}
fn enable_osc_slow_clk_impl(_clocks: &mut ClockTree, _en: bool) {
todo!();
}
fn enable_rc_slow_clk_impl(_clocks: &mut ClockTree, en: bool) {
if en {
const RTC_CNTL_SCK_DCAP_DEFAULT: u8 = 128;
crate::soc::regi2c::I2C_DIG_REG_SCK_DCAP.write_reg(RTC_CNTL_SCK_DCAP_DEFAULT);
}
PMU::regs()
.hp_sleep_lp_ck_power()
.modify(|_, w| w.hp_sleep_xpd_rc32k().bit(en));
LP_CLKRST::regs()
.clk_to_hp()
.modify(|_, w| w.icg_hp_osc32k().bit(en));
}
fn enable_hp_root_clk_impl(_clocks: &mut ClockTree, _en: bool) {
}
fn configure_hp_root_clk_impl(
_clocks: &mut ClockTree,
_old_config: Option<HpRootClkConfig>,
_new_config: HpRootClkConfig,
) {
}
fn configure_cpu_clk_impl(
_clocks: &mut ClockTree,
_old_config: Option<CpuClkConfig>,
_new_config: CpuClkConfig,
) {
}
fn configure_ahb_clk_impl(
_clocks: &mut ClockTree,
_old_config: Option<AhbClkConfig>,
_new_config: AhbClkConfig,
) {
}
fn enable_mspi_fast_clk_impl(_clocks: &mut ClockTree, _en: bool) {
}
fn configure_mspi_fast_clk_impl(
_clocks: &mut ClockTree,
_old_config: Option<MspiFastClkConfig>,
_new_config: MspiFastClkConfig,
) {
}
fn enable_soc_root_clk_impl(_clocks: &mut ClockTree, _en: bool) {
}
fn configure_soc_root_clk_impl(
_clocks: &mut ClockTree,
_old_config: Option<SocRootClkConfig>,
new_config: SocRootClkConfig,
) {
PCR::regs().sysclk_conf().modify(|_, w| unsafe {
w.soc_clk_sel().bits(match new_config {
SocRootClkConfig::Xtal => 0,
SocRootClkConfig::Pll => 1,
SocRootClkConfig::RcFast => 2,
})
});
}
fn enable_cpu_hs_div_impl(_clocks: &mut ClockTree, _en: bool) {
}
fn configure_cpu_hs_div_impl(
_clocks: &mut ClockTree,
_old_config: Option<CpuHsDivConfig>,
new_config: CpuHsDivConfig,
) {
PCR::regs()
.cpu_freq_conf()
.modify(|_, w| unsafe { w.cpu_hs_div_num().bits(new_config.divisor() as u8) });
}
fn enable_cpu_ls_div_impl(_clocks: &mut ClockTree, _en: bool) {
}
fn configure_cpu_ls_div_impl(
_clocks: &mut ClockTree,
_old_config: Option<CpuLsDivConfig>,
new_config: CpuLsDivConfig,
) {
PCR::regs()
.cpu_freq_conf()
.modify(|_, w| unsafe { w.cpu_ls_div_num().bits(new_config.divisor() as u8) });
}
fn enable_ahb_hs_div_impl(_clocks: &mut ClockTree, _en: bool) {
}
fn configure_ahb_hs_div_impl(
_clocks: &mut ClockTree,
_old_config: Option<AhbHsDivConfig>,
new_config: AhbHsDivConfig,
) {
PCR::regs()
.ahb_freq_conf()
.modify(|_, w| unsafe { w.ahb_hs_div_num().bits(new_config.divisor() as u8) });
}
fn enable_ahb_ls_div_impl(_clocks: &mut ClockTree, _en: bool) {
}
fn configure_ahb_ls_div_impl(
_clocks: &mut ClockTree,
_old_config: Option<AhbLsDivConfig>,
new_config: AhbLsDivConfig,
) {
PCR::regs()
.ahb_freq_conf()
.modify(|_, w| unsafe { w.ahb_ls_div_num().bits(new_config.divisor() as u8) });
}
fn enable_apb_clk_impl(_clocks: &mut ClockTree, _en: bool) {
}
fn configure_apb_clk_impl(
_clocks: &mut ClockTree,
_old_config: Option<ApbClkConfig>,
new_config: ApbClkConfig,
) {
PCR::regs()
.apb_freq_conf()
.modify(|_, w| unsafe { w.apb_div_num().bits(new_config.divisor() as u8) });
}
fn enable_mspi_fast_hs_clk_impl(_clocks: &mut ClockTree, _en: bool) {
}
fn configure_mspi_fast_hs_clk_impl(
_clocks: &mut ClockTree,
_old_config: Option<MspiFastHsClkConfig>,
new_config: MspiFastHsClkConfig,
) {
PCR::regs()
.mspi_clk_conf()
.modify(|_, w| unsafe { w.mspi_fast_hs_div_num().bits(new_config.divisor() as u8) });
}
fn enable_mspi_fast_ls_clk_impl(_clocks: &mut ClockTree, _en: bool) {
}
fn configure_mspi_fast_ls_clk_impl(
_clocks: &mut ClockTree,
_old_config: Option<MspiFastLsClkConfig>,
new_config: MspiFastLsClkConfig,
) {
PCR::regs()
.mspi_clk_conf()
.modify(|_, w| unsafe { w.mspi_fast_ls_div_num().bits(new_config.divisor() as u8) });
}
fn enable_pll_f48m_impl(_clocks: &mut ClockTree, _en: bool) {
}
fn enable_pll_f80m_impl(_clocks: &mut ClockTree, _en: bool) {
}
fn enable_pll_f160m_impl(_clocks: &mut ClockTree, _en: bool) {
}
fn enable_pll_f240m_impl(_clocks: &mut ClockTree, _en: bool) {
}
fn enable_ledc_sclk_impl(_clocks: &mut ClockTree, en: bool) {
PCR::regs()
.ledc_sclk_conf()
.modify(|_, w| w.ledc_sclk_en().bit(en));
}
fn configure_ledc_sclk_impl(
_clocks: &mut ClockTree,
_old_config: Option<LedcSclkConfig>,
new_config: LedcSclkConfig,
) {
PCR::regs().ledc_sclk_conf().modify(|_, w| unsafe {
w.ledc_sclk_sel().bits(match new_config {
LedcSclkConfig::PllF80m => 1,
LedcSclkConfig::RcFastClk => 2,
LedcSclkConfig::XtalClk => 3,
})
});
}
fn enable_xtal_d2_clk_impl(_clocks: &mut ClockTree, _en: bool) {
}
fn enable_lp_fast_clk_impl(_clocks: &mut ClockTree, _en: bool) {
}
fn configure_lp_fast_clk_impl(
_clocks: &mut ClockTree,
_old_config: Option<LpFastClkConfig>,
new_config: LpFastClkConfig,
) {
LP_CLKRST::regs().lp_clk_conf().modify(|_, w| {
w.fast_clk_sel().bit(match new_config {
LpFastClkConfig::RcFastClk => false,
LpFastClkConfig::XtalD2Clk => true,
})
});
}
fn enable_lp_slow_clk_impl(_clocks: &mut ClockTree, _en: bool) {
}
fn configure_lp_slow_clk_impl(
_clocks: &mut ClockTree,
_old_config: Option<LpSlowClkConfig>,
new_config: LpSlowClkConfig,
) {
LP_CLKRST::regs().lp_clk_conf().modify(|_, w| unsafe {
w.slow_clk_sel().bits(match new_config {
LpSlowClkConfig::Xtal32k => 1,
LpSlowClkConfig::RcSlow => 0,
LpSlowClkConfig::OscSlow => 2,
})
});
}
fn enable_timg_calibration_clock_impl(_clocks: &mut ClockTree, _en: bool) {
}
fn configure_timg_calibration_clock_impl(
_clocks: &mut ClockTree,
_old_config: Option<TimgCalibrationClockConfig>,
new_config: TimgCalibrationClockConfig,
) {
TIMG0::regs().rtccalicfg().modify(|_, w| unsafe {
w.rtc_cali_clk_sel().bits(match new_config {
TimgCalibrationClockConfig::RcSlowClk => 0,
TimgCalibrationClockConfig::RcFastDivClk => 1,
TimgCalibrationClockConfig::Xtal32kClk => 2,
})
});
}
impl McpwmInstance {
fn enable_function_clock_impl(self, _clocks: &mut ClockTree, en: bool) {
PCR::regs()
.pwm_clk_conf()
.modify(|_, w| w.pwm_clkm_en().bit(en));
}
fn configure_function_clock_impl(
self,
_clocks: &mut ClockTree,
_old_config: Option<McpwmFunctionClockConfig>,
new_config: McpwmFunctionClockConfig,
) {
PCR::regs().pwm_clk_conf().modify(|_, w| unsafe {
w.pwm_clkm_sel().bits(match new_config {
McpwmFunctionClockConfig::PllF160m => 1,
McpwmFunctionClockConfig::XtalClk => 2,
McpwmFunctionClockConfig::RcFastClk => 3,
})
});
}
}
impl ParlIoInstance {
fn enable_rx_clock_impl(self, _clocks: &mut ClockTree, en: bool) {
PCR::regs()
.parl_clk_rx_conf()
.modify(|_, w| w.parl_clk_rx_en().bit(en));
}
fn configure_rx_clock_impl(
self,
_clocks: &mut ClockTree,
_old_config: Option<ParlIoRxClockConfig>,
new_config: ParlIoRxClockConfig,
) {
PCR::regs().parl_clk_rx_conf().modify(|_, w| unsafe {
w.parl_clk_rx_sel().bits(match new_config {
ParlIoRxClockConfig::XtalClk => 0,
ParlIoRxClockConfig::RcFastClk => 2,
ParlIoRxClockConfig::PllF240m => 1,
})
});
}
fn enable_tx_clock_impl(self, _clocks: &mut ClockTree, en: bool) {
PCR::regs()
.parl_clk_tx_conf()
.modify(|_, w| w.parl_clk_tx_en().bit(en));
}
fn configure_tx_clock_impl(
self,
_clocks: &mut ClockTree,
_old_config: Option<ParlIoTxClockConfig>,
new_config: ParlIoTxClockConfig,
) {
PCR::regs().parl_clk_tx_conf().modify(|_, w| unsafe {
w.parl_clk_tx_sel().bits(match new_config {
ParlIoTxClockConfig::XtalClk => 0,
ParlIoTxClockConfig::RcFastClk => 2,
ParlIoTxClockConfig::PllF240m => 1,
})
});
}
}
impl RmtInstance {
fn enable_sclk_impl(self, _clocks: &mut ClockTree, en: bool) {
PCR::regs()
.rmt_sclk_conf()
.modify(|_, w| w.sclk_en().bit(en));
}
fn configure_sclk_impl(
self,
_clocks: &mut ClockTree,
_old_config: Option<RmtSclkConfig>,
new_config: RmtSclkConfig,
) {
PCR::regs().rmt_sclk_conf().modify(|_, w| unsafe {
w.sclk_sel().bits(match new_config {
RmtSclkConfig::PllF80m => 1,
RmtSclkConfig::RcFastClk => 2,
RmtSclkConfig::XtalClk => 3,
})
});
}
}
impl TimgInstance {
fn enable_function_clock_impl(self, _clocks: &mut ClockTree, en: bool) {
let timg = match self {
TimgInstance::Timg0 => 0,
TimgInstance::Timg1 => 1,
};
PCR::regs()
.timergroup(timg)
.timer_clk_conf()
.modify(|_, w| w.timer_clk_en().bit(en));
}
fn configure_function_clock_impl(
self,
_clocks: &mut ClockTree,
_old_config: Option<TimgFunctionClockConfig>,
new_config: TimgFunctionClockConfig,
) {
let timg = match self {
TimgInstance::Timg0 => 0,
TimgInstance::Timg1 => 1,
};
PCR::regs()
.timergroup(timg)
.timer_clk_conf()
.modify(|_, w| unsafe {
w.timer_clk_sel().bits(match new_config {
TimgFunctionClockConfig::XtalClk => 0,
TimgFunctionClockConfig::RcFastClk => 2,
TimgFunctionClockConfig::PllF80m => 1,
})
});
}
fn enable_wdt_clock_impl(self, _clocks: &mut ClockTree, en: bool) {
let timg = match self {
TimgInstance::Timg0 => 0,
TimgInstance::Timg1 => 1,
};
PCR::regs()
.timergroup(timg)
.wdt_clk_conf()
.modify(|_, w| w.wdt_clk_en().bit(en));
}
fn configure_wdt_clock_impl(
self,
_clocks: &mut ClockTree,
_old_config: Option<TimgWdtClockConfig>,
new_config: TimgWdtClockConfig,
) {
let timg = match self {
TimgInstance::Timg0 => 0,
TimgInstance::Timg1 => 1,
};
PCR::regs()
.timergroup(timg)
.wdt_clk_conf()
.modify(|_, w| unsafe {
w.wdt_clk_sel().bits(match new_config {
TimgWdtClockConfig::XtalClk => 0,
TimgWdtClockConfig::PllF80m => 1,
TimgWdtClockConfig::RcFastClk => 2,
})
});
}
}
impl UartInstance {
fn enable_function_clock_impl(self, _clocks: &mut ClockTree, en: bool) {
let uart = match self {
UartInstance::Uart0 => 0,
UartInstance::Uart1 => 1,
};
PCR::regs()
.uart(uart)
.clk_conf()
.modify(|_, w| w.sclk_en().bit(en));
}
fn configure_function_clock_impl(
self,
_clocks: &mut ClockTree,
_old_config: Option<UartFunctionClockConfig>,
new_config: UartFunctionClockConfig,
) {
let uart = match self {
UartInstance::Uart0 => 0,
UartInstance::Uart1 => 1,
};
PCR::regs().uart(uart).clk_conf().modify(|_, w| unsafe {
w.sclk_sel().bits(match new_config.sclk {
UartFunctionClockSclk::PllF80m => 1,
UartFunctionClockSclk::RcFast => 2,
UartFunctionClockSclk::Xtal => 3,
});
w.sclk_div_a().bits(0);
w.sclk_div_b().bits(0);
w.sclk_div_num().bits(new_config.div_num as _);
w
});
}
fn enable_baud_rate_generator_impl(self, _clocks: &mut ClockTree, _en: bool) {
}
fn configure_baud_rate_generator_impl(
self,
_clocks: &mut ClockTree,
_old_config: Option<UartBaudRateGeneratorConfig>,
new_config: UartBaudRateGeneratorConfig,
) {
let regs = match self {
UartInstance::Uart0 => UART0::regs(),
UartInstance::Uart1 => UART1::regs(),
};
regs.clkdiv().write(|w| unsafe {
w.clkdiv().bits(new_config.integral as _);
w.frag().bits(new_config.fractional as _)
});
}
}