1use super::PsramSize;
2use crate::peripherals::{EXTMEM, IO_MUX, SPI0, SPI1};
3
4const EXTMEM_ORIGIN: u32 = 0x3C000000;
5
6#[derive(Copy, Clone, Debug, Default, PartialEq)]
8#[cfg_attr(feature = "defmt", derive(defmt::Format))]
9pub enum FlashFreq {
10 FlashFreq20m = 20,
12 FlashFreq40m = 40,
14 #[default]
16 FlashFreq80m = 80,
17 FlashFreq120m = 120,
20}
21
22#[derive(Copy, Clone, Debug, Default, PartialEq)]
24#[cfg_attr(feature = "defmt", derive(defmt::Format))]
25#[allow(missing_docs)]
26pub enum SpiRamFreq {
27 #[default]
29 Freq40m = 40,
30 Freq80m = 80,
32 Freq120m = 120,
35}
36
37#[derive(Copy, Clone, Debug, Default, PartialEq)]
39#[cfg_attr(feature = "defmt", derive(defmt::Format))]
40pub enum SpiTimingConfigCoreClock {
41 #[default]
43 SpiTimingConfigCoreClock80m = 80,
44 SpiTimingConfigCoreClock120m = 120,
46 SpiTimingConfigCoreClock160m = 160,
48 SpiTimingConfigCoreClock240m = 240,
50}
51
52#[derive(Copy, Clone, Debug, Default, PartialEq)]
54#[cfg_attr(feature = "defmt", derive(defmt::Format))]
55pub struct PsramConfig {
56 pub size: PsramSize,
58 pub core_clock: Option<SpiTimingConfigCoreClock>,
60 pub flash_frequency: FlashFreq,
62 pub ram_frequency: SpiRamFreq,
64}
65
66#[procmacros::ram]
70pub(crate) fn init_psram(config: PsramConfig) {
71 let mut config = config;
72
73 if config.core_clock.is_none() {
74 cfg_if::cfg_if! {
75 if #[cfg(psram_mode_octal)] {
76 config.core_clock = Some(if config.ram_frequency == SpiRamFreq::Freq80m {
77 SpiTimingConfigCoreClock::SpiTimingConfigCoreClock160m
78 } else if config.ram_frequency == SpiRamFreq::Freq120m {
79 SpiTimingConfigCoreClock::SpiTimingConfigCoreClock240m
80 } else {
81 SpiTimingConfigCoreClock::SpiTimingConfigCoreClock80m
82 });
83 } else {
84 config.core_clock = Some( if config.ram_frequency == SpiRamFreq::Freq120m {
85 SpiTimingConfigCoreClock::SpiTimingConfigCoreClock120m
86 } else {
87 SpiTimingConfigCoreClock::SpiTimingConfigCoreClock80m
88 });
89 }
90 }
91 }
92
93 utils::psram_init(&mut config);
94
95 const MMU_ACCESS_SPIRAM: u32 = 1 << 15;
96 const START_PAGE: u32 = 0;
97
98 unsafe extern "C" {
99 fn Cache_Suspend_DCache();
100
101 fn Cache_Resume_DCache(param: u32);
102
103 fn cache_dbus_mmu_set(
112 ext_ram: u32,
113 vaddr: u32,
114 paddr: u32,
115 psize: u32,
116 num: u32,
117 fixed: u32,
118 ) -> i32;
119 }
120
121 let start = unsafe {
122 const MMU_PAGE_SIZE: u32 = 0x10000;
123 const ICACHE_MMU_SIZE: usize = 0x800;
124 const FLASH_MMU_TABLE_SIZE: usize = ICACHE_MMU_SIZE / core::mem::size_of::<u32>();
125 const MMU_INVALID: u32 = 1 << 14;
126 const DR_REG_MMU_TABLE: u32 = 0x600C5000;
127
128 let mmu_table_ptr = DR_REG_MMU_TABLE as *const u32;
136 let mut mapped_pages = 0;
137
138 for i in (0..(FLASH_MMU_TABLE_SIZE - 1)).rev() {
141 if mmu_table_ptr.add(i).read_volatile() != MMU_INVALID {
142 mapped_pages = (i + 1) as u32;
143 break;
144 }
145 }
146 let start = EXTMEM_ORIGIN + (MMU_PAGE_SIZE * mapped_pages);
147 debug!("PSRAM start address = {:x}", start);
148
149 Cache_Suspend_DCache();
151
152 let cache_dbus_mmu_set_res = cache_dbus_mmu_set(
153 MMU_ACCESS_SPIRAM,
154 start,
155 START_PAGE << 16,
156 64,
157 config.size.get() as u32 / 1024 / 64, 0,
159 );
160
161 EXTMEM::regs().dcache_ctrl1().modify(|_, w| {
162 w.dcache_shut_core0_bus()
163 .clear_bit()
164 .dcache_shut_core1_bus()
165 .clear_bit()
166 });
167
168 Cache_Resume_DCache(0);
169
170 if cache_dbus_mmu_set_res != 0 {
172 panic!("cache_dbus_mmu_set failed");
173 }
174
175 start
176 };
177
178 unsafe {
179 super::MAPPED_PSRAM.memory_range = start as usize..start as usize + config.size.get();
180 }
181}
182
183#[cfg(psram_mode_quad)]
184pub(crate) mod utils {
185 use procmacros::ram;
186
187 use super::*;
188
189 const PSRAM_RESET_EN: u16 = 0x66;
190 const PSRAM_RESET: u16 = 0x99;
191 const PSRAM_DEVICE_ID: u16 = 0x9F;
192 const CS_PSRAM_SEL: u8 = 1 << 1;
193
194 #[ram]
195 pub(crate) fn psram_init(config: &mut super::PsramConfig) {
196 psram_gpio_config();
197 psram_set_cs_timing();
198
199 if config.size.is_auto() {
200 psram_disable_qio_mode_spi1();
201
202 let mut dev_id = 0u32;
204 psram_exec_cmd(
205 CommandMode::PsramCmdSpi,
206 PSRAM_DEVICE_ID,
207 8, 0,
209 24, 0, core::ptr::null(),
212 0, &mut dev_id as *mut _ as *mut u8,
214 24, CS_PSRAM_SEL, false,
217 );
218 info!("chip id = {:x}", dev_id);
219
220 let size = if dev_id != 0xffffff {
221 const PSRAM_ID_EID_S: u32 = 16;
222 const PSRAM_ID_EID_M: u32 = 0xff;
223 const PSRAM_EID_SIZE_M: u32 = 0x07;
224 const PSRAM_EID_SIZE_S: u32 = 5;
225
226 let size_id = ((((dev_id) >> PSRAM_ID_EID_S) & PSRAM_ID_EID_M) >> PSRAM_EID_SIZE_S)
227 & PSRAM_EID_SIZE_M;
228
229 const PSRAM_EID_SIZE_32MBITS: u32 = 1;
230 const PSRAM_EID_SIZE_64MBITS: u32 = 2;
231
232 match size_id {
233 PSRAM_EID_SIZE_64MBITS => 64 / 8 * 1024 * 1024,
234 PSRAM_EID_SIZE_32MBITS => 32 / 8 * 1024 * 1024,
235 _ => 16 / 8 * 1024 * 1024,
236 }
237 } else {
238 0
239 };
240
241 info!("size is {}", size);
242
243 config.size = PsramSize::Size(size);
244 }
245
246 psram_reset_mode_spi1();
248 psram_enable_qio_mode_spi1();
250
251 mspi_timing_psram_tuning();
254
255 config_psram_spi_phases();
257 mspi_timing_enter_high_speed_mode(true, config);
260 }
261
262 const PSRAM_CS_IO: u8 = 26;
263 const SPI_CS1_GPIO_NUM: u8 = 26;
264 const FUNC_SPICS1_SPICS1: u8 = 0;
265 const PIN_FUNC_GPIO: u8 = 2;
266 const PSRAM_SPIWP_SD3_IO: u8 = 10;
267 const ESP_ROM_EFUSE_FLASH_DEFAULT_SPI: u32 = 0;
268 const SPICS1_OUT_IDX: u8 = 6;
269
270 const PSRAM_QUAD_WRITE: u32 = 0x38;
271 const PSRAM_FAST_READ_QUAD: u32 = 0xEB;
272 const PSRAM_FAST_READ_QUAD_DUMMY: u32 = 6;
273 const SPI_MEM_CLKCNT_N_S: u32 = 16;
274 const SPI_MEM_SCLKCNT_N_S: u32 = 16;
275 const SPI_MEM_CLKCNT_H_S: u32 = 8;
276 const SPI_MEM_SCLKCNT_H_S: u32 = 8;
277 const SPI_MEM_CLKCNT_L_S: u32 = 0;
278 const SPI_MEM_SCLKCNT_L_S: u32 = 0;
279
280 unsafe extern "C" {
281 fn esp_rom_efuse_get_flash_gpio_info() -> u32;
282
283 fn esp_rom_efuse_get_flash_wp_gpio() -> u8;
284
285 fn esp_rom_gpio_connect_out_signal(
286 gpio_num: u8,
287 signal_idx: u8,
288 out_inv: bool,
289 oen_inv: bool,
290 );
291
292 fn esp_rom_spiflash_select_qio_pins(wp_gpio_num: u8, spiconfig: u32);
308 }
309
310 #[ram]
313 fn config_psram_spi_phases() {
314 unsafe {
315 let spi = SPI0::regs();
316 spi.cache_sctrl()
318 .modify(|_, w| w.usr_sram_dio().clear_bit()); spi.cache_sctrl().modify(|_, w| w.usr_sram_qio().set_bit()); spi.cache_sctrl()
323 .modify(|_, w| w.cache_sram_usr_rcmd().set_bit()); spi.cache_sctrl()
326 .modify(|_, w| w.cache_sram_usr_wcmd().set_bit()); spi.sram_dwr_cmd()
329 .modify(|_, w| w.cache_sram_usr_wr_cmd_bitlen().bits(7));
330
331 spi.sram_dwr_cmd().modify(|_, w| {
332 w.cache_sram_usr_wr_cmd_value()
333 .bits(PSRAM_QUAD_WRITE as u16)
334 });
335
336 spi.sram_drd_cmd()
337 .modify(|_, w| w.cache_sram_usr_rd_cmd_bitlen().bits(7));
338
339 spi.sram_drd_cmd().modify(|_, w| {
340 w.cache_sram_usr_rd_cmd_value()
341 .bits(PSRAM_FAST_READ_QUAD as u16)
342 });
343
344 spi.cache_sctrl()
346 .modify(|_, w| w.sram_addr_bitlen().bits(23));
347
348 spi.cache_sctrl()
353 .modify(|_, w| w.usr_rd_sram_dummy().set_bit()); spi.cache_sctrl().modify(|_, w| {
356 w.sram_rdummy_cyclelen()
357 .bits((PSRAM_FAST_READ_QUAD_DUMMY - 1) as u8)
358 });
359
360 spi.misc().modify(|_, w| w.cs1_dis().clear_bit());
362 }
363 }
364
365 #[ram]
366 fn mspi_timing_psram_tuning() {
367 }
370
371 #[ram]
380 fn mspi_timing_enter_high_speed_mode(control_spi1: bool, config: &PsramConfig) {
381 let core_clock: SpiTimingConfigCoreClock = mspi_core_clock(config);
382 let flash_div: u32 = flash_clock_divider(config);
383 let psram_div: u32 = psram_clock_divider(config);
384
385 info!(
386 "PSRAM core_clock {:?}, flash_div = {}, psram_div = {}",
387 core_clock, flash_div, psram_div
388 );
389
390 spi0_timing_config_set_core_clock(core_clock);
394
395 spi0_timing_config_set_flash_clock(flash_div);
396 if control_spi1 {
397 spi1_timing_config_set_flash_clock(flash_div);
398 }
399 spi0_timing_config_set_psram_clock(psram_div);
401
402 }
406
407 #[ram]
408 fn spi0_timing_config_set_core_clock(core_clock: SpiTimingConfigCoreClock) {
409 unsafe {
410 SPI0::regs().core_clk_sel().modify(|_, w| {
411 w.core_clk_sel().bits(match core_clock {
412 SpiTimingConfigCoreClock::SpiTimingConfigCoreClock80m => 0,
413 SpiTimingConfigCoreClock::SpiTimingConfigCoreClock120m => 1,
414 SpiTimingConfigCoreClock::SpiTimingConfigCoreClock160m => 2,
415 SpiTimingConfigCoreClock::SpiTimingConfigCoreClock240m => 3,
416 })
417 });
418 }
419 }
420
421 #[ram]
422 fn spi0_timing_config_set_flash_clock(freqdiv: u32) {
423 if freqdiv == 1 {
424 SPI0::regs()
425 .clock()
426 .modify(|_, w| w.clk_equ_sysclk().set_bit());
427 } else {
428 let freqbits: u32 = ((freqdiv - 1) << SPI_MEM_CLKCNT_N_S)
429 | ((freqdiv / 2 - 1) << SPI_MEM_CLKCNT_H_S)
430 | ((freqdiv - 1) << SPI_MEM_CLKCNT_L_S);
431 unsafe {
432 SPI0::regs().clock().modify(|_, w| w.bits(freqbits));
433 }
434 }
435 }
436
437 #[ram]
438 fn spi1_timing_config_set_flash_clock(freqdiv: u32) {
439 if freqdiv == 1 {
440 SPI1::regs()
441 .clock()
442 .modify(|_, w| w.clk_equ_sysclk().set_bit());
443 } else {
444 let freqbits: u32 = ((freqdiv - 1) << SPI_MEM_CLKCNT_N_S)
445 | ((freqdiv / 2 - 1) << SPI_MEM_CLKCNT_H_S)
446 | ((freqdiv - 1) << SPI_MEM_CLKCNT_L_S);
447 unsafe {
448 SPI1::regs().clock().modify(|_, w| w.bits(freqbits));
449 }
450 }
451 }
452
453 #[ram]
454 fn spi0_timing_config_set_psram_clock(freqdiv: u32) {
455 if freqdiv == 1 {
456 SPI0::regs()
457 .sram_clk()
458 .modify(|_, w| w.sclk_equ_sysclk().set_bit());
459 } else {
460 let freqbits: u32 = ((freqdiv - 1) << SPI_MEM_SCLKCNT_N_S)
461 | ((freqdiv / 2 - 1) << SPI_MEM_SCLKCNT_H_S)
462 | ((freqdiv - 1) << SPI_MEM_SCLKCNT_L_S);
463 unsafe {
464 SPI0::regs().sram_clk().modify(|_, w| w.bits(freqbits));
465 }
466 }
467 }
468
469 #[ram]
470 fn mspi_core_clock(config: &PsramConfig) -> SpiTimingConfigCoreClock {
471 config.core_clock.unwrap_or_default()
472 }
473
474 #[ram]
475 fn flash_clock_divider(config: &PsramConfig) -> u32 {
476 config.core_clock.unwrap_or_default() as u32 / config.flash_frequency as u32
477 }
478
479 #[ram]
480 fn psram_clock_divider(config: &PsramConfig) -> u32 {
481 config.core_clock.unwrap_or_default() as u32 / config.ram_frequency as u32
482 }
483
484 #[ram]
486 fn psram_reset_mode_spi1() {
487 psram_exec_cmd(
488 CommandMode::PsramCmdSpi,
489 PSRAM_RESET_EN,
490 8, 0,
492 0, 0, core::ptr::null(),
495 0, core::ptr::null_mut(),
497 0, CS_PSRAM_SEL, false,
500 ); psram_exec_cmd(
503 CommandMode::PsramCmdSpi,
504 PSRAM_RESET,
505 8, 0,
507 0, 0, core::ptr::null(),
510 0, core::ptr::null_mut(),
512 0, CS_PSRAM_SEL, false,
515 ); }
517
518 #[derive(PartialEq)]
519 #[allow(unused)]
520 enum CommandMode {
521 PsramCmdQpi = 0,
522 PsramCmdSpi = 1,
523 }
524
525 #[expect(clippy::too_many_arguments)]
526 #[ram]
527 fn psram_exec_cmd(
528 mode: CommandMode,
529 cmd: u16,
530 cmd_bit_len: u16,
531 addr: u32,
532 addr_bit_len: u32,
533 dummy_bits: u32,
534 mosi_data: *const u8,
535 mosi_bit_len: u32,
536 miso_data: *mut u8,
537 miso_bit_len: u32,
538 cs_mask: u8,
539 is_write_erase_operation: bool,
540 ) {
541 unsafe extern "C" {
542 fn esp_rom_spi_cmd_start(
550 spi_num: u32,
551 rx_buf: *const u8,
552 rx_len: u16,
553 cs_en_mask: u8,
554 is_write_erase: bool,
555 );
556 }
557
558 unsafe {
559 let spi1 = SPI1::regs();
560 let backup_usr = spi1.user().read().bits();
561 let backup_usr1 = spi1.user1().read().bits();
562 let backup_usr2 = spi1.user2().read().bits();
563 let backup_ctrl = spi1.ctrl().read().bits();
564 psram_set_op_mode(mode);
565 _psram_exec_cmd(
566 cmd,
567 cmd_bit_len,
568 addr,
569 addr_bit_len,
570 dummy_bits,
571 mosi_data,
572 mosi_bit_len,
573 miso_data,
574 miso_bit_len,
575 );
576 esp_rom_spi_cmd_start(
577 1,
578 miso_data,
579 (miso_bit_len / 8) as u16,
580 cs_mask,
581 is_write_erase_operation,
582 );
583
584 spi1.user().write(|w| w.bits(backup_usr));
585 spi1.user1().write(|w| w.bits(backup_usr1));
586 spi1.user2().write(|w| w.bits(backup_usr2));
587 spi1.ctrl().write(|w| w.bits(backup_ctrl));
588 }
589 }
590
591 #[expect(clippy::too_many_arguments)]
592 #[ram]
593 fn _psram_exec_cmd(
594 cmd: u16,
595 cmd_bit_len: u16,
596 addr: u32,
597 addr_bit_len: u32,
598 dummy_bits: u32,
599 mosi_data: *const u8,
600 mosi_bit_len: u32,
601 miso_data: *mut u8,
602 miso_bit_len: u32,
603 ) {
604 #[repr(C)]
605 struct esp_rom_spi_cmd_t {
606 cmd: u16, cmd_bit_len: u16, addr: *const u32, addr_bit_len: u32, tx_data: *const u32, tx_data_bit_len: u32, rx_data: *mut u32, rx_data_bit_len: u32, dummy_bit_len: u32,
615 }
616
617 unsafe extern "C" {
618 fn esp_rom_spi_cmd_config(spi_num: u32, pcmd: *const esp_rom_spi_cmd_t);
622 }
623
624 let conf = esp_rom_spi_cmd_t {
625 cmd,
626 cmd_bit_len,
627 addr: &addr,
628 addr_bit_len,
629 tx_data: mosi_data as *const u32,
630 tx_data_bit_len: mosi_bit_len,
631 rx_data: miso_data as *mut u32,
632 rx_data_bit_len: miso_bit_len,
633 dummy_bit_len: dummy_bits,
634 };
635
636 unsafe {
637 esp_rom_spi_cmd_config(1, &conf);
638 }
639 }
640
641 #[ram]
642 fn psram_set_op_mode(mode: CommandMode) {
643 unsafe extern "C" {
644 fn esp_rom_spi_set_op_mode(spi: u32, mode: u32);
645 }
646
647 const ESP_ROM_SPIFLASH_QIO_MODE: u32 = 0;
648 const ESP_ROM_SPIFLASH_SLOWRD_MODE: u32 = 5;
649
650 unsafe {
651 match mode {
652 CommandMode::PsramCmdQpi => {
653 esp_rom_spi_set_op_mode(1, ESP_ROM_SPIFLASH_QIO_MODE);
654 SPI1::regs().ctrl().modify(|_, w| w.fcmd_quad().set_bit());
655 }
656 CommandMode::PsramCmdSpi => {
657 esp_rom_spi_set_op_mode(1, ESP_ROM_SPIFLASH_SLOWRD_MODE);
658 }
659 }
660 }
661 }
662
663 #[ram]
665 fn psram_disable_qio_mode_spi1() {
666 const PSRAM_EXIT_QMODE: u16 = 0xF5;
667 const CS_PSRAM_SEL: u8 = 1 << 1;
668
669 psram_exec_cmd(
670 CommandMode::PsramCmdQpi,
671 PSRAM_EXIT_QMODE,
672 8, 0,
674 0, 0, core::ptr::null(),
677 0, core::ptr::null_mut(),
679 0, CS_PSRAM_SEL, false, );
683 }
684
685 #[ram]
687 fn psram_enable_qio_mode_spi1() {
688 const PSRAM_ENTER_QMODE: u16 = 0x35;
689 const CS_PSRAM_SEL: u8 = 1 << 1;
690
691 psram_exec_cmd(
692 CommandMode::PsramCmdSpi,
693 PSRAM_ENTER_QMODE,
694 8, 0,
696 0, 0, core::ptr::null(),
699 0, core::ptr::null_mut(),
701 0, CS_PSRAM_SEL, false, );
705 }
706
707 #[ram]
708 fn psram_set_cs_timing() {
709 unsafe {
710 SPI0::regs()
713 .spi_smem_ac()
714 .modify(|_, w| w.spi_smem_cs_hold_time().bits(0));
715 SPI0::regs()
716 .spi_smem_ac()
717 .modify(|_, w| w.spi_smem_cs_setup_time().bits(0));
718 SPI0::regs()
719 .spi_smem_ac()
720 .modify(|_, w| w.spi_smem_cs_hold().set_bit());
721 SPI0::regs()
722 .spi_smem_ac()
723 .modify(|_, w| w.spi_smem_cs_setup().set_bit());
724 }
725 }
726
727 #[ram]
728 fn psram_gpio_config() {
729 let cs1_io: u8 = PSRAM_CS_IO;
731 if cs1_io == SPI_CS1_GPIO_NUM {
732 unsafe {
733 IO_MUX::regs()
734 .gpio(cs1_io as usize)
735 .modify(|_, w| w.mcu_sel().bits(FUNC_SPICS1_SPICS1));
736 }
737 } else {
738 unsafe {
739 esp_rom_gpio_connect_out_signal(cs1_io, SPICS1_OUT_IDX, false, false);
740
741 IO_MUX::regs()
742 .gpio(cs1_io as usize)
743 .modify(|_, w| w.mcu_sel().bits(PIN_FUNC_GPIO));
744 }
745 }
746
747 let mut wp_io: u8 = PSRAM_SPIWP_SD3_IO;
749 let spiconfig = unsafe { esp_rom_efuse_get_flash_gpio_info() };
750 if spiconfig == ESP_ROM_EFUSE_FLASH_DEFAULT_SPI {
751 } else {
754 wp_io = unsafe { esp_rom_efuse_get_flash_wp_gpio() };
757 }
758 unsafe {
760 esp_rom_spiflash_select_qio_pins(wp_io, spiconfig);
761 }
762 }
763}
764
765#[cfg(psram_mode_octal)]
766pub(crate) mod utils {
767 use procmacros::ram;
768
769 use super::*;
770
771 const OPI_PSRAM_SYNC_READ: u16 = 0x0000;
772 const OPI_PSRAM_SYNC_WRITE: u16 = 0x8080;
773 const OPI_PSRAM_REG_READ: u16 = 0x4040;
774 const OPI_PSRAM_REG_WRITE: u16 = 0xC0C0;
775 const OCT_PSRAM_RD_CMD_BITLEN: u8 = 16;
776 const OCT_PSRAM_WR_CMD_BITLEN: u8 = 16;
777 const OCT_PSRAM_ADDR_BITLEN: u8 = 32;
778 const OCT_PSRAM_RD_DUMMY_BITLEN: u8 = 2 * (10 - 1);
779 const OCT_PSRAM_WR_DUMMY_BITLEN: u8 = 2 * (5 - 1);
780 const OCT_PSRAM_CS1_IO: u8 = SPI_CS1_GPIO_NUM;
781 const OCT_PSRAM_VENDOR_ID: u8 = 0xD;
782
783 const OCT_PSRAM_CS_SETUP_TIME: u8 = 3;
784 const OCT_PSRAM_CS_HOLD_TIME: u8 = 3;
785 const OCT_PSRAM_CS_HOLD_DELAY: u8 = 2;
786
787 const PSRAM_SIZE_2MB: usize = 2 * 1024 * 1024;
788 const PSRAM_SIZE_4MB: usize = 4 * 1024 * 1024;
789 const PSRAM_SIZE_8MB: usize = 8 * 1024 * 1024;
790 const PSRAM_SIZE_16MB: usize = 16 * 1024 * 1024;
791 const PSRAM_SIZE_32MB: usize = 32 * 1024 * 1024;
792
793 const SPI_CS1_GPIO_NUM: u8 = 26;
794 const FUNC_SPICS1_SPICS1: u8 = 0;
795
796 const SPI_MEM_CLKCNT_N_S: u32 = 16;
797 const SPI_MEM_SCLKCNT_N_S: u32 = 16;
798 const SPI_MEM_CLKCNT_H_S: u32 = 8;
799 const SPI_MEM_SCLKCNT_H_S: u32 = 8;
800 const SPI_MEM_CLKCNT_L_S: u32 = 0;
801 const SPI_MEM_SCLKCNT_L_S: u32 = 0;
802 const ESP_ROM_SPIFLASH_OPI_DTR_MODE: u8 = 7;
803
804 unsafe extern "C" {
805 fn esp_rom_opiflash_exec_cmd(
821 spi_num: u32,
822 mode: u8,
823 cmd: u32,
824 cmd_bit_len: u32,
825 addr: u32,
826 addr_bit_len: u32,
827 dummy_bits: u32,
828 mosi_data: *const u8,
829 mosi_bit_len: u32,
830 miso_data: *mut u8,
831 miso_bit_len: u32,
832 cs_mask: u32,
833 is_write_erase_operation: bool,
834 );
835
836 fn esp_rom_spi_set_dtr_swap_mode(spi: u32, wr_swap: bool, rd_swap: bool);
841
842 fn esp_rom_opiflash_pin_config();
843 }
844
845 #[derive(Default)]
847 #[repr(C)]
848 struct OpiPsramModeReg {
849 pub mr0: u8,
851 pub mr1: u8,
853 pub mr2: u8,
855 pub mr3: u8,
857 pub mr4: u8,
859 pub mr8: u8,
861 }
862
863 #[allow(unused)]
864 impl OpiPsramModeReg {
865 fn drive_str(&self) -> u8 {
866 self.mr0 & 0b11
867 }
868
869 fn set_drive_str(&mut self, value: u8) {
870 self.mr0 &= !0b11;
871 self.mr0 |= value & 0b11;
872 }
873
874 fn read_latency(&self) -> u8 {
875 (self.mr0 >> 2) & 0b111
876 }
877
878 fn set_read_latency(&mut self, value: u8) {
879 self.mr0 &= !(0b111 << 2);
880 self.mr0 |= (value & 0b111) << 2;
881 }
882
883 fn lt(&self) -> u8 {
884 (self.mr0 >> 5) & 0b1
885 }
886
887 fn set_lt(&mut self, value: u8) {
888 self.mr0 &= !(0b1 << 5);
889 self.mr0 |= (value & 0b1) << 5;
890 }
891
892 fn rsvd0_1(&self) -> u8 {
893 (self.mr0 >> 6) & 0b11
894 }
895
896 fn set_rsvd0_1(&mut self, value: u8) {
897 self.mr0 &= !(0b11 << 6);
898 self.mr0 |= (value & 0b11) << 6;
899 }
900
901 fn vendor_id(&self) -> u8 {
902 self.mr1 & 0b11111
903 }
904
905 fn set_vendor_id(&mut self, value: u8) {
906 self.mr1 &= !0b11111;
907 self.mr1 |= value & 0b11111;
908 }
909
910 fn rsvd0_2(&self) -> u8 {
911 (self.mr1 >> 5) & 0b111
912 }
913
914 fn set_rsvd0_2(&mut self, value: u8) {
915 self.mr1 &= !(0b111 << 5);
916 self.mr1 |= (value & 0b111) << 5;
917 }
918
919 fn density(&self) -> u8 {
920 self.mr2 & 0b111
921 }
922
923 fn set_density(&mut self, value: u8) {
924 self.mr2 &= !0b111;
925 self.mr2 |= value & 0b111;
926 }
927
928 fn dev_id(&self) -> u8 {
929 (self.mr2 >> 3) & 0b11
930 }
931
932 fn set_dev_id(&mut self, value: u8) {
933 self.mr2 &= !(0b11 << 3);
934 self.mr2 |= (value & 0b11) << 3;
935 }
936
937 fn rsvd1_2(&self) -> u8 {
938 (self.mr2 >> 5) & 0b11
939 }
940
941 fn set_rsvd1_2(&mut self, value: u8) {
942 self.mr2 &= !(0b11 << 5);
943 self.mr2 |= (value & 0b11) << 5;
944 }
945
946 fn gb(&self) -> u8 {
947 (self.mr2 >> 7) & 0b1
948 }
949
950 fn set_gb(&mut self, value: u8) {
951 self.mr2 &= !(0b1 << 7);
952 self.mr2 |= (value & 0b1) << 7;
953 }
954
955 fn rsvd3_7(&self) -> u8 {
956 self.mr3 & 0b11111
957 }
958
959 fn set_rsvd3_7(&mut self, value: u8) {
960 self.mr3 &= !0b11111;
961 self.mr3 |= value & 0b11111;
962 }
963
964 fn srf(&self) -> u8 {
965 (self.mr3 >> 5) & 0b1
966 }
967
968 fn set_srf(&mut self, value: u8) {
969 self.mr3 &= !(0b1 << 5);
970 self.mr3 |= (value & 0b1) << 5;
971 }
972
973 fn vcc(&self) -> u8 {
974 (self.mr3 >> 6) & 0b1
975 }
976
977 fn set_vcc(&mut self, value: u8) {
978 self.mr3 &= !(0b1 << 6);
979 self.mr3 |= (value & 0b1) << 6;
980 }
981
982 fn rsvd0(&self) -> u8 {
983 (self.mr3 >> 7) & 0b1
984 }
985
986 fn set_rsvd0(&mut self, value: u8) {
987 self.mr3 &= !(0b1 << 7);
988 self.mr3 |= (value & 0b1) << 7;
989 }
990
991 fn pasr(&self) -> u8 {
992 self.mr4 & 0b111
993 }
994
995 fn set_pasr(&mut self, value: u8) {
996 self.mr4 &= !0b111;
997 self.mr4 |= value & 0b111;
998 }
999
1000 fn rf(&self) -> u8 {
1001 (self.mr4 >> 3) & 0b1
1002 }
1003
1004 fn set_rf(&mut self, value: u8) {
1005 self.mr4 &= !(0b1 << 3);
1006 self.mr4 |= (value & 0b1) << 3;
1007 }
1008
1009 fn rsvd3(&self) -> u8 {
1010 (self.mr4 >> 4) & 0b1
1011 }
1012
1013 fn set_rsvd3(&mut self, value: u8) {
1014 self.mr4 &= !(0b1 << 4);
1015 self.mr4 |= (value & 0b1) << 4;
1016 }
1017
1018 fn wr_latency(&self) -> u8 {
1019 (self.mr4 >> 5) & 0b111
1020 }
1021
1022 fn set_wr_latency(&mut self, value: u8) {
1023 self.mr4 &= !(0b111 << 5);
1024 self.mr4 |= (value & 0b111) << 5;
1025 }
1026
1027 fn bl(&self) -> u8 {
1028 self.mr8 & 0b11
1029 }
1030
1031 fn set_bl(&mut self, value: u8) {
1032 self.mr8 &= !0b11;
1033 self.mr8 |= value & 0b11;
1034 }
1035
1036 fn bt(&self) -> u8 {
1037 (self.mr8 >> 2) & 0b1
1038 }
1039
1040 fn set_bt(&mut self, value: u8) {
1041 self.mr8 &= !(0b1 << 2);
1042 self.mr8 |= (value & 0b1) << 2;
1043 }
1044
1045 fn rsvd0_4(&self) -> u8 {
1046 (self.mr8 >> 3) & 0b11111
1047 }
1048
1049 fn set_rsvd0_4(&mut self, value: u8) {
1050 self.mr8 &= !(0b11111 << 3);
1051 self.mr8 |= (value & 0b11111) << 3;
1052 }
1053 }
1054
1055 #[ram]
1056 pub(crate) fn psram_init(config: &mut PsramConfig) {
1057 mspi_pin_init();
1058 init_psram_pins();
1059 set_psram_cs_timing();
1060
1061 spi_timing_enter_mspi_low_speed_mode(true);
1066
1067 unsafe {
1068 SPI1::regs()
1070 .ddr()
1071 .modify(|_, w| w.spi_fmem_var_dummy().set_bit());
1072 esp_rom_spi_set_dtr_swap_mode(1, false, false);
1073 }
1074
1075 let mut mode_reg = OpiPsramModeReg::default();
1077 mode_reg.set_lt(1);
1078 mode_reg.set_read_latency(2);
1079 mode_reg.set_drive_str(0);
1080 mode_reg.set_bl(3);
1081 mode_reg.set_bt(0);
1082
1083 init_psram_mode_reg(1, &mode_reg);
1084 psram_mode_reg(1, &mut mode_reg);
1086
1087 print_psram_info(&mode_reg);
1088
1089 if mode_reg.vendor_id() != OCT_PSRAM_VENDOR_ID {
1090 warn!(
1091 "PSRAM ID read error: {:x}, PSRAM chip not found or not supported, or wrong PSRAM line mode",
1092 mode_reg.vendor_id()
1093 );
1094 return;
1095 }
1096
1097 let psram_size = match mode_reg.density() {
1098 0x0 => PSRAM_SIZE_2MB,
1099 0x1 => PSRAM_SIZE_4MB,
1100 0x3 => PSRAM_SIZE_8MB,
1101 0x5 => PSRAM_SIZE_16MB,
1102 0x7 => PSRAM_SIZE_32MB,
1103 _ => 0,
1104 };
1105 info!("{} bytes of PSRAM", psram_size);
1106
1107 if config.size.is_auto() {
1108 config.size = PsramSize::Size(psram_size);
1109 }
1110
1111 spi_timing_enter_mspi_high_speed_mode(true, config);
1119
1120 spi_flash_set_rom_required_regs();
1123
1124 config_psram_spi_phases();
1129 }
1130
1131 fn config_psram_spi_phases() {
1134 unsafe {
1135 let spi = SPI0::regs();
1136 spi.cache_sctrl()
1138 .modify(|_, w| w.cache_sram_usr_wcmd().set_bit());
1139
1140 spi.sram_dwr_cmd().modify(|_, w| {
1141 w.cache_sram_usr_wr_cmd_bitlen()
1142 .bits(OCT_PSRAM_WR_CMD_BITLEN - 1)
1143 });
1144 spi.sram_dwr_cmd()
1145 .modify(|_, w| w.cache_sram_usr_wr_cmd_value().bits(OPI_PSRAM_SYNC_WRITE));
1146
1147 spi.cache_sctrl()
1149 .modify(|_, w| w.cache_sram_usr_rcmd().set_bit());
1150
1151 spi.sram_drd_cmd().modify(|_, w| {
1152 w.cache_sram_usr_rd_cmd_bitlen()
1153 .bits(OCT_PSRAM_RD_CMD_BITLEN - 1)
1154 });
1155 spi.sram_drd_cmd()
1156 .modify(|_, w| w.cache_sram_usr_rd_cmd_value().bits(OPI_PSRAM_SYNC_READ));
1157
1158 spi.cache_sctrl()
1160 .modify(|_, w| w.sram_addr_bitlen().bits(OCT_PSRAM_ADDR_BITLEN - 1));
1161 spi.cache_sctrl()
1162 .modify(|_, w| w.cache_usr_scmd_4byte().set_bit());
1163
1164 spi.cache_sctrl()
1166 .modify(|_, w| w.usr_rd_sram_dummy().set_bit());
1167 spi.cache_sctrl()
1168 .modify(|_, w| w.usr_wr_sram_dummy().set_bit());
1169 spi.cache_sctrl()
1170 .modify(|_, w| w.sram_rdummy_cyclelen().bits(OCT_PSRAM_RD_DUMMY_BITLEN - 1));
1171 spi.spi_smem_ddr()
1172 .modify(|_, w| w.spi_smem_var_dummy().set_bit());
1173 spi.cache_sctrl()
1174 .modify(|_, w| w.sram_wdummy_cyclelen().bits(OCT_PSRAM_WR_DUMMY_BITLEN - 1));
1175
1176 spi.spi_smem_ddr().modify(|_, w| w.wdat_swp().clear_bit());
1177 spi.spi_smem_ddr().modify(|_, w| w.rdat_swp().clear_bit());
1178 spi.spi_smem_ddr().modify(|_, w| w.en().set_bit());
1179
1180 spi.sram_cmd().modify(|_, w| w.sdummy_out().set_bit());
1181 spi.sram_cmd().modify(|_, w| w.scmd_oct().set_bit());
1182 spi.sram_cmd().modify(|_, w| w.saddr_oct().set_bit());
1183 spi.sram_cmd().modify(|_, w| w.sdout_oct().set_bit());
1184 spi.sram_cmd().modify(|_, w| w.sdin_oct().set_bit());
1185
1186 spi.cache_sctrl().modify(|_, w| w.sram_oct().set_bit());
1187 }
1188 }
1189
1190 #[ram]
1191 fn spi_flash_set_rom_required_regs() {
1192 SPI1::regs()
1194 .ddr()
1195 .modify(|_, w| w.spi_fmem_var_dummy().clear_bit());
1196 }
1202
1203 #[ram]
1204 fn mspi_pin_init() {
1205 unsafe { esp_rom_opiflash_pin_config() };
1206 spi_timing_set_pin_drive_strength();
1207 }
1209
1210 #[ram]
1211 fn spi_timing_set_pin_drive_strength() {
1212 unsafe {
1215 SPI0::regs()
1216 .date()
1217 .modify(|_, w| w.spi_spiclk_pad_drv_ctl_en().set_bit());
1218 SPI0::regs()
1219 .date()
1220 .modify(|_, w| w.spi_smem_spiclk_fun_drv().bits(3));
1221 SPI0::regs()
1222 .date()
1223 .modify(|_, w| w.spi_fmem_spiclk_fun_drv().bits(3));
1224
1225 let pins = [27usize, 28, 31, 32, 33, 34, 35, 36, 37];
1227 for pin in pins {
1228 IO_MUX::regs().gpio(pin).modify(|_, w| w.fun_drv().bits(3));
1229 }
1230 }
1231 }
1232
1233 fn spi_timing_enter_mspi_low_speed_mode(control_spi1: bool) {
1234 spi0_timing_config_set_core_clock(SpiTimingConfigCoreClock::SpiTimingConfigCoreClock80m); spi0_timing_config_set_flash_clock(4);
1247 if control_spi1 {
1248 spi1_timing_config_set_flash_clock(4);
1250 }
1251
1252 spi0_timing_config_set_psram_clock(4);
1254
1255 }
1258
1259 fn spi_timing_enter_mspi_high_speed_mode(control_spi1: bool, config: &PsramConfig) {
1267 let flash_div: u32 = flash_clock_divider(config);
1268 let psram_div: u32 = psram_clock_divider(config);
1269
1270 spi0_timing_config_set_core_clock(config.core_clock.unwrap_or_default()); spi0_timing_config_set_flash_clock(flash_div);
1274 if control_spi1 {
1275 spi1_timing_config_set_flash_clock(flash_div);
1276 }
1277 spi0_timing_config_set_psram_clock(psram_div);
1279
1280 }
1283
1284 fn set_psram_cs_timing() {
1285 unsafe {
1286 let spi = SPI0::regs();
1287 spi.spi_smem_ac()
1291 .modify(|_, w| w.spi_smem_cs_hold().set_bit());
1292 spi.spi_smem_ac()
1293 .modify(|_, w| w.spi_smem_cs_setup().set_bit());
1294
1295 spi.spi_smem_ac()
1296 .modify(|_, w| w.spi_smem_cs_hold_time().bits(OCT_PSRAM_CS_HOLD_TIME));
1297 spi.spi_smem_ac()
1298 .modify(|_, w| w.spi_smem_cs_setup_time().bits(OCT_PSRAM_CS_SETUP_TIME));
1299
1300 spi.spi_smem_ac()
1303 .modify(|_, w| w.spi_smem_cs_hold_delay().bits(OCT_PSRAM_CS_HOLD_DELAY));
1304 }
1305 }
1306
1307 fn init_psram_pins() {
1308 unsafe {
1310 IO_MUX::regs()
1311 .gpio(OCT_PSRAM_CS1_IO as usize)
1312 .modify(|_, w| w.mcu_sel().bits(FUNC_SPICS1_SPICS1));
1313 }
1314
1315 unsafe {
1317 IO_MUX::regs()
1318 .gpio(OCT_PSRAM_CS1_IO as usize)
1319 .modify(|_, w| w.fun_drv().bits(3));
1320 }
1321
1322 unsafe {
1324 SPI0::regs()
1325 .date()
1326 .modify(|_, w| w.spi_smem_spiclk_fun_drv().bits(3));
1327 }
1328 }
1329
1330 fn psram_mode_reg(spi_num: u32, out_reg: &mut OpiPsramModeReg) {
1331 let mode = ESP_ROM_SPIFLASH_OPI_DTR_MODE;
1332 let cmd_len: u32 = 16;
1333 let addr_bit_len: u32 = 32;
1334 let dummy: u32 = OCT_PSRAM_RD_DUMMY_BITLEN as u32;
1335 let mut data_bit_len: u32 = 16;
1336
1337 unsafe {
1338 esp_rom_opiflash_exec_cmd(
1340 spi_num,
1341 mode,
1342 OPI_PSRAM_REG_READ as u32,
1343 cmd_len,
1344 0x0,
1345 addr_bit_len,
1346 dummy,
1347 core::ptr::null(),
1348 0,
1349 &mut out_reg.mr0,
1350 data_bit_len,
1351 1 << 1,
1352 false,
1353 );
1354 esp_rom_opiflash_exec_cmd(
1356 spi_num,
1357 mode,
1358 OPI_PSRAM_REG_READ as u32,
1359 cmd_len,
1360 0x2,
1361 addr_bit_len,
1362 dummy,
1363 core::ptr::null(),
1364 0,
1365 &mut out_reg.mr2,
1366 data_bit_len,
1367 1 << 1,
1368 false,
1369 );
1370 data_bit_len = 8;
1371 esp_rom_opiflash_exec_cmd(
1373 spi_num,
1374 mode,
1375 OPI_PSRAM_REG_READ as u32,
1376 cmd_len,
1377 0x4,
1378 addr_bit_len,
1379 dummy,
1380 core::ptr::null(),
1381 0,
1382 &mut out_reg.mr4,
1383 data_bit_len,
1384 1 << 1,
1385 false,
1386 );
1387 esp_rom_opiflash_exec_cmd(
1389 spi_num,
1390 mode,
1391 OPI_PSRAM_REG_READ as u32,
1392 cmd_len,
1393 0x8,
1394 addr_bit_len,
1395 dummy,
1396 core::ptr::null(),
1397 0,
1398 &mut out_reg.mr8,
1399 data_bit_len,
1400 1 << 1,
1401 false,
1402 );
1403 }
1404 }
1405
1406 fn init_psram_mode_reg(spi_num: u32, mode_reg_config: &OpiPsramModeReg) {
1408 let mode = ESP_ROM_SPIFLASH_OPI_DTR_MODE;
1409 let cmd_len: u32 = 16;
1410 let addr: u32 = 0x0; let addr_bit_len: u32 = 32;
1412 let dummy = OCT_PSRAM_RD_DUMMY_BITLEN as u32;
1413 let mut mode_reg = OpiPsramModeReg::default();
1414 let data_bit_len: u32 = 16;
1415
1416 unsafe {
1418 esp_rom_opiflash_exec_cmd(
1419 spi_num,
1420 mode,
1421 OPI_PSRAM_REG_READ as u32,
1422 cmd_len,
1423 addr,
1424 addr_bit_len,
1425 dummy,
1426 core::ptr::null(),
1427 0,
1428 &mut mode_reg.mr0,
1429 data_bit_len,
1430 1 << 1,
1431 false,
1432 );
1433 }
1434
1435 mode_reg.set_lt(mode_reg_config.lt());
1437 mode_reg.set_read_latency(mode_reg_config.read_latency());
1438 mode_reg.set_drive_str(mode_reg_config.drive_str());
1439
1440 unsafe {
1442 esp_rom_opiflash_exec_cmd(
1443 spi_num,
1444 mode,
1445 OPI_PSRAM_REG_WRITE as u32,
1446 cmd_len,
1447 addr,
1448 addr_bit_len,
1449 0,
1450 &mode_reg.mr0,
1451 16,
1452 core::ptr::null_mut(),
1453 0,
1454 1 << 1,
1455 false,
1456 );
1457 }
1458
1459 }
1461
1462 fn print_psram_info(reg_val: &OpiPsramModeReg) {
1463 info!(
1464 "vendor id : {:02x} ({})",
1465 reg_val.vendor_id(),
1466 if reg_val.vendor_id() == 0x0d {
1467 "AP"
1468 } else {
1469 "UNKNOWN"
1470 }
1471 );
1472 info!(
1473 "dev id : {:02x} (generation {})",
1474 reg_val.dev_id(),
1475 reg_val.dev_id() + 1
1476 );
1477 info!(
1478 "density : {:02x} ({} Mbit)",
1479 reg_val.density(),
1480 if reg_val.density() == 0x1 {
1481 32
1482 } else if reg_val.density() == 0x3 {
1483 64
1484 } else if reg_val.density() == 0x5 {
1485 128
1486 } else if reg_val.density() == 0x7 {
1487 256
1488 } else {
1489 0
1490 }
1491 );
1492 info!(
1493 "good-die : {:02x} ({})",
1494 reg_val.gb(),
1495 if reg_val.gb() == 1 { "Pass" } else { "Fail" }
1496 );
1497 info!(
1498 "Latency : {:02x} ({})",
1499 reg_val.lt(),
1500 if reg_val.lt() == 1 {
1501 "Fixed"
1502 } else {
1503 "Variable"
1504 }
1505 );
1506 info!(
1507 "VCC : {:02x} ({})",
1508 reg_val.vcc(),
1509 if reg_val.vcc() == 1 { "3V" } else { "1.8V" }
1510 );
1511 info!(
1512 "SRF : {:02x} ({} Refresh)",
1513 reg_val.srf(),
1514 if reg_val.srf() == 0x1 { "Fast" } else { "Slow" }
1515 );
1516 info!(
1517 "BurstType : {:02x} ({} Wrap)",
1518 reg_val.bt(),
1519 if reg_val.bt() == 1 && reg_val.bl() != 3 {
1520 "Hybrid"
1521 } else {
1522 ""
1523 }
1524 );
1525 info!(
1526 "BurstLen : {:02x} ({} Byte)",
1527 reg_val.bl(),
1528 if reg_val.bl() == 0x00 {
1529 16
1530 } else if reg_val.bl() == 0x01 {
1531 32
1532 } else if reg_val.bl() == 0x10 {
1533 64
1534 } else {
1535 1024
1536 }
1537 );
1538 info!(
1539 "Readlatency : {:02x} ({} cycles@{})",
1540 reg_val.read_latency(),
1541 reg_val.read_latency() * 2 + 6,
1542 if reg_val.lt() == 1 {
1543 "Fixed"
1544 } else {
1545 "Variable"
1546 }
1547 );
1548 info!(
1549 "DriveStrength: {:02x} (1/{})",
1550 reg_val.drive_str(),
1551 if reg_val.drive_str() == 0x00 {
1552 1
1553 } else if reg_val.drive_str() == 0x01 {
1554 2
1555 } else if reg_val.drive_str() == 0x02 {
1556 4
1557 } else {
1558 8
1559 }
1560 );
1561 }
1562
1563 #[ram]
1564 fn spi0_timing_config_set_core_clock(core_clock: SpiTimingConfigCoreClock) {
1565 unsafe {
1566 SPI0::regs().core_clk_sel().modify(|_, w| {
1567 w.core_clk_sel().bits(match core_clock {
1568 SpiTimingConfigCoreClock::SpiTimingConfigCoreClock80m => 0,
1569 SpiTimingConfigCoreClock::SpiTimingConfigCoreClock120m => 1,
1570 SpiTimingConfigCoreClock::SpiTimingConfigCoreClock160m => 2,
1571 SpiTimingConfigCoreClock::SpiTimingConfigCoreClock240m => 3,
1572 })
1573 });
1574 }
1575 }
1576
1577 #[ram]
1578 fn spi0_timing_config_set_flash_clock(freqdiv: u32) {
1579 if freqdiv == 1 {
1580 SPI0::regs()
1581 .clock()
1582 .modify(|_, w| w.clk_equ_sysclk().set_bit());
1583 } else {
1584 let freqbits: u32 = ((freqdiv - 1) << SPI_MEM_CLKCNT_N_S)
1585 | ((freqdiv / 2 - 1) << SPI_MEM_CLKCNT_H_S)
1586 | ((freqdiv - 1) << SPI_MEM_CLKCNT_L_S);
1587 unsafe {
1588 SPI0::regs().clock().modify(|_, w| w.bits(freqbits));
1589 }
1590 }
1591 }
1592
1593 #[ram]
1594 fn spi1_timing_config_set_flash_clock(freqdiv: u32) {
1595 if freqdiv == 1 {
1596 SPI1::regs()
1597 .clock()
1598 .modify(|_, w| w.clk_equ_sysclk().set_bit());
1599 } else {
1600 let freqbits: u32 = ((freqdiv - 1) << SPI_MEM_CLKCNT_N_S)
1601 | ((freqdiv / 2 - 1) << SPI_MEM_CLKCNT_H_S)
1602 | ((freqdiv - 1) << SPI_MEM_CLKCNT_L_S);
1603 unsafe {
1604 SPI1::regs().clock().modify(|_, w| w.bits(freqbits));
1605 }
1606 }
1607 }
1608
1609 #[ram]
1610 fn spi0_timing_config_set_psram_clock(freqdiv: u32) {
1611 if freqdiv == 1 {
1612 SPI0::regs()
1613 .sram_clk()
1614 .modify(|_, w| w.sclk_equ_sysclk().set_bit());
1615 } else {
1616 let freqbits: u32 = ((freqdiv - 1) << SPI_MEM_SCLKCNT_N_S)
1617 | ((freqdiv / 2 - 1) << SPI_MEM_SCLKCNT_H_S)
1618 | ((freqdiv - 1) << SPI_MEM_SCLKCNT_L_S);
1619 unsafe {
1620 SPI0::regs().sram_clk().modify(|_, w| w.bits(freqbits));
1621 }
1622 }
1623 }
1624
1625 #[ram]
1626 fn flash_clock_divider(config: &PsramConfig) -> u32 {
1627 config.core_clock.unwrap_or_default() as u32 / config.flash_frequency as u32
1628 }
1629
1630 #[ram]
1631 fn psram_clock_divider(config: &PsramConfig) -> u32 {
1632 config.core_clock.unwrap_or_default() as u32 / config.ram_frequency as u32
1633 }
1634}