#![allow(dead_code, reason = "Some of this is bound to be unused")]
#![allow(missing_docs, reason = "Experimental")]
use esp_rom_sys::rom::{ets_delay_us, ets_update_cpu_frequency_rom};
use crate::{
peripherals::{I2C_ANA_MST, LPWR, RMT, SYSTEM, TIMG0, TIMG1, UART0, UART1, UART2},
soc::regi2c,
time::Rate,
};
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,
_240MHz = 240,
}
impl CpuClock {
const PRESET_80: ClockConfig = ClockConfig {
xtal_clk: None,
system_pre_div: None,
pll_clk: Some(PllClkConfig::_480),
cpu_pll_div_out: Some(CpuPllDivOutConfig::_80),
cpu_clk: Some(CpuClkConfig::Pll),
rc_fast_clk_div_n: Some(RcFastClkDivNConfig::new(0)),
rtc_slow_clk: Some(RtcSlowClkConfig::RcSlow),
rtc_fast_clk: Some(RtcFastClkConfig::Rc),
low_power_clk: Some(LowPowerClkConfig::RtcSlow),
timg_calibration_clock: None,
};
const PRESET_160: ClockConfig = ClockConfig {
xtal_clk: None,
system_pre_div: None,
pll_clk: Some(PllClkConfig::_480),
cpu_pll_div_out: Some(CpuPllDivOutConfig::_160),
cpu_clk: Some(CpuClkConfig::Pll),
rc_fast_clk_div_n: Some(RcFastClkDivNConfig::new(0)),
rtc_slow_clk: Some(RtcSlowClkConfig::RcSlow),
rtc_fast_clk: Some(RtcFastClkConfig::Rc),
low_power_clk: Some(LowPowerClkConfig::RtcSlow),
timg_calibration_clock: None,
};
const PRESET_240: ClockConfig = ClockConfig {
xtal_clk: None,
system_pre_div: None,
pll_clk: Some(PllClkConfig::_480),
cpu_pll_div_out: Some(CpuPllDivOutConfig::_240),
cpu_clk: Some(CpuClkConfig::Pll),
rc_fast_clk_div_n: Some(RcFastClkDivNConfig::new(0)),
rtc_slow_clk: Some(RtcSlowClkConfig::RcSlow),
rtc_fast_clk: Some(RtcFastClkConfig::Rc),
low_power_clk: Some(LowPowerClkConfig::RtcSlow),
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,
CpuClock::_240MHz => CpuClock::PRESET_240,
}
}
}
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),
v if v == CpuClock::PRESET_240 => Some(CpuClock::_240MHz),
_ => None,
}
}
pub(crate) fn configure(mut self) {
if self.xtal_clk.is_none() {
self.xtal_clk = Some(XtalClkConfig::_40);
}
ClockTree::with(|clocks| {
configure_xtal_clk(clocks, XtalClkConfig::_40);
configure_system_pre_div(clocks, SystemPreDivConfig::new(0));
configure_cpu_clk(clocks, CpuClkConfig::Xtal);
});
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) {
I2C_ANA_MST::regs()
.ana_config()
.modify(|_, w| w.bbpll_pd().bit(!en));
LPWR::regs().options0().modify(|_, w| {
let power_down = !en;
w.bb_i2c_force_pd().bit(power_down);
w.bbpll_force_pd().bit(power_down);
w.bbpll_i2c_force_pd().bit(power_down)
});
if !en {
return;
}
ensure_voltage_raised(clocks);
let pll_freq = unwrap!(clocks.pll_clk);
let xtal_freq = unwrap!(clocks.xtal_clk);
let div_ref: u8;
let div7_0: u8;
let dr1: u8;
let dr3: u8;
let dchgp: u8;
let dcur: u8;
let dbias = 3;
match pll_freq {
PllClkConfig::_480 => {
match xtal_freq {
XtalClkConfig::_40 => {
div_ref = 0;
div7_0 = 8;
dr1 = 0;
dr3 = 0;
dchgp = 5;
dcur = 3;
}
}
regi2c::I2C_BBPLL_REG4.write_reg(0x6b);
}
PllClkConfig::_320 => {
match xtal_freq {
XtalClkConfig::_40 => {
div_ref = 0;
div7_0 = 4;
dr1 = 0;
dr3 = 0;
dchgp = 5;
dcur = 3;
}
}
regi2c::I2C_BBPLL_REG4.write_reg(0x69);
}
}
const I2C_BBPLL_OC_DCHGP_LSB: u32 = 4;
const I2C_BBPLL_OC_DLREF_SEL_LSB: u32 = 6;
const I2C_BBPLL_OC_DHREF_SEL_LSB: u32 = 4;
let i2c_bbpll_lref = (dchgp << I2C_BBPLL_OC_DCHGP_LSB) | div_ref;
let i2c_bbpll_dcur =
(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(div7_0);
regi2c::I2C_BBPLL_OC_DR1.write_field(dr1);
regi2c::I2C_BBPLL_OC_DR3.write_field(dr3);
regi2c::I2C_BBPLL_REG6.write_reg(i2c_bbpll_dcur);
regi2c::I2C_BBPLL_OC_VCO_DBIAS.write_field(dbias);
I2C_ANA_MST::regs().ana_conf0().modify(|_, w| {
w.bbpll_stop_force_high().clear_bit();
w.bbpll_stop_force_low().set_bit()
});
while I2C_ANA_MST::regs()
.ana_conf0()
.read()
.bbpll_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()
});
ensure_voltage_minimal(clocks);
}
fn configure_pll_clk_impl(
_clocks: &mut ClockTree,
_old_config: Option<PllClkConfig>,
_config: PllClkConfig,
) {
}
fn enable_rc_fast_clk_impl(_clocks: &mut ClockTree, en: bool) {
const RTC_CNTL_FOSC_DFREQ_DEFAULT: u8 = 100;
LPWR::regs().clk_conf().modify(|_, w| {
unsafe { w.ck8m_dfreq().bits(RTC_CNTL_FOSC_DFREQ_DEFAULT) };
w.enb_ck8m().bit(!en);
w.dig_clk8m_en().bit(en); w.ck8m_force_pd().clear_bit();
w.ck8m_force_pu().clear_bit()
});
LPWR::regs()
.timer1()
.modify(|_, w| unsafe { w.ck8m_wait().bits(if en { 5 } else { 20 }) });
}
fn enable_xtal32k_clk_impl(_clocks: &mut ClockTree, en: bool) {
const CLK_LL_XTAL_32K_DAC_VAL: u8 = 3;
const CLK_LL_XTAL_32K_DRES_VAL: u8 = 3;
const CLK_LL_XTAL_32K_DGM_VAL: u8 = 3;
const CLK_LL_XTAL_32K_DBUF_VAL: bool = true; LPWR::regs().ext_xtl_conf().modify(|_, w| unsafe {
w.xtal32k_gpio_sel().bit(false);
w.dac_xtal_32k().bits(CLK_LL_XTAL_32K_DAC_VAL);
w.dres_xtal_32k().bits(CLK_LL_XTAL_32K_DRES_VAL);
w.dgm_xtal_32k().bits(CLK_LL_XTAL_32K_DGM_VAL);
w.dbuf_xtal_32k().bit(CLK_LL_XTAL_32K_DBUF_VAL);
w.xpd_xtal_32k().bit(en)
});
LPWR::regs()
.clk_conf()
.modify(|_, w| w.dig_xtal32k_en().bit(en));
}
fn enable_rc_slow_clk_impl(_clocks: &mut ClockTree, en: bool) {
if en {
const RTC_CNTL_SCK_DCAP_DEFAULT: u8 = 255;
LPWR::regs()
.rtc()
.modify(|_, w| unsafe { w.sck_dcap().bits(RTC_CNTL_SCK_DCAP_DEFAULT) });
let slow_clk_conf = LPWR::regs().slow_clk_conf();
let new_value = slow_clk_conf.modify(|_, w| w.ana_clk_div_vld().clear_bit());
let new_value = slow_clk_conf.write(|w| unsafe {
w.bits(new_value);
w.ana_clk_div().bits(0)
});
slow_clk_conf.write(|w| {
unsafe { w.bits(new_value) };
w.ana_clk_div_vld().set_bit()
});
}
}
fn enable_rc_fast_div_clk_impl(_clocks: &mut ClockTree, en: bool) {
LPWR::regs()
.clk_conf()
.modify(|_, w| w.enb_ck8m_div().bit(!en));
}
fn enable_system_pre_div_in_impl(_clocks: &mut ClockTree, _en: bool) {
}
fn configure_system_pre_div_in_impl(
_clocks: &mut ClockTree,
_old_config: Option<SystemPreDivInConfig>,
_new_config: SystemPreDivInConfig,
) {
}
fn enable_system_pre_div_impl(_clocks: &mut ClockTree, _en: bool) {
}
fn configure_system_pre_div_impl(
_clocks: &mut ClockTree,
_old_config: Option<SystemPreDivConfig>,
new_config: SystemPreDivConfig,
) {
SYSTEM::regs()
.sysclk_conf()
.modify(|_, w| unsafe { w.pre_div_cnt().bits(new_config.divisor() as u16 & 0x3FF) });
}
fn enable_cpu_pll_div_out_impl(_clocks: &mut ClockTree, _en: bool) {
}
fn configure_cpu_pll_div_out_impl(
_clocks: &mut ClockTree,
_old_config: Option<CpuPllDivOutConfig>,
_config: CpuPllDivOutConfig,
) {
}
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,
) {
}
fn enable_crypto_pwm_clk_impl(_clocks: &mut ClockTree, _en: bool) {
}
fn configure_crypto_pwm_clk_impl(
_clocks: &mut ClockTree,
_old_config: Option<CryptoPwmClkConfig>,
_new_config: CryptoPwmClkConfig,
) {
}
fn configure_cpu_clk_impl(
clocks: &mut ClockTree,
_old_config: Option<CpuClkConfig>,
new_config: CpuClkConfig,
) {
let clock_source_sel0_bit = match new_config {
CpuClkConfig::Xtal => 0,
CpuClkConfig::RcFast => 2,
CpuClkConfig::Pll => 1,
};
let clock_source_sel1_bit = clocks.pll_clk == Some(PllClkConfig::_480);
let clock_source_sel2_bit = match (clocks.pll_clk, clocks.cpu_pll_div_out) {
(Some(_), Some(CpuPllDivOutConfig::_80)) => 0,
(Some(_), Some(CpuPllDivOutConfig::_160)) => 1,
(Some(PllClkConfig::_480), Some(CpuPllDivOutConfig::_240)) => 2,
_ => 0,
};
ensure_voltage_raised(clocks);
if new_config == CpuClkConfig::Pll {
SYSTEM::regs().cpu_per_conf().modify(|_, w| {
unsafe { w.cpuperiod_sel().bits(clock_source_sel2_bit) };
w.pll_freq_sel().bit(clock_source_sel1_bit)
});
}
SYSTEM::regs().sysclk_conf().modify(|_, w| unsafe {
w.pre_div_cnt().bits(0);
w.soc_clk_sel().bits(clock_source_sel0_bit)
});
let cpu_freq = Rate::from_hz(cpu_clk_frequency(clocks));
ets_update_cpu_frequency_rom(cpu_freq.as_mhz());
ensure_voltage_minimal(clocks);
}
const RTC_CNTL_DBIAS_1V10: u8 = 4;
const RTC_CNTL_DBIAS_1V25: u8 = 7;
const V_RTC_MID_MUL10000: i32 = 10181;
const V_DIG_MID_MUL10000: i32 = 10841;
const K_RTC_MID_MUL10000: i32 = 198;
const K_DIG_MID_MUL10000: i32 = 211;
use crate::efuse;
const fn sign_extend(value: u8, bits: u8) -> i32 {
let sign_bit = 1 << (bits - 1);
let mask = !(sign_bit as u32 - 1);
if value & sign_bit != 0 {
(value as i32) | mask as i32
} else {
value as i32
}
}
fn dig_dbias_v1() -> u8 {
efuse::read_field_le(efuse::DIG_DBIAS_HVT)
}
fn rtc_dbias_v1(dig_dbias: u8) -> u8 {
let k_rtc_ldo = efuse::read_field_le::<u8>(efuse::K_RTC_LDO);
let k_dig_ldo = efuse::read_field_le::<u8>(efuse::K_DIG_LDO);
let v_rtc_bias20 = efuse::read_field_le::<u8>(efuse::V_RTC_DBIAS20);
let v_dig_bias20 = efuse::read_field_le::<u8>(efuse::V_DIG_DBIAS20);
let k_rtc_ldo = sign_extend(k_rtc_ldo, 7);
let k_dig_ldo = sign_extend(k_dig_ldo, 7);
let v_rtc_bias20 = sign_extend(v_rtc_bias20, 8);
let v_dig_bias20 = sign_extend(v_dig_bias20, 8);
let v_rtc_dbias20_real_mul10000 = V_RTC_MID_MUL10000 + v_rtc_bias20 * 10000 / 500;
let v_dig_dbias20_real_mul10000 = V_DIG_MID_MUL10000 + v_dig_bias20 * 10000 / 500;
let k_rtc_ldo_real_mul10000 = K_RTC_MID_MUL10000 + k_rtc_ldo;
let k_dig_ldo_real_mul10000 = K_DIG_MID_MUL10000 + k_dig_ldo;
let v_dig_nearest_1v15_mul10000 =
v_dig_dbias20_real_mul10000 + k_dig_ldo_real_mul10000 * (dig_dbias as i32 - 20);
search_nearest(
v_rtc_dbias20_real_mul10000,
k_rtc_ldo_real_mul10000,
v_dig_nearest_1v15_mul10000 - 250,
)
}
fn dig1v3_dbias_v1() -> u8 {
let k_dig_ldo = efuse::read_field_le::<u8>(efuse::K_DIG_LDO);
let v_dig_bias20 = efuse::read_field_le::<u8>(efuse::V_DIG_DBIAS20);
let k_dig_ldo = sign_extend(k_dig_ldo, 7);
let v_dig_bias20 = sign_extend(v_dig_bias20, 8);
let v_dig_dbias20_real_mul10000 = V_DIG_MID_MUL10000 + v_dig_bias20 * 10000 / 500;
let k_dig_ldo_real_mul10000 = K_DIG_MID_MUL10000 + k_dig_ldo;
search_nearest(v_dig_dbias20_real_mul10000, k_dig_ldo_real_mul10000, 13000)
}
fn search_nearest(v: i32, k: i32, max: i32) -> u8 {
for dbias in 15..31 {
let nearest = v + k * (dbias as i32 - 20);
if nearest >= max {
return dbias;
}
}
31
}
fn pvt_supported() -> bool {
let (blk_major, blk_minor) = efuse::block_version();
(blk_major == 0 && blk_minor == 1) || (blk_major == 1 && blk_minor >= 2) || blk_major > 1
}
fn ensure_voltage_raised(clocks: &mut ClockTree) {
let cpu_freq = cpu_clk_frequency(clocks);
let pd_slave = cpu_freq / 80_000_000;
if cpu_freq == 240_000_000 {
let mut rtc_dbias_pvt_240m = 28;
let mut dig_dbias_pvt_240m = 28;
if pvt_supported() {
let dig_dbias = dig_dbias_v1();
if dig_dbias != 0 {
let dig1v3_dbias = dig1v3_dbias_v1();
dig_dbias_pvt_240m = dig1v3_dbias.min(dig_dbias + 3);
rtc_dbias_pvt_240m = rtc_dbias_v1(dig_dbias_pvt_240m);
}
}
regi2c::I2C_DIG_REG_EXT_RTC_DREG.write_field(rtc_dbias_pvt_240m);
regi2c::I2C_DIG_REG_EXT_DIG_DREG.write_field(dig_dbias_pvt_240m);
ets_delay_us(40);
}
LPWR::regs()
.date()
.modify(|_, w| unsafe { w.ldo_slave().bits(0x7 >> pd_slave) });
}
fn ensure_voltage_minimal(clocks: &mut ClockTree) {
let cpu_freq = cpu_clk_frequency(clocks);
let pd_slave = cpu_freq / 80_000_000;
if cpu_freq < 240_000_000 {
let mut rtc_dbias_pvt_non_240m = 27;
let mut dig_dbias_pvt_non_240m = 27;
if pvt_supported() {
let dig_dbias = dig_dbias_v1();
if dig_dbias != 0 {
let dig1v3_dbias = dig1v3_dbias_v1();
dig_dbias_pvt_non_240m = dig1v3_dbias.min(dig_dbias + 2);
rtc_dbias_pvt_non_240m = rtc_dbias_v1(dig_dbias_pvt_non_240m);
}
}
regi2c::I2C_DIG_REG_EXT_RTC_DREG.write_field(rtc_dbias_pvt_non_240m);
regi2c::I2C_DIG_REG_EXT_DIG_DREG.write_field(dig_dbias_pvt_non_240m);
ets_delay_us(40);
}
LPWR::regs()
.date()
.modify(|_, w| unsafe { w.ldo_slave().bits(0x7 >> pd_slave) });
}
fn enable_pll_d2_impl(_clocks: &mut ClockTree, _en: bool) {
}
fn enable_pll_160m_impl(_clocks: &mut ClockTree, _en: bool) {
}
fn enable_apb_80m_impl(_clocks: &mut ClockTree, _en: bool) {
}
fn enable_rc_fast_clk_div_n_impl(_clocks: &mut ClockTree, _en: bool) {
}
fn configure_rc_fast_clk_div_n_impl(
_clocks: &mut ClockTree,
_old_config: Option<RcFastClkDivNConfig>,
new_config: RcFastClkDivNConfig,
) {
let clk_conf = LPWR::regs().clk_conf();
let new_value = clk_conf.modify(|_, w| w.ck8m_div_sel_vld().clear_bit());
let new_value = clk_conf.write(|w| unsafe {
w.bits(new_value);
w.ck8m_div_sel().bits(new_config.divisor() as u8)
});
clk_conf.write(|w| {
unsafe { w.bits(new_value) };
w.ck8m_div_sel_vld().set_bit()
});
}
fn enable_xtal_div_clk_impl(_clocks: &mut ClockTree, _en: bool) {
}
fn enable_rtc_slow_clk_impl(_clocks: &mut ClockTree, _en: bool) {
}
fn configure_rtc_slow_clk_impl(
_clocks: &mut ClockTree,
_old_config: Option<RtcSlowClkConfig>,
new_config: RtcSlowClkConfig,
) {
LPWR::regs().clk_conf().modify(|_, w| unsafe {
w.ana_clk_rtc_sel().bits(match new_config {
RtcSlowClkConfig::Xtal32k => 1,
RtcSlowClkConfig::RcSlow => 0,
RtcSlowClkConfig::RcFast => 2,
})
});
ets_delay_us(300);
}
fn enable_rtc_fast_clk_impl(_clocks: &mut ClockTree, _en: bool) {
}
fn configure_rtc_fast_clk_impl(
_clocks: &mut ClockTree,
_old_config: Option<RtcFastClkConfig>,
new_config: RtcFastClkConfig,
) {
LPWR::regs().clk_conf().modify(|_, w| match new_config {
RtcFastClkConfig::Xtal => w.fast_clk_rtc_sel().clear_bit(),
RtcFastClkConfig::Rc => w.fast_clk_rtc_sel().set_bit(),
});
ets_delay_us(3);
}
fn enable_low_power_clk_impl(_clocks: &mut ClockTree, _en: bool) {
}
fn configure_low_power_clk_impl(
_clocks: &mut ClockTree,
_old_config: Option<LowPowerClkConfig>,
new_config: LowPowerClkConfig,
) {
SYSTEM::regs().bt_lpck_div_frac().modify(|_, w| {
w.lpclk_sel_8m()
.bit(new_config == LowPowerClkConfig::RcFast);
w.lpclk_sel_rtc_slow()
.bit(new_config == LowPowerClkConfig::RtcSlow);
w.lpclk_sel_xtal()
.bit(new_config == LowPowerClkConfig::Xtal);
w.lpclk_sel_xtal32k()
.bit(new_config == LowPowerClkConfig::Xtal32k)
});
}
fn enable_uart_mem_clk_impl(_clocks: &mut ClockTree, en: bool) {
let regs = SYSTEM::regs();
if en {
regs.perip_rst_en0()
.modify(|_, w| w.uart_mem_rst().bit(true));
regs.perip_rst_en0()
.modify(|_, w| w.uart_mem_rst().bit(false));
}
regs.perip_clk_en0()
.modify(|_, w| w.uart_mem_clk_en().bit(en));
}
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) {
}
fn configure_function_clock_impl(
self,
_clocks: &mut ClockTree,
_old_config: Option<McpwmFunctionClockConfig>,
_new_config: McpwmFunctionClockConfig,
) {
}
}
impl RmtInstance {
fn enable_sclk_impl(self, _clocks: &mut ClockTree, en: bool) {
RMT::regs()
.sys_conf()
.modify(|_, w| w.sclk_active().bit(en));
}
fn configure_sclk_impl(
self,
_clocks: &mut ClockTree,
_old_config: Option<RmtSclkConfig>,
new_config: RmtSclkConfig,
) {
RMT::regs().sys_conf().modify(|_, w| unsafe {
w.clk_en().clear_bit();
w.sclk_sel().bits(match new_config {
RmtSclkConfig::ApbClk => 1,
RmtSclkConfig::RcFastClk => 2,
RmtSclkConfig::XtalClk => 3,
})
});
}
}
impl TimgInstance {
fn enable_function_clock_impl(self, _clocks: &mut ClockTree, en: bool) {
let regs = match self {
TimgInstance::Timg0 => TIMG0::regs(),
TimgInstance::Timg1 => TIMG1::regs(),
};
regs.regclk().modify(|_, w| w.clk_en().bit(en));
}
fn configure_function_clock_impl(
self,
_clocks: &mut ClockTree,
_old_config: Option<TimgFunctionClockConfig>,
new_config: TimgFunctionClockConfig,
) {
let regs = match self {
TimgInstance::Timg0 => TIMG0::regs(),
TimgInstance::Timg1 => TIMG1::regs(),
};
regs.t(0).config().modify(|_, w| {
w.use_xtal()
.bit(new_config == TimgFunctionClockConfig::XtalClk)
});
regs.t(1).config().modify(|_, w| {
w.use_xtal()
.bit(new_config == TimgFunctionClockConfig::XtalClk)
});
}
}
impl UartInstance {
fn enable_function_clock_impl(self, _clocks: &mut ClockTree, en: bool) {
let regs = match self {
UartInstance::Uart0 => UART0::regs(),
UartInstance::Uart1 => UART1::regs(),
UartInstance::Uart2 => UART2::regs(),
};
regs.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 regs = match self {
UartInstance::Uart0 => UART0::regs(),
UartInstance::Uart1 => UART1::regs(),
UartInstance::Uart2 => UART2::regs(),
};
regs.clk_conf().modify(|_, w| unsafe {
w.sclk_sel().bits(match new_config.sclk {
UartFunctionClockSclk::Apb => 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(),
UartInstance::Uart2 => UART2::regs(),
};
regs.clkdiv().write(|w| unsafe {
w.clkdiv().bits(new_config.integral as _);
w.frag().bits(new_config.fractional as _)
});
}
fn enable_mem_clock_impl(self, _clocks: &mut ClockTree, _en: bool) {
}
fn configure_mem_clock_impl(
self,
_clocks: &mut ClockTree,
_old_config: Option<UartMemClockConfig>,
_new_config: UartMemClockConfig,
) {
}
}