zynq::ddr, main: parameters, memtest

master
Astro 3 years ago
parent e61d1268ac
commit 9b4f07f37c
  1. 7
      src/main.rs
  2. 48
      src/zynq/clocks.rs
  3. 73
      src/zynq/ddr/mod.rs

@ -87,6 +87,9 @@ const HWADDR: [u8; 6] = [0, 0x23, 0xde, 0xea, 0xbe, 0xef];
fn main() {
println!("Main.");
zynq::clocks::CpuClocks::enable_ddr(1_066_000_000);
let pll_status = zynq::slcr::RegisterBlock::new().pll_status.read();
println!("PLLs: {}", pll_status);
let clocks = zynq::clocks::CpuClocks::get();
println!("Clocks: {:?}", clocks);
println!("CPU speeds: {}/{}/{}/{} MHz",
@ -94,7 +97,9 @@ 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 mut ddr = zynq::ddr::DdrRam::new();
println!("DDR: {:?}", ddr.status());
ddr.memtest();
let eth = zynq::eth::Eth::default(HWADDR.clone());
println!("Eth on");

@ -1,4 +1,4 @@
use crate::regs::{RegisterR, RegisterRW};
use crate::regs::{RegisterR, RegisterW, RegisterRW};
use super::slcr;
#[cfg(feature = "target_zc706")]
@ -90,18 +90,32 @@ impl CpuClocks {
pll / u32::from(uart_clk_ctrl.divisor())
}
/// Zynq-7000 AP SoC Technical Reference Manual:
/// 25.10.4 PLLs
pub fn enable_ddr(target_clock: u32) {
let fdiv = (target_clock / PS_CLK).min(66) as u16;
let regs = slcr::RegisterBlock::new();
regs.ddr_pll_ctrl.modify(|_, w| w
.pll_pwrdwn(false)
.pll_reset(true)
.pll_bypass_force(true)
.pll_fdiv(fdiv)
);
let (pll_res, pll_cp, lock_cnt) = PLL_FDIV_LOCK_PARAM.iter()
.filter(|(fdiv_max, _)| fdiv <= *fdiv_max)
.last()
.expect("PLL_FDIV_LOCK_PARAM")
.1.clone();
regs.ddr_pll_cfg.write(
slcr::PllCfg::zeroed()
.pll_res(pll_res)
.pll_cp(pll_cp)
.lock_cnt(lock_cnt)
);
regs.ddr_pll_ctrl.modify(|_, w| w
.pll_reset(true)
);
let fdiv = (target_clock / PS_CLK).max(127) as u16;
regs.ddr_pll_ctrl.modify(|_, w| w
.pll_pwrdwn(false)
.pll_reset(false)
.pll_fdiv(fdiv)
);
while ! regs.pll_status.read().ddr_pll_lock() {}
regs.ddr_pll_ctrl.modify(|_, w| w
@ -110,3 +124,27 @@ impl CpuClocks {
);
}
}
/// (pll_fdiv_max, (pll_cp, pll_res, lock_cnt))
const PLL_FDIV_LOCK_PARAM: &[(u16, (u8, u8, u16))] = &[
(13, (2, 6, 750)),
(14, (2, 6, 700)),
(15, (2, 6, 650)),
(16, (2, 10, 625)),
(17, (2, 10, 575)),
(18, (2, 10, 550)),
(19, (2, 10, 525)),
(20, (2, 12, 500)),
(21, (2, 12, 475)),
(22, (2, 12, 450)),
(23, (2, 12, 425)),
(25, (2, 12, 400)),
(26, (2, 12, 375)),
(28, (2, 12, 350)),
(30, (2, 12, 325)),
(33, (2, 2, 300)),
(36, (2, 2, 275)),
(40, (2, 2, 250)),
(47, (3, 12, 250)),
(66, (2, 4, 250)),
];

@ -1,11 +1,19 @@
use crate::regs::{RegisterR, RegisterW, RegisterRW};
use crate::println;
use super::slcr;
use super::clocks::CpuClocks;
mod regs;
#[cfg(feature = "target_zc706")]
/// Micron MT41J256M8HX-15E: 667 MHz DDR3
const DDR_FREQ: u32 = 666_666_666;
#[cfg(feature = "target_cora_z7_10")]
/// Micron MT41K256M16HA-125: 800 MHz DDR3L
const DDR_FREQ: u32 = 800_000_000;
/// MT41K256M16HA-125
const DCI_FREQ: u32 = 10_000_000;
pub struct DdrRam {
@ -131,12 +139,24 @@ impl DdrRam {
slcr.ddriob_drive_slew_clock.write(0x00F9861C);
}
// Enable internal V[REF]
#[cfg(feature = "target_zc706")]
let vref_sel = slcr::DdriobVrefSel::Vref0_75V;
#[cfg(feature = "target_cora_z7_10")]
let vref_sel = slcr::DdriobVrefSel::Vref0_675V;
// // Enable internal V[REF]
// slcr.ddriob_ddr_ctrl.modify(|_, w| w
// .vref_ext_en_lower(false)
// .vref_ext_en_upper(false)
// .vref_sel(vref_sel)
// .vref_int_en(true)
// );
// Enable external V[REF]
slcr.ddriob_ddr_ctrl.modify(|_, w| w
.vref_ext_en_lower(false)
.vref_ext_en_upper(false)
.vref_sel(slcr::DdriobVrefSel::Vref0_75V)
.vref_int_en(true)
.vref_ext_en_lower(true)
.vref_ext_en_upper(true)
.vref_sel(vref_sel)
.vref_int_en(false)
);
});
}
@ -158,4 +178,47 @@ impl DdrRam {
pub fn status(&self) -> regs::ControllerStatus {
self.regs.mode_sts_reg.read().operating_mode()
}
// TODO: move into trait
pub fn ptr(&mut self) -> *mut u8 {
// 0x0010_0000 as *mut _
0x0020_0000 as *mut _
}
pub fn size(&self) -> usize {
// #[cfg(feature = "target_zc706")]
// 1024 * 1024 * 1024
4 * 1024 * 1024
}
pub fn memtest(&mut self) {
let slice = unsafe {
core::slice::from_raw_parts_mut(self.ptr(), self.size())
};
let patterns: &'static [u8] = &[0, 0xff, 0x55, 0xaa, 0];
let mut expected = None;
for (i, pattern) in patterns.iter().enumerate() {
println!("memtest phase {} (status: {:?})", i, self.status());
let slice_len = slice.len();
let mut progress = 0;
for (j, b) in slice.iter_mut().enumerate() {
expected.map(|expected| {
let read: u8 = *b;
if read != expected {
println!("{:08X}: expected {:02X}, read {:02X}", b as *mut u8 as usize, expected, read);
}
});
*b = *pattern;
// println!("{:08X}", b as *mut u8 as usize);
let new_progress = 100 * j / slice_len;
if new_progress > progress {
progress = new_progress;
println!("{}%", progress);
}
}
expected = Some(*pattern);
}
}
}

Loading…
Cancel
Save