esp_hal/psram/
esp32s31.rs1use super::{EXTMEM_ORIGIN, PsramSize};
4use crate::{
5 clock::ll::{ClockTree, PsramFunctionClockConfig, PsramInstance},
6 peripherals::HP_SYS_CLKRST,
7};
8
9mod oct_hex;
10
11#[derive(Copy, Clone, Debug, Default, PartialEq)]
13#[cfg_attr(feature = "defmt", derive(defmt::Format))]
14#[instability::unstable]
15pub struct PsramConfig {
16 pub size: PsramSize,
18
19 pub timing: PsramTimingParams,
21 }
25
26#[derive(Copy, Clone, Debug, PartialEq)]
31#[cfg_attr(feature = "defmt", derive(defmt::Format))]
32pub struct PsramTimingParams {
33 pub clock_source: PsramFunctionClockConfig,
35
36 pub clock: u32,
38
39 pub mr0_rl: u8,
41
42 pub mr4_wl: u8,
44
45 pub rd_dummy_bits: u8,
49
50 pub wr_dummy_bits: u8,
54
55 pub reg_dummy_bits: u32,
57}
58
59impl Default for PsramTimingParams {
60 fn default() -> Self {
61 Self::MHZ_250
62 }
63}
64
65impl PsramTimingParams {
66 pub const MHZ_20: Self = Self {
68 clock_source: PsramFunctionClockConfig::Mpll,
69 clock: 20,
70 mr0_rl: 2,
71 mr4_wl: 2,
72 rd_dummy_bits: 17,
73 wr_dummy_bits: 7,
74 reg_dummy_bits: 8,
75 };
76
77 pub const MHZ_80: Self = Self {
79 clock_source: PsramFunctionClockConfig::Mpll,
80 clock: 80,
81 mr0_rl: 2,
82 mr4_wl: 2,
83 rd_dummy_bits: 17,
84 wr_dummy_bits: 7,
85 reg_dummy_bits: 8,
86 };
87
88 pub const MHZ_125: Self = Self {
90 clock_source: PsramFunctionClockConfig::Mpll,
91 clock: 125,
92 mr0_rl: 2,
93 mr4_wl: 2,
94 rd_dummy_bits: 17,
95 wr_dummy_bits: 7,
96 reg_dummy_bits: 8,
97 };
98
99 pub const MHZ_200: Self = Self {
101 clock_source: PsramFunctionClockConfig::Mpll,
102 clock: 200,
103 mr0_rl: 4,
104 mr4_wl: 1,
105 rd_dummy_bits: 25,
106 wr_dummy_bits: 11,
107 reg_dummy_bits: 12,
108 };
109
110 pub const MHZ_250: Self = Self {
112 clock_source: PsramFunctionClockConfig::Mpll,
113 clock: 250,
114 mr0_rl: 6,
115 mr4_wl: 3,
116 rd_dummy_bits: 33,
117 wr_dummy_bits: 15,
118 reg_dummy_bits: 16,
119 };
120}
121
122#[crate::ram]
124pub(crate) fn init_psram(config: &mut PsramConfig) -> bool {
125 enable_psram_mspi();
127 reset_psram_mspi();
128
129 ClockTree::with(|clocks| {
130 PsramInstance::Psram.configure_function_clock(clocks, config.timing.clock_source);
131 PsramInstance::Psram.request_function_clock(clocks);
132 });
133
134 if !oct_hex::set_bus_clock(config.timing.clock) {
136 return false;
137 }
138 oct_hex::enable_dll();
139 oct_hex::psram_pad_init(false); oct_hex::set_cs_timing();
141
142 oct_hex::init_mr_registers(&config.timing, false);
144
145 if config.size.is_auto() {
146 config.size = PsramSize::Size(oct_hex::psram_detect_size(&config.timing));
147 }
148
149 oct_hex::configure_psram_mspi(&config.timing, false);
151 oct_hex::mmu_map_psram(config.size.get());
152
153 true
154}
155
156pub(crate) fn map_psram(config: PsramConfig) -> core::ops::Range<usize> {
157 let start = EXTMEM_ORIGIN;
158 start..start + config.size.get()
159}
160
161fn enable_psram_mspi() {
162 HP_SYS_CLKRST::regs()
163 .psram_ctrl0()
164 .modify(|_, w| w.sys_clk_en().set_bit());
165}
166
167fn reset_psram_mspi() {
168 HP_SYS_CLKRST::regs().psram_ctrl0().modify(|_, w| {
169 w.axi_rst_en().set_bit();
170 w.apb_rst_en().set_bit()
171 });
172 HP_SYS_CLKRST::regs().psram_ctrl0().modify(|_, w| {
173 w.axi_rst_en().clear_bit();
174 w.apb_rst_en().clear_bit()
175 });
176}