diff --git a/src/main.rs b/src/main.rs index 8ae32576..95815602 100644 --- a/src/main.rs +++ b/src/main.rs @@ -94,6 +94,7 @@ fn main() { clocks.cpu_3x2x() / 1_000_000, clocks.cpu_2x() / 1_000_000, clocks.cpu_1x() / 1_000_000); + let ddr = zynq::ddr::DdrRam::new(); let eth = zynq::eth::Eth::default(HWADDR.clone()); println!("Eth on"); diff --git a/src/zynq/ddr/mod.rs b/src/zynq/ddr/mod.rs index c579983c..6cc4b0fc 100644 --- a/src/zynq/ddr/mod.rs +++ b/src/zynq/ddr/mod.rs @@ -2,12 +2,13 @@ use crate::regs::{RegisterR, RegisterW, RegisterRW}; use super::slcr; use super::clocks::CpuClocks; +mod regs; + /// Micron MT41J256M8HX-15E: 667 MHz DDR3 const DDR_FREQ: u32 = 666_666_666; const DCI_FREQ: u32 = 10_000_000; -pub struct DdrRam { -} +pub struct DdrRam; impl DdrRam { pub fn new() -> Self { @@ -15,9 +16,9 @@ impl DdrRam { Self::clock_setup(&clocks); Self::calibrate_iob_impedance(&clocks); Self::configure_iob(); + Self::reset_ddrc(); - let ram = DdrRam {}; - ram + DdrRam } /// Zynq-7000 AP SoC Technical Reference Manual: @@ -130,4 +131,17 @@ impl DdrRam { ); }); } + + /// Reset DDR controller + fn reset_ddrc() { + let regs = unsafe { regs::RegisterBlock::new() }; + regs.ddrc_ctrl.modify(|_, w| w + .soft_rstb(false) + ); + regs.ddrc_ctrl.modify(|_, w| w + .soft_rstb(true) + .powerdown_en(false) + .data_bus_width(regs::DataBusWidth::Width32bit) + ); + } } diff --git a/src/zynq/ddr/regs.rs b/src/zynq/ddr/regs.rs index 77bb5914..753af76d 100644 --- a/src/zynq/ddr/regs.rs +++ b/src/zynq/ddr/regs.rs @@ -2,9 +2,15 @@ use volatile_register::{RO, WO, RW}; use crate::{register, register_bit, register_bits, register_bits_typed}; +#[repr(u8)] +pub enum DataBusWidth { + Width32bit = 0b00, + Width16bit = 0b01, +} + #[repr(C)] pub struct RegisterBlock { - pub ddrc_ctrl: RW, + pub ddrc_ctrl: DdrcCtrl, pub two_rank_cfg: RW, pub hpr_reg: RW, pub lpr_reg: RW, @@ -135,3 +141,16 @@ pub struct RegisterBlock { pub lpddr_ctrl3: RW, } +impl RegisterBlock { + pub unsafe fn new() -> &'static mut Self { + &mut *(0xF8006000 as *mut _) + } +} + +register!(ddrc_ctrl, DdrcCtrl, RW, u32); +register_bit!(ddrc_ctrl, + /// `false` resets controller, `true` continues + soft_rstb, 0); +register_bit!(ddrc_ctrl, powerdown_en, 1); +register_bits_typed!(ddrc_ctrl, data_bus_width, u8, DataBusWidth, 2, 3); +// (ddrc_ctrl) ...