diff --git a/src/gateware/kasli_soc.py b/src/gateware/kasli_soc.py index e12caab2..6f62d826 100755 --- a/src/gateware/kasli_soc.py +++ b/src/gateware/kasli_soc.py @@ -113,6 +113,9 @@ class GenericStandalone(SoCCore): platform.add_platform_command("create_clock -name clk_fpga_0 -period 8 [get_pins \"PS7/FCLKCLK[0]\"]") platform.add_platform_command("set_input_jitter clk_fpga_0 0.24") + self.rustc_cfg["HAS_SI5324"] = None + self.rustc_cfg["SI5324_SOFT_RESET"] = None + self.crg = self.ps7 # HACK for eem_7series to find the clock self.submodules.rtio_crg = RTIOCRG(self.platform) self.csr_devices.append("rtio_crg") diff --git a/src/libboard_artiq/src/si5324.rs b/src/libboard_artiq/src/si5324.rs index 5de0fdc0..c8a8a9a4 100644 --- a/src/libboard_artiq/src/si5324.rs +++ b/src/libboard_artiq/src/si5324.rs @@ -1,11 +1,22 @@ use core::result; use log::info; -use libboard_zynq::i2c::I2c; +use libboard_zynq::{i2c::I2c, timer::GlobalTimer, time::Milliseconds}; +use embedded_hal::blocking::delay::DelayUs; +#[cfg(not(si5324_soft_reset))] +use pl::csr; type Result = result::Result; const ADDRESS: u8 = 0x68; +#[cfg(not(si5324_soft_reset))] +fn hard_reset(timer: GlobalTimer) { + unsafe { csr::si5324_rst_n::out_write(0); } + timer.delay_us(1_000); + unsafe { csr::si5324_rst_n::out_write(1); } + timer.delay_us(10_000); +} + // NOTE: the logical parameters DO NOT MAP to physical values written // into registers. They have to be mapped; see the datasheet. // DSPLLsim reports the logical parameters in the design summary, not @@ -135,9 +146,10 @@ fn ident(i2c: &mut I2c) -> Result { Ok(((read(i2c, 134)? as u16) << 8) | (read(i2c, 135)? as u16)) } -fn soft_reset(_i2c: &mut I2c) -> Result<()> { - //TODO write_no_ack_value(i2c, 136, read(136)? | 0x80)?; - //TODO clock::spin_us(10_000); +#[cfg(si5324_soft_reset)] +fn soft_reset(i2c: &mut I2c, timer: GlobalTimer) -> Result<()> { + write_no_ack_value(i2c, 136, read(i2c, 136)? | 0x80)?; + timer.delay_us(10_000); Ok(()) } @@ -156,20 +168,23 @@ fn locked(i2c: &mut I2c) -> Result { Ok((read(i2c, 130)? & 0x01) == 0) // LOL_INT=0 } -fn monitor_lock(i2c: &mut I2c) -> Result<()> { +fn monitor_lock(i2c: &mut I2c, timer: GlobalTimer) -> Result<()> { info!("waiting for Si5324 lock..."); - // TODO let t = clock::get_ms(); + let timeout = timer.get_time() + Milliseconds(20_000); while !locked(i2c)? { // Yes, lock can be really slow. - /*if clock::get_ms() > t + 20000 { + if timer.get_time() > timeout { return Err("Si5324 lock timeout"); - }*/ + } } info!(" ...locked"); Ok(()) } -fn init(i2c: &mut I2c) -> Result<()> { +fn init(i2c: &mut I2c, timer: GlobalTimer) -> Result<()> { + #[cfg(not(si5324_soft_reset))] + hard_reset(timer); + #[cfg(feature = "target_kasli_soc")] { i2c.pca9548_select(0x70, 0)?; @@ -180,16 +195,17 @@ fn init(i2c: &mut I2c) -> Result<()> { return Err("Si5324 does not have expected product number"); } - soft_reset(i2c)?; + #[cfg(si5324_soft_reset)] + soft_reset(i2c, timer)?; Ok(()) } -pub fn bypass(i2c: &mut I2c, input: Input) -> Result<()> { +pub fn bypass(i2c: &mut I2c, input: Input, timer: GlobalTimer) -> Result<()> { let cksel_reg = match input { Input::Ckin1 => 0b00, Input::Ckin2 => 0b01, }; - init(i2c)?; + init(i2c, timer)?; rmw(i2c, 21, |v| v & 0xfe)?; // CKSEL_PIN=0 rmw(i2c, 3, |v| (v & 0x3f) | (cksel_reg << 6))?; // CKSEL_REG rmw(i2c, 4, |v| (v & 0x3f) | (0b00 << 6))?; // AUTOSEL_REG=b00 @@ -198,14 +214,14 @@ pub fn bypass(i2c: &mut I2c, input: Input) -> Result<()> { Ok(()) } -pub fn setup(i2c: &mut I2c, settings: &FrequencySettings, input: Input) -> Result<()> { +pub fn setup(i2c: &mut I2c, settings: &FrequencySettings, input: Input, timer: GlobalTimer) -> Result<()> { let s = map_frequency_settings(settings)?; let cksel_reg = match input { Input::Ckin1 => 0b00, Input::Ckin2 => 0b01, }; - init(i2c)?; + init(i2c, timer)?; if settings.crystal_ref { rmw(i2c, 0, |v| v | 0x40)?; // FREE_RUN=1 } @@ -240,11 +256,11 @@ pub fn setup(i2c: &mut I2c, settings: &FrequencySettings, input: Input) -> Resul return Err("Si5324 misses clock input signal"); } - monitor_lock(i2c)?; + monitor_lock(i2c, timer)?; Ok(()) } -pub fn select_input(i2c: &mut I2c, input: Input) -> Result<()> { +pub fn select_input(i2c: &mut I2c, input: Input, timer: GlobalTimer) -> Result<()> { let cksel_reg = match input { Input::Ckin1 => 0b00, Input::Ckin2 => 0b01, @@ -253,6 +269,6 @@ pub fn select_input(i2c: &mut I2c, input: Input) -> Result<()> { if !has_ckin(i2c, input)? { return Err("Si5324 misses clock input signal"); } - monitor_lock(i2c)?; + monitor_lock(i2c, timer)?; Ok(()) -} +} \ No newline at end of file diff --git a/src/runtime/src/main.rs b/src/runtime/src/main.rs index ac6bb65b..52a12227 100644 --- a/src/runtime/src/main.rs +++ b/src/runtime/src/main.rs @@ -23,7 +23,7 @@ use libconfig::Config; use libregister::RegisterW; use libcortex_a9::l2c::enable_l2_cache; use libboard_artiq::{logger, identifier_read}; -#[cfg(feature = "target_kasli_soc")] +#[cfg(has_si5324)] use libboard_artiq::si5324; mod proto_async; @@ -46,7 +46,6 @@ mod analyzer; mod irq; mod i2c; - fn init_gateware() { // Set up PS->PL clocks slcr::RegisterBlock::unlocked(|slcr| { @@ -148,7 +147,7 @@ async fn report_async_rtio_errors() { } } -#[cfg(feature = "target_kasli_soc")] +#[cfg(has_si5324)] // 125MHz output, from crystal, 7 Hz const SI5324_SETTINGS: si5324::FrequencySettings = si5324::FrequencySettings { @@ -185,9 +184,9 @@ pub fn main_core0() { info!("detected gateware: {}", identifier_read(&mut [0; 64])); i2c::init(); - #[cfg(feature = "target_kasli_soc")] + #[cfg(has_si5324)] si5324::setup(unsafe { (&mut i2c::I2C_BUS).as_mut().unwrap() }, - &SI5324_SETTINGS, si5324::Input::Ckin2).expect("cannot initialize Si5324"); + &SI5324_SETTINGS, si5324::Input::Ckin2, timer).expect("cannot initialize Si5324"); let cfg = match Config::new() { Ok(cfg) => cfg,