use super::{EXTMEM_ORIGIN, PsramSize};
use crate::{
clock::ll::{ClockTree, PsramFunctionClockConfig, PsramInstance},
peripherals::HP_SYS_CLKRST,
};
mod oct_hex;
#[derive(Copy, Clone, Debug, Default, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[instability::unstable]
pub struct PsramConfig {
pub size: PsramSize,
pub timing: PsramTimingParams,
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct PsramTimingParams {
pub clock_source: PsramFunctionClockConfig,
pub clock: u32,
pub mr0_rl: u8,
pub mr4_wl: u8,
pub rd_dummy_bits: u8,
pub wr_dummy_bits: u8,
pub reg_dummy_bits: u32,
}
impl Default for PsramTimingParams {
fn default() -> Self {
Self::MHZ_250
}
}
impl PsramTimingParams {
pub const MHZ_20: Self = Self {
clock_source: PsramFunctionClockConfig::Mpll,
clock: 20,
mr0_rl: 2,
mr4_wl: 2,
rd_dummy_bits: 17,
wr_dummy_bits: 7,
reg_dummy_bits: 8,
};
pub const MHZ_80: Self = Self {
clock_source: PsramFunctionClockConfig::Mpll,
clock: 80,
mr0_rl: 2,
mr4_wl: 2,
rd_dummy_bits: 17,
wr_dummy_bits: 7,
reg_dummy_bits: 8,
};
pub const MHZ_125: Self = Self {
clock_source: PsramFunctionClockConfig::Mpll,
clock: 125,
mr0_rl: 2,
mr4_wl: 2,
rd_dummy_bits: 17,
wr_dummy_bits: 7,
reg_dummy_bits: 8,
};
pub const MHZ_200: Self = Self {
clock_source: PsramFunctionClockConfig::Mpll,
clock: 200,
mr0_rl: 4,
mr4_wl: 1,
rd_dummy_bits: 25,
wr_dummy_bits: 11,
reg_dummy_bits: 12,
};
pub const MHZ_250: Self = Self {
clock_source: PsramFunctionClockConfig::Mpll,
clock: 250,
mr0_rl: 6,
mr4_wl: 3,
rd_dummy_bits: 33,
wr_dummy_bits: 15,
reg_dummy_bits: 16,
};
}
#[crate::ram]
pub(crate) fn init_psram(config: &mut PsramConfig) -> bool {
enable_psram_mspi();
reset_psram_mspi();
ClockTree::with(|clocks| {
PsramInstance::Psram.configure_function_clock(clocks, config.timing.clock_source);
PsramInstance::Psram.request_function_clock(clocks);
});
if !oct_hex::set_bus_clock(config.timing.clock) {
return false;
}
oct_hex::enable_dll();
oct_hex::psram_pad_init(false); oct_hex::set_cs_timing();
oct_hex::init_mr_registers(&config.timing, false);
if config.size.is_auto() {
config.size = PsramSize::Size(oct_hex::psram_detect_size(&config.timing));
}
oct_hex::configure_psram_mspi(&config.timing, false);
oct_hex::mmu_map_psram(config.size.get());
true
}
pub(crate) fn map_psram(config: PsramConfig) -> core::ops::Range<usize> {
let start = EXTMEM_ORIGIN;
start..start + config.size.get()
}
fn enable_psram_mspi() {
HP_SYS_CLKRST::regs()
.psram_ctrl0()
.modify(|_, w| w.sys_clk_en().set_bit());
}
fn reset_psram_mspi() {
HP_SYS_CLKRST::regs().psram_ctrl0().modify(|_, w| {
w.axi_rst_en().set_bit();
w.apb_rst_en().set_bit()
});
HP_SYS_CLKRST::regs().psram_ctrl0().modify(|_, w| {
w.axi_rst_en().clear_bit();
w.apb_rst_en().clear_bit()
});
}