1use super::{EXTMEM_ORIGIN, PsramSize};
4use crate::{
5 clock::ll::{ClockTree, PsramFunctionClockConfig, PsramInstance},
6 efuse,
7 peripherals::{HP_SYS, HP_SYS_CLKRST, MEMSPI2, PMU},
8};
9
10mod oct_hex;
11
12#[derive(Copy, Clone, Debug, Default, PartialEq)]
14#[cfg_attr(feature = "defmt", derive(defmt::Format))]
15#[instability::unstable]
16pub enum PsramMode {
17 #[default]
19 Hex,
20
21 Oct,
23}
24
25#[derive(Copy, Clone, Debug, Default, PartialEq)]
27#[cfg_attr(feature = "defmt", derive(defmt::Format))]
28#[instability::unstable]
29pub struct PsramConfig {
30 pub mode: PsramMode,
32
33 pub size: PsramSize,
35
36 pub timing: PsramTimingParams,
38 }
42
43#[derive(Copy, Clone, Debug, PartialEq)]
48#[cfg_attr(feature = "defmt", derive(defmt::Format))]
49pub struct PsramTimingParams {
50 pub clock_source: PsramFunctionClockConfig,
52
53 pub clock: u32,
55
56 pub mr0_rl: u8,
58
59 pub mr4_wl: u8,
61
62 pub rd_dummy_bits: u8,
66
67 pub wr_dummy_bits: u8,
71
72 pub reg_dummy_bits: u32,
74}
75
76impl Default for PsramTimingParams {
77 fn default() -> Self {
78 Self::MHZ_250
79 }
80}
81
82impl PsramTimingParams {
83 pub const MHZ_20: Self = Self {
85 clock_source: PsramFunctionClockConfig::Mpll,
86 clock: 20,
87 mr0_rl: 2,
88 mr4_wl: 2,
89 rd_dummy_bits: 17,
90 wr_dummy_bits: 7,
91 reg_dummy_bits: 8,
92 };
93
94 pub const MHZ_80: Self = Self {
96 clock_source: PsramFunctionClockConfig::Mpll,
97 clock: 80,
98 mr0_rl: 2,
99 mr4_wl: 2,
100 rd_dummy_bits: 17,
101 wr_dummy_bits: 7,
102 reg_dummy_bits: 8,
103 };
104
105 pub const MHZ_125: Self = Self {
107 clock_source: PsramFunctionClockConfig::Mpll,
108 clock: 125,
109 mr0_rl: 2,
110 mr4_wl: 2,
111 rd_dummy_bits: 17,
112 wr_dummy_bits: 7,
113 reg_dummy_bits: 8,
114 };
115
116 pub const MHZ_200: Self = Self {
118 clock_source: PsramFunctionClockConfig::Mpll,
119 clock: 200,
120 mr0_rl: 4,
121 mr4_wl: 1,
122 rd_dummy_bits: 25,
123 wr_dummy_bits: 11,
124 reg_dummy_bits: 12,
125 };
126
127 pub const MHZ_250: Self = Self {
129 clock_source: PsramFunctionClockConfig::Mpll,
130 clock: 250,
131 mr0_rl: 6,
132 mr4_wl: 3,
133 rd_dummy_bits: 33,
134 wr_dummy_bits: 15,
135 reg_dummy_bits: 16,
136 };
137}
138
139#[crate::ram]
141pub(crate) fn init_psram(config: &mut PsramConfig) -> bool {
142 psram_phy_ldo_init();
143
144 enable_psram_mspi();
146 reset_psram_mspi();
147
148 ClockTree::with(|clocks| {
149 PsramInstance::Psram.configure_function_clock(clocks, config.timing.clock_source);
150 PsramInstance::Psram.request_function_clock(clocks);
151 });
152
153 if !oct_hex::set_bus_clock(config.timing.clock) {
155 return false;
156 }
157 let is_hex = matches!(config.mode, PsramMode::Hex);
158 oct_hex::enable_dll();
159 oct_hex::psram_pad_init(is_hex); oct_hex::set_cs_timing();
161
162 oct_hex::init_mr_registers(&config.timing, is_hex);
164
165 if config.size.is_auto() {
166 config.size = PsramSize::Size(oct_hex::psram_detect_size(&config.timing));
167 }
168
169 oct_hex::configure_psram_mspi(&config.timing, is_hex);
171
172 if efuse::chip_revision() == efuse::ChipRevision::from_combined(300) {
176 debug!("Applying P4 v3.0 PSRAM workaround");
177 p4_rev3_psram_workaround();
178 }
179
180 oct_hex::mmu_map_psram(config.size.get());
181
182 true
183}
184
185pub(crate) fn map_psram(config: PsramConfig) -> core::ops::Range<usize> {
186 let start = EXTMEM_ORIGIN;
187 start..start + config.size.get()
188}
189
190fn psram_phy_ldo_init() {
192 PMU::regs()
193 .ext_ldo_p0_0p1a()
194 .write(|w| unsafe { w.bits(0x4020_0100) });
195 PMU::regs()
196 .ext_ldo_p0_0p1a_ana()
197 .write(|w| unsafe { w.bits(0xB100_0000) });
198
199 PMU::regs()
200 .ext_ldo_p0_0p2a()
201 .write(|w| unsafe { w.bits(0x4020_0000) });
202 PMU::regs()
203 .ext_ldo_p0_0p2a_ana()
204 .write(|w| unsafe { w.bits(0xA000_0000) });
205
206 PMU::regs()
207 .ext_ldo_p0_0p3a()
208 .write(|w| unsafe { w.bits(0x4020_0000) });
209 PMU::regs()
210 .ext_ldo_p0_0p3a_ana()
211 .write(|w| unsafe { w.bits(0xA000_0000) });
212
213 PMU::regs()
214 .ext_ldo_p1_0p1a()
215 .write(|w| unsafe { w.bits(0x4020_0180) });
216 PMU::regs()
217 .ext_ldo_p1_0p1a_ana()
218 .write(|w| unsafe { w.bits(0x5700_0000) });
219
220 PMU::regs()
221 .ext_ldo_p1_0p2a()
222 .write(|w| unsafe { w.bits(0x4020_0000) });
223 PMU::regs()
224 .ext_ldo_p1_0p2a_ana()
225 .write(|w| unsafe { w.bits(0xA000_0000) });
226
227 PMU::regs()
228 .ext_ldo_p1_0p3a()
229 .write(|w| unsafe { w.bits(0x4020_0000) });
230 PMU::regs()
231 .ext_ldo_p1_0p3a_ana()
232 .write(|w| unsafe { w.bits(0xA000_0000) });
233
234 crate::rom::ets_delay_us(50);
236}
237
238fn enable_psram_mspi() {
239 HP_SYS_CLKRST::regs()
240 .soc_clk_ctrl0()
241 .modify(|_, w| w.psram_sys_clk_en().set_bit());
242}
243
244fn reset_psram_mspi() {
245 HP_SYS_CLKRST::regs().hp_rst_en0().modify(|_, w| {
246 w.rst_en_dual_mspi_axi().set_bit();
247 w.rst_en_dual_mspi_apb().set_bit()
248 });
249 HP_SYS_CLKRST::regs().hp_rst_en0().modify(|_, w| {
250 w.rst_en_dual_mspi_axi().clear_bit();
251 w.rst_en_dual_mspi_apb().clear_bit()
252 });
253}
254
255fn p4_rev3_psram_workaround() {
260 let cache_fctrl = MEMSPI2::regs().cache_fctrl().read().bits();
262 let cache_sctrl = MEMSPI2::regs().cache_sctrl().read().bits();
263 let sram_cmd = MEMSPI2::regs().sram_cmd().read().bits();
264 let sram_drd_cmd = MEMSPI2::regs().sram_drd_cmd().read().bits();
265 let sram_dwr_cmd = MEMSPI2::regs().sram_dwr_cmd().read().bits();
266 let sram_clk = MEMSPI2::regs().sram_clk().read().bits();
267 let ctrl1 = MEMSPI2::regs().ctrl1().read().bits();
268 let smem_ddr = MEMSPI2::regs().smem_ddr().read().bits();
269 let timing_cali = MEMSPI2::regs().timing_cali().read().bits();
270 let smem_timing_cali = MEMSPI2::regs().smem_timing_cali().read().bits();
271 let smem_ac = MEMSPI2::regs().smem_ac().read().bits();
272
273 HP_SYS::regs()
275 .core_err_resp_dis()
276 .write(|w| unsafe { w.bits(0x7) });
277
278 unsafe {
279 oct_hex::write_psram_mmu_entry(0, 0);
282
283 let _ = core::ptr::read_volatile(0x8800_0000u32 as *const u32);
286 let _ = core::ptr::read_volatile(0x8800_0080u32 as *const u32);
287
288 crate::rom::ets_delay_us(1);
289 }
290
291 reset_psram_mspi();
294
295 HP_SYS::regs()
297 .core_err_resp_dis()
298 .write(|w| unsafe { w.bits(0) });
299
300 unsafe {
302 MEMSPI2::regs().cache_fctrl().write(|w| w.bits(cache_fctrl));
303 MEMSPI2::regs().cache_sctrl().write(|w| w.bits(cache_sctrl));
304 MEMSPI2::regs().sram_cmd().write(|w| w.bits(sram_cmd));
305 MEMSPI2::regs()
306 .sram_drd_cmd()
307 .write(|w| w.bits(sram_drd_cmd));
308 MEMSPI2::regs()
309 .sram_dwr_cmd()
310 .write(|w| w.bits(sram_dwr_cmd));
311 MEMSPI2::regs().sram_clk().write(|w| w.bits(sram_clk));
312 MEMSPI2::regs().ctrl1().write(|w| w.bits(ctrl1));
313 MEMSPI2::regs().smem_ddr().write(|w| w.bits(smem_ddr));
314 MEMSPI2::regs().timing_cali().write(|w| w.bits(timing_cali));
315 MEMSPI2::regs()
316 .smem_timing_cali()
317 .write(|w| w.bits(smem_timing_cali));
318 MEMSPI2::regs().smem_ac().write(|w| w.bits(smem_ac));
319 }
320}