This commit is contained in:
Robin Mueller
2025-10-20 22:24:25 +02:00
parent 5235eb422d
commit 3533faa7cc
4 changed files with 78 additions and 3 deletions

View File

@@ -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;

View File

@@ -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);
});
}
}

View File

@@ -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(),
}
}
}

View File

@@ -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<SdclkFrequencySelect>,
sdclk_frequency_select: Option<SdClockDivisor>,
#[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::<Registers>(), 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) }
}
}