forked from M-Labs/zynq-rs
zynq::ddr: add clock_setup(), calibrate_iob_impedance()
This commit is contained in:
parent
c046bbf8a2
commit
afda48e3fe
@ -1,27 +1,28 @@
|
|||||||
use crate::regs::RegisterW;
|
use crate::regs::{RegisterR, RegisterW, RegisterRW};
|
||||||
use super::slcr;
|
use super::slcr;
|
||||||
use super::clocks::CpuClocks;
|
use super::clocks::CpuClocks;
|
||||||
|
|
||||||
/// Micron MT41J256M8HX-15E: 667 MHz
|
/// Micron MT41J256M8HX-15E: 667 MHz
|
||||||
const DDR_FREQ: u32 = 666_666_666;
|
const DDR_FREQ: u32 = 666_666_666;
|
||||||
|
const DCI_FREQ: u32 = 10_000_000;
|
||||||
|
|
||||||
pub struct DdrRam {
|
pub struct DdrRam {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DdrRam {
|
impl DdrRam {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self::clock_setup();
|
let clocks = CpuClocks::get();
|
||||||
|
Self::clock_setup(&clocks);
|
||||||
|
Self::calibrate_iob_impedance(&clocks);
|
||||||
|
|
||||||
let ram = DdrRam {};
|
let ram = DdrRam {};
|
||||||
// TODO: ram.
|
|
||||||
ram
|
ram
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clock_setup() {
|
fn clock_setup(clocks: &CpuClocks) {
|
||||||
let clocks = CpuClocks::get();
|
|
||||||
let ddr3x_clk_divisor = ((clocks.ddr - 1) / DDR_FREQ + 1).min(255) as u8;
|
let ddr3x_clk_divisor = ((clocks.ddr - 1) / DDR_FREQ + 1).min(255) as u8;
|
||||||
let ddr2x_clk_divisor = 3 * ddr3x_clk_divisor / 2;
|
let ddr2x_clk_divisor = 3 * ddr3x_clk_divisor / 2;
|
||||||
|
|
||||||
slcr::RegisterBlock::unlocked(|slcr| {
|
slcr::RegisterBlock::unlocked(|slcr| {
|
||||||
slcr.ddr_pll_ctrl.write(
|
slcr.ddr_pll_ctrl.write(
|
||||||
slcr::PllCtrl::zeroed()
|
slcr::PllCtrl::zeroed()
|
||||||
@ -36,4 +37,47 @@ impl DdrRam {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn calibrate_iob_impedance(clocks: &CpuClocks) {
|
||||||
|
let divisor0 = (clocks.ddr / DCI_FREQ)
|
||||||
|
.max(1).min(63) as u8;
|
||||||
|
let divisor1 = (clocks.ddr / DCI_FREQ / u32::from(divisor0))
|
||||||
|
.max(1).min(63) as u8;
|
||||||
|
|
||||||
|
slcr::RegisterBlock::unlocked(|slcr| {
|
||||||
|
// Step 1.
|
||||||
|
slcr.dci_clk_ctrl.write(
|
||||||
|
slcr::DciClkCtrl::zeroed()
|
||||||
|
.clkact(true)
|
||||||
|
.divisor0(divisor0)
|
||||||
|
.divisor1(divisor1)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Step 2.a.
|
||||||
|
slcr.ddriob_dci_ctrl.modify(|_, w|
|
||||||
|
w.reset(false)
|
||||||
|
);
|
||||||
|
slcr.ddriob_dci_ctrl.modify(|_, w|
|
||||||
|
w.reset(true)
|
||||||
|
);
|
||||||
|
// Step 3.b. for DDR3
|
||||||
|
slcr.ddriob_dci_ctrl.modify(|_, w|
|
||||||
|
w.nref_opt1(0)
|
||||||
|
.nref_opt2(0)
|
||||||
|
.nref_opt4(1)
|
||||||
|
.pref_opt1(0)
|
||||||
|
.pref_opt2(0)
|
||||||
|
);
|
||||||
|
// Step 2.c.
|
||||||
|
slcr.ddriob_dci_ctrl.modify(|_, w|
|
||||||
|
w.update_control(false)
|
||||||
|
);
|
||||||
|
// Step 2.d.
|
||||||
|
slcr.ddriob_dci_ctrl.modify(|_, w|
|
||||||
|
w.enable(true)
|
||||||
|
);
|
||||||
|
// Step 2.e.
|
||||||
|
while ! slcr.ddriob_dci_status.read().done() {}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ pub struct RegisterBlock {
|
|||||||
reserved1: [u32; 1],
|
reserved1: [u32; 1],
|
||||||
pub arm_clk_ctrl: ArmClkCtrl,
|
pub arm_clk_ctrl: ArmClkCtrl,
|
||||||
pub ddr_clk_ctrl: DdrClkCtrl,
|
pub ddr_clk_ctrl: DdrClkCtrl,
|
||||||
pub dci_clk_ctrl: RW<u32>,
|
pub dci_clk_ctrl: DciClkCtrl,
|
||||||
pub aper_clk_ctrl: AperClkCtrl,
|
pub aper_clk_ctrl: AperClkCtrl,
|
||||||
pub usb0_clk_ctrl: RW<u32>,
|
pub usb0_clk_ctrl: RW<u32>,
|
||||||
pub usb1_clk_ctrl: RW<u32>,
|
pub usb1_clk_ctrl: RW<u32>,
|
||||||
@ -201,8 +201,8 @@ pub struct RegisterBlock {
|
|||||||
pub w_diff: RW<u32>,
|
pub w_diff: RW<u32>,
|
||||||
pub w_clock: RW<u32>,
|
pub w_clock: RW<u32>,
|
||||||
pub ddriob_ddr_ctrl: RW<u32>,
|
pub ddriob_ddr_ctrl: RW<u32>,
|
||||||
pub ddriob_dci_ctrl: RW<u32>,
|
pub ddriob_dci_ctrl: DdriobDciCtrl,
|
||||||
pub ddriob_dci_status: RW<u32>,
|
pub ddriob_dci_status: DdriobDciStatus,
|
||||||
}
|
}
|
||||||
register_at!(RegisterBlock, 0xF8000000, new);
|
register_at!(RegisterBlock, 0xF8000000, new);
|
||||||
|
|
||||||
@ -275,6 +275,11 @@ register_bit!(ddr_clk_ctrl, ddr_2xclkact, 1);
|
|||||||
register_bits!(ddr_clk_ctrl, ddr_3xclk_divisor, u8, 20, 25);
|
register_bits!(ddr_clk_ctrl, ddr_3xclk_divisor, u8, 20, 25);
|
||||||
register_bits!(ddr_clk_ctrl, ddr_2xclk_divisor, u8, 26, 31);
|
register_bits!(ddr_clk_ctrl, ddr_2xclk_divisor, u8, 26, 31);
|
||||||
|
|
||||||
|
register!(dci_clk_ctrl, DciClkCtrl, RW, u32);
|
||||||
|
register_bit!(dci_clk_ctrl, clkact, 0);
|
||||||
|
register_bits!(dci_clk_ctrl, divisor0, u8, 8, 13);
|
||||||
|
register_bits!(dci_clk_ctrl, divisor1, u8, 20, 25);
|
||||||
|
|
||||||
register!(clk_621_true, Clk621True, RW, u32);
|
register!(clk_621_true, Clk621True, RW, u32);
|
||||||
register_bit!(clk_621_true, clk_621_true, 0);
|
register_bit!(clk_621_true, clk_621_true, 0);
|
||||||
|
|
||||||
@ -457,3 +462,17 @@ mio_pin_register!(mio_pin_53, MioPin53);
|
|||||||
|
|
||||||
register!(gpiob_ctrl, GpiobCtrl, RW, u32);
|
register!(gpiob_ctrl, GpiobCtrl, RW, u32);
|
||||||
register_bit!(gpiob_ctrl, vref_en, 0);
|
register_bit!(gpiob_ctrl, vref_en, 0);
|
||||||
|
|
||||||
|
register!(ddriob_dci_ctrl, DdriobDciCtrl, RW, u32);
|
||||||
|
register_bit!(ddriob_dci_ctrl, reset, 0);
|
||||||
|
register_bit!(ddriob_dci_ctrl, enable, 0);
|
||||||
|
register_bits!(ddriob_dci_ctrl, nref_opt1, u8, 6, 7);
|
||||||
|
register_bits!(ddriob_dci_ctrl, nref_opt2, u8, 8, 10);
|
||||||
|
register_bits!(ddriob_dci_ctrl, nref_opt4, u8, 11, 13);
|
||||||
|
register_bits!(ddriob_dci_ctrl, pref_opt1, u8, 14, 15);
|
||||||
|
register_bits!(ddriob_dci_ctrl, pref_opt2, u8, 17, 19);
|
||||||
|
register_bit!(ddriob_dci_ctrl, update_control, 20);
|
||||||
|
|
||||||
|
register!(ddriob_dci_status, DdriobDciStatus, RW, u32);
|
||||||
|
register_bit!(ddriob_dci_status, done, 0);
|
||||||
|
register_bit!(ddriob_dci_status, lock, 13);
|
||||||
|
Loading…
Reference in New Issue
Block a user