use super::Error;
use crate::prelude::*;
use crate::target::generic::Variant::Val;
const DELAY_PLL_ENABLE_WITH_150K: MicroSeconds = MicroSeconds(80);
const DELAY_PLL_ENABLE_WITH_32K: MicroSeconds = MicroSeconds(160);
const I2C_BLOCK: u8 = 0x66;
mod i2c {
pub const IR_CAL_DELAY: u8 = 0;
pub const IR_CAL_EXT_CAP: u8 = 1;
pub const OC_LREF: u8 = 2;
pub const OC_DIV_7_0: u8 = 3;
pub const OC_ENB_FCAL: u8 = 4;
pub const OC_DCUR: u8 = 5;
pub const BBADC_DSMP: u8 = 9;
pub const OC_ENB_VCON: u8 = 10;
pub const ENDIV5: u8 = 11;
pub const BBADC_CAL_7_0: u8 = 12;
}
mod val {
pub const ENDIV5_VAL_320M: u8 = 0x43;
pub const BBADC_DSMP_VAL_320M: u8 = 0x84;
pub const ENDIV5_VAL_480M: u8 = 0xc3;
pub const BBADC_DSMP_VAL_480M: u8 = 0x74;
pub const IR_CAL_DELAY_VAL: u8 = 0x18;
pub const IR_CAL_EXT_CAP_VAL: u8 = 0x20;
pub const OC_ENB_FCAL_VAL: u8 = 0x9a;
pub const OC_ENB_VCON_VAL: u8 = 0x00;
pub const BBADC_CAL_7_0_VAL: u8 = 0x00;
}
struct Config(u8, u8, u8, u8, u8, u8);
impl Config {
const PLL_320M_XTAL_40M: Config = Config(0, 32, 0, 0, 6, 3);
const PLL_320M_XTAL_26M: Config = Config(12, 224, 4, 1, 0, 1);
const PLL_320M_XTAL_24M: Config = Config(11, 224, 4, 1, 0, 1);
const PLL_480M_XTAL_40M: Config = Config(0, 28, 0, 0, 6, 3);
const PLL_480M_XTAL_26M: Config = Config(12, 144, 4, 1, 0, 1);
const PLL_480M_XTAL_24M: Config = Config(11, 144, 4, 1, 0, 1);
fn get_lref(&self) -> u8 {
(self.3 << 7) | (self.2 << 4) | self.0
}
fn get_div7_0(&self) -> u8 {
self.1
}
fn get_dcur(&self) -> u8 {
(self.5 << 6) | self.4
}
}
impl super::ClockControl {
fn write_i2c(&mut self, address: u8, data: u8) {
self.rtc_control.pll.write(|w| unsafe {
w.block()
.bits(I2C_BLOCK)
.addr()
.bits(address)
.data()
.bits(data)
.write()
.set_bit()
});
while self.rtc_control.pll.read().busy().bit_is_set() {}
}
fn _read_i2c(&mut self, address: u8) -> u8 {
self.rtc_control.pll.write(|w| unsafe {
w.block()
.bits(I2C_BLOCK)
.addr()
.bits(address)
.write()
.clear_bit()
});
while self.rtc_control.pll.read().busy().bit_is_set() {}
self.rtc_control.pll.read().data().bits()
}
pub(crate) fn pll_disable(&mut self) {
self.rtc_control.options0.modify(|_, w| {
w.bias_i2c_force_pd()
.bit(self.rtc_control.ana_conf.read().plla_force_pd().bit())
.bb_i2c_force_pd()
.set_bit()
.bbpll_force_pd()
.set_bit()
.bbpll_i2c_force_pd()
.set_bit()
});
self.pll_frequency = super::FREQ_OFF;
self.pll_d2_frequency = super::FREQ_OFF;
}
pub(crate) fn pll_enable(&mut self, high: bool) -> Result<(), Error> {
self.rtc_control.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()
});
self.write_i2c(i2c::IR_CAL_DELAY, val::IR_CAL_DELAY_VAL);
self.write_i2c(i2c::IR_CAL_EXT_CAP, val::IR_CAL_EXT_CAP_VAL);
self.write_i2c(i2c::OC_ENB_FCAL, val::OC_ENB_FCAL_VAL);
self.write_i2c(i2c::OC_ENB_VCON, val::OC_ENB_VCON_VAL);
self.write_i2c(i2c::BBADC_CAL_7_0, val::BBADC_CAL_7_0_VAL);
self.set_pll_frequency(high)
}
pub(crate) fn set_pll_frequency(&mut self, high: bool) -> Result<(), Error> {
let pll_config = match high {
false => {
self.pll_frequency = super::PLL_FREQ_320M;
self.pll_d2_frequency = self.pll_frequency / 2;
self.write_i2c(i2c::ENDIV5, val::ENDIV5_VAL_320M);
self.write_i2c(i2c::BBADC_DSMP, val::BBADC_DSMP_VAL_320M);
match self.xtal_frequency {
Hertz(40_000_000) => Config::PLL_320M_XTAL_40M,
Hertz(26_000_000) => Config::PLL_320M_XTAL_26M,
Hertz(24_000_000) => Config::PLL_320M_XTAL_24M,
_ => return Err(Error::UnsupportedPLLConfig),
}
}
true => {
self.pll_frequency = super::PLL_FREQ_480M;
self.pll_d2_frequency = self.pll_frequency / 2;
self.write_i2c(i2c::ENDIV5, val::ENDIV5_VAL_480M);
self.write_i2c(i2c::BBADC_DSMP, val::BBADC_DSMP_VAL_480M);
match self.xtal_frequency {
Hertz(40_000_000) => Config::PLL_480M_XTAL_40M,
Hertz(26_000_000) => Config::PLL_480M_XTAL_26M,
Hertz(24_000_000) => Config::PLL_480M_XTAL_24M,
_ => return Err(Error::UnsupportedPLLConfig),
}
}
};
self.write_i2c(i2c::OC_LREF, pll_config.get_lref());
self.write_i2c(i2c::OC_DIV_7_0, pll_config.get_div7_0());
self.write_i2c(i2c::OC_DCUR, pll_config.get_dcur());
let delay_us = if let Ok(super::SlowRTCSource::RTC150k) = self.slow_rtc_source() {
DELAY_PLL_ENABLE_WITH_150K
} else {
DELAY_PLL_ENABLE_WITH_32K
};
self.delay(delay_us);
Ok(())
}
pub fn pll_frequency(&self) -> Hertz {
if self.rtc_control.options0.read().bbpll_force_pd().bit() {
return super::FREQ_OFF;
}
match self
.dport_control
.cpu_per_conf()
.read()
.cpuperiod_sel()
.variant()
{
Val(super::CPUPERIOD_SEL_A::SEL_80) => super::PLL_FREQ_320M,
Val(super::CPUPERIOD_SEL_A::SEL_160) => super::PLL_FREQ_320M,
Val(super::CPUPERIOD_SEL_A::SEL_240) => super::PLL_FREQ_480M,
_ => super::FREQ_OFF,
}
}
}