From 3533faa7cce84d7a07a52da3605229a99ec989be Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 20 Oct 2025 22:24:25 +0200 Subject: [PATCH] continue --- zynq/zynq7000-hal/src/lib.rs | 1 + zynq/zynq7000-hal/src/sdio.rs | 59 +++++++++++++++++++++++++++++++++++ zynq/zynq7000/src/lib.rs | 4 +++ zynq/zynq7000/src/sdio.rs | 17 ++++++++-- 4 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 zynq/zynq7000-hal/src/sdio.rs diff --git a/zynq/zynq7000-hal/src/lib.rs b/zynq/zynq7000-hal/src/lib.rs index e2cf379..ce9ffc8 100644 --- a/zynq/zynq7000-hal/src/lib.rs +++ b/zynq/zynq7000-hal/src/lib.rs @@ -38,6 +38,7 @@ pub mod log; pub mod prelude; pub mod priv_tim; pub mod qspi; +pub mod sdio; pub mod slcr; pub mod spi; pub mod time; diff --git a/zynq/zynq7000-hal/src/sdio.rs b/zynq/zynq7000-hal/src/sdio.rs new file mode 100644 index 0000000..3b78cf9 --- /dev/null +++ b/zynq/zynq7000-hal/src/sdio.rs @@ -0,0 +1,59 @@ +use zynq7000::{ + sdio::SdClockDivisor, + slcr::{clocks::SrcSelIo, reset::DualRefAndClockReset}, +}; + +use crate::{clocks::Clocks, slcr::Slcr, time::Hertz}; + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum SdioId { + Sdio0, + Sdio1, +} + +pub struct SdioDivisors { + /// Divisor which will be used during the initialization phase when ACMD41 is issued. + /// + /// The SD card specification mentions that the clock needs to be between 100 and 400 kHz for + /// that phase. + pub divisor_init_phase: SdClockDivisor, + /// Divisor for the regular data transfer phase. Common target speeds are 25 MHz or 50 MHz. + pub divisor_normal: SdClockDivisor, +} + +impl SdioDivisors { + pub fn calculate(src_sel: SrcSelIo, clocks: &Clocks, target_speed: Hertz) { + + } +} +/// Reset the UART peripheral using the SLCR reset register for UART. +/// +/// Please note that this function will interfere with an already configured +/// UART instance. +#[inline] +pub fn reset(id: SdioId, cycles: u32) { + let assert_reset = match id { + SdioId::Sdio0 => DualRefAndClockReset::builder() + .with_periph1_ref_rst(false) + .with_periph0_ref_rst(true) + .with_periph1_cpu1x_rst(false) + .with_periph0_cpu1x_rst(true) + .build(), + SdioId::Sdio1 => DualRefAndClockReset::builder() + .with_periph1_ref_rst(true) + .with_periph0_ref_rst(false) + .with_periph1_cpu1x_rst(true) + .with_periph0_cpu1x_rst(false) + .build(), + }; + unsafe { + Slcr::with(|regs| { + regs.reset_ctrl().write_sdio(assert_reset); + // Keep it in reset for a few cycle.. not sure if this is necessary. + for _ in 0..cycles { + cortex_ar::asm::nop(); + } + regs.reset_ctrl().write_sdio(DualRefAndClockReset::DEFAULT); + }); + } +} diff --git a/zynq/zynq7000/src/lib.rs b/zynq/zynq7000/src/lib.rs index 77e23f5..8718c33 100644 --- a/zynq/zynq7000/src/lib.rs +++ b/zynq/zynq7000/src/lib.rs @@ -64,6 +64,8 @@ pub struct Peripherals { pub qspi: qspi::MmioRegisters<'static>, pub devcfg: devcfg::MmioRegisters<'static>, pub xadc: xadc::MmioRegisters<'static>, + pub sdio_0: sdio::MmioRegisters<'static>, + pub sdio_1: sdio::MmioRegisters<'static>, } impl Peripherals { @@ -104,6 +106,8 @@ impl Peripherals { qspi: qspi::Registers::new_mmio_fixed(), devcfg: devcfg::Registers::new_mmio_fixed(), xadc: xadc::Registers::new_mmio_fixed(), + sdio_0: sdio::Registers::new_mmio_fixed_0(), + sdio_1: sdio::Registers::new_mmio_fixed_1(), } } } diff --git a/zynq/zynq7000/src/sdio.rs b/zynq/zynq7000/src/sdio.rs index 2de5ecc..f124ce7 100644 --- a/zynq/zynq7000/src/sdio.rs +++ b/zynq/zynq7000/src/sdio.rs @@ -251,7 +251,7 @@ pub struct HostPowerBlockgapWakeupControl { #[bitbybit::bitenum(u8, exhaustive = false)] #[derive(Debug, PartialEq, Eq)] -pub enum SdclkFrequencySelect { +pub enum SdClockDivisor { Div256 = 0x80, Div128 = 0x40, Div64 = 0x20, @@ -277,7 +277,7 @@ pub struct ClockAndTimeoutAndSwResetControl { #[bits(16..=19, rw)] data_timeout_counter_value: u4, #[bits(8..=15, rw)] - sdclk_frequency_select: Option, + sdclk_frequency_select: Option, #[bit(2, rw)] sd_clock_enable: bool, #[bit(1, r)] @@ -388,7 +388,6 @@ pub struct InterruptMask { transfer_complete: bool, #[bit(0, rw)] command_complete: bool, - } #[derive(derive_mmio::Mmio)] @@ -430,3 +429,15 @@ pub struct Registers { } static_assertions::const_assert_eq!(core::mem::size_of::(), 0x100); + +impl Registers { + #[inline] + pub fn new_mmio_fixed_0() -> MmioRegisters<'static> { + unsafe { Self::new_mmio_at(SDIO_BASE_ADDR_0) } + } + + #[inline] + pub fn new_mmio_fixed_1() -> MmioRegisters<'static> { + unsafe { Self::new_mmio_at(SDIO_BASE_ADDR_1) } + } +}