diff --git a/src/zynq/clocks.rs b/src/zynq/clocks.rs index 8f2401a7..45fda27d 100644 --- a/src/zynq/clocks.rs +++ b/src/zynq/clocks.rs @@ -99,29 +99,30 @@ impl CpuClocks { .nth(0) .expect("PLL_FDIV_LOCK_PARAM") .1.clone(); - let slcr = slcr::RegisterBlock::new(); - slcr.ddr_pll_ctrl.modify(|_, w| w - .pll_pwrdwn(false) - .pll_bypass_force(true) - .pll_fdiv(fdiv) - ); - slcr.ddr_pll_cfg.write( - slcr::PllCfg::zeroed() - .pll_res(pll_res) - .pll_cp(pll_cp) - .lock_cnt(lock_cnt) - ); - slcr.ddr_pll_ctrl.modify(|_, w| w - .pll_reset(true) - ); - slcr.ddr_pll_ctrl.modify(|_, w| w - .pll_reset(false) - ); - while ! slcr.pll_status.read().ddr_pll_lock() {} - slcr.ddr_pll_ctrl.modify(|_, w| w - .pll_bypass_force(false) - .pll_bypass_qual(false) - ); + slcr::RegisterBlock::unlocked(|regs| { + regs.ddr_pll_ctrl.modify(|_, w| w + .pll_pwrdwn(false) + .pll_bypass_force(true) + .pll_fdiv(fdiv) + ); + 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) + ); + regs.ddr_pll_ctrl.modify(|_, w| w + .pll_reset(false) + ); + while ! regs.pll_status.read().ddr_pll_lock() {} + regs.ddr_pll_ctrl.modify(|_, w| w + .pll_bypass_force(false) + .pll_bypass_qual(false) + ); + }); } } diff --git a/src/zynq/ddr/mod.rs b/src/zynq/ddr/mod.rs index b2c0432e..fba49f9d 100644 --- a/src/zynq/ddr/mod.rs +++ b/src/zynq/ddr/mod.rs @@ -42,14 +42,15 @@ impl DdrRam { let ddr3x_clk_divisor = ((clocks.ddr - 1) / DDR_FREQ + 1).min(255) as u8; let ddr2x_clk_divisor = 3 * ddr3x_clk_divisor / 2; - let slcr = slcr::RegisterBlock::new(); - slcr.ddr_clk_ctrl.write( - slcr::DdrClkCtrl::zeroed() - .ddr_2xclkact(true) - .ddr_3xclkact(true) - .ddr_2xclk_divisor(ddr2x_clk_divisor) - .ddr_3xclk_divisor(ddr3x_clk_divisor) - ); + slcr::RegisterBlock::unlocked(|slcr| { + slcr.ddr_clk_ctrl.write( + slcr::DdrClkCtrl::zeroed() + .ddr_2xclkact(true) + .ddr_3xclkact(true) + .ddr_2xclk_divisor(ddr2x_clk_divisor) + .ddr_3xclk_divisor(ddr3x_clk_divisor) + ); + }); clocks } @@ -61,99 +62,101 @@ impl DdrRam { let divisor1 = (clocks.ddr / DCI_FREQ / u32::from(divisor0)) .max(1).min(63) as u8; - let slcr = slcr::RegisterBlock::new(); - // Step 1. - slcr.dci_clk_ctrl.write( - slcr::DciClkCtrl::zeroed() - .clkact(true) - .divisor0(divisor0) - .divisor1(divisor1) - ); + 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/DDR3L - 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() {} + // 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/DDR3L + 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() {} + }); } /// Zynq-7000 AP SoC Technical Reference Manual: /// 10.6.3 DDR IOB Configuration fn configure_iob() { - let slcr = slcr::RegisterBlock::new(); - let addr_config = slcr::DdriobConfig::zeroed() - .output_en(slcr::DdriobOutputEn::Obuf); - slcr.ddriob_addr0.write(addr_config.clone()); - slcr.ddriob_addr1.write(addr_config); + slcr::RegisterBlock::unlocked(|slcr| { + let addr_config = slcr::DdriobConfig::zeroed() + .output_en(slcr::DdriobOutputEn::Obuf); + slcr.ddriob_addr0.write(addr_config.clone()); + slcr.ddriob_addr1.write(addr_config); - let data_config = slcr::DdriobConfig::zeroed() - .inp_type(slcr::DdriobInputType::VrefDifferential) - .term_en(true) - .dci_type(slcr::DdriobDciType::Termination) - .output_en(slcr::DdriobOutputEn::Obuf); - slcr.ddriob_data0.write(data_config.clone()); - slcr.ddriob_data1.write(data_config); + let data_config = slcr::DdriobConfig::zeroed() + .inp_type(slcr::DdriobInputType::VrefDifferential) + .term_en(true) + .dci_type(slcr::DdriobDciType::Termination) + .output_en(slcr::DdriobOutputEn::Obuf); + slcr.ddriob_data0.write(data_config.clone()); + slcr.ddriob_data1.write(data_config); - let diff_config = slcr::DdriobConfig::zeroed() - .inp_type(slcr::DdriobInputType::Differential) - .term_en(true) - .dci_type(slcr::DdriobDciType::Termination) - .output_en(slcr::DdriobOutputEn::Obuf); - slcr.ddriob_diff0.write(diff_config.clone()); - slcr.ddriob_diff1.write(diff_config); + let diff_config = slcr::DdriobConfig::zeroed() + .inp_type(slcr::DdriobInputType::Differential) + .term_en(true) + .dci_type(slcr::DdriobDciType::Termination) + .output_en(slcr::DdriobOutputEn::Obuf); + slcr.ddriob_diff0.write(diff_config.clone()); + slcr.ddriob_diff1.write(diff_config); - slcr.ddriob_clock.write( - slcr::DdriobConfig::zeroed() - .output_en(slcr::DdriobOutputEn::Obuf) - ); + slcr.ddriob_clock.write( + slcr::DdriobConfig::zeroed() + .output_en(slcr::DdriobOutputEn::Obuf) + ); - unsafe { - // Not documented in Technical Reference Manual - slcr.ddriob_drive_slew_addr.write(0x0018C61C); - slcr.ddriob_drive_slew_data.write(0x00F9861C); - slcr.ddriob_drive_slew_diff.write(0x00F9861C); - slcr.ddriob_drive_slew_clock.write(0x00F9861C); - } + unsafe { + // Not documented in Technical Reference Manual + slcr.ddriob_drive_slew_addr.write(0x0018C61C); + slcr.ddriob_drive_slew_data.write(0x00F9861C); + slcr.ddriob_drive_slew_diff.write(0x00F9861C); + slcr.ddriob_drive_slew_clock.write(0x00F9861C); + } - #[cfg(feature = "target_zc706")] - let vref_sel = slcr::DdriobVrefSel::Vref0_75V; - #[cfg(feature = "target_cora_z7_10")] - let vref_sel = slcr::DdriobVrefSel::Vref0_675V; + #[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(true) - .vref_ext_en_upper(true) - .vref_sel(vref_sel) - .vref_int_en(false) - ); + // // 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(true) + .vref_ext_en_upper(true) + .vref_sel(vref_sel) + .vref_int_en(false) + ); + }); } /// Reset DDR controller diff --git a/src/zynq/eth/mod.rs b/src/zynq/eth/mod.rs index 51680a28..a4a59400 100644 --- a/src/zynq/eth/mod.rs +++ b/src/zynq/eth/mod.rs @@ -27,131 +27,132 @@ pub struct Eth<'r, RX, TX> { impl<'r> Eth<'r, (), ()> { pub fn default(macaddr: [u8; 6]) -> Self { - let slcr = slcr::RegisterBlock::new(); - // Manual example: 0x0000_1280 - // MDIO - slcr.mio_pin_53.write( - slcr::MioPin53::zeroed() - .l3_sel(0b100) - .io_type(slcr::IoBufferType::Lvcmos18) - .pullup(true) - ); - // MDC - slcr.mio_pin_52.write( - slcr::MioPin52::zeroed() - .l3_sel(0b100) - .io_type(slcr::IoBufferType::Lvcmos18) - .pullup(true) - ); - // Manual example: 0x0000_3902 - // TX_CLK - slcr.mio_pin_16.write( - slcr::MioPin16::zeroed() - .l0_sel(true) - .speed(true) - .io_type(slcr::IoBufferType::Hstl) - .pullup(true) - .disable_rcvr(true) - ); - // TX_CTRL - slcr.mio_pin_21.write( - slcr::MioPin21::zeroed() - .l0_sel(true) - .speed(true) - .io_type(slcr::IoBufferType::Hstl) - .pullup(true) - .disable_rcvr(true) - ); - // TXD3 - slcr.mio_pin_20.write( - slcr::MioPin20::zeroed() - .l0_sel(true) - .speed(true) - .io_type(slcr::IoBufferType::Hstl) - .pullup(true) - .disable_rcvr(true) - ); - // TXD2 - slcr.mio_pin_19.write( - slcr::MioPin19::zeroed() - .l0_sel(true) - .speed(true) - .io_type(slcr::IoBufferType::Hstl) - .pullup(true) - .disable_rcvr(true) - ); - // TXD1 - slcr.mio_pin_18.write( - slcr::MioPin18::zeroed() - .l0_sel(true) - .speed(true) - .io_type(slcr::IoBufferType::Hstl) - .pullup(true) - .disable_rcvr(true) - ); - // TXD0 - slcr.mio_pin_17.write( - slcr::MioPin17::zeroed() - .l0_sel(true) - .speed(true) - .io_type(slcr::IoBufferType::Hstl) - .pullup(true) - .disable_rcvr(true) - ); - // Manual example: 0x0000_1903 - // RX_CLK - slcr.mio_pin_22.write( - slcr::MioPin22::zeroed() - .tri_enable(true) - .l0_sel(true) - .io_type(slcr::IoBufferType::Hstl) - .pullup(true) - ); - // RX_CTRL - slcr.mio_pin_27.write( - slcr::MioPin27::zeroed() - .tri_enable(true) - .l0_sel(true) - .io_type(slcr::IoBufferType::Hstl) - .pullup(true) - ); - // RXD3 - slcr.mio_pin_26.write( - slcr::MioPin26::zeroed() - .tri_enable(true) - .l0_sel(true) - .io_type(slcr::IoBufferType::Hstl) - .pullup(true) - ); - // RXD2 - slcr.mio_pin_25.write( - slcr::MioPin25::zeroed() - .tri_enable(true) - .l0_sel(true) - .io_type(slcr::IoBufferType::Hstl) - .pullup(true) - ); - // RXD1 - slcr.mio_pin_24.write( - slcr::MioPin24::zeroed() - .tri_enable(true) - .l0_sel(true) - .io_type(slcr::IoBufferType::Hstl) - .pullup(true) - ); - // RXD0 - slcr.mio_pin_23.write( - slcr::MioPin23::zeroed() - .tri_enable(true) - .l0_sel(true) - .io_type(slcr::IoBufferType::Hstl) - .pullup(true) - ); - // VREF internal generator - slcr.gpiob_ctrl.write( - slcr::GpiobCtrl::zeroed() - .vref_en(true) - ); + slcr::RegisterBlock::unlocked(|slcr| { + // Manual example: 0x0000_1280 + // MDIO + slcr.mio_pin_53.write( + slcr::MioPin53::zeroed() + .l3_sel(0b100) + .io_type(slcr::IoBufferType::Lvcmos18) + .pullup(true) + ); + // MDC + slcr.mio_pin_52.write( + slcr::MioPin52::zeroed() + .l3_sel(0b100) + .io_type(slcr::IoBufferType::Lvcmos18) + .pullup(true) + ); + // Manual example: 0x0000_3902 + // TX_CLK + slcr.mio_pin_16.write( + slcr::MioPin16::zeroed() + .l0_sel(true) + .speed(true) + .io_type(slcr::IoBufferType::Hstl) + .pullup(true) + .disable_rcvr(true) + ); + // TX_CTRL + slcr.mio_pin_21.write( + slcr::MioPin21::zeroed() + .l0_sel(true) + .speed(true) + .io_type(slcr::IoBufferType::Hstl) + .pullup(true) + .disable_rcvr(true) + ); + // TXD3 + slcr.mio_pin_20.write( + slcr::MioPin20::zeroed() + .l0_sel(true) + .speed(true) + .io_type(slcr::IoBufferType::Hstl) + .pullup(true) + .disable_rcvr(true) + ); + // TXD2 + slcr.mio_pin_19.write( + slcr::MioPin19::zeroed() + .l0_sel(true) + .speed(true) + .io_type(slcr::IoBufferType::Hstl) + .pullup(true) + .disable_rcvr(true) + ); + // TXD1 + slcr.mio_pin_18.write( + slcr::MioPin18::zeroed() + .l0_sel(true) + .speed(true) + .io_type(slcr::IoBufferType::Hstl) + .pullup(true) + .disable_rcvr(true) + ); + // TXD0 + slcr.mio_pin_17.write( + slcr::MioPin17::zeroed() + .l0_sel(true) + .speed(true) + .io_type(slcr::IoBufferType::Hstl) + .pullup(true) + .disable_rcvr(true) + ); + // Manual example: 0x0000_1903 + // RX_CLK + slcr.mio_pin_22.write( + slcr::MioPin22::zeroed() + .tri_enable(true) + .l0_sel(true) + .io_type(slcr::IoBufferType::Hstl) + .pullup(true) + ); + // RX_CTRL + slcr.mio_pin_27.write( + slcr::MioPin27::zeroed() + .tri_enable(true) + .l0_sel(true) + .io_type(slcr::IoBufferType::Hstl) + .pullup(true) + ); + // RXD3 + slcr.mio_pin_26.write( + slcr::MioPin26::zeroed() + .tri_enable(true) + .l0_sel(true) + .io_type(slcr::IoBufferType::Hstl) + .pullup(true) + ); + // RXD2 + slcr.mio_pin_25.write( + slcr::MioPin25::zeroed() + .tri_enable(true) + .l0_sel(true) + .io_type(slcr::IoBufferType::Hstl) + .pullup(true) + ); + // RXD1 + slcr.mio_pin_24.write( + slcr::MioPin24::zeroed() + .tri_enable(true) + .l0_sel(true) + .io_type(slcr::IoBufferType::Hstl) + .pullup(true) + ); + // RXD0 + slcr.mio_pin_23.write( + slcr::MioPin23::zeroed() + .tri_enable(true) + .l0_sel(true) + .io_type(slcr::IoBufferType::Hstl) + .pullup(true) + ); + // VREF internal generator + slcr.gpiob_ctrl.write( + slcr::GpiobCtrl::zeroed() + .vref_en(true) + ); + }); Self::gem0(macaddr) } @@ -197,22 +198,23 @@ impl<'r, RX, TX> Eth<'r, RX, TX> { 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 slcr = slcr::RegisterBlock::new(); - slcr.gem0_clk_ctrl.write( - // 0x0050_0801: 8, 5: 100 Mb/s - // ...: 8, 1: 1000 Mb/s - slcr::GemClkCtrl::zeroed() - .clkact(true) - .srcsel(slcr::PllSource::IoPll) - .divisor(d0 as u8) - .divisor1(d1 as u8) - ); - // Enable gem0 recv clock - slcr.gem0_rclk_ctrl.write( - // 0x0000_0801 - slcr::RclkCtrl::zeroed() - .clkact(true) - ); + slcr::RegisterBlock::unlocked(|slcr| { + slcr.gem0_clk_ctrl.write( + // 0x0050_0801: 8, 5: 100 Mb/s + // ...: 8, 1: 1000 Mb/s + slcr::GemClkCtrl::zeroed() + .clkact(true) + .srcsel(slcr::PllSource::IoPll) + .divisor(d0 as u8) + .divisor1(d1 as u8) + ); + // Enable gem0 recv clock + slcr.gem0_rclk_ctrl.write( + // 0x0000_0801 + slcr::RclkCtrl::zeroed() + .clkact(true) + ); + }); } pub fn setup_gem1_clock(tx_clock: u32) { @@ -220,20 +222,21 @@ impl<'r, RX, TX> Eth<'r, RX, TX> { 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 slcr = slcr::RegisterBlock::new(); - slcr.gem1_clk_ctrl.write( - slcr::GemClkCtrl::zeroed() - .clkact(true) - .srcsel(slcr::PllSource::IoPll) - .divisor(d0 as u8) - .divisor1(d1 as u8) - ); - // Enable gem1 recv clock - slcr.gem1_rclk_ctrl.write( - // 0x0000_0801 - slcr::RclkCtrl::zeroed() - .clkact(true) - ); + slcr::RegisterBlock::unlocked(|slcr| { + slcr.gem1_clk_ctrl.write( + slcr::GemClkCtrl::zeroed() + .clkact(true) + .srcsel(slcr::PllSource::IoPll) + .divisor(d0 as u8) + .divisor1(d1 as u8) + ); + // Enable gem1 recv clock + slcr.gem1_rclk_ctrl.write( + // 0x0000_0801 + slcr::RclkCtrl::zeroed() + .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> { diff --git a/src/zynq/uart/mod.rs b/src/zynq/uart/mod.rs index b6d8a3b5..973cb48d 100644 --- a/src/zynq/uart/mod.rs +++ b/src/zynq/uart/mod.rs @@ -14,53 +14,56 @@ pub struct Uart { impl Uart { #[cfg(feature = "target_zc706")] pub fn serial(baudrate: u32) -> Self { - let slcr = slcr::RegisterBlock::new(); - // Route UART 1 RxD/TxD Signals to MIO Pins - // TX pin - slcr.mio_pin_48.write( - slcr::MioPin48::zeroed() - .l3_sel(0b111) - .io_type(slcr::IoBufferType::Lvcmos18) - .pullup(true) - ); - // RX pin - slcr.mio_pin_49.write( - slcr::MioPin49::zeroed() - .tri_enable(true) - .l3_sel(0b111) - .io_type(slcr::IoBufferType::Lvcmos18) - .pullup(true) - ); + slcr::RegisterBlock::unlocked(|slcr| { + // Route UART 1 RxD/TxD Signals to MIO Pins + // TX pin + slcr.mio_pin_48.write( + slcr::MioPin48::zeroed() + .l3_sel(0b111) + .io_type(slcr::IoBufferType::Lvcmos18) + .pullup(true) + ); + // RX pin + slcr.mio_pin_49.write( + slcr::MioPin49::zeroed() + .tri_enable(true) + .l3_sel(0b111) + .io_type(slcr::IoBufferType::Lvcmos18) + .pullup(true) + ); + }); Self::uart1(baudrate) } #[cfg(feature = "target_cora_z7_10")] pub fn serial(baudrate: u32) -> Self { - let slcr = slcr::RegisterBlock::new(); - // Route UART 0 RxD/TxD Signals to MIO Pins - // TX pin - slcr.mio_pin_15.write( - slcr::MioPin15::zeroed() - .l3_sel(0b111) - .io_type(slcr::IoBufferType::Lvcmos33) - .pullup(true) - ); - // RX pin - slcr.mio_pin_14.write( - slcr::MioPin14::zeroed() - .tri_enable(true) - .l3_sel(0b111) - .io_type(slcr::IoBufferType::Lvcmos33) - .pullup(true) - ); + slcr::RegisterBlock::unlocked(|slcr| { + // Route UART 0 RxD/TxD Signals to MIO Pins + // TX pin + slcr.mio_pin_15.write( + slcr::MioPin15::zeroed() + .l3_sel(0b111) + .io_type(slcr::IoBufferType::Lvcmos33) + .pullup(true) + ); + // RX pin + slcr.mio_pin_14.write( + slcr::MioPin14::zeroed() + .tri_enable(true) + .l3_sel(0b111) + .io_type(slcr::IoBufferType::Lvcmos33) + .pullup(true) + ); + }); Self::uart0(baudrate) } pub fn uart0(baudrate: u32) -> Self { - let slcr = slcr::RegisterBlock::new(); - slcr.uart_rst_ctrl.reset_uart0(); - slcr.aper_clk_ctrl.enable_uart0(); - slcr.uart_clk_ctrl.enable_uart0(); + slcr::RegisterBlock::unlocked(|slcr| { + slcr.uart_rst_ctrl.reset_uart0(); + slcr.aper_clk_ctrl.enable_uart0(); + slcr.uart_clk_ctrl.enable_uart0(); + }); let mut self_ = Uart { regs: regs::RegisterBlock::uart0(), }; @@ -69,10 +72,11 @@ impl Uart { } pub fn uart1(baudrate: u32) -> Self { - let slcr = slcr::RegisterBlock::new(); - slcr.uart_rst_ctrl.reset_uart1(); - slcr.aper_clk_ctrl.enable_uart1(); - slcr.uart_clk_ctrl.enable_uart1(); + slcr::RegisterBlock::unlocked(|slcr| { + slcr.uart_rst_ctrl.reset_uart1(); + slcr.aper_clk_ctrl.enable_uart1(); + slcr.uart_clk_ctrl.enable_uart1(); + }); let mut self_ = Uart { regs: regs::RegisterBlock::uart1(), };