firmware: support for multiple JESD DACs

This commit is contained in:
Sebastien Bourdeauducq 2017-08-31 13:05:48 +08:00
parent a4144a07c4
commit 0a5904bbaa
3 changed files with 44 additions and 45 deletions

View File

@ -2,7 +2,7 @@ use csr;
use clock; use clock;
use ad9154_reg; use ad9154_reg;
fn spi_setup() { fn spi_setup(dacno: u8) {
unsafe { unsafe {
csr::converter_spi::offline_write(1); csr::converter_spi::offline_write(1);
csr::converter_spi::cs_polarity_write(0); csr::converter_spi::cs_polarity_write(0);
@ -14,7 +14,7 @@ fn spi_setup() {
csr::converter_spi::clk_div_read_write(16); csr::converter_spi::clk_div_read_write(16);
csr::converter_spi::xfer_len_write_write(24); csr::converter_spi::xfer_len_write_write(24);
csr::converter_spi::xfer_len_read_write(0); csr::converter_spi::xfer_len_read_write(0);
csr::converter_spi::cs_write(1 << csr::CONFIG_CONVERTER_SPI_DAC_CS); csr::converter_spi::cs_write(1 << (csr::CONFIG_CONVERTER_SPI_FIRST_AD9154_CS + dacno as u32));
csr::converter_spi::offline_write(0); csr::converter_spi::offline_write(0);
} }
} }
@ -35,39 +35,39 @@ fn read(addr: u16) -> u8 {
} }
} }
fn jesd_reset(rst: bool) { fn jesd_reset(dacno: u8, rst: bool) {
unsafe { unsafe {
csr::ad9154::jesd_jreset_write(if rst {1} else {0}) (csr::AD9154[dacno as usize].jesd_jreset_write)(if rst {1} else {0})
} }
} }
fn jesd_enable(en: bool) { fn jesd_enable(dacno: u8, en: bool) {
unsafe { unsafe {
csr::ad9154::jesd_control_enable_write(if en {1} else {0}) (csr::AD9154[dacno as usize].jesd_control_enable_write)(if en {1} else {0})
} }
} }
fn jesd_ready() -> bool { fn jesd_ready(dacno: u8) -> bool {
unsafe { unsafe {
csr::ad9154::jesd_control_ready_read() != 0 (csr::AD9154[dacno as usize].jesd_control_ready_read)() != 0
} }
} }
fn jesd_prbs(en: bool) { fn jesd_prbs(dacno: u8, en: bool) {
unsafe { unsafe {
csr::ad9154::jesd_control_prbs_config_write(if en {1} else {0}) (csr::AD9154[dacno as usize].jesd_control_prbs_config_write)(if en {1} else {0})
} }
} }
fn jesd_stpl(en: bool) { fn jesd_stpl(dacno: u8, en: bool) {
unsafe { unsafe {
csr::ad9154::jesd_control_stpl_enable_write(if en {1} else {0}) (csr::AD9154[dacno as usize].jesd_control_stpl_enable_write)(if en {1} else {0})
} }
} }
fn jesd_jsync() -> bool { fn jesd_jsync(dacno: u8) -> bool {
unsafe { unsafe {
csr::ad9154::jesd_control_jsync_read() != 0 (csr::AD9154[dacno as usize].jesd_control_jsync_read)() != 0
} }
} }
@ -421,19 +421,24 @@ fn monitor() {
write(ad9154_reg::IRQ_STATUS3, 0x00); write(ad9154_reg::IRQ_STATUS3, 0x00);
} }
fn cfg() -> Result<(), &'static str> { fn cfg(dacno: u8) -> Result<(), &'static str> {
jesd_enable(false); spi_setup(dacno);
jesd_prbs(false); // Release the JESD clock domain reset late, as we need to
jesd_stpl(false); // set up clock chips before.
jesd_reset(dacno, false);
jesd_enable(dacno, false);
jesd_prbs(dacno, false);
jesd_stpl(dacno, false);
clock::spin_us(10000); clock::spin_us(10000);
jesd_enable(true); jesd_enable(dacno, true);
dac_setup()?; dac_setup()?;
jesd_enable(false); jesd_enable(dacno, false);
clock::spin_us(10000); clock::spin_us(10000);
jesd_enable(true); jesd_enable(dacno, true);
monitor(); monitor();
let t = clock::get_ms(); let t = clock::get_ms();
while !jesd_ready() { while !jesd_ready(dacno) {
if clock::get_ms() > t + 200 { if clock::get_ms() > t + 200 {
return Err("JESD ready timeout"); return Err("JESD ready timeout");
} }
@ -442,7 +447,7 @@ fn cfg() -> Result<(), &'static str> {
if read(ad9154_reg::CODEGRPSYNCFLG) != 0x0f { if read(ad9154_reg::CODEGRPSYNCFLG) != 0x0f {
return Err("bad CODEGRPSYNCFLG") return Err("bad CODEGRPSYNCFLG")
} }
if !jesd_jsync() { if !jesd_jsync(dacno) {
return Err("bad SYNC") return Err("bad SYNC")
} }
if read(ad9154_reg::FRAMESYNCFLG) != 0x0f { if read(ad9154_reg::FRAMESYNCFLG) != 0x0f {
@ -458,18 +463,10 @@ fn cfg() -> Result<(), &'static str> {
} }
pub fn init() -> Result<(), &'static str> { pub fn init() -> Result<(), &'static str> {
spi_setup(); for dacno in 0..csr::AD9154.len() {
let dacno = dacno as u8;
// Release the JESD clock domain reset late, as we need to debug!("setting up DAC #{}", dacno);
// set up clock chips before. cfg(dacno)?;
jesd_reset(false);
for i in 0..99 {
let outcome = cfg();
match outcome {
Ok(_) => return outcome,
Err(e) => warn!("config attempt #{} failed ({}), retrying", i, e)
} }
} Ok(())
cfg()
} }

View File

@ -13,7 +13,7 @@ fn spi_setup() {
csr::converter_spi::clk_div_read_write(16); csr::converter_spi::clk_div_read_write(16);
csr::converter_spi::xfer_len_write_write(24); csr::converter_spi::xfer_len_write_write(24);
csr::converter_spi::xfer_len_read_write(0); csr::converter_spi::xfer_len_read_write(0);
csr::converter_spi::cs_write(1 << csr::CONFIG_CONVERTER_SPI_CLK_CS); csr::converter_spi::cs_write(1 << csr::CONFIG_CONVERTER_SPI_AD9516_CS);
csr::converter_spi::offline_write(0); csr::converter_spi::offline_write(0);
} }
} }

View File

@ -192,12 +192,14 @@ class Phaser(MiniSoC, AMPSoC):
self.comb += ad9154_spi.en.eq(1) self.comb += ad9154_spi.en.eq(1)
self.submodules.converter_spi = spi_csr.SPIMaster(ad9154_spi) self.submodules.converter_spi = spi_csr.SPIMaster(ad9154_spi)
self.csr_devices.append("converter_spi") self.csr_devices.append("converter_spi")
self.config["CONVERTER_SPI_DAC_CS"] = 0
self.config["CONVERTER_SPI_CLK_CS"] = 1
self.config["HAS_AD9516"] = None self.config["HAS_AD9516"] = None
self.config["CONVERTER_SPI_AD9516_CS"] = 1
self.config["CONVERTER_SPI_FIRST_AD9154_CS"] = 0
self.submodules.ad9154 = AD9154(platform) self.submodules.ad9154_0 = AD9154(platform)
self.csr_devices.append("ad9154") self.csr_devices.append("ad9154_0")
self.config["HAS_AD9154"] = None
self.add_csr_group("ad9154", ["ad9154_0"])
rtio_channels = [] rtio_channels = []
@ -218,7 +220,7 @@ class Phaser(MiniSoC, AMPSoC):
self.config["RTIO_FIRST_SAWG_CHANNEL"] = len(rtio_channels) self.config["RTIO_FIRST_SAWG_CHANNEL"] = len(rtio_channels)
rtio_channels.extend(rtio.Channel.from_phy(phy) rtio_channels.extend(rtio.Channel.from_phy(phy)
for sawg in self.ad9154.sawgs for sawg in self.ad9154_0.sawgs
for phy in sawg.phys) for phy in sawg.phys)
self.config["HAS_RTIO_LOG"] = None self.config["HAS_RTIO_LOG"] = None
@ -226,7 +228,7 @@ class Phaser(MiniSoC, AMPSoC):
rtio_channels.append(rtio.LogChannel()) rtio_channels.append(rtio.LogChannel())
self.submodules.rtio_crg = _PhaserCRG( self.submodules.rtio_crg = _PhaserCRG(
platform, self.ad9154.jesd.cd_jesd.clk) platform, self.ad9154_0.jesd.cd_jesd.clk)
self.csr_devices.append("rtio_crg") self.csr_devices.append("rtio_crg")
self.submodules.rtio_core = rtio.Core(rtio_channels) self.submodules.rtio_core = rtio.Core(rtio_channels)
self.csr_devices.append("rtio_core") self.csr_devices.append("rtio_core")
@ -248,8 +250,8 @@ class Phaser(MiniSoC, AMPSoC):
platform.add_false_path_constraints( platform.add_false_path_constraints(
self.crg.cd_sys.clk, self.rtio_crg.cd_rtio.clk) self.crg.cd_sys.clk, self.rtio_crg.cd_rtio.clk)
platform.add_false_path_constraints( platform.add_false_path_constraints(
self.crg.cd_sys.clk, self.ad9154.jesd.cd_jesd.clk) self.crg.cd_sys.clk, self.ad9154_0.jesd.cd_jesd.clk)
for phy in self.ad9154.jesd.phys: for phy in self.ad9154_0.jesd.phys:
platform.add_false_path_constraints( platform.add_false_path_constraints(
self.crg.cd_sys.clk, phy.transmitter.cd_tx.clk) self.crg.cd_sys.clk, phy.transmitter.cd_tx.clk)