1use core::ops::Range;
2
3use procmacros::ram;
4
5use super::{EXTMEM_ORIGIN, PsramSize};
6use crate::peripherals::{EXTMEM, IO_MUX, MMU_TABLE, SPI0, SPI1};
7
8#[derive(Copy, Clone, Debug, Default, PartialEq)]
10#[cfg_attr(feature = "defmt", derive(defmt::Format))]
11pub enum PsramMode {
12 #[default]
14 Auto,
15
16 QuadSpi,
18
19 OctalSpi,
21}
22
23#[derive(Copy, Clone, Debug, Default, PartialEq)]
25#[cfg_attr(feature = "defmt", derive(defmt::Format))]
26pub enum FlashFreq {
27 FlashFreq20m = 20,
29 FlashFreq40m = 40,
31 #[default]
33 FlashFreq80m = 80,
34 FlashFreq120m = 120,
37}
38
39#[derive(Copy, Clone, Debug, Default, PartialEq)]
41#[cfg_attr(feature = "defmt", derive(defmt::Format))]
42pub enum SpiRamFreq {
43 Freq40m = 40,
45 #[default]
47 Freq80m = 80,
48 Freq120m = 120,
51}
52
53#[derive(Copy, Clone, Debug, Default, PartialEq)]
55#[cfg_attr(feature = "defmt", derive(defmt::Format))]
56pub enum SpiTimingConfigCoreClock {
57 #[default]
59 SpiTimingConfigCoreClock80m = 80,
60 SpiTimingConfigCoreClock120m = 120,
62 SpiTimingConfigCoreClock160m = 160,
64 SpiTimingConfigCoreClock240m = 240,
66}
67
68#[derive(Copy, Clone, Debug, Default, PartialEq)]
70#[cfg_attr(feature = "defmt", derive(defmt::Format))]
71pub struct PsramConfig {
72 pub mode: PsramMode,
74 pub size: PsramSize,
76 pub core_clock: Option<SpiTimingConfigCoreClock>,
78 pub flash_frequency: FlashFreq,
80 pub ram_frequency: SpiRamFreq,
82}
83
84#[procmacros::ram]
86pub(crate) fn init_psram(config: &mut PsramConfig) -> bool {
87 let success = match config.mode {
88 PsramMode::Auto => {
89 let mut success = octal_spi_impl::psram_init(config);
90
91 if !success {
92 success = quad_spi_impl::psram_init(config);
93 }
94
95 success
96 }
97 PsramMode::QuadSpi => quad_spi_impl::psram_init(config),
98 PsramMode::OctalSpi => octal_spi_impl::psram_init(config),
99 };
100
101 if !success {
102 warn!(
103 "Failed to configure PSRAM. This may indicate a missing/inoperable PSRAM chip, or an incorrect PSRAM configuration. Check if the PSRAM chip is present and the configuration is correct."
104 );
105 }
106
107 success
108}
109
110#[procmacros::ram]
111pub(crate) fn map_psram(config: PsramConfig) -> Range<usize> {
112 const MMU_ACCESS_SPIRAM: u32 = 1 << 15;
113 const START_PAGE: u32 = 0;
114
115 unsafe extern "C" {
116 fn Cache_Suspend_DCache() -> u32;
117
118 fn Cache_Resume_DCache(param: u32);
119
120 fn cache_dbus_mmu_set(
129 ext_ram: u32,
130 vaddr: u32,
131 paddr: u32,
132 psize: u32,
133 num: u32,
134 fixed: u32,
135 ) -> i32;
136 }
137
138 const MMU_PAGE_SIZE: u32 = property!("mmu.page_size");
139
140 fn mmu_entry_is_valid(entry_id: usize) -> bool {
141 !MMU_TABLE::regs().entry(entry_id).read().invalid().bit()
142 }
143
144 let mut mapped_pages = 0;
152
153 let flash_mmu_table_size: usize = MMU_TABLE::regs().entry_iter().count();
156 for i in (0..(flash_mmu_table_size - 1)).rev() {
157 if mmu_entry_is_valid(i) {
158 mapped_pages = (i + 1) as u32;
159 break;
160 }
161 }
162 let start = EXTMEM_ORIGIN as u32 + (MMU_PAGE_SIZE * mapped_pages);
163 debug!("PSRAM start address = {:x}", start);
164
165 unsafe { Cache_Suspend_DCache() };
167
168 let cache_dbus_mmu_set_res = unsafe {
169 cache_dbus_mmu_set(
170 MMU_ACCESS_SPIRAM,
171 start,
172 START_PAGE << 16,
173 64,
174 config.size.get() as u32 / 1024 / 64, 0,
176 )
177 };
178
179 EXTMEM::regs().dcache_ctrl1().modify(|_, w| {
180 w.dcache_shut_core0_bus().clear_bit();
181 w.dcache_shut_core1_bus().clear_bit()
182 });
183
184 unsafe { Cache_Resume_DCache(0) };
185
186 if cache_dbus_mmu_set_res != 0 {
188 panic!("cache_dbus_mmu_set failed");
189 }
190
191 start as usize..start as usize + config.size.get()
192}
193
194pub(crate) mod quad_spi_impl {
195 use super::*;
196 use crate::psram::quad_xtensa;
197
198 const PSRAM_CS_IO: u8 = 26;
199 const SPI_CS1_GPIO_NUM: u8 = 26;
200 const FUNC_SPICS1_SPICS1: u8 = 0;
201 const PIN_FUNC_GPIO: u8 = 2;
202 const PSRAM_SPIWP_SD3_IO: u8 = 10;
203 const ESP_ROM_EFUSE_FLASH_DEFAULT_SPI: u32 = 0;
204 const SPICS1_OUT_IDX: u8 = 6;
205
206 #[ram]
207 pub(crate) fn psram_init(config: &mut PsramConfig) -> bool {
208 psram_gpio_config();
209 psram_set_cs_timing();
210
211 if config.size.is_auto() {
212 let Some(size) = quad_xtensa::detect_quad_size() else {
213 return false;
214 };
215 config.size = PsramSize::Size(size);
216 }
217
218 if config.core_clock.is_none() {
219 config.core_clock = Some(if config.ram_frequency == SpiRamFreq::Freq120m {
220 SpiTimingConfigCoreClock::SpiTimingConfigCoreClock120m
221 } else {
222 SpiTimingConfigCoreClock::SpiTimingConfigCoreClock80m
223 });
224 }
225
226 quad_xtensa::psram_reset_mode_spi1();
227 quad_xtensa::psram_enable_qio_mode_spi1();
228
229 mspi_timing_psram_tuning();
232
233 quad_xtensa::config_psram_spi_phases();
234 mspi_timing_enter_high_speed_mode(true, config);
235
236 info!("PSRAM initialized successfully in Quad SPI mode");
237 true
238 }
239
240 unsafe extern "C" {
241 fn esp_rom_efuse_get_flash_gpio_info() -> u32;
242
243 fn esp_rom_efuse_get_flash_wp_gpio() -> u8;
244
245 fn esp_rom_gpio_connect_out_signal(
246 gpio_num: u8,
247 signal_idx: u8,
248 out_inv: bool,
249 oen_inv: bool,
250 );
251
252 fn esp_rom_spiflash_select_qio_pins(wp_gpio_num: u8, spiconfig: u32);
268 }
269
270 #[ram]
271 fn mspi_timing_psram_tuning() {
272 }
275
276 #[ram]
285 fn mspi_timing_enter_high_speed_mode(control_spi1: bool, config: &PsramConfig) {
286 let core_clock: SpiTimingConfigCoreClock = mspi_core_clock(config);
287 let flash_div: u32 = flash_clock_divider(config);
288 let psram_div: u32 = psram_clock_divider(config);
289
290 info!(
291 "PSRAM {} MHz, flash {} MHz, core_clock {:?}, flash_div = {}, psram_div = {}",
292 config.ram_frequency as u32,
293 config.flash_frequency as u32,
294 core_clock,
295 flash_div,
296 psram_div
297 );
298
299 spi0_timing_config_set_core_clock(core_clock);
303
304 spi0_timing_config_set_flash_clock(flash_div);
305 if control_spi1 {
306 spi1_timing_config_set_flash_clock(flash_div);
307 }
308 quad_xtensa::spi0_timing_config_set_psram_clock(psram_div);
309 }
310
311 #[ram]
312 fn spi0_timing_config_set_core_clock(core_clock: SpiTimingConfigCoreClock) {
313 unsafe {
314 SPI0::regs().core_clk_sel().modify(|_, w| {
315 w.core_clk_sel().bits(match core_clock {
316 SpiTimingConfigCoreClock::SpiTimingConfigCoreClock80m => 0,
317 SpiTimingConfigCoreClock::SpiTimingConfigCoreClock120m => 1,
318 SpiTimingConfigCoreClock::SpiTimingConfigCoreClock160m => 2,
319 SpiTimingConfigCoreClock::SpiTimingConfigCoreClock240m => 3,
320 })
321 });
322 }
323 }
324
325 #[ram]
326 fn mspi_core_clock(config: &PsramConfig) -> SpiTimingConfigCoreClock {
327 config.core_clock.unwrap_or_default()
328 }
329
330 #[ram]
331 fn flash_clock_divider(config: &PsramConfig) -> u32 {
332 config.core_clock.unwrap_or_default() as u32 / config.flash_frequency as u32
333 }
334
335 #[ram]
336 fn psram_clock_divider(config: &PsramConfig) -> u32 {
337 config.core_clock.unwrap_or_default() as u32 / config.ram_frequency as u32
338 }
339
340 #[ram]
341 fn psram_set_cs_timing() {
342 SPI0::regs().spi_smem_ac().modify(|_, w| unsafe {
345 w.spi_smem_cs_hold_time().bits(0);
346 w.spi_smem_cs_setup_time().bits(0);
347 w.spi_smem_cs_hold().set_bit();
348 w.spi_smem_cs_setup().set_bit()
349 });
350 }
351
352 #[ram]
353 fn psram_gpio_config() {
354 let cs1_io: u8 = PSRAM_CS_IO;
356 let mcu_sel = if cs1_io == SPI_CS1_GPIO_NUM {
357 FUNC_SPICS1_SPICS1
358 } else {
359 unsafe {
360 esp_rom_gpio_connect_out_signal(cs1_io, SPICS1_OUT_IDX, false, false);
361 PIN_FUNC_GPIO
362 }
363 };
364
365 IO_MUX::regs()
366 .gpio(cs1_io as usize)
367 .modify(|_, w| unsafe { w.mcu_sel().bits(mcu_sel) });
368
369 let mut wp_io: u8 = PSRAM_SPIWP_SD3_IO;
371 let spiconfig = unsafe { esp_rom_efuse_get_flash_gpio_info() };
372 if spiconfig == ESP_ROM_EFUSE_FLASH_DEFAULT_SPI {
373 } else {
376 wp_io = unsafe { esp_rom_efuse_get_flash_wp_gpio() };
379 }
380 unsafe {
382 esp_rom_spiflash_select_qio_pins(wp_io, spiconfig);
383 }
384 }
385}
386
387pub(crate) mod octal_spi_impl {
388 use super::*;
389 use crate::psram::quad_xtensa;
390
391 const OPI_PSRAM_SYNC_READ: u16 = 0x0000;
392 const OPI_PSRAM_SYNC_WRITE: u16 = 0x8080;
393 const OPI_PSRAM_REG_READ: u16 = 0x4040;
394 const OPI_PSRAM_REG_WRITE: u16 = 0xC0C0;
395 const OCT_PSRAM_RD_CMD_BITLEN: u8 = 16;
396 const OCT_PSRAM_WR_CMD_BITLEN: u8 = 16;
397 const OCT_PSRAM_ADDR_BITLEN: u8 = 32;
398 const OCT_PSRAM_RD_DUMMY_BITLEN: u8 = 2 * (10 - 1);
399 const OCT_PSRAM_WR_DUMMY_BITLEN: u8 = 2 * (5 - 1);
400 const OCT_PSRAM_CS1_IO: u8 = SPI_CS1_GPIO_NUM;
401 const OCT_PSRAM_VENDOR_ID: u8 = 0xD;
402
403 const OCT_PSRAM_CS_SETUP_TIME: u8 = 3;
404 const OCT_PSRAM_CS_HOLD_TIME: u8 = 3;
405 const OCT_PSRAM_CS_HOLD_DELAY: u8 = 2;
406
407 const SPI_CS1_GPIO_NUM: u8 = 26;
408 const FUNC_SPICS1_SPICS1: u8 = 0;
409
410 const ESP_ROM_SPIFLASH_OPI_DTR_MODE: u8 = 7;
411
412 unsafe extern "C" {
413 fn esp_rom_opiflash_exec_cmd(
429 spi_num: u32,
430 mode: u8,
431 cmd: u32,
432 cmd_bit_len: u32,
433 addr: u32,
434 addr_bit_len: u32,
435 dummy_bits: u32,
436 mosi_data: *const u8,
437 mosi_bit_len: u32,
438 miso_data: *mut u8,
439 miso_bit_len: u32,
440 cs_mask: u32,
441 is_write_erase_operation: bool,
442 );
443
444 fn esp_rom_spi_set_dtr_swap_mode(spi: u32, wr_swap: bool, rd_swap: bool);
449
450 fn esp_rom_opiflash_pin_config();
451 }
452
453 #[derive(Default)]
455 #[repr(C)]
456 struct OpiPsramModeReg {
457 pub mr0: u8,
459 pub mr1: u8,
461 pub mr2: u8,
463 pub mr3: u8,
465 pub mr4: u8,
467 pub mr8: u8,
469 }
470
471 #[allow(unused)]
472 impl OpiPsramModeReg {
473 fn drive_str(&self) -> u8 {
474 self.mr0 & 0b11
475 }
476
477 fn set_drive_str(&mut self, value: u8) {
478 self.mr0 &= !0b11;
479 self.mr0 |= value & 0b11;
480 }
481
482 fn read_latency(&self) -> u8 {
483 (self.mr0 >> 2) & 0b111
484 }
485
486 fn set_read_latency(&mut self, value: u8) {
487 self.mr0 &= !(0b111 << 2);
488 self.mr0 |= (value & 0b111) << 2;
489 }
490
491 fn lt(&self) -> u8 {
492 (self.mr0 >> 5) & 0b1
493 }
494
495 fn set_lt(&mut self, value: u8) {
496 self.mr0 &= !(0b1 << 5);
497 self.mr0 |= (value & 0b1) << 5;
498 }
499
500 fn rsvd0_1(&self) -> u8 {
501 (self.mr0 >> 6) & 0b11
502 }
503
504 fn set_rsvd0_1(&mut self, value: u8) {
505 self.mr0 &= !(0b11 << 6);
506 self.mr0 |= (value & 0b11) << 6;
507 }
508
509 fn vendor_id(&self) -> u8 {
510 self.mr1 & 0b11111
511 }
512
513 fn set_vendor_id(&mut self, value: u8) {
514 self.mr1 &= !0b11111;
515 self.mr1 |= value & 0b11111;
516 }
517
518 fn rsvd0_2(&self) -> u8 {
519 (self.mr1 >> 5) & 0b111
520 }
521
522 fn set_rsvd0_2(&mut self, value: u8) {
523 self.mr1 &= !(0b111 << 5);
524 self.mr1 |= (value & 0b111) << 5;
525 }
526
527 fn density(&self) -> u8 {
528 self.mr2 & 0b111
529 }
530
531 fn set_density(&mut self, value: u8) {
532 self.mr2 &= !0b111;
533 self.mr2 |= value & 0b111;
534 }
535
536 fn dev_id(&self) -> u8 {
537 (self.mr2 >> 3) & 0b11
538 }
539
540 fn set_dev_id(&mut self, value: u8) {
541 self.mr2 &= !(0b11 << 3);
542 self.mr2 |= (value & 0b11) << 3;
543 }
544
545 fn rsvd1_2(&self) -> u8 {
546 (self.mr2 >> 5) & 0b11
547 }
548
549 fn set_rsvd1_2(&mut self, value: u8) {
550 self.mr2 &= !(0b11 << 5);
551 self.mr2 |= (value & 0b11) << 5;
552 }
553
554 fn gb(&self) -> u8 {
555 (self.mr2 >> 7) & 0b1
556 }
557
558 fn set_gb(&mut self, value: u8) {
559 self.mr2 &= !(0b1 << 7);
560 self.mr2 |= (value & 0b1) << 7;
561 }
562
563 fn rsvd3_7(&self) -> u8 {
564 self.mr3 & 0b11111
565 }
566
567 fn set_rsvd3_7(&mut self, value: u8) {
568 self.mr3 &= !0b11111;
569 self.mr3 |= value & 0b11111;
570 }
571
572 fn srf(&self) -> u8 {
573 (self.mr3 >> 5) & 0b1
574 }
575
576 fn set_srf(&mut self, value: u8) {
577 self.mr3 &= !(0b1 << 5);
578 self.mr3 |= (value & 0b1) << 5;
579 }
580
581 fn vcc(&self) -> u8 {
582 (self.mr3 >> 6) & 0b1
583 }
584
585 fn set_vcc(&mut self, value: u8) {
586 self.mr3 &= !(0b1 << 6);
587 self.mr3 |= (value & 0b1) << 6;
588 }
589
590 fn rsvd0(&self) -> u8 {
591 (self.mr3 >> 7) & 0b1
592 }
593
594 fn set_rsvd0(&mut self, value: u8) {
595 self.mr3 &= !(0b1 << 7);
596 self.mr3 |= (value & 0b1) << 7;
597 }
598
599 fn pasr(&self) -> u8 {
600 self.mr4 & 0b111
601 }
602
603 fn set_pasr(&mut self, value: u8) {
604 self.mr4 &= !0b111;
605 self.mr4 |= value & 0b111;
606 }
607
608 fn rf(&self) -> u8 {
609 (self.mr4 >> 3) & 0b1
610 }
611
612 fn set_rf(&mut self, value: u8) {
613 self.mr4 &= !(0b1 << 3);
614 self.mr4 |= (value & 0b1) << 3;
615 }
616
617 fn rsvd3(&self) -> u8 {
618 (self.mr4 >> 4) & 0b1
619 }
620
621 fn set_rsvd3(&mut self, value: u8) {
622 self.mr4 &= !(0b1 << 4);
623 self.mr4 |= (value & 0b1) << 4;
624 }
625
626 fn wr_latency(&self) -> u8 {
627 (self.mr4 >> 5) & 0b111
628 }
629
630 fn set_wr_latency(&mut self, value: u8) {
631 self.mr4 &= !(0b111 << 5);
632 self.mr4 |= (value & 0b111) << 5;
633 }
634
635 fn bl(&self) -> u8 {
636 self.mr8 & 0b11
637 }
638
639 fn set_bl(&mut self, value: u8) {
640 self.mr8 &= !0b11;
641 self.mr8 |= value & 0b11;
642 }
643
644 fn bt(&self) -> u8 {
645 (self.mr8 >> 2) & 0b1
646 }
647
648 fn set_bt(&mut self, value: u8) {
649 self.mr8 &= !(0b1 << 2);
650 self.mr8 |= (value & 0b1) << 2;
651 }
652
653 fn rsvd0_4(&self) -> u8 {
654 (self.mr8 >> 3) & 0b11111
655 }
656
657 fn set_rsvd0_4(&mut self, value: u8) {
658 self.mr8 &= !(0b11111 << 3);
659 self.mr8 |= (value & 0b11111) << 3;
660 }
661 }
662
663 #[ram]
664 pub(crate) fn psram_init(config: &mut PsramConfig) -> bool {
665 mspi_pin_init();
666 set_psram_cs_timing();
667
668 spi_timing_enter_mspi_low_speed_mode(true);
673
674 unsafe {
675 SPI1::regs()
677 .ddr()
678 .modify(|_, w| w.spi_fmem_var_dummy().set_bit());
679 esp_rom_spi_set_dtr_swap_mode(1, false, false);
680 }
681
682 let mut mode_reg = OpiPsramModeReg::default();
684 mode_reg.set_lt(1);
685 mode_reg.set_read_latency(2);
686 mode_reg.set_drive_str(0);
687 mode_reg.set_bl(3);
688 mode_reg.set_bt(0);
689
690 init_psram_mode_reg(1, &mode_reg);
691 psram_mode_reg(1, &mut mode_reg);
693
694 print_psram_info(&mode_reg);
695
696 if mode_reg.vendor_id() != OCT_PSRAM_VENDOR_ID {
697 debug!(
698 "Unknown PSRAM vendor ID: {:x}. PSRAM chip not found or not supported. Check if the interface mode is configured correctly.",
699 mode_reg.vendor_id()
700 );
701 return false;
702 }
703
704 let psram_size = match mode_reg.density() {
705 0x0 => 2 * 1024 * 1024,
706 0x1 => 4 * 1024 * 1024,
707 0x3 => 8 * 1024 * 1024,
708 0x5 => 16 * 1024 * 1024,
709 0x7 => 32 * 1024 * 1024,
710 _ => 0,
711 };
712 info!("{} bytes of PSRAM", psram_size);
713
714 if config.core_clock.is_none() {
715 config.core_clock = Some(if config.ram_frequency == SpiRamFreq::Freq80m {
716 SpiTimingConfigCoreClock::SpiTimingConfigCoreClock160m
717 } else if config.ram_frequency == SpiRamFreq::Freq120m {
718 SpiTimingConfigCoreClock::SpiTimingConfigCoreClock240m
719 } else {
720 SpiTimingConfigCoreClock::SpiTimingConfigCoreClock80m
721 });
722 }
723 if config.size.is_auto() {
724 config.size = PsramSize::Size(psram_size);
725 }
726
727 spi_timing_enter_mspi_high_speed_mode(true, config);
735
736 spi_flash_set_rom_required_regs();
739
740 config_psram_spi_phases();
745
746 info!("PSRAM initialized successfully in Octal SPI mode");
747 true
748 }
749
750 fn config_psram_spi_phases() {
753 SPI0::regs().cache_sctrl().modify(|_, w| unsafe {
754 w.sram_oct().set_bit();
755
756 w.cache_sram_usr_rcmd().set_bit();
757 w.cache_sram_usr_wcmd().set_bit();
758
759 w.sram_addr_bitlen().bits(OCT_PSRAM_ADDR_BITLEN - 1);
761 w.cache_usr_scmd_4byte().set_bit();
762
763 w.usr_rd_sram_dummy().set_bit();
765 w.usr_wr_sram_dummy().set_bit();
766 w.sram_rdummy_cyclelen().bits(OCT_PSRAM_RD_DUMMY_BITLEN - 1);
767 w.sram_wdummy_cyclelen().bits(OCT_PSRAM_WR_DUMMY_BITLEN - 1)
768 });
769
770 SPI0::regs().sram_dwr_cmd().modify(|_, w| unsafe {
772 w.cache_sram_usr_wr_cmd_value().bits(OPI_PSRAM_SYNC_WRITE);
773 w.cache_sram_usr_wr_cmd_bitlen()
774 .bits(OCT_PSRAM_WR_CMD_BITLEN - 1)
775 });
776
777 SPI0::regs().sram_drd_cmd().modify(|_, w| unsafe {
779 w.cache_sram_usr_rd_cmd_bitlen()
780 .bits(OCT_PSRAM_RD_CMD_BITLEN - 1);
781 w.cache_sram_usr_rd_cmd_value().bits(OPI_PSRAM_SYNC_READ)
782 });
783
784 SPI0::regs().spi_smem_ddr().modify(|_, w| {
785 w.spi_smem_var_dummy().set_bit();
786 w.wdat_swp().clear_bit();
787 w.rdat_swp().clear_bit();
788 w.en().set_bit()
789 });
790
791 SPI0::regs().sram_cmd().modify(|_, w| {
792 w.sdummy_out().set_bit();
793 w.scmd_oct().set_bit();
794 w.saddr_oct().set_bit();
795 w.sdout_oct().set_bit();
796 w.sdin_oct().set_bit()
797 });
798 }
799
800 #[ram]
801 fn spi_flash_set_rom_required_regs() {
802 SPI1::regs()
804 .ddr()
805 .modify(|_, w| w.spi_fmem_var_dummy().clear_bit());
806 }
812
813 #[ram]
814 fn mspi_pin_init() {
815 unsafe { esp_rom_opiflash_pin_config() };
816 SPI0::regs().date().modify(|_, w| unsafe {
821 w.spi_spiclk_pad_drv_ctl_en().set_bit();
822 w.spi_smem_spiclk_fun_drv().bits(3);
823 w.spi_fmem_spiclk_fun_drv().bits(3)
824 });
825
826 let pins = [
828 OCT_PSRAM_CS1_IO as usize,
829 27,
830 28,
831 31,
832 32,
833 33,
834 34,
835 35,
836 36,
837 37,
838 ];
839 for pin in pins {
840 IO_MUX::regs()
841 .gpio(pin)
842 .modify(|_, w| unsafe { w.fun_drv().bits(3) });
843 }
844
845 IO_MUX::regs()
846 .gpio(OCT_PSRAM_CS1_IO as usize)
847 .modify(|_, w| unsafe { w.mcu_sel().bits(FUNC_SPICS1_SPICS1) });
848 }
849
850 fn spi_timing_enter_mspi_low_speed_mode(control_spi1: bool) {
851 spi0_timing_config_set_core_clock(SpiTimingConfigCoreClock::SpiTimingConfigCoreClock80m); spi0_timing_config_set_flash_clock(4);
864 if control_spi1 {
865 spi1_timing_config_set_flash_clock(4);
867 }
868
869 quad_xtensa::spi0_timing_config_set_psram_clock(4);
871
872 }
875
876 fn spi_timing_enter_mspi_high_speed_mode(control_spi1: bool, config: &PsramConfig) {
884 let flash_div: u32 = flash_clock_divider(config);
885 let psram_div: u32 = psram_clock_divider(config);
886
887 spi0_timing_config_set_core_clock(config.core_clock.unwrap_or_default()); spi0_timing_config_set_flash_clock(flash_div);
891 if control_spi1 {
892 spi1_timing_config_set_flash_clock(flash_div);
893 }
894 quad_xtensa::spi0_timing_config_set_psram_clock(psram_div);
896
897 }
900
901 fn set_psram_cs_timing() {
902 SPI0::regs().spi_smem_ac().modify(|_, w| unsafe {
906 w.spi_smem_cs_hold().set_bit();
907 w.spi_smem_cs_setup().set_bit();
908 w.spi_smem_cs_hold_time().bits(OCT_PSRAM_CS_HOLD_TIME);
909 w.spi_smem_cs_setup_time().bits(OCT_PSRAM_CS_SETUP_TIME);
910
911 w.spi_smem_cs_hold_delay().bits(OCT_PSRAM_CS_HOLD_DELAY)
914 });
915 }
916
917 fn psram_mode_reg(spi_num: u32, out_reg: &mut OpiPsramModeReg) {
918 let mode = ESP_ROM_SPIFLASH_OPI_DTR_MODE;
919 let cmd_len: u32 = 16;
920 let addr_bit_len: u32 = 32;
921 let dummy: u32 = OCT_PSRAM_RD_DUMMY_BITLEN as u32;
922 let mut data_bit_len: u32 = 16;
923
924 unsafe {
925 esp_rom_opiflash_exec_cmd(
927 spi_num,
928 mode,
929 OPI_PSRAM_REG_READ as u32,
930 cmd_len,
931 0x0,
932 addr_bit_len,
933 dummy,
934 core::ptr::null(),
935 0,
936 &mut out_reg.mr0,
937 data_bit_len,
938 1 << 1,
939 false,
940 );
941 esp_rom_opiflash_exec_cmd(
943 spi_num,
944 mode,
945 OPI_PSRAM_REG_READ as u32,
946 cmd_len,
947 0x2,
948 addr_bit_len,
949 dummy,
950 core::ptr::null(),
951 0,
952 &mut out_reg.mr2,
953 data_bit_len,
954 1 << 1,
955 false,
956 );
957 data_bit_len = 8;
958 esp_rom_opiflash_exec_cmd(
960 spi_num,
961 mode,
962 OPI_PSRAM_REG_READ as u32,
963 cmd_len,
964 0x4,
965 addr_bit_len,
966 dummy,
967 core::ptr::null(),
968 0,
969 &mut out_reg.mr4,
970 data_bit_len,
971 1 << 1,
972 false,
973 );
974 esp_rom_opiflash_exec_cmd(
976 spi_num,
977 mode,
978 OPI_PSRAM_REG_READ as u32,
979 cmd_len,
980 0x8,
981 addr_bit_len,
982 dummy,
983 core::ptr::null(),
984 0,
985 &mut out_reg.mr8,
986 data_bit_len,
987 1 << 1,
988 false,
989 );
990 }
991 }
992
993 fn init_psram_mode_reg(spi_num: u32, mode_reg_config: &OpiPsramModeReg) {
995 let mode = ESP_ROM_SPIFLASH_OPI_DTR_MODE;
996 let cmd_len: u32 = 16;
997 let addr: u32 = 0x0; let addr_bit_len: u32 = 32;
999 let dummy = OCT_PSRAM_RD_DUMMY_BITLEN as u32;
1000 let mut mode_reg = OpiPsramModeReg::default();
1001 let data_bit_len: u32 = 16;
1002
1003 unsafe {
1005 esp_rom_opiflash_exec_cmd(
1006 spi_num,
1007 mode,
1008 OPI_PSRAM_REG_READ as u32,
1009 cmd_len,
1010 addr,
1011 addr_bit_len,
1012 dummy,
1013 core::ptr::null(),
1014 0,
1015 &mut mode_reg.mr0,
1016 data_bit_len,
1017 1 << 1,
1018 false,
1019 );
1020 }
1021
1022 mode_reg.set_lt(mode_reg_config.lt());
1024 mode_reg.set_read_latency(mode_reg_config.read_latency());
1025 mode_reg.set_drive_str(mode_reg_config.drive_str());
1026
1027 unsafe {
1029 esp_rom_opiflash_exec_cmd(
1030 spi_num,
1031 mode,
1032 OPI_PSRAM_REG_WRITE as u32,
1033 cmd_len,
1034 addr,
1035 addr_bit_len,
1036 0,
1037 &mode_reg.mr0,
1038 16,
1039 core::ptr::null_mut(),
1040 0,
1041 1 << 1,
1042 false,
1043 );
1044 }
1045
1046 }
1048
1049 fn print_psram_info(reg_val: &OpiPsramModeReg) {
1050 info!(
1051 "vendor id : {:02x} ({})",
1052 reg_val.vendor_id(),
1053 if reg_val.vendor_id() == 0x0d {
1054 "AP"
1055 } else {
1056 "UNKNOWN"
1057 }
1058 );
1059 info!(
1060 "dev id : {:02x} (generation {})",
1061 reg_val.dev_id(),
1062 reg_val.dev_id() + 1
1063 );
1064 info!(
1065 "density : {:02x} ({} Mbit)",
1066 reg_val.density(),
1067 if reg_val.density() == 0x1 {
1068 32
1069 } else if reg_val.density() == 0x3 {
1070 64
1071 } else if reg_val.density() == 0x5 {
1072 128
1073 } else if reg_val.density() == 0x7 {
1074 256
1075 } else {
1076 0
1077 }
1078 );
1079 info!(
1080 "good-die : {:02x} ({})",
1081 reg_val.gb(),
1082 if reg_val.gb() == 1 { "Pass" } else { "Fail" }
1083 );
1084 info!(
1085 "Latency : {:02x} ({})",
1086 reg_val.lt(),
1087 if reg_val.lt() == 1 {
1088 "Fixed"
1089 } else {
1090 "Variable"
1091 }
1092 );
1093 info!(
1094 "VCC : {:02x} ({})",
1095 reg_val.vcc(),
1096 if reg_val.vcc() == 1 { "3V" } else { "1.8V" }
1097 );
1098 info!(
1099 "SRF : {:02x} ({} Refresh)",
1100 reg_val.srf(),
1101 if reg_val.srf() == 0x1 { "Fast" } else { "Slow" }
1102 );
1103 info!(
1104 "BurstType : {:02x} ({} Wrap)",
1105 reg_val.bt(),
1106 if reg_val.bt() == 1 && reg_val.bl() != 3 {
1107 "Hybrid"
1108 } else {
1109 ""
1110 }
1111 );
1112 info!(
1113 "BurstLen : {:02x} ({} Byte)",
1114 reg_val.bl(),
1115 if reg_val.bl() == 0x00 {
1116 16
1117 } else if reg_val.bl() == 0x01 {
1118 32
1119 } else if reg_val.bl() == 0x10 {
1120 64
1121 } else {
1122 1024
1123 }
1124 );
1125 info!(
1126 "Readlatency : {:02x} ({} cycles@{})",
1127 reg_val.read_latency(),
1128 reg_val.read_latency() * 2 + 6,
1129 if reg_val.lt() == 1 {
1130 "Fixed"
1131 } else {
1132 "Variable"
1133 }
1134 );
1135 info!(
1136 "DriveStrength: {:02x} (1/{})",
1137 reg_val.drive_str(),
1138 if reg_val.drive_str() == 0x00 {
1139 1
1140 } else if reg_val.drive_str() == 0x01 {
1141 2
1142 } else if reg_val.drive_str() == 0x02 {
1143 4
1144 } else {
1145 8
1146 }
1147 );
1148 }
1149
1150 #[ram]
1151 fn spi0_timing_config_set_core_clock(core_clock: SpiTimingConfigCoreClock) {
1152 unsafe {
1153 SPI0::regs().core_clk_sel().modify(|_, w| {
1154 w.core_clk_sel().bits(match core_clock {
1155 SpiTimingConfigCoreClock::SpiTimingConfigCoreClock80m => 0,
1156 SpiTimingConfigCoreClock::SpiTimingConfigCoreClock120m => 1,
1157 SpiTimingConfigCoreClock::SpiTimingConfigCoreClock160m => 2,
1158 SpiTimingConfigCoreClock::SpiTimingConfigCoreClock240m => 3,
1159 })
1160 });
1161 }
1162 }
1163
1164 #[ram]
1165 fn flash_clock_divider(config: &PsramConfig) -> u32 {
1166 config.core_clock.unwrap_or_default() as u32 / config.flash_frequency as u32
1167 }
1168
1169 #[ram]
1170 fn psram_clock_divider(config: &PsramConfig) -> u32 {
1171 config.core_clock.unwrap_or_default() as u32 / config.ram_frequency as u32
1172 }
1173}
1174
1175#[ram]
1176fn spi0_timing_config_set_flash_clock(freqdiv: u32) {
1177 if freqdiv == 1 {
1178 SPI0::regs().clock().write(|w| unsafe {
1179 w.clk_equ_sysclk().set_bit();
1180 w.clkcnt_h().bits(0);
1181 w.clkcnt_n().bits(0);
1182 w.clkcnt_l().bits(0)
1183 });
1184 } else {
1185 SPI0::regs().clock().write(|w| unsafe {
1186 w.clk_equ_sysclk().clear_bit();
1187 w.clkcnt_h().bits((freqdiv / 2 - 1) as u8);
1188 w.clkcnt_n().bits((freqdiv - 1) as u8);
1189 w.clkcnt_l().bits((freqdiv - 1) as u8)
1190 });
1191 }
1192}
1193
1194#[ram]
1195fn spi1_timing_config_set_flash_clock(freqdiv: u32) {
1196 if freqdiv == 1 {
1197 SPI1::regs().clock().write(|w| unsafe {
1198 w.clk_equ_sysclk().set_bit();
1199 w.clkcnt_h().bits(0);
1200 w.clkcnt_n().bits(0);
1201 w.clkcnt_l().bits(0)
1202 });
1203 } else {
1204 SPI1::regs().clock().write(|w| unsafe {
1205 w.clk_equ_sysclk().clear_bit();
1206 w.clkcnt_h().bits((freqdiv / 2 - 1) as u8);
1207 w.clkcnt_n().bits((freqdiv - 1) as u8);
1208 w.clkcnt_l().bits((freqdiv - 1) as u8)
1209 });
1210 }
1211}