Compare commits

..

No commits in common. "afd96bd887b5ca3972b9713f9d72a02ddd5a34dc" and "6e50b32e80749d5ce36003730dbf30bd36cf6eb2" have entirely different histories.

5 changed files with 313 additions and 352 deletions

View File

@ -90,30 +90,6 @@ impl CpuClocks {
pll / u32::from(uart_clk_ctrl.divisor()) pll / u32::from(uart_clk_ctrl.divisor())
} }
/// Zynq-7000 AP SoC Technical Reference Manual:
/// 25.10.4 PLLs
pub fn enable_io(target_clock: u32) {
let fdiv = (target_clock / PS_CLK).min(66) as u16;
slcr::RegisterBlock::unlocked(|slcr| {
slcr.io_pll_ctrl.modify(|_, w| w
.pll_pwrdwn(false)
.pll_bypass_force(true)
.pll_fdiv(fdiv)
);
slcr.io_pll_ctrl.modify(|_, w| w
.pll_reset(true)
);
slcr.io_pll_ctrl.modify(|_, w| w
.pll_reset(false)
);
while ! slcr.pll_status.read().io_pll_lock() {}
slcr.io_pll_ctrl.modify(|_, w| w
.pll_bypass_force(false)
.pll_bypass_qual(false)
);
});
}
/// Zynq-7000 AP SoC Technical Reference Manual: /// Zynq-7000 AP SoC Technical Reference Manual:
/// 25.10.4 PLLs /// 25.10.4 PLLs
pub fn enable_ddr(target_clock: u32) { pub fn enable_ddr(target_clock: u32) {
@ -123,30 +99,29 @@ impl CpuClocks {
.nth(0) .nth(0)
.expect("PLL_FDIV_LOCK_PARAM") .expect("PLL_FDIV_LOCK_PARAM")
.1.clone(); .1.clone();
slcr::RegisterBlock::unlocked(|regs| { let slcr = slcr::RegisterBlock::new();
regs.ddr_pll_ctrl.modify(|_, w| w slcr.ddr_pll_ctrl.modify(|_, w| w
.pll_pwrdwn(false) .pll_pwrdwn(false)
.pll_bypass_force(true) .pll_bypass_force(true)
.pll_fdiv(fdiv) .pll_fdiv(fdiv)
); );
regs.ddr_pll_cfg.write( slcr.ddr_pll_cfg.write(
slcr::PllCfg::zeroed() slcr::PllCfg::zeroed()
.pll_res(pll_res) .pll_res(pll_res)
.pll_cp(pll_cp) .pll_cp(pll_cp)
.lock_cnt(lock_cnt) .lock_cnt(lock_cnt)
); );
regs.ddr_pll_ctrl.modify(|_, w| w slcr.ddr_pll_ctrl.modify(|_, w| w
.pll_reset(true) .pll_reset(true)
); );
regs.ddr_pll_ctrl.modify(|_, w| w slcr.ddr_pll_ctrl.modify(|_, w| w
.pll_reset(false) .pll_reset(false)
); );
while ! regs.pll_status.read().ddr_pll_lock() {} while ! slcr.pll_status.read().ddr_pll_lock() {}
regs.ddr_pll_ctrl.modify(|_, w| w slcr.ddr_pll_ctrl.modify(|_, w| w
.pll_bypass_force(false) .pll_bypass_force(false)
.pll_bypass_qual(false) .pll_bypass_qual(false)
); );
});
} }
} }

View File

@ -36,17 +36,13 @@ impl DdrRam {
/// 10.6.1 DDR Clock Initialization /// 10.6.1 DDR Clock Initialization
fn clock_setup() -> CpuClocks { fn clock_setup() -> CpuClocks {
let clocks = CpuClocks::get(); let clocks = CpuClocks::get();
if clocks.ddr == 0 {
CpuClocks::enable_ddr(clocks.arm); CpuClocks::enable_ddr(clocks.arm);
}
let clocks = CpuClocks::get(); let clocks = CpuClocks::get();
println!("Clocks: {:?}", clocks);
let ddr3x_clk_divisor = ((DDR_FREQ - 1 + clocks.ddr) / DDR_FREQ).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;
println!("DDR 3x/2x clocks: {}/{}", clocks.ddr / u32::from(ddr3x_clk_divisor), clocks.ddr / u32::from(ddr2x_clk_divisor));
slcr::RegisterBlock::unlocked(|slcr| { let slcr = slcr::RegisterBlock::new();
slcr.ddr_clk_ctrl.write( slcr.ddr_clk_ctrl.write(
slcr::DdrClkCtrl::zeroed() slcr::DdrClkCtrl::zeroed()
.ddr_2xclkact(true) .ddr_2xclkact(true)
@ -54,7 +50,6 @@ impl DdrRam {
.ddr_2xclk_divisor(ddr2x_clk_divisor) .ddr_2xclk_divisor(ddr2x_clk_divisor)
.ddr_3xclk_divisor(ddr3x_clk_divisor) .ddr_3xclk_divisor(ddr3x_clk_divisor)
); );
});
clocks clocks
} }
@ -65,9 +60,8 @@ impl DdrRam {
.max(1).min(63) as u8; .max(1).min(63) as u8;
let divisor1 = (clocks.ddr / DCI_FREQ / u32::from(divisor0)) let divisor1 = (clocks.ddr / DCI_FREQ / u32::from(divisor0))
.max(1).min(63) as u8; .max(1).min(63) as u8;
println!("DDR DCI clock: {} Hz", clocks.ddr / u32::from(divisor0) / u32::from(divisor1));
slcr::RegisterBlock::unlocked(|slcr| { let slcr = slcr::RegisterBlock::new();
// Step 1. // Step 1.
slcr.dci_clk_ctrl.write( slcr.dci_clk_ctrl.write(
slcr::DciClkCtrl::zeroed() slcr::DciClkCtrl::zeroed()
@ -101,13 +95,12 @@ impl DdrRam {
); );
// Step 2.e. // Step 2.e.
while ! slcr.ddriob_dci_status.read().done() {} while ! slcr.ddriob_dci_status.read().done() {}
});
} }
/// Zynq-7000 AP SoC Technical Reference Manual: /// Zynq-7000 AP SoC Technical Reference Manual:
/// 10.6.3 DDR IOB Configuration /// 10.6.3 DDR IOB Configuration
fn configure_iob() { fn configure_iob() {
slcr::RegisterBlock::unlocked(|slcr| { let slcr = slcr::RegisterBlock::new();
let addr_config = slcr::DdriobConfig::zeroed() let addr_config = slcr::DdriobConfig::zeroed()
.output_en(slcr::DdriobOutputEn::Obuf); .output_en(slcr::DdriobOutputEn::Obuf);
slcr.ddriob_addr0.write(addr_config.clone()); slcr.ddriob_addr0.write(addr_config.clone());
@ -161,7 +154,6 @@ impl DdrRam {
.vref_sel(vref_sel) .vref_sel(vref_sel)
.vref_int_en(false) .vref_int_en(false)
); );
});
} }
/// Reset DDR controller /// Reset DDR controller

View File

@ -27,7 +27,7 @@ pub struct Eth<'r, RX, TX> {
impl<'r> Eth<'r, (), ()> { impl<'r> Eth<'r, (), ()> {
pub fn default(macaddr: [u8; 6]) -> Self { pub fn default(macaddr: [u8; 6]) -> Self {
slcr::RegisterBlock::unlocked(|slcr| { let slcr = slcr::RegisterBlock::new();
// Manual example: 0x0000_1280 // Manual example: 0x0000_1280
// MDIO // MDIO
slcr.mio_pin_53.write( slcr.mio_pin_53.write(
@ -152,7 +152,6 @@ impl<'r> Eth<'r, (), ()> {
slcr::GpiobCtrl::zeroed() slcr::GpiobCtrl::zeroed()
.vref_en(true) .vref_en(true)
); );
});
Self::gem0(macaddr) Self::gem0(macaddr)
} }
@ -198,7 +197,7 @@ impl<'r, RX, TX> Eth<'r, RX, TX> {
let d0 = ((tx_clock - 1 + io_pll) / tx_clock).max(1).min(63); let d0 = ((tx_clock - 1 + io_pll) / tx_clock).max(1).min(63);
let d1 = (io_pll / tx_clock / d0).max(1).min(63); let d1 = (io_pll / tx_clock / d0).max(1).min(63);
slcr::RegisterBlock::unlocked(|slcr| { let slcr = slcr::RegisterBlock::new();
slcr.gem0_clk_ctrl.write( slcr.gem0_clk_ctrl.write(
// 0x0050_0801: 8, 5: 100 Mb/s // 0x0050_0801: 8, 5: 100 Mb/s
// ...: 8, 1: 1000 Mb/s // ...: 8, 1: 1000 Mb/s
@ -214,7 +213,6 @@ impl<'r, RX, TX> Eth<'r, RX, TX> {
slcr::RclkCtrl::zeroed() slcr::RclkCtrl::zeroed()
.clkact(true) .clkact(true)
); );
});
} }
pub fn setup_gem1_clock(tx_clock: u32) { pub fn setup_gem1_clock(tx_clock: u32) {
@ -222,7 +220,7 @@ impl<'r, RX, TX> Eth<'r, RX, TX> {
let d0 = ((tx_clock - 1 + io_pll) / tx_clock).max(1).min(63); let d0 = ((tx_clock - 1 + io_pll) / tx_clock).max(1).min(63);
let d1 = (io_pll / tx_clock / d0).max(1).min(63); let d1 = (io_pll / tx_clock / d0).max(1).min(63);
slcr::RegisterBlock::unlocked(|slcr| { let slcr = slcr::RegisterBlock::new();
slcr.gem1_clk_ctrl.write( slcr.gem1_clk_ctrl.write(
slcr::GemClkCtrl::zeroed() slcr::GemClkCtrl::zeroed()
.clkact(true) .clkact(true)
@ -236,7 +234,6 @@ impl<'r, RX, TX> Eth<'r, RX, TX> {
slcr::RclkCtrl::zeroed() slcr::RclkCtrl::zeroed()
.clkact(true) .clkact(true)
); );
});
} }
pub fn start_rx<'rx>(self, rx_list: &'rx mut [rx::DescEntry], rx_buffers: &'rx mut [[u8; MTU]]) -> Eth<'r, rx::DescList<'rx>, TX> { pub fn start_rx<'rx>(self, rx_list: &'rx mut [rx::DescEntry], rx_buffers: &'rx mut [[u8; MTU]]) -> Eth<'r, rx::DescList<'rx>, TX> {

View File

@ -247,7 +247,8 @@ pub struct RegisterBlock {
register_at!(RegisterBlock, 0xF8000000, new); register_at!(RegisterBlock, 0xF8000000, new);
impl RegisterBlock { impl RegisterBlock {
/// Required to modify any sclr register /// Required to modify these sclr registers: scl, pss_rst_ctrl,
/// apu_ctrl, and wdt_clk_sel
pub fn unlocked<F: FnMut(&mut Self) -> R, R>(mut f: F) -> R { pub fn unlocked<F: FnMut(&mut Self) -> R, R>(mut f: F) -> R {
let mut self_ = Self::new(); let mut self_ = Self::new();
self_.slcr_unlock.unlock(); self_.slcr_unlock.unlock();

View File

@ -14,7 +14,7 @@ pub struct Uart {
impl Uart { impl Uart {
#[cfg(feature = "target_zc706")] #[cfg(feature = "target_zc706")]
pub fn serial(baudrate: u32) -> Self { pub fn serial(baudrate: u32) -> Self {
slcr::RegisterBlock::unlocked(|slcr| { let slcr = slcr::RegisterBlock::new();
// Route UART 1 RxD/TxD Signals to MIO Pins // Route UART 1 RxD/TxD Signals to MIO Pins
// TX pin // TX pin
slcr.mio_pin_48.write( slcr.mio_pin_48.write(
@ -31,13 +31,12 @@ impl Uart {
.io_type(slcr::IoBufferType::Lvcmos18) .io_type(slcr::IoBufferType::Lvcmos18)
.pullup(true) .pullup(true)
); );
});
Self::uart1(baudrate) Self::uart1(baudrate)
} }
#[cfg(feature = "target_cora_z7_10")] #[cfg(feature = "target_cora_z7_10")]
pub fn serial(baudrate: u32) -> Self { pub fn serial(baudrate: u32) -> Self {
slcr::RegisterBlock::unlocked(|slcr| { let slcr = slcr::RegisterBlock::new();
// Route UART 0 RxD/TxD Signals to MIO Pins // Route UART 0 RxD/TxD Signals to MIO Pins
// TX pin // TX pin
slcr.mio_pin_15.write( slcr.mio_pin_15.write(
@ -54,16 +53,14 @@ impl Uart {
.io_type(slcr::IoBufferType::Lvcmos33) .io_type(slcr::IoBufferType::Lvcmos33)
.pullup(true) .pullup(true)
); );
});
Self::uart0(baudrate) Self::uart0(baudrate)
} }
pub fn uart0(baudrate: u32) -> Self { pub fn uart0(baudrate: u32) -> Self {
slcr::RegisterBlock::unlocked(|slcr| { let slcr = slcr::RegisterBlock::new();
slcr.uart_rst_ctrl.reset_uart0(); slcr.uart_rst_ctrl.reset_uart0();
slcr.aper_clk_ctrl.enable_uart0(); slcr.aper_clk_ctrl.enable_uart0();
slcr.uart_clk_ctrl.enable_uart0(); slcr.uart_clk_ctrl.enable_uart0();
});
let mut self_ = Uart { let mut self_ = Uart {
regs: regs::RegisterBlock::uart0(), regs: regs::RegisterBlock::uart0(),
}; };
@ -72,11 +69,10 @@ impl Uart {
} }
pub fn uart1(baudrate: u32) -> Self { pub fn uart1(baudrate: u32) -> Self {
slcr::RegisterBlock::unlocked(|slcr| { let slcr = slcr::RegisterBlock::new();
slcr.uart_rst_ctrl.reset_uart1(); slcr.uart_rst_ctrl.reset_uart1();
slcr.aper_clk_ctrl.enable_uart1(); slcr.aper_clk_ctrl.enable_uart1();
slcr.uart_clk_ctrl.enable_uart1(); slcr.uart_clk_ctrl.enable_uart1();
});
let mut self_ = Uart { let mut self_ = Uart {
regs: regs::RegisterBlock::uart1(), regs: regs::RegisterBlock::uart1(),
}; };