forked from M-Labs/zynq-rs
1
0
Fork 0

devc working!

This commit is contained in:
pca006132 2020-06-15 16:07:31 +08:00
parent 82ec1ba7a7
commit e0f26871db
2 changed files with 171 additions and 25 deletions

View File

@ -1,11 +1,23 @@
use libregister::*;
use crate::slcr;
use libregister::*;
use log::debug;
mod regs;
pub struct DevC {
regs: &'static mut regs::RegisterBlock,
}
/// DMA transfer type for PCAP
/// All insecure, we do not implement encrypted transfer
#[derive(PartialEq)]
pub enum TransferType {
PcapWrite,
PcapReadback,
ConcurrentReadWrite,
}
pub const INVALID_ADDR: u32 = 0xFFFFFFFF;
impl DevC {
pub fn new() -> Self {
DevC {
@ -14,16 +26,22 @@ impl DevC {
}
pub fn enable(&mut self) {
self.regs.control.modify(|_, w| {
w.pcap_mode(true)
.pcap_pr(true)
})
unsafe {
// unlock register with magic pattern
self.regs.unlock.write(0x757BDF0D);
}
self.regs
.control
.modify(|_, w| w.pcap_mode(true).pcap_pr(true));
self.regs
.int_mask
.write(self::regs::int_mask::Write { inner: 0xFFFFFFFF });
self.clear_interrupts();
}
pub fn disable(&mut self) {
self.regs.control.modify(|_, w| {
w.pcap_mode(false)
.pcap_pr(false)
})
self.regs
.control
.modify(|_, w| w.pcap_mode(false).pcap_pr(false))
}
pub fn is_done(&self) -> bool {
@ -32,15 +50,141 @@ impl DevC {
self.regs.int_sts.read().ixr_pcfg_done()
}
pub fn program(&mut self) {
pub fn program(&mut self, src_addr: u32, len: u32) {
debug!("Init preload FPGA");
slcr::RegisterBlock::unlocked(|slcr| {
slcr.init_preload_fpga();
});
debug!("Toggling PROG_B");
// set PCFG_PROG_B to high low high
self.regs.control.modify(|_, w| w.pcfg_prog_b(true));
self.regs.control.modify(|_, w| w.pcfg_prog_b(false));
while self.regs.status.read().pcfg_init() {}
self.regs.control.modify(|_, w| w.pcfg_prog_b(true));
while !self.regs.status.read().pcfg_init() {}
self.regs.int_sts.write(
self::regs::IntSts::zeroed()
.pss_cfg_reset_b_int(true)
.ixr_pcfg_cfg_rst(true),
);
debug!("ADDR: {:0X}", src_addr);
self.dma_transfer(
src_addr | 0x1,
INVALID_ADDR | 0x1,
len,
len,
TransferType::PcapWrite,
);
self.wait_dma_transfer_complete();
debug!("INT_STS: {:0X}", self.regs.int_sts.read().inner);
debug!("STATUS: {:0X}", self.regs.status.read().inner);
debug!("Waiting for done");
while !self.is_done() {}
debug!("INT_STS: {:0X}", self.regs.int_sts.read().inner);
debug!("Init postload FPGA");
slcr::RegisterBlock::unlocked(|slcr| {
slcr.init_postload_fpga();
});
}
/// Initiate DMA transaction, all lengths are in words.
/// > This function is not meant to be used directly.
fn initiate_dma(&mut self, src_addr: u32, dest_addr: u32, src_len: u32, dest_len: u32) {
self.regs.dma_src_addr.modify(|_, w| w.src_addr(src_addr));
self.regs
.dma_dest_addr
.modify(|_, w| w.dest_addr(dest_addr));
self.regs.dma_src_len.modify(|_, w| w.dma_len(src_len));
self.regs.dma_dest_len.modify(|_, w| w.dma_len(dest_len));
}
/// DMA transfer, all lengths are in words.
pub fn dma_transfer(
&mut self,
src_addr: u32,
dest_addr: u32,
src_len: u32,
dest_len: u32,
transfer_type: TransferType,
) -> Result<(), &str> {
if self.regs.status.read().dma_cmd_q_f() {
return Err("DMA busy");
}
if transfer_type != TransferType::ConcurrentReadWrite
&& !self.regs.status.read().pcfg_init()
{
return Err("Fabric not initialized");
}
match &transfer_type {
TransferType::PcapReadback => {
// clear internal PCAP loopback
self.regs.mctrl.modify(|_, w| w.pcap_lpbk(false));
// send READ frame command
self.initiate_dma(src_addr, INVALID_ADDR, src_len, 0);
// wait until DMA done
while !self.regs.int_sts.read().ixr_d_p_done() {}
// initiate the DMA write
self.initiate_dma(INVALID_ADDR, dest_addr, 0, dest_len);
}
TransferType::PcapWrite | TransferType::ConcurrentReadWrite => {
self.regs
.mctrl
.modify(|_, w| w.pcap_lpbk(transfer_type == TransferType::ConcurrentReadWrite));
// PCAP data transmitted every clock
self.regs.control.modify(|_, w| w.pcap_rate_en(false));
self.initiate_dma(src_addr, dest_addr, src_len, dest_len);
}
}
Ok(())
}
pub fn wait_dma_transfer_complete(&mut self) {
debug!("Wait for DMA done");
while !self.regs.int_sts.read().ixr_dma_done() {}
self.regs
.int_sts
.write(self::regs::IntSts::zeroed().ixr_dma_done(true));
}
pub fn dump_registers(&self) {
debug!("Control: 0x{:0X}", self.regs.control.read().inner);
debug!("Status: 0x{:0X}", self.regs.status.read().inner);
debug!("INT STS: 0x{:0X}", self.regs.int_sts.read().inner);
}
pub fn clear_interrupts(&mut self) {
self.regs.int_sts.modify(|_, w| {
w.pss_gts_usr_b_int(true)
.pss_fst_cfg_b_int(true)
.pss_gpwrdwn_b_int(true)
.pss_gts_cfg_b_int(true)
.pss_cfg_reset_b_int(true)
.ixr_axi_wto(true)
.ixr_axi_werr(true)
.ixr_axi_rto(true)
.ixr_axi_rerr(true)
.ixr_rx_fifo_ov(true)
.ixr_wr_fifo_lvl(true)
.ixr_rd_fifo_lvl(true)
.ixr_dma_cmd_err(true)
.ixr_dma_q_ov(true)
.ixr_dma_done(true)
.ixr_d_p_done(true)
.ixr_p2d_len_err(true)
.ixr_pcfg_hmac_err(true)
.ixr_pcfg_seu_err(true)
.ixr_pcfg_por_b(true)
.ixr_pcfg_cfg_rst(true)
.ixr_pcfg_done(true)
.ixr_pcfg_init_pe(true)
.ixr_pcfg_init_ne(true)
})
}
}

View File

@ -2,12 +2,13 @@ use libregister::{
register, register_at,
register_bit, register_bits, register_bits_typed,
};
use volatile_register::WO;
#[repr(C)]
pub struct RegisterBlock {
pub control: Control,
pub cfg: Cfg,
pub lock: Lock,
pub cfg: Cfg,
pub int_sts: IntSts,
pub int_mask: IntMask,
pub status: Status,
@ -15,9 +16,13 @@ pub struct RegisterBlock {
pub dma_dest_addr: DmaDestAddr,
pub dma_src_len: DmaSrcLen,
pub dma_dest_len: DmaDestLen,
unused0: u32,
pub multiboot_addr: MultibootAddr,
pub unlock: Unlock,
unused1: u32,
pub unlock: WO<u32>,
unused2: [u32; 18],
pub mctrl: MCtrl,
unused3: [u32; 31],
pub xadcif_cfg: XADCIfCfg,
pub xadcif_int_sts: XADCIfIntSts,
pub xadcif_int_mask: XADCIfIntMask,
@ -71,18 +76,18 @@ pub enum WFifoTh {
ThreeFourthEmpty = 0b10, // Three fourth empty for write
Empty = 0b11, // Empty for write
}
register_bits_typed!(cfg, wfifo_th, u8, WFifoTh, 10, 11);
register_bits_typed!(cfg, wfifo_th, u8, WFifoTh, 8, 9);
register_bit!(cfg, rclk_edge, 7);
register_bit!(cfg, wclk_edge, 6);
register_bit!(cfg, disable_src_inc, 5);
register_bit!(cfg, disable_dst_inc, 4);
register!(int_sts, IntSts, RW, u32);
register_bit!(int_sts, pps_gts_usr_b_int, 31);
register_bit!(int_sts, pps_fst_cfg_b_int, 30);
register_bit!(int_sts, pps_gpwrdwn_b_int, 29);
register_bit!(int_sts, pps_gts_cfg_b_int, 27);
register_bit!(int_sts, pps_cfg_reset_b_int, 26);
register_bit!(int_sts, pss_gts_usr_b_int, 31);
register_bit!(int_sts, pss_fst_cfg_b_int, 30);
register_bit!(int_sts, pss_gpwrdwn_b_int, 29);
register_bit!(int_sts, pss_gts_cfg_b_int, 28);
register_bit!(int_sts, pss_cfg_reset_b_int, 27);
register_bit!(int_sts, ixr_axi_wto, 23);
register_bit!(int_sts, ixr_axi_werr, 22);
register_bit!(int_sts, ixr_axi_rto, 21);
@ -148,23 +153,20 @@ register_bit!(status, efuse_sec_en, 2);
register_bit!(status, efuse_jtag_dis, 1);
register!(dma_src_addr, DmaSrcAddr, RW, u32);
register_bits!(dma_src_addr, src_addr, u8, 0, 31);
register_bits!(dma_src_addr, src_addr, u32, 0, 31);
register!(dma_dest_addr, DmaDestAddr, RW, u32);
register_bits!(dma_dest_addr, dest_addr, u8, 0, 31);
register_bits!(dma_dest_addr, dest_addr, u32, 0, 31);
register!(dma_src_len, DmaSrcLen, RW, u32);
register_bits!(dma_src_len, dma_len, u8, 0, 26);
register_bits!(dma_src_len, dma_len, u32, 0, 26);
register!(dma_dest_len, DmaDestLen, RW, u32);
register_bits!(dma_dest_len, dma_len, u8, 0, 26);
register_bits!(dma_dest_len, dma_len, u32, 0, 26);
register!(multiboot_addr, MultibootAddr, RW, u32);
register_bits!(multiboot_addr, multiboot_addr, u8, 0, 12);
register!(unlock, Unlock, RW, u32);
register_bits!(unlock, unlock, u8, 0, 31);
register!(mctrl, MCtrl, RW, u32);
register_bits!(mctrl, ps_version, u8, 28, 31);
register_bit!(mctrl, pcfg_por_b, 8);