Files
zynq7000-rs/zynq7000/src/slcr/mod.rs

225 lines
4.9 KiB
Rust

//! System Level Control Registers (slcr)
//!
//! Writing any of these registers required unlocking the SLCR first.
use arbitrary_int::{u3, u4};
pub use clocks::{ClockControl, MmioClockControl};
pub use reset::{MmioResetControl, ResetControl};
const SLCR_BASE_ADDR: usize = 0xF8000000;
const CLOCK_CONTROL_OFFSET: usize = 0x100;
const RESET_BLOCK_OFFSET: usize = 0x200;
const GPIOB_OFFSET: usize = 0xB00;
const DDRIOB_OFFSET: usize = 0xB40;
pub mod clocks;
pub mod mio;
pub mod reset;
#[derive(derive_mmio::Mmio)]
#[repr(C)]
pub struct DdrIoB {
ddriob_addr0: u32,
ddriob_addr1: u32,
ddriob_data0: u32,
ddriob_data1: u32,
ddriob_diff0: u32,
ddriob_diff1: u32,
ddriob_clock: u32,
ddriob_drive_slew_addr: u32,
ddriob_drive_slew_data: u32,
ddriob_drive_slew_diff: u32,
ddriob_drive_slew_clock: u32,
ddriob_ddr_ctrl: u32,
ddriob_dci_ctrl: u32,
ddriob_dci_status: u32,
}
impl DdrIoB {
/// Create a new handle to this peripheral.
///
/// Writing to this register requires unlocking the SLCR registers first.
///
/// # Safety
///
/// If you create multiple instances of this handle at the same time, you are responsible for
/// ensuring that there are no read-modify-write races on any of the registers.
pub unsafe fn new_mmio_fixed() -> MmioDdrIoB<'static> {
unsafe { Self::new_mmio_at(SLCR_BASE_ADDR + DDRIOB_OFFSET) }
}
}
static_assertions::const_assert_eq!(core::mem::size_of::<DdrIoB>(), 0x38);
#[bitbybit::bitenum(u3, exhaustive = false)]
pub enum VrefSel {
Disabled = 0b000,
Vref0_9V = 0b001,
}
#[bitbybit::bitfield(u32)]
#[derive(Debug)]
pub struct GpiobControl {
#[bit(11, rw)]
vref_sw_en: bool,
#[bits(4..=6, rw)]
vref_sel: Option<VrefSel>,
#[bit(0, rw)]
vref_en: bool,
}
#[derive(derive_mmio::Mmio)]
#[repr(C)]
pub struct GpiobRegisters {
ctrl: GpiobControl,
cfg_cmos18: u32,
cfg_cmos25: u32,
cfg_cmos33: u32,
_gap17: u32,
cfg_hstl: u32,
drvr_bias_ctrl: u32,
}
impl GpiobRegisters {
/// Create a new handle to this peripheral.
///
/// Writing to this register requires unlocking the SLCR registers first.
///
/// # Safety
///
/// If you create multiple instances of this handle at the same time, you are responsible for
/// ensuring that there are no read-modify-write races on any of the registers.
pub unsafe fn new_mmio_fixed() -> MmioGpiobRegisters<'static> {
unsafe { Self::new_mmio_at(SLCR_BASE_ADDR + GPIOB_OFFSET) }
}
}
#[bitbybit::bitfield(u32)]
#[derive(Debug)]
pub struct BootModeRegister {
#[bit(4, r)]
pll_bypass: bool,
#[bits(0..=3, r)]
boot_mode: u4,
}
#[bitbybit::bitenum(u4)]
#[derive(Debug, PartialEq, Eq)]
pub enum LevelShifterConfig {
DisableAll = 0x00,
EnablePsToPl = 0xA,
EnableAll = 0xF,
}
#[bitbybit::bitfield(u32)]
pub struct LevelShifterReg {
#[bits(0..=3, rw)]
user_lvl_shftr_en: Option<LevelShifterConfig>,
}
/// System Level Control Registers
#[derive(derive_mmio::Mmio)]
#[repr(C)]
pub struct Slcr {
/// Secure configuration lock.
scl: u32,
/// SLCR write protection lock
lock: u32,
/// SLCR write protection unlock
unlock: u32,
/// SLCR write protection status
lock_status: u32,
_gap0: [u32; 0x3C],
#[mmio(inner)]
clk_ctrl: ClockControl,
_gap1: [u32; 0x0E],
#[mmio(inner)]
reset_ctrl: ResetControl,
_gap2: [u32; 0x02],
reboot_status: u32,
boot_mode: BootModeRegister,
_gap3: [u32; 0x28],
apu_ctrl: u32,
wdt_clk_set: u32,
_gap4: [u32; 0x4E],
tz_dma_ns: u32,
tz_dma_irq_ns: u32,
tz_dma_periph_ns: u32,
_gap5: [u32; 0x39],
pss_idcode: u32,
_gap6: [u32; 0x33],
ddr_urgent: u32,
_gap7: [u32; 0x02],
ddr_cal_start: u32,
_gap8: u32,
ddr_ref_start: u32,
ddr_cmd_status: u32,
ddr_urgent_sel: u32,
ddr_dfi_status: u32,
_gap9: [u32; 0x37],
mio_pins: [mio::Config; 0x36],
_gap10: [u32; 0x0B],
mio_loopback: u32,
_gap11: u32,
mio_mst_tri_0: u32,
mio_mst_tri_1: u32,
_gap12: [u32; 7],
sd_0_wp_cd_sel: u32,
sd_1_wp_cd_sel: u32,
_gap13: [u32; 0x32],
lvl_shftr_en: LevelShifterReg,
_gap14: [u32; 0x03],
ocm_cfg: u32,
_gap15: [u32; 0x42],
reserved: u32,
_gap16: [u32; 0x38],
_gap18: [u32; 0x09],
#[mmio(inner)]
gpiob: GpiobRegisters,
#[mmio(inner)]
ddriob: DdrIoB,
}
static_assertions::const_assert_eq!(core::mem::size_of::<Slcr>(), 0xB78);
impl Slcr {
/// Create a new handle to this peripheral.
///
/// Writing to this register requires unlocking the SLCR registers first.
///
/// # Safety
///
/// If you create multiple instances of this handle at the same time, you are responsible for
/// ensuring that there are no read-modify-write races on any of the registers.
pub unsafe fn new_mmio_fixed() -> MmioSlcr<'static> {
unsafe { Self::new_mmio_at(SLCR_BASE_ADDR) }
}
}