ddr: improve dci divisors calculation

This commit is contained in:
Astro 2020-07-28 00:38:48 +02:00
parent 0aa75d3544
commit ef4fb598fb

View File

@ -56,14 +56,35 @@ impl DdrRam {
clocks clocks
} }
fn calculate_dci_divisors(clocks: &Clocks) -> (u8, u8) {
let target = (DCI_FREQ - 1 + clocks.ddr) / DCI_FREQ;
let mut best = None;
let mut best_error = 0;
for divisor0 in 1..63 {
for divisor1 in 1..63 {
let current = (divisor0 as u32) * (divisor1 as u32);
let error = if current > target {
current - target
} else {
target - current
};
if best.is_none() || best_error > error {
best = Some((divisor0, divisor1));
best_error = error;
}
}
}
best.unwrap()
}
/// Zynq-7000 AP SoC Technical Reference Manual: /// Zynq-7000 AP SoC Technical Reference Manual:
/// 10.6.2 DDR IOB Impedance Calibration /// 10.6.2 DDR IOB Impedance Calibration
fn calibrate_iob_impedance(clocks: &Clocks) { fn calibrate_iob_impedance(clocks: &Clocks) {
let divisor0 = ((DCI_FREQ - 1 + clocks.ddr) / DCI_FREQ) let (divisor0, divisor1) = Self::calculate_dci_divisors(clocks);
.max(1).min(63) as u8; debug!("DDR DCI clock: {} Hz (divisors={}*{})",
let divisor1 = ((DCI_FREQ - 1 + clocks.ddr) / DCI_FREQ / u32::from(divisor0)) clocks.ddr / u32::from(divisor0) / u32::from(divisor1),
.max(1).min(63) as u8; divisor0, divisor1);
debug!("DDR DCI clock: {} Hz", clocks.ddr / u32::from(divisor0) / u32::from(divisor1));
slcr::RegisterBlock::unlocked(|slcr| { slcr::RegisterBlock::unlocked(|slcr| {
// Step 1. // Step 1.