forked from M-Labs/artiq-zynq
Merge branch 'master' into drtio_port
This commit is contained in:
commit
b95692548e
@ -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("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")
|
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.crg = self.ps7 # HACK for eem_7series to find the clock
|
||||||
self.submodules.rtio_crg = RTIOCRG(self.platform)
|
self.submodules.rtio_crg = RTIOCRG(self.platform)
|
||||||
self.csr_devices.append("rtio_crg")
|
self.csr_devices.append("rtio_crg")
|
||||||
|
@ -1,11 +1,22 @@
|
|||||||
use core::result;
|
use core::result;
|
||||||
use log::info;
|
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<T> = result::Result<T, &'static str>;
|
type Result<T> = result::Result<T, &'static str>;
|
||||||
|
|
||||||
const ADDRESS: u8 = 0x68;
|
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
|
// NOTE: the logical parameters DO NOT MAP to physical values written
|
||||||
// into registers. They have to be mapped; see the datasheet.
|
// into registers. They have to be mapped; see the datasheet.
|
||||||
// DSPLLsim reports the logical parameters in the design summary, not
|
// DSPLLsim reports the logical parameters in the design summary, not
|
||||||
@ -135,9 +146,10 @@ fn ident(i2c: &mut I2c) -> Result<u16> {
|
|||||||
Ok(((read(i2c, 134)? as u16) << 8) | (read(i2c, 135)? as u16))
|
Ok(((read(i2c, 134)? as u16) << 8) | (read(i2c, 135)? as u16))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn soft_reset(_i2c: &mut I2c) -> Result<()> {
|
#[cfg(si5324_soft_reset)]
|
||||||
//TODO write_no_ack_value(i2c, 136, read(136)? | 0x80)?;
|
fn soft_reset(i2c: &mut I2c, timer: GlobalTimer) -> Result<()> {
|
||||||
//TODO clock::spin_us(10_000);
|
write_no_ack_value(i2c, 136, read(i2c, 136)? | 0x80)?;
|
||||||
|
timer.delay_us(10_000);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,20 +168,23 @@ fn locked(i2c: &mut I2c) -> Result<bool> {
|
|||||||
Ok((read(i2c, 130)? & 0x01) == 0) // LOL_INT=0
|
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...");
|
info!("waiting for Si5324 lock...");
|
||||||
// TODO let t = clock::get_ms();
|
let timeout = timer.get_time() + Milliseconds(20_000);
|
||||||
while !locked(i2c)? {
|
while !locked(i2c)? {
|
||||||
// Yes, lock can be really slow.
|
// Yes, lock can be really slow.
|
||||||
/*if clock::get_ms() > t + 20000 {
|
if timer.get_time() > timeout {
|
||||||
return Err("Si5324 lock timeout");
|
return Err("Si5324 lock timeout");
|
||||||
}*/
|
}
|
||||||
}
|
}
|
||||||
info!(" ...locked");
|
info!(" ...locked");
|
||||||
Ok(())
|
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")]
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
{
|
{
|
||||||
i2c.pca9548_select(0x70, 0)?;
|
i2c.pca9548_select(0x70, 0)?;
|
||||||
@ -180,16 +195,17 @@ fn init(i2c: &mut I2c) -> Result<()> {
|
|||||||
return Err("Si5324 does not have expected product number");
|
return Err("Si5324 does not have expected product number");
|
||||||
}
|
}
|
||||||
|
|
||||||
soft_reset(i2c)?;
|
#[cfg(si5324_soft_reset)]
|
||||||
|
soft_reset(i2c, timer)?;
|
||||||
Ok(())
|
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 {
|
let cksel_reg = match input {
|
||||||
Input::Ckin1 => 0b00,
|
Input::Ckin1 => 0b00,
|
||||||
Input::Ckin2 => 0b01,
|
Input::Ckin2 => 0b01,
|
||||||
};
|
};
|
||||||
init(i2c)?;
|
init(i2c, timer)?;
|
||||||
rmw(i2c, 21, |v| v & 0xfe)?; // CKSEL_PIN=0
|
rmw(i2c, 21, |v| v & 0xfe)?; // CKSEL_PIN=0
|
||||||
rmw(i2c, 3, |v| (v & 0x3f) | (cksel_reg << 6))?; // CKSEL_REG
|
rmw(i2c, 3, |v| (v & 0x3f) | (cksel_reg << 6))?; // CKSEL_REG
|
||||||
rmw(i2c, 4, |v| (v & 0x3f) | (0b00 << 6))?; // AUTOSEL_REG=b00
|
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(())
|
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 s = map_frequency_settings(settings)?;
|
||||||
let cksel_reg = match input {
|
let cksel_reg = match input {
|
||||||
Input::Ckin1 => 0b00,
|
Input::Ckin1 => 0b00,
|
||||||
Input::Ckin2 => 0b01,
|
Input::Ckin2 => 0b01,
|
||||||
};
|
};
|
||||||
|
|
||||||
init(i2c)?;
|
init(i2c, timer)?;
|
||||||
if settings.crystal_ref {
|
if settings.crystal_ref {
|
||||||
rmw(i2c, 0, |v| v | 0x40)?; // FREE_RUN=1
|
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");
|
return Err("Si5324 misses clock input signal");
|
||||||
}
|
}
|
||||||
|
|
||||||
monitor_lock(i2c)?;
|
monitor_lock(i2c, timer)?;
|
||||||
Ok(())
|
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 {
|
let cksel_reg = match input {
|
||||||
Input::Ckin1 => 0b00,
|
Input::Ckin1 => 0b00,
|
||||||
Input::Ckin2 => 0b01,
|
Input::Ckin2 => 0b01,
|
||||||
@ -253,6 +269,6 @@ pub fn select_input(i2c: &mut I2c, input: Input) -> Result<()> {
|
|||||||
if !has_ckin(i2c, input)? {
|
if !has_ckin(i2c, input)? {
|
||||||
return Err("Si5324 misses clock input signal");
|
return Err("Si5324 misses clock input signal");
|
||||||
}
|
}
|
||||||
monitor_lock(i2c)?;
|
monitor_lock(i2c, timer)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
@ -23,7 +23,7 @@ use libconfig::Config;
|
|||||||
use libregister::RegisterW;
|
use libregister::RegisterW;
|
||||||
use libcortex_a9::l2c::enable_l2_cache;
|
use libcortex_a9::l2c::enable_l2_cache;
|
||||||
use libboard_artiq::{logger, identifier_read};
|
use libboard_artiq::{logger, identifier_read};
|
||||||
#[cfg(feature = "target_kasli_soc")]
|
#[cfg(has_si5324)]
|
||||||
use libboard_artiq::si5324;
|
use libboard_artiq::si5324;
|
||||||
|
|
||||||
mod proto_async;
|
mod proto_async;
|
||||||
@ -46,7 +46,6 @@ mod analyzer;
|
|||||||
mod irq;
|
mod irq;
|
||||||
mod i2c;
|
mod i2c;
|
||||||
|
|
||||||
|
|
||||||
fn init_gateware() {
|
fn init_gateware() {
|
||||||
// Set up PS->PL clocks
|
// Set up PS->PL clocks
|
||||||
slcr::RegisterBlock::unlocked(|slcr| {
|
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
|
// 125MHz output, from crystal, 7 Hz
|
||||||
const SI5324_SETTINGS: si5324::FrequencySettings
|
const SI5324_SETTINGS: si5324::FrequencySettings
|
||||||
= si5324::FrequencySettings {
|
= si5324::FrequencySettings {
|
||||||
@ -185,9 +184,9 @@ pub fn main_core0() {
|
|||||||
info!("detected gateware: {}", identifier_read(&mut [0; 64]));
|
info!("detected gateware: {}", identifier_read(&mut [0; 64]));
|
||||||
|
|
||||||
i2c::init();
|
i2c::init();
|
||||||
#[cfg(feature = "target_kasli_soc")]
|
#[cfg(has_si5324)]
|
||||||
si5324::setup(unsafe { (&mut i2c::I2C_BUS).as_mut().unwrap() },
|
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() {
|
let cfg = match Config::new() {
|
||||||
Ok(cfg) => cfg,
|
Ok(cfg) => cfg,
|
||||||
|
Loading…
Reference in New Issue
Block a user