1use super::PsramSize;
2
3const EXTMEM_ORIGIN: usize = 0x3F800000;
4
5#[derive(PartialEq, Eq, Clone, Copy, Debug, Default)]
7#[cfg_attr(feature = "defmt", derive(defmt::Format))]
8#[allow(missing_docs)]
9pub enum PsramCacheSpeed {
10 #[default]
11 PsramCacheF80mS40m = 0,
12 PsramCacheF40mS40m,
13 PsramCacheF80mS80m,
14}
15
16#[derive(PartialEq, Eq, Clone, Copy, Debug, Default)]
20#[cfg_attr(feature = "defmt", derive(defmt::Format))]
21pub enum PsramVaddrMode {
22 #[default]
26 Normal = 0,
27 LowHigh,
32 Evenodd,
37}
38
39#[derive(Copy, Clone, Debug, Default)]
41#[cfg_attr(feature = "defmt", derive(defmt::Format))]
42pub struct PsramConfig {
43 pub size: PsramSize,
45 pub cache_speed: PsramCacheSpeed,
47 pub psram_vaddr_mode: PsramVaddrMode,
49}
50
51pub(crate) fn init_psram(config: PsramConfig) {
55 let mut config = config;
56
57 utils::psram_init(&config);
58
59 if config.size.is_auto() {
60 const MAX_MEM_SIZE: usize = 4 * 1024 * 1024;
61
62 utils::s_mapping(EXTMEM_ORIGIN as u32, MAX_MEM_SIZE as u32);
68
69 let guessed_size = unsafe {
70 let ptr = EXTMEM_ORIGIN as *mut u8;
71 for i in (1023..MAX_MEM_SIZE).step_by(1024) {
72 ptr.add(i).write_volatile(0x7f);
73 }
74
75 let mut last_correctly_read = 0;
76 for i in (1023..MAX_MEM_SIZE).step_by(1024) {
77 if ptr.add(i).read_volatile() == 0x7f {
78 last_correctly_read = i;
79 } else {
80 break;
81 }
82 }
83
84 last_correctly_read + 1
85 };
86
87 info!("Assuming {} bytes of PSRAM", guessed_size);
88 config.size = PsramSize::Size(guessed_size);
89 } else {
90 utils::s_mapping(EXTMEM_ORIGIN as u32, config.size.get() as u32);
91 }
92
93 unsafe {
94 super::MAPPED_PSRAM.memory_range = EXTMEM_ORIGIN..EXTMEM_ORIGIN + config.size.get();
95 }
96}
97
98pub(crate) mod utils {
99 use core::ptr::addr_of_mut;
100
101 use procmacros::ram;
102
103 use super::*;
104 use crate::peripherals::{DPORT, SPI0, SPI1};
105
106 #[ram]
107 pub(crate) fn s_mapping(v_start: u32, size: u32) {
108 cache_sram_mmu_set(0, 0, v_start, 0, 32, size / 1024 / 32);
110 DPORT::regs()
112 .app_cache_ctrl1()
113 .modify(|_, w| w.app_cache_mask_dram1().clear_bit());
114
115 cache_sram_mmu_set(1, 0, v_start, 0, 32, size / 1024 / 32);
116 }
117
118 #[ram]
121 fn cache_sram_mmu_set(
122 cpu_no: u32,
123 pid: u32,
124 vaddr: u32,
125 paddr: u32,
126 psize: u32,
127 num: u32,
128 ) -> i32 {
129 unsafe { cache_sram_mmu_set_rom(cpu_no, pid, vaddr, paddr, psize, num) }
130 }
131
132 const D0WD_PSRAM_CLK_IO: u8 = 17;
136 const D0WD_PSRAM_CS_IO: u8 = 16;
137
138 const D2WD_PSRAM_CLK_IO: u8 = 9; const D2WD_PSRAM_CS_IO: u8 = 10; const PICO_PSRAM_CLK_IO: u8 = 6;
144 const PICO_PSRAM_CS_IO: u8 = 10; const PICO_V3_02_PSRAM_CLK_IO: u8 = 10;
147 const PICO_V3_02_PSRAM_CS_IO: u8 = 9;
148 const PICO_V3_02_PSRAM_SPIWP_SD3_IO: u8 = 18;
149
150 const ESP_ROM_EFUSE_FLASH_DEFAULT_SPI: u32 = 0;
151 const ESP_ROM_EFUSE_FLASH_DEFAULT_HSPI: u32 = 1;
152
153 const SPI_IOMUX_PIN_NUM_CLK: u8 = 6;
154 const SPI_IOMUX_PIN_NUM_CS: u8 = 11;
155
156 const PSRAM_SPIQ_SD0_IO: u8 = 7;
162 const PSRAM_SPID_SD1_IO: u8 = 8;
163 const PSRAM_SPIWP_SD3_IO: u8 = 10;
164 const PSRAM_SPIHD_SD2_IO: u8 = 9;
165
166 const FLASH_HSPI_CLK_IO: u8 = 14;
167 const FLASH_HSPI_CS_IO: u8 = 15;
168
169 const PSRAM_HSPI_SPIQ_SD0_IO: u8 = 12;
170 const PSRAM_HSPI_SPID_SD1_IO: u8 = 13;
171 const PSRAM_HSPI_SPIWP_SD3_IO: u8 = 2;
172 const PSRAM_HSPI_SPIHD_SD2_IO: u8 = 4;
173
174 const DR_REG_SPI1_BASE: u32 = 0x3ff42000;
175 const SPI1_USER_REG: u32 = DR_REG_SPI1_BASE + 0x1C;
176 const SPI1_W0_REG: u32 = DR_REG_SPI1_BASE + 0x80;
177
178 const fn psram_cs_hold_time_from_psram_speed(speed: PsramCacheSpeed) -> u32 {
179 match speed {
180 PsramCacheSpeed::PsramCacheF80mS40m => 0,
181 PsramCacheSpeed::PsramCacheF40mS40m => 0,
182 PsramCacheSpeed::PsramCacheF80mS80m => 1,
183 }
184 }
185
186 const PSRAM_INTERNAL_IO_28: u32 = 28;
187 const PSRAM_INTERNAL_IO_29: u32 = 29;
188 const SIG_GPIO_OUT_IDX: u32 = 256;
189 const SPICLK_OUT_IDX: u32 = 0;
190 const SIG_IN_FUNC224_IDX: u32 = 224;
191 const SIG_IN_FUNC225_IDX: u32 = 225;
192 const SPICS0_OUT_IDX: u32 = 5;
193 const SPICS1_OUT_IDX: u32 = 6;
194 const SPIQ_OUT_IDX: u32 = 1;
195 const SPIQ_IN_IDX: u32 = 1;
196 const SPID_OUT_IDX: u32 = 2;
197 const SPID_IN_IDX: u32 = 2;
198 const SPIWP_OUT_IDX: u32 = 4;
199 const SPIWP_IN_IDX: u32 = 4;
200 const SPIHD_OUT_IDX: u32 = 3;
201 const SPIHD_IN_IDX: u32 = 3;
202 const FUNC_SD_CLK_SPICLK: u32 = 1;
203 const PIN_FUNC_GPIO: u32 = 2;
204
205 const PSRAM_QUAD_WRITE: u32 = 0x38;
206 const PSRAM_FAST_READ_QUAD_DUMMY: u32 = 0x5;
207 const PSRAM_FAST_READ_QUAD: u32 = 0xEB;
208
209 const SPI_FWRITE_DUAL_S: u32 = 12;
210 const SPI_FWRITE_DUAL_M: u32 = 1 << 12;
211
212 const SPI_FREAD_QIO_M: u32 = 1 << 24;
213 const SPI0_R_QIO_DUMMY_CYCLELEN: u32 = 3;
214 const SPI_FREAD_DIO_M: u32 = 1 << 23;
215 const SPI0_R_DIO_DUMMY_CYCLELEN: u32 = 1;
216 const SPI0_R_DIO_ADDR_BITSLEN: u32 = 27;
217 const SPI_FREAD_QUAD_M: u32 = 1 << 20;
218 const SPI_FREAD_DUAL_M: u32 = 1 << 14;
219 const SPI0_R_FAST_DUMMY_CYCLELEN: u32 = 7;
220 const PSRAM_IO_MATRIX_DUMMY_40M: u8 = 1;
221 const PSRAM_IO_MATRIX_DUMMY_80M: u8 = 2;
222
223 const _SPI_CACHE_PORT: u8 = 0;
224 const _SPI_FLASH_PORT: u8 = 1;
225 const _SPI_80M_CLK_DIV: u8 = 1;
226 const _SPI_40M_CLK_DIV: u8 = 2;
227
228 const FLASH_ID_GD25LQ32C: u32 = 0xC86016;
229
230 const EFUSE_SPICONFIG_RET_SPICLK_MASK: u32 = 0x3f;
231 const EFUSE_SPICONFIG_RET_SPICLK_SHIFT: u8 = 0;
232 const EFUSE_SPICONFIG_RET_SPIQ_MASK: u32 = 0x3f;
233 const EFUSE_SPICONFIG_RET_SPIQ_SHIFT: u8 = 6;
234 const EFUSE_SPICONFIG_RET_SPID_MASK: u32 = 0x3f;
235 const EFUSE_SPICONFIG_RET_SPID_SHIFT: u8 = 12;
236 const EFUSE_SPICONFIG_RET_SPICS0_MASK: u32 = 0x3f;
237 const EFUSE_SPICONFIG_RET_SPICS0_SHIFT: u8 = 18;
238 const EFUSE_SPICONFIG_RET_SPIHD_MASK: u32 = 0x3f;
239 const EFUSE_SPICONFIG_RET_SPIHD_SHIFT: u8 = 24;
240
241 fn efuse_spiconfig_ret(spi_config: u32, mask: u32, shift: u8) -> u8 {
242 (((spi_config) >> shift) & mask) as u8
243 }
244
245 #[derive(PartialEq, Eq, Debug, Default)]
246 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
247 struct PsramIo {
248 flash_clk_io: u8,
249 flash_cs_io: u8,
250 psram_clk_io: u8,
251 psram_cs_io: u8,
252 psram_spiq_sd0_io: u8,
253 psram_spid_sd1_io: u8,
254 psram_spiwp_sd3_io: u8,
255 psram_spihd_sd2_io: u8,
256 }
257
258 #[derive(PartialEq, Eq, Copy, Clone, Debug)]
259 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
260 enum PsramClkMode {
261 PsramClkModeNorm = 0, PsramClkModeDclk = 1, }
264
265 #[repr(C)]
266 pub(super) struct EspRomSpiflashChip {
267 pub device_id: u32,
268 pub chip_size: u32, pub block_size: u32,
270 pub sector_size: u32,
271 pub page_size: u32,
272 pub status_mask: u32,
273 }
274
275 unsafe extern "C" {
276 fn esp_rom_efuse_get_flash_gpio_info() -> u32;
277
278 fn esp_rom_gpio_connect_out_signal(
279 gpio_num: u32,
280 signal_idx: u32,
281 out_inv: bool,
282 oen_inv: bool,
283 );
284
285 fn esp_rom_gpio_connect_in_signal(gpio_num: u32, signal_idx: u32, inv: bool);
286
287 fn esp_rom_spiflash_config_clk(freqdiv: u8, spi: u8) -> i32;
288
289 static mut g_rom_spiflash_dummy_len_plus: u8;
290
291 pub(super) static g_rom_flashchip: EspRomSpiflashChip;
292
293 fn cache_sram_mmu_set_rom(
294 cpu_no: u32,
295 pid: u32,
296 vaddr: u32,
297 paddr: u32,
298 psize: u32,
299 num: u32,
300 ) -> i32;
301 }
302
303 #[ram]
304 pub(crate) fn psram_init(config: &PsramConfig) {
305 let chip = crate::efuse::Efuse::chip_type();
306
307 let mode = config.cache_speed;
308 let mut psram_io = PsramIo::default();
309 let clk_mode;
310
311 match chip {
312 crate::efuse::ChipType::Esp32D0wdq6 | crate::efuse::ChipType::Esp32D0wdq5 => {
313 clk_mode = PsramClkMode::PsramClkModeNorm;
314 psram_io.psram_clk_io = D0WD_PSRAM_CLK_IO;
315 psram_io.psram_cs_io = D0WD_PSRAM_CS_IO;
316 }
317 crate::efuse::ChipType::Esp32D2wdq5 => {
318 clk_mode = PsramClkMode::PsramClkModeDclk;
319 psram_io.psram_clk_io = D2WD_PSRAM_CLK_IO;
320 psram_io.psram_cs_io = D2WD_PSRAM_CS_IO;
321 }
322 crate::efuse::ChipType::Esp32Picod2 => {
323 clk_mode = PsramClkMode::PsramClkModeNorm;
324 psram_io.psram_clk_io = PICO_PSRAM_CLK_IO;
325 psram_io.psram_cs_io = PICO_PSRAM_CS_IO;
326 }
327 crate::efuse::ChipType::Esp32Picod4 => {
328 panic!("PSRAM is unsupported on this chip");
329 }
330 crate::efuse::ChipType::Esp32Picov302 => {
331 clk_mode = PsramClkMode::PsramClkModeNorm;
332 psram_io.psram_clk_io = PICO_V3_02_PSRAM_CLK_IO;
333 psram_io.psram_cs_io = PICO_V3_02_PSRAM_CS_IO;
334 }
335 crate::efuse::ChipType::Unknown => {
336 panic!("Unknown chip type. PSRAM is not supported");
337 }
338 }
339
340 let spiconfig = unsafe { esp_rom_efuse_get_flash_gpio_info() };
341 if spiconfig == ESP_ROM_EFUSE_FLASH_DEFAULT_SPI {
342 psram_io.flash_clk_io = SPI_IOMUX_PIN_NUM_CLK;
343 psram_io.flash_cs_io = SPI_IOMUX_PIN_NUM_CS;
344 psram_io.psram_spiq_sd0_io = PSRAM_SPIQ_SD0_IO;
345 psram_io.psram_spid_sd1_io = PSRAM_SPID_SD1_IO;
346 psram_io.psram_spiwp_sd3_io = PSRAM_SPIWP_SD3_IO;
347 psram_io.psram_spihd_sd2_io = PSRAM_SPIHD_SD2_IO;
348 } else if spiconfig == ESP_ROM_EFUSE_FLASH_DEFAULT_HSPI {
349 psram_io.flash_clk_io = FLASH_HSPI_CLK_IO;
350 psram_io.flash_cs_io = FLASH_HSPI_CS_IO;
351 psram_io.psram_spiq_sd0_io = PSRAM_HSPI_SPIQ_SD0_IO;
352 psram_io.psram_spid_sd1_io = PSRAM_HSPI_SPID_SD1_IO;
353 psram_io.psram_spiwp_sd3_io = PSRAM_HSPI_SPIWP_SD3_IO;
354 psram_io.psram_spihd_sd2_io = PSRAM_HSPI_SPIHD_SD2_IO;
355 } else if chip == crate::efuse::ChipType::Esp32Picov302 {
356 psram_io.flash_clk_io = efuse_spiconfig_ret(
357 spiconfig,
358 EFUSE_SPICONFIG_RET_SPICLK_MASK,
359 EFUSE_SPICONFIG_RET_SPICLK_SHIFT,
360 );
361 psram_io.flash_cs_io = efuse_spiconfig_ret(
362 spiconfig,
363 EFUSE_SPICONFIG_RET_SPICS0_MASK,
364 EFUSE_SPICONFIG_RET_SPICS0_SHIFT,
365 );
366 psram_io.psram_spiq_sd0_io = efuse_spiconfig_ret(
367 spiconfig,
368 EFUSE_SPICONFIG_RET_SPIQ_MASK,
369 EFUSE_SPICONFIG_RET_SPIQ_SHIFT,
370 );
371 psram_io.psram_spid_sd1_io = efuse_spiconfig_ret(
372 spiconfig,
373 EFUSE_SPICONFIG_RET_SPID_MASK,
374 EFUSE_SPICONFIG_RET_SPID_SHIFT,
375 );
376 psram_io.psram_spihd_sd2_io = efuse_spiconfig_ret(
377 spiconfig,
378 EFUSE_SPICONFIG_RET_SPIHD_MASK,
379 EFUSE_SPICONFIG_RET_SPIHD_SHIFT,
380 );
381 psram_io.psram_spiwp_sd3_io = PICO_V3_02_PSRAM_SPIWP_SD3_IO;
382 } else {
383 panic!("Getting Flash/PSRAM pins from efuse is not supported");
384 }
392 info!("PS-RAM pins {:?}", &psram_io);
393
394 unsafe {
395 SPI0::regs().ext3().modify(|_, w| w.bits(0x1));
396 SPI1::regs()
397 .user()
398 .modify(|_, w| w.usr_prep_hold().clear_bit());
399 }
400
401 psram_spi_init(mode, clk_mode);
402
403 match mode {
404 PsramCacheSpeed::PsramCacheF80mS80m => unsafe {
405 esp_rom_gpio_connect_out_signal(
406 psram_io.psram_clk_io as u32,
407 SPICLK_OUT_IDX,
408 false,
409 false,
410 );
411 },
412 _ => unsafe {
413 if clk_mode == PsramClkMode::PsramClkModeDclk {
414 esp_rom_gpio_connect_out_signal(
423 PSRAM_INTERNAL_IO_28,
424 SPICLK_OUT_IDX,
425 false,
426 false,
427 );
428 esp_rom_gpio_connect_in_signal(PSRAM_INTERNAL_IO_28, SIG_IN_FUNC224_IDX, false);
429 esp_rom_gpio_connect_out_signal(
430 PSRAM_INTERNAL_IO_29,
431 SIG_IN_FUNC224_IDX,
432 false,
433 false,
434 );
435 esp_rom_gpio_connect_in_signal(PSRAM_INTERNAL_IO_29, SIG_IN_FUNC225_IDX, false);
436 esp_rom_gpio_connect_out_signal(
437 psram_io.psram_clk_io as u32,
438 SIG_IN_FUNC225_IDX,
439 false,
440 false,
441 );
442 } else {
443 esp_rom_gpio_connect_out_signal(
444 psram_io.psram_clk_io as u32,
445 SPICLK_OUT_IDX,
446 false,
447 false,
448 );
449 }
450 },
451 }
452
453 let extra_dummy = psram_gpio_config(&psram_io, mode);
454 info!("extra dummy = {}", extra_dummy);
455
456 unsafe {
459 esp_rom_gpio_connect_out_signal(PSRAM_INTERNAL_IO_28, SIG_GPIO_OUT_IDX, false, false);
460 esp_rom_gpio_connect_out_signal(PSRAM_INTERNAL_IO_29, SIG_GPIO_OUT_IDX, false, false);
461 esp_rom_gpio_connect_out_signal(
462 psram_io.psram_clk_io as u32,
463 SPICLK_OUT_IDX,
464 false,
465 false,
466 );
467 }
468
469 psram_set_cs_timing_spi1(mode, clk_mode);
471 psram_set_cs_timing_spi0(mode, clk_mode); psram_enable_qio_mode_spi1(clk_mode, mode);
473
474 let psram_vaddr_mode = config.psram_vaddr_mode;
475 info!("PS-RAM vaddrmode = {:?}", psram_vaddr_mode);
476
477 psram_cache_init(mode, psram_vaddr_mode, clk_mode, extra_dummy);
478 }
479
480 fn psram_cache_init(
482 psram_cache_mode: PsramCacheSpeed,
483 vaddrmode: PsramVaddrMode,
484 clk_mode: PsramClkMode,
485 extra_dummy: u32,
486 ) {
487 unsafe {
488 let spi = SPI0::regs();
489 info!(
490 "PS-RAM cache_init, psram_cache_mode={:?}, extra_dummy={}, clk_mode={:?}",
491 psram_cache_mode, extra_dummy, clk_mode
492 );
493 match psram_cache_mode {
494 PsramCacheSpeed::PsramCacheF80mS80m => {
495 spi.date().modify(|r, w| {
499 let current_bits = r.bits();
500 let new_bits = current_bits & !((1 << 31) | (1 << 30));
501 w.bits(new_bits)
502 });
503 }
507 PsramCacheSpeed::PsramCacheF80mS40m => {
508 spi.clock().modify(|_, w| w.clk_equ_sysclk().clear_bit());
509 spi.clock().modify(|_, w| w.clkdiv_pre().bits(0));
510 spi.clock().modify(|_, w| w.clkcnt_n().bits(1));
511 spi.clock().modify(|_, w| w.clkcnt_h().bits(0));
512 spi.clock().modify(|_, w| w.clkcnt_l().bits(1));
513
514 spi.date().modify(|r, w| {
515 let current_bits = r.bits();
516 let new_bits = (current_bits | (1 << 31)) & !(1 << 30);
517 w.bits(new_bits)
518 });
519 }
520 _ => {
521 spi.date().modify(|r, w| {
522 let current_bits = r.bits();
523 let new_bits = current_bits & !((1 << 31) | (1 << 30));
524 w.bits(new_bits)
525 });
526 }
527 }
528
529 spi.cache_sctrl()
530 .modify(|_, w| w.usr_sram_dio().clear_bit()); spi.cache_sctrl().modify(|_, w| w.usr_sram_qio().set_bit()); spi.cache_sctrl()
533 .modify(|_, w| w.cache_sram_usr_rcmd().set_bit()); spi.cache_sctrl()
535 .modify(|_, w| w.cache_sram_usr_wcmd().set_bit()); spi.cache_sctrl()
537 .modify(|_, w| w.sram_addr_bitlen().bits(23)); spi.cache_sctrl()
539 .modify(|_, w| w.usr_rd_sram_dummy().set_bit()); spi.sram_drd_cmd()
543 .modify(|_, w| w.cache_sram_usr_rd_cmd_bitlen().bits(7));
544 spi.sram_drd_cmd().modify(|_, w| {
545 w.cache_sram_usr_rd_cmd_value()
546 .bits(PSRAM_FAST_READ_QUAD as u16)
547 });
548 spi.sram_dwr_cmd()
549 .modify(|_, w| w.cache_sram_usr_wr_cmd_bitlen().bits(7));
550 spi.sram_dwr_cmd().modify(|_, w| {
551 w.cache_sram_usr_wr_cmd_value()
552 .bits(PSRAM_QUAD_WRITE as u16)
553 });
554
555 spi.cache_sctrl().modify(|_, w| {
557 w.sram_dummy_cyclelen()
558 .bits((PSRAM_FAST_READ_QUAD_DUMMY + extra_dummy) as u8)
559 });
560
561 match psram_cache_mode {
562 PsramCacheSpeed::PsramCacheF80mS80m => (), _ => {
564 if clk_mode == PsramClkMode::PsramClkModeDclk {
565 spi.sram_drd_cmd()
566 .modify(|_, w| w.cache_sram_usr_rd_cmd_bitlen().bits(15)); spi.sram_drd_cmd().modify(|_, w| {
569 w.cache_sram_usr_rd_cmd_value()
570 .bits((PSRAM_FAST_READ_QUAD << 8) as u16)
571 }); spi.sram_dwr_cmd()
574 .modify(|_, w| w.cache_sram_usr_wr_cmd_bitlen().bits(15)); spi.sram_dwr_cmd().modify(|_, w| {
576 w.cache_sram_usr_wr_cmd_value()
577 .bits((PSRAM_QUAD_WRITE << 8) as u16)
578 }); spi.cache_sctrl().modify(|_, w| {
580 w.sram_dummy_cyclelen()
581 .bits((PSRAM_FAST_READ_QUAD_DUMMY + extra_dummy) as u8)
582 }); }
584 }
585 }
586
587 let dport = DPORT::regs();
588
589 dport
590 .pro_cache_ctrl()
591 .modify(|_, w| w.pro_dram_hl().clear_bit().pro_dram_split().clear_bit());
592 dport
593 .app_cache_ctrl()
594 .modify(|_, w| w.app_dram_hl().clear_bit().app_dram_split().clear_bit());
595 if vaddrmode == PsramVaddrMode::LowHigh {
596 dport
597 .pro_cache_ctrl()
598 .modify(|_, w| w.pro_dram_hl().set_bit());
599 dport
600 .app_cache_ctrl()
601 .modify(|_, w| w.app_dram_hl().set_bit());
602 } else if vaddrmode == PsramVaddrMode::Evenodd {
603 dport
604 .pro_cache_ctrl()
605 .modify(|_, w| w.pro_dram_split().set_bit());
606 dport
607 .app_cache_ctrl()
608 .modify(|_, w| w.app_dram_split().set_bit());
609 }
610
611 dport.pro_cache_ctrl1().modify(|_, w| {
614 w.pro_cache_mask_dram1()
615 .clear_bit()
616 .pro_cache_mask_opsdram()
617 .clear_bit()
618 });
619 dport
620 .pro_cache_ctrl1()
621 .modify(|_, w| w.pro_cmmu_sram_page_mode().bits(0));
622
623 dport.app_cache_ctrl1().modify(|_, w| {
626 w.app_cache_mask_dram1()
627 .clear_bit()
628 .app_cache_mask_opsdram()
629 .clear_bit()
630 });
631 dport
632 .app_cache_ctrl1()
633 .modify(|_, w| w.app_cmmu_sram_page_mode().bits(0));
634
635 spi.pin().modify(|_, w| w.cs1_dis().clear_bit());
637 }
638 }
639
640 #[ram]
642 fn psram_spi_init(
643 mode: PsramCacheSpeed,
645 clk_mode: PsramClkMode,
646 ) {
647 unsafe {
648 let spi = SPI1::regs();
649 spi.slave().modify(|_, w| w.trans_inten().clear_bit());
651 spi.pin().modify(|_, w| w.ck_idle_edge().clear_bit());
653 spi.user().modify(|_, w| w.ck_out_edge().clear_bit());
654 spi.ctrl().modify(|_, w| w.wr_bit_order().clear_bit());
656 spi.ctrl().modify(|_, w| w.rd_bit_order().clear_bit());
657 spi.user().modify(|_, w| w.doutdin().clear_bit());
659 spi.user1().modify(|_, w| w.bits(0));
661 spi.slave().modify(|_, w| w.mode().clear_bit());
663
664 let ptr = SPI1_W0_REG as *mut u32;
665 for i in 0..16 {
666 ptr.offset(i).write_volatile(0);
667 }
668
669 psram_set_cs_timing_spi1(mode, clk_mode);
670 }
671 }
672
673 fn psram_set_cs_timing_spi1(psram_cache_mode: PsramCacheSpeed, clk_mode: PsramClkMode) {
674 unsafe {
675 let spi = SPI1::regs();
676 if clk_mode == PsramClkMode::PsramClkModeNorm {
677 spi.user().modify(|_, w| w.cs_hold().set_bit());
678 spi.user().modify(|_, w| w.cs_setup().set_bit());
679
680 spi.ctrl2().modify(|_, w| {
681 w.hold_time()
682 .bits(psram_cs_hold_time_from_psram_speed(psram_cache_mode) as u8)
683 });
684
685 spi.ctrl2().modify(|_, w| w.setup_time().bits(0));
687 } else {
688 spi.user().modify(|_, w| w.cs_hold().clear_bit());
689 spi.user().modify(|_, w| w.cs_setup().clear_bit());
690 }
691 }
692 }
693
694 fn psram_set_cs_timing_spi0(psram_cache_mode: PsramCacheSpeed, clk_mode: PsramClkMode) {
695 unsafe {
696 let spi = SPI0::regs();
697 if clk_mode == PsramClkMode::PsramClkModeNorm {
698 spi.user().modify(|_, w| w.cs_hold().set_bit());
699 spi.user().modify(|_, w| w.cs_setup().set_bit());
700
701 spi.ctrl2().modify(|_, w| {
702 w.hold_time()
703 .bits(psram_cs_hold_time_from_psram_speed(psram_cache_mode) as u8)
704 });
705
706 spi.ctrl2().modify(|_, w| w.setup_time().bits(0));
708 } else {
709 spi.user().modify(|_, w| w.cs_hold().clear_bit());
710 spi.user().modify(|_, w| w.cs_setup().clear_bit());
711 }
712 }
713 }
714
715 #[derive(Default, Debug, Copy, Clone, PartialEq)]
716 struct PsramCmd {
717 cmd: u16, cmd_bit_len: u16, addr: u32, addr_bit_len: u16, tx_data: *const u32, tx_data_bit_len: u16, rx_data: *mut u32, rx_data_bit_len: u16, dummy_bit_len: u32,
726 }
727
728 const PSRAM_ENTER_QMODE: u32 = 0x35;
729
730 #[ram]
732 fn psram_enable_qio_mode_spi1(clk_mode: PsramClkMode, psram_mode: PsramCacheSpeed) {
733 let mut ps_cmd: PsramCmd = PsramCmd::default();
734 let addr: u32 = PSRAM_ENTER_QMODE << 24;
735
736 ps_cmd.cmd_bit_len = 0;
737 if clk_mode == PsramClkMode::PsramClkModeDclk {
738 match psram_mode {
739 PsramCacheSpeed::PsramCacheF80mS80m => (),
740 _ => {
741 ps_cmd.cmd_bit_len = 2;
742 }
743 }
744 }
745 ps_cmd.cmd = 0;
746 ps_cmd.addr = addr;
747 ps_cmd.addr_bit_len = 8;
748 ps_cmd.tx_data = core::ptr::null();
749 ps_cmd.tx_data_bit_len = 0;
750 ps_cmd.rx_data = core::ptr::null_mut();
751 ps_cmd.rx_data_bit_len = 0;
752 ps_cmd.dummy_bit_len = 0;
753 let (backup_usr, backup_usr1, backup_usr2) = psram_cmd_config_spi1(&ps_cmd);
754 psram_cmd_recv_start_spi1(core::ptr::null_mut(), 0, PsramCmdMode::PsramCmdQpi);
755 psram_cmd_end_spi1(backup_usr, backup_usr1, backup_usr2);
756 }
757
758 #[ram]
759 fn psram_cmd_end_spi1(backup_usr: u32, backup_usr1: u32, backup_usr2: u32) {
760 unsafe {
761 let spi = SPI1::regs();
762 while spi.cmd().read().usr().bit_is_set() {}
763
764 spi.user().write(|w| w.bits(backup_usr));
765 spi.user1().write(|w| w.bits(backup_usr1));
766 spi.user2().write(|w| w.bits(backup_usr2));
767 }
768 }
769
770 #[ram]
772 fn psram_cmd_config_spi1(p_in_data: &PsramCmd) -> (u32, u32, u32) {
773 unsafe {
774 let spi = SPI1::regs();
775 while spi.cmd().read().usr().bit_is_set() {}
776
777 let backup_usr = spi.user().read().bits();
778 let backup_usr1 = spi.user1().read().bits();
779 let backup_usr2 = spi.user2().read().bits();
780
781 if p_in_data.cmd_bit_len != 0 {
783 spi.user2().modify(|_, w| {
785 w.usr_command_bitlen()
786 .bits((p_in_data.cmd_bit_len - 1) as u8)
787 });
788 spi.user().modify(|_, w| w.usr_command().set_bit());
790 spi.user2()
792 .modify(|_, w| w.usr_command_value().bits(p_in_data.cmd));
793 } else {
794 spi.user().modify(|_, w| w.usr_command().clear_bit());
795 spi.user2().modify(|_, w| w.usr_command_bitlen().bits(0));
796 }
797 if p_in_data.addr_bit_len != 0 {
799 spi.user1()
800 .modify(|_, w| w.usr_addr_bitlen().bits((p_in_data.addr_bit_len - 1) as u8));
801 spi.user().modify(|_, w| w.usr_addr().set_bit());
803 spi.addr().modify(|_, w| w.bits(p_in_data.addr));
805 } else {
806 spi.user().modify(|_, w| w.usr_addr().clear_bit());
807 spi.user1().modify(|_, w| w.usr_addr_bitlen().bits(0));
808 }
809 let p_tx_val = p_in_data.tx_data;
811 if p_in_data.tx_data_bit_len != 0 {
812 spi.user().modify(|_, w| w.usr_mosi().set_bit());
814 let len = p_in_data.tx_data_bit_len.div_ceil(32);
816 if !p_tx_val.is_null() {
817 for i in 0..len {
818 spi.w(i as usize)
819 .write(|w| w.bits(p_tx_val.offset(i as isize).read_volatile()));
820 }
821 }
822 spi.mosi_dlen().modify(|_, w| {
824 w.usr_mosi_dbitlen()
825 .bits((p_in_data.tx_data_bit_len - 1) as u32)
826 });
827 } else {
828 spi.user().modify(|_, w| w.usr_mosi().clear_bit());
829 spi.mosi_dlen().modify(|_, w| w.usr_mosi_dbitlen().bits(0));
830 }
831 if p_in_data.rx_data_bit_len != 0 {
833 spi.user().modify(|_, w| w.usr_miso().set_bit());
835 spi.miso_dlen().modify(|_, w| {
837 w.usr_miso_dbitlen()
838 .bits((p_in_data.rx_data_bit_len - 1) as u32)
839 });
840 } else {
841 spi.user().modify(|_, w| w.usr_miso().clear_bit());
842 spi.miso_dlen().modify(|_, w| w.usr_miso_dbitlen().bits(0));
843 }
844 if p_in_data.dummy_bit_len != 0 {
845 spi.user().modify(|_, w| w.usr_dummy().set_bit()); spi.user1().modify(|_, w| {
847 w.usr_dummy_cyclelen()
848 .bits((p_in_data.dummy_bit_len - 1) as u8)
849 }); } else {
851 spi.user().modify(|_, w| w.usr_dummy().clear_bit()); spi.user1().modify(|_, w| w.usr_dummy_cyclelen().bits(0)); }
854
855 (backup_usr, backup_usr1, backup_usr2)
856 }
857 }
858
859 #[derive(Debug, Clone, Copy, PartialEq)]
860 enum PsramCmdMode {
861 PsramCmdQpi,
862 PsramCmdSpi,
863 }
864
865 #[ram]
867 fn psram_cmd_recv_start_spi1(
868 p_rx_data: *mut u32,
869 rx_data_len_words: usize,
870 cmd_mode: PsramCmdMode,
871 ) {
872 unsafe {
873 let spi = SPI1::regs();
874 spi.pin().modify(|_, w| w.cs1_dis().clear_bit());
876 spi.pin().modify(|_, w| w.cs0_dis().set_bit());
877
878 let mode_backup: u32 = (spi.user().read().bits() >> SPI_FWRITE_DUAL_S) & 0xf;
879 let rd_mode_backup: u32 = spi.ctrl().read().bits()
880 & (SPI_FREAD_DIO_M | SPI_FREAD_DUAL_M | SPI_FREAD_QUAD_M | SPI_FREAD_QIO_M);
881
882 if cmd_mode == PsramCmdMode::PsramCmdSpi {
883 psram_set_basic_write_mode_spi1();
884 psram_set_basic_read_mode_spi1();
885 } else if cmd_mode == PsramCmdMode::PsramCmdQpi {
886 psram_set_qio_write_mode_spi1();
887 psram_set_qio_read_mode_spi1();
888 }
889
890 while SPI1::regs().ext2().read().bits() != 0 {}
892
893 DPORT::regs()
895 .host_inf_sel()
896 .modify(|r, w| w.bits(r.bits() | (1 << 14)));
897
898 spi.cmd().modify(|_, w| w.usr().set_bit());
900 while spi.cmd().read().usr().bit_is_set() {}
901
902 DPORT::regs()
904 .host_inf_sel()
905 .modify(|r, w| w.bits(r.bits() & !(1 << 14)));
906
907 set_peri_reg_bits(
910 SPI1_USER_REG,
911 if !p_rx_data.is_null() {
912 SPI_FWRITE_DUAL_M
913 } else {
914 0xf
915 },
916 mode_backup,
917 SPI_FWRITE_DUAL_S,
918 );
919
920 spi.ctrl().modify(|_, w| {
921 w.fread_dio().clear_bit();
922 w.fread_dual().clear_bit();
923 w.fread_quad().clear_bit();
924 w.fread_qio().clear_bit()
925 });
926 spi.ctrl().modify(|r, w| w.bits(r.bits() | rd_mode_backup));
927
928 spi.pin().modify(|_, w| w.cs1_dis().set_bit());
930 spi.pin().modify(|_, w| w.cs0_dis().clear_bit());
931
932 if !p_rx_data.is_null() {
933 for i in 0..rx_data_len_words {
935 p_rx_data.add(i).write_volatile(spi.w(i).read().bits());
936 }
937 }
938 }
939 }
940
941 fn psram_set_basic_write_mode_spi1() {
943 SPI1::regs().user().modify(|_, w| {
944 w.fwrite_qio().clear_bit();
945 w.fwrite_dio().clear_bit();
946 w.fwrite_quad().clear_bit();
947 w.fwrite_dual().clear_bit()
948 });
949 }
950
951 fn psram_set_qio_write_mode_spi1() {
953 SPI1::regs().user().modify(|_, w| {
954 w.fwrite_qio().set_bit();
955 w.fwrite_dio().clear_bit();
956 w.fwrite_quad().clear_bit();
957 w.fwrite_dual().clear_bit()
958 });
959 }
960
961 fn psram_set_qio_read_mode_spi1() {
963 SPI1::regs().ctrl().modify(|_, w| {
964 w.fread_qio().set_bit();
965 w.fread_quad().clear_bit();
966 w.fread_dual().clear_bit();
967 w.fread_dio().clear_bit()
968 });
969 }
970
971 fn psram_set_basic_read_mode_spi1() {
973 SPI1::regs().ctrl().modify(|_, w| {
974 w.fread_qio().clear_bit();
975 w.fread_quad().clear_bit();
976 w.fread_dual().clear_bit();
977 w.fread_dio().clear_bit()
978 });
979 }
980
981 fn psram_gpio_config(psram_io: &PsramIo, mode: PsramCacheSpeed) -> u32 {
983 unsafe {
984 let spi = SPI0::regs();
985 let g_rom_spiflash_dummy_len_plus_ptr = addr_of_mut!(g_rom_spiflash_dummy_len_plus);
986
987 #[derive(Debug, Clone, Copy)]
988 enum Field {
989 McuSel,
990 FunDrv,
991 }
992
993 macro_rules! apply_to_field {
994 ($w:ident, $field:expr, $bits:expr) => {
995 match $field {
996 Field::McuSel => $w.mcu_sel().bits($bits),
997 Field::FunDrv => $w.fun_drv().bits($bits),
998 }
999 };
1000 }
1001
1002 fn configure_gpio(gpio: u8, field: Field, bits: u8) {
1003 unsafe {
1004 let ptr = match gpio {
1007 6 => crate::peripherals::IO_MUX::regs().gpio6(),
1008 7 => crate::peripherals::IO_MUX::regs().gpio7(),
1009 8 => crate::peripherals::IO_MUX::regs().gpio8(),
1010 9 => crate::peripherals::IO_MUX::regs().gpio9(),
1011 10 => crate::peripherals::IO_MUX::regs().gpio10(),
1012 11 => crate::peripherals::IO_MUX::regs().gpio11(),
1013 _ => crate::gpio::io_mux_reg(gpio),
1014 };
1015
1016 ptr.modify(|_, w| apply_to_field!(w, field, bits));
1017 }
1018 }
1019
1020 let spi_cache_dummy;
1021 let rd_mode_reg = spi.ctrl().read().bits();
1022 if (rd_mode_reg & SPI_FREAD_QIO_M) != 0 {
1023 spi_cache_dummy = SPI0_R_QIO_DUMMY_CYCLELEN;
1024 } else if (rd_mode_reg & SPI_FREAD_DIO_M) != 0 {
1025 spi_cache_dummy = SPI0_R_DIO_DUMMY_CYCLELEN;
1026 spi.user1()
1027 .modify(|_, w| w.usr_addr_bitlen().bits(SPI0_R_DIO_ADDR_BITSLEN as u8));
1028 } else {
1029 spi_cache_dummy = SPI0_R_FAST_DUMMY_CYCLELEN;
1030 }
1031
1032 let extra_dummy;
1033
1034 match mode {
1035 PsramCacheSpeed::PsramCacheF80mS40m => {
1036 extra_dummy = PSRAM_IO_MATRIX_DUMMY_40M;
1037
1038 g_rom_spiflash_dummy_len_plus_ptr
1039 .offset(_SPI_CACHE_PORT as isize)
1040 .write_volatile(PSRAM_IO_MATRIX_DUMMY_80M);
1041 g_rom_spiflash_dummy_len_plus_ptr
1042 .offset(_SPI_FLASH_PORT as isize)
1043 .write_volatile(PSRAM_IO_MATRIX_DUMMY_40M);
1044
1045 spi.user1().modify(|_, w| {
1046 w.usr_dummy_cyclelen()
1047 .bits(spi_cache_dummy as u8 + PSRAM_IO_MATRIX_DUMMY_80M)
1048 }); esp_rom_spiflash_config_clk(_SPI_80M_CLK_DIV, _SPI_CACHE_PORT);
1051 esp_rom_spiflash_config_clk(_SPI_40M_CLK_DIV, _SPI_FLASH_PORT);
1052
1053 configure_gpio(psram_io.flash_clk_io, Field::FunDrv, 3);
1056 configure_gpio(psram_io.psram_clk_io, Field::FunDrv, 2);
1057 }
1058 PsramCacheSpeed::PsramCacheF80mS80m => {
1059 extra_dummy = PSRAM_IO_MATRIX_DUMMY_80M;
1060 g_rom_spiflash_dummy_len_plus_ptr
1061 .offset(_SPI_CACHE_PORT as isize)
1062 .write_volatile(PSRAM_IO_MATRIX_DUMMY_80M);
1063 g_rom_spiflash_dummy_len_plus_ptr
1064 .offset(_SPI_FLASH_PORT as isize)
1065 .write_volatile(PSRAM_IO_MATRIX_DUMMY_80M);
1066
1067 spi.user1().modify(|_, w| {
1068 w.usr_dummy_cyclelen()
1069 .bits(spi_cache_dummy as u8 + PSRAM_IO_MATRIX_DUMMY_80M)
1070 }); esp_rom_spiflash_config_clk(_SPI_80M_CLK_DIV, _SPI_CACHE_PORT);
1073 esp_rom_spiflash_config_clk(_SPI_80M_CLK_DIV, _SPI_FLASH_PORT);
1074
1075 configure_gpio(psram_io.flash_clk_io, Field::FunDrv, 3);
1077 configure_gpio(psram_io.psram_clk_io, Field::FunDrv, 3);
1078 }
1079 PsramCacheSpeed::PsramCacheF40mS40m => {
1080 extra_dummy = PSRAM_IO_MATRIX_DUMMY_40M;
1081
1082 g_rom_spiflash_dummy_len_plus_ptr
1083 .offset(_SPI_CACHE_PORT as isize)
1084 .write_volatile(PSRAM_IO_MATRIX_DUMMY_40M);
1085 g_rom_spiflash_dummy_len_plus_ptr
1086 .offset(_SPI_FLASH_PORT as isize)
1087 .write_volatile(PSRAM_IO_MATRIX_DUMMY_40M);
1088
1089 spi.user1().modify(|_, w| {
1090 w.usr_dummy_cyclelen()
1091 .bits(spi_cache_dummy as u8 + PSRAM_IO_MATRIX_DUMMY_40M)
1092 }); esp_rom_spiflash_config_clk(_SPI_40M_CLK_DIV, _SPI_CACHE_PORT);
1095 esp_rom_spiflash_config_clk(_SPI_40M_CLK_DIV, _SPI_FLASH_PORT);
1096
1097 configure_gpio(psram_io.flash_clk_io, Field::FunDrv, 2);
1099 configure_gpio(psram_io.psram_clk_io, Field::FunDrv, 2);
1100 }
1101 }
1102
1103 spi.user().modify(|_, w| w.usr_dummy().set_bit()); esp_rom_gpio_connect_out_signal(
1109 psram_io.flash_cs_io as u32,
1110 SPICS0_OUT_IDX,
1111 false,
1112 false,
1113 );
1114 esp_rom_gpio_connect_out_signal(
1115 psram_io.psram_cs_io as u32,
1116 SPICS1_OUT_IDX,
1117 false,
1118 false,
1119 );
1120 esp_rom_gpio_connect_out_signal(
1121 psram_io.psram_spiq_sd0_io as u32,
1122 SPIQ_OUT_IDX,
1123 false,
1124 false,
1125 );
1126 esp_rom_gpio_connect_in_signal(psram_io.psram_spiq_sd0_io as u32, SPIQ_IN_IDX, false);
1127 esp_rom_gpio_connect_out_signal(
1128 psram_io.psram_spid_sd1_io as u32,
1129 SPID_OUT_IDX,
1130 false,
1131 false,
1132 );
1133 esp_rom_gpio_connect_in_signal(psram_io.psram_spid_sd1_io as u32, SPID_IN_IDX, false);
1134 esp_rom_gpio_connect_out_signal(
1135 psram_io.psram_spiwp_sd3_io as u32,
1136 SPIWP_OUT_IDX,
1137 false,
1138 false,
1139 );
1140 esp_rom_gpio_connect_in_signal(psram_io.psram_spiwp_sd3_io as u32, SPIWP_IN_IDX, false);
1141 esp_rom_gpio_connect_out_signal(
1142 psram_io.psram_spihd_sd2_io as u32,
1143 SPIHD_OUT_IDX,
1144 false,
1145 false,
1146 );
1147 esp_rom_gpio_connect_in_signal(psram_io.psram_spihd_sd2_io as u32, SPIHD_IN_IDX, false);
1148
1149 if (psram_io.flash_clk_io == SPI_IOMUX_PIN_NUM_CLK)
1151 && (psram_io.flash_clk_io != psram_io.psram_clk_io)
1152 {
1153 configure_gpio(
1155 psram_io.flash_clk_io,
1156 Field::McuSel,
1157 FUNC_SD_CLK_SPICLK as u8,
1158 );
1159 } else {
1160 configure_gpio(psram_io.flash_clk_io, Field::McuSel, PIN_FUNC_GPIO as u8);
1162 }
1163 configure_gpio(psram_io.flash_cs_io, Field::McuSel, PIN_FUNC_GPIO as u8);
1164 configure_gpio(psram_io.psram_cs_io, Field::McuSel, PIN_FUNC_GPIO as u8);
1165 configure_gpio(psram_io.psram_clk_io, Field::McuSel, PIN_FUNC_GPIO as u8);
1166 configure_gpio(
1167 psram_io.psram_spiq_sd0_io,
1168 Field::McuSel,
1169 PIN_FUNC_GPIO as u8,
1170 );
1171 configure_gpio(
1172 psram_io.psram_spid_sd1_io,
1173 Field::McuSel,
1174 PIN_FUNC_GPIO as u8,
1175 );
1176 configure_gpio(
1177 psram_io.psram_spihd_sd2_io,
1178 Field::McuSel,
1179 PIN_FUNC_GPIO as u8,
1180 );
1181 configure_gpio(
1182 psram_io.psram_spiwp_sd3_io,
1183 Field::McuSel,
1184 PIN_FUNC_GPIO as u8,
1185 );
1186
1187 let flash_id: u32 = g_rom_flashchip.device_id;
1188 info!("Flash-ID = {}", flash_id);
1189 info!("Flash size = {}", g_rom_flashchip.chip_size);
1190
1191 if flash_id == FLASH_ID_GD25LQ32C {
1192 configure_gpio(psram_io.flash_cs_io, Field::FunDrv, 3);
1194 configure_gpio(psram_io.flash_clk_io, Field::FunDrv, 3);
1195 configure_gpio(psram_io.psram_cs_io, Field::FunDrv, 3);
1196 configure_gpio(psram_io.psram_clk_io, Field::FunDrv, 3);
1197 configure_gpio(psram_io.psram_spiq_sd0_io, Field::FunDrv, 3);
1198 configure_gpio(psram_io.psram_spid_sd1_io, Field::FunDrv, 3);
1199 configure_gpio(psram_io.psram_spihd_sd2_io, Field::FunDrv, 3);
1200 configure_gpio(psram_io.psram_spiwp_sd3_io, Field::FunDrv, 3);
1201 }
1202
1203 extra_dummy as u32
1204 }
1205 }
1206
1207 fn set_peri_reg_bits(reg: u32, bitmap: u32, value: u32, shift: u32) {
1208 unsafe {
1209 (reg as *mut u32).write_volatile(
1210 ((reg as *mut u32).read_volatile() & !(bitmap << shift))
1211 | ((value & bitmap) << shift),
1212 );
1213 }
1214 }
1215}