Skip to main content

esp_hal/psram/
esp32.rs

1use core::ops::Range;
2
3use super::{EXTMEM_ORIGIN, PsramSize};
4
5/// Cache Speed
6#[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/// PSRAM virtual address mode.
17///
18/// Specifies how PSRAM is mapped for the CPU cores.
19#[derive(PartialEq, Eq, Clone, Copy, Debug, Default)]
20#[cfg_attr(feature = "defmt", derive(defmt::Format))]
21pub enum PsramVaddrMode {
22    /// App and pro CPU use their own flash cache for external RAM access.
23    ///
24    /// In this mode both cores access the same physical PSRAM.
25    #[default]
26    Normal = 0,
27    /// App and pro CPU share external RAM caches: pro CPU has low * 2M, app
28    /// CPU has high 2M.
29    ///
30    /// In this mode the two cores will access different parts of PSRAM.
31    LowHigh,
32    /// App and pro CPU share external RAM caches: pro CPU does even 32 byte
33    /// ranges, app does odd ones.
34    ///
35    /// In this mode the two cores will access different parts of PSRAM.
36    Evenodd,
37}
38
39/// PSRAM configuration
40#[derive(Copy, Clone, Debug, Default)]
41#[cfg_attr(feature = "defmt", derive(defmt::Format))]
42pub struct PsramConfig {
43    /// PSRAM size
44    pub size: PsramSize,
45    /// Cache speed
46    pub cache_speed: PsramCacheSpeed,
47    /// PSRAM virtual address mode
48    pub psram_vaddr_mode: PsramVaddrMode,
49}
50
51/// Initialize PSRAM to be used for data.
52#[procmacros::ram]
53pub(crate) fn init_psram(config: &mut PsramConfig) -> bool {
54    utils::psram_init(config);
55    true
56}
57
58#[procmacros::ram]
59pub(crate) fn map_psram(mut config: PsramConfig) -> Range<usize> {
60    if config.size.is_auto() {
61        const MAX_MEM_SIZE: usize = 4 * 1024 * 1024;
62
63        // Reading the device-id turned out to not work as expected (some bits flipped
64        // for unknown reason)
65        //
66        // As a workaround we just map 4m (maximum we can do) and
67        // probe how much memory we can write/read
68        utils::s_mapping(EXTMEM_ORIGIN as u32, MAX_MEM_SIZE as u32);
69
70        let guessed_size = unsafe {
71            let ptr = EXTMEM_ORIGIN as *mut u8;
72            for i in (1023..MAX_MEM_SIZE).step_by(1024) {
73                ptr.add(i).write_volatile(0x7f);
74            }
75
76            let mut last_correctly_read = 0;
77            for i in (1023..MAX_MEM_SIZE).step_by(1024) {
78                if ptr.add(i).read_volatile() == 0x7f {
79                    last_correctly_read = i;
80                } else {
81                    break;
82                }
83            }
84
85            last_correctly_read + 1
86        };
87
88        info!("Assuming {} bytes of PSRAM", guessed_size);
89        config.size = PsramSize::Size(guessed_size);
90    }
91
92    utils::s_mapping(EXTMEM_ORIGIN as u32, config.size.get() as u32);
93
94    EXTMEM_ORIGIN..EXTMEM_ORIGIN + config.size.get()
95}
96
97pub(crate) mod utils {
98    use core::ptr::addr_of_mut;
99
100    use procmacros::ram;
101
102    use super::*;
103    use crate::peripherals::{DPORT, SPI0, SPI1};
104
105    #[ram]
106    pub(crate) fn s_mapping(v_start: u32, size: u32) {
107        // Enable external RAM in MMU
108        cache_sram_mmu_set(0, 0, v_start, 0, 32, size / 1024 / 32);
109        // Flush and enable icache for APP CPU
110        DPORT::regs()
111            .app_cache_ctrl1()
112            .modify(|_, w| w.app_cache_mask_dram1().clear_bit());
113
114        cache_sram_mmu_set(1, 0, v_start, 0, 32, size / 1024 / 32);
115    }
116
117    // we can use the ROM version of this: it works well enough and keeps the size
118    // of the binary down.
119    #[ram]
120    fn cache_sram_mmu_set(
121        cpu_no: u32,
122        pid: u32,
123        vaddr: u32,
124        paddr: u32,
125        psize: u32,
126        num: u32,
127    ) -> i32 {
128        unsafe { cache_sram_mmu_set_rom(cpu_no, pid, vaddr, paddr, psize, num) }
129    }
130
131    // PSRAM clock and cs IO should be configured based on hardware design.
132    // For ESP32-WROVER or ESP32-WROVER-B module, the clock IO is IO17, the cs IO is
133    // IO16, they are the default value for these two configs.
134    const D0WD_PSRAM_CLK_IO: u8 = 17;
135    const D0WD_PSRAM_CS_IO: u8 = 16;
136
137    const D2WD_PSRAM_CLK_IO: u8 = 9; // Default value is 9
138    const D2WD_PSRAM_CS_IO: u8 = 10; // Default value is 10
139
140    // For ESP32-PICO chip, the psram share clock with flash. The flash clock pin is
141    // fixed, which is IO6.
142    const PICO_PSRAM_CLK_IO: u8 = 6;
143    const PICO_PSRAM_CS_IO: u8 = 10; // Default value is 10
144
145    const PICO_V3_02_PSRAM_CLK_IO: u8 = 10;
146    const PICO_V3_02_PSRAM_CS_IO: u8 = 9;
147    const PICO_V3_02_PSRAM_SPIWP_SD3_IO: u8 = 18;
148
149    const ESP_ROM_EFUSE_FLASH_DEFAULT_SPI: u32 = 0;
150    const ESP_ROM_EFUSE_FLASH_DEFAULT_HSPI: u32 = 1;
151
152    const SPI_IOMUX_PIN_NUM_CLK: u8 = 6;
153    const SPI_IOMUX_PIN_NUM_CS: u8 = 11;
154
155    // IO-pins for PSRAM.
156    // WARNING: PSRAM shares all but the CS and CLK pins with the flash, so these
157    // defines hardcode the flash pins as well, making this code incompatible
158    // with either a setup that has the flash on non-standard pins or ESP32s
159    // with built-in flash.
160    const PSRAM_SPIQ_SD0_IO: u8 = 7;
161    const PSRAM_SPID_SD1_IO: u8 = 8;
162    const PSRAM_SPIWP_SD3_IO: u8 = 10;
163    const PSRAM_SPIHD_SD2_IO: u8 = 9;
164
165    const FLASH_HSPI_CLK_IO: u8 = 14;
166    const FLASH_HSPI_CS_IO: u8 = 15;
167
168    const PSRAM_HSPI_SPIQ_SD0_IO: u8 = 12;
169    const PSRAM_HSPI_SPID_SD1_IO: u8 = 13;
170    const PSRAM_HSPI_SPIWP_SD3_IO: u8 = 2;
171    const PSRAM_HSPI_SPIHD_SD2_IO: u8 = 4;
172
173    const DR_REG_SPI1_BASE: u32 = 0x3ff42000;
174    const SPI1_USER_REG: u32 = DR_REG_SPI1_BASE + 0x1C;
175    const SPI1_W0_REG: u32 = DR_REG_SPI1_BASE + 0x80;
176
177    const fn psram_cs_hold_time_from_psram_speed(speed: PsramCacheSpeed) -> u32 {
178        match speed {
179            PsramCacheSpeed::PsramCacheF80mS40m => 0,
180            PsramCacheSpeed::PsramCacheF40mS40m => 0,
181            PsramCacheSpeed::PsramCacheF80mS80m => 1,
182        }
183    }
184
185    const PSRAM_INTERNAL_IO_28: u32 = 28;
186    const PSRAM_INTERNAL_IO_29: u32 = 29;
187    const SIG_GPIO_OUT_IDX: u32 = 256;
188    const SPICLK_OUT_IDX: u32 = 0;
189    const SIG_IN_FUNC224_IDX: u32 = 224;
190    const SIG_IN_FUNC225_IDX: u32 = 225;
191    const SPICS0_OUT_IDX: u32 = 5;
192    const SPICS1_OUT_IDX: u32 = 6;
193    const SPIQ_OUT_IDX: u32 = 1;
194    const SPIQ_IN_IDX: u32 = 1;
195    const SPID_OUT_IDX: u32 = 2;
196    const SPID_IN_IDX: u32 = 2;
197    const SPIWP_OUT_IDX: u32 = 4;
198    const SPIWP_IN_IDX: u32 = 4;
199    const SPIHD_OUT_IDX: u32 = 3;
200    const SPIHD_IN_IDX: u32 = 3;
201    const FUNC_SD_CLK_SPICLK: u32 = 1;
202    const PIN_FUNC_GPIO: u32 = 2;
203
204    const PSRAM_QUAD_WRITE: u32 = 0x38;
205    const PSRAM_FAST_READ_QUAD_DUMMY: u32 = 0x5;
206    const PSRAM_FAST_READ_QUAD: u32 = 0xEB;
207
208    const SPI_FWRITE_DUAL_S: u32 = 12;
209    const SPI_FWRITE_DUAL_M: u32 = 1 << 12;
210
211    const SPI_FREAD_QIO_M: u32 = 1 << 24;
212    const SPI0_R_QIO_DUMMY_CYCLELEN: u32 = 3;
213    const SPI_FREAD_DIO_M: u32 = 1 << 23;
214    const SPI0_R_DIO_DUMMY_CYCLELEN: u32 = 1;
215    const SPI0_R_DIO_ADDR_BITSLEN: u32 = 27;
216    const SPI_FREAD_QUAD_M: u32 = 1 << 20;
217    const SPI_FREAD_DUAL_M: u32 = 1 << 14;
218    const SPI0_R_FAST_DUMMY_CYCLELEN: u32 = 7;
219    const PSRAM_IO_MATRIX_DUMMY_40M: u8 = 1;
220    const PSRAM_IO_MATRIX_DUMMY_80M: u8 = 2;
221
222    const _SPI_CACHE_PORT: u8 = 0;
223    const _SPI_FLASH_PORT: u8 = 1;
224    const _SPI_80M_CLK_DIV: u8 = 1;
225    const _SPI_40M_CLK_DIV: u8 = 2;
226
227    const FLASH_ID_GD25LQ32C: u32 = 0xC86016;
228
229    const EFUSE_SPICONFIG_RET_SPICLK_MASK: u32 = 0x3f;
230    const EFUSE_SPICONFIG_RET_SPICLK_SHIFT: u8 = 0;
231    const EFUSE_SPICONFIG_RET_SPIQ_MASK: u32 = 0x3f;
232    const EFUSE_SPICONFIG_RET_SPIQ_SHIFT: u8 = 6;
233    const EFUSE_SPICONFIG_RET_SPID_MASK: u32 = 0x3f;
234    const EFUSE_SPICONFIG_RET_SPID_SHIFT: u8 = 12;
235    const EFUSE_SPICONFIG_RET_SPICS0_MASK: u32 = 0x3f;
236    const EFUSE_SPICONFIG_RET_SPICS0_SHIFT: u8 = 18;
237    const EFUSE_SPICONFIG_RET_SPIHD_MASK: u32 = 0x3f;
238    const EFUSE_SPICONFIG_RET_SPIHD_SHIFT: u8 = 24;
239
240    fn efuse_spiconfig_ret(spi_config: u32, mask: u32, shift: u8) -> u8 {
241        (((spi_config) >> shift) & mask) as u8
242    }
243
244    #[derive(PartialEq, Eq, Debug, Default)]
245    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
246    struct PsramIo {
247        flash_clk_io: u8,
248        flash_cs_io: u8,
249        psram_clk_io: u8,
250        psram_cs_io: u8,
251        psram_spiq_sd0_io: u8,
252        psram_spid_sd1_io: u8,
253        psram_spiwp_sd3_io: u8,
254        psram_spihd_sd2_io: u8,
255    }
256
257    #[derive(PartialEq, Eq, Copy, Clone, Debug)]
258    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
259    enum PsramClkMode {
260        PsramClkModeNorm = 0, // Normal SPI mode
261        PsramClkModeDclk = 1, // Two extra clock cycles after CS is set high level
262    }
263
264    #[repr(C)]
265    pub(super) struct EspRomSpiflashChip {
266        pub device_id: u32,
267        pub chip_size: u32, // chip size in bytes
268        pub block_size: u32,
269        pub sector_size: u32,
270        pub page_size: u32,
271        pub status_mask: u32,
272    }
273
274    unsafe extern "C" {
275        fn esp_rom_efuse_get_flash_gpio_info() -> u32;
276
277        fn esp_rom_gpio_connect_out_signal(
278            gpio_num: u32,
279            signal_idx: u32,
280            out_inv: bool,
281            oen_inv: bool,
282        );
283
284        fn esp_rom_gpio_connect_in_signal(gpio_num: u32, signal_idx: u32, inv: bool);
285
286        fn esp_rom_spiflash_config_clk(freqdiv: u8, spi: u8) -> i32;
287
288        static mut g_rom_spiflash_dummy_len_plus: u8;
289
290        pub(super) static g_rom_flashchip: EspRomSpiflashChip;
291
292        fn cache_sram_mmu_set_rom(
293            cpu_no: u32,
294            pid: u32,
295            vaddr: u32,
296            paddr: u32,
297            psize: u32,
298            num: u32,
299        ) -> i32;
300    }
301
302    #[ram]
303    pub(crate) fn psram_init(config: &PsramConfig) {
304        let chip = crate::efuse::chip_type();
305
306        let mode = config.cache_speed;
307        let mut psram_io = PsramIo::default();
308        let clk_mode;
309
310        match chip {
311            crate::efuse::ChipType::Esp32D0wdq6 | crate::efuse::ChipType::Esp32D0wdq5 => {
312                clk_mode = PsramClkMode::PsramClkModeNorm;
313                psram_io.psram_clk_io = D0WD_PSRAM_CLK_IO;
314                psram_io.psram_cs_io = D0WD_PSRAM_CS_IO;
315            }
316            crate::efuse::ChipType::Esp32D2wdq5 => {
317                clk_mode = PsramClkMode::PsramClkModeDclk;
318                psram_io.psram_clk_io = D2WD_PSRAM_CLK_IO;
319                psram_io.psram_cs_io = D2WD_PSRAM_CS_IO;
320            }
321            crate::efuse::ChipType::Esp32Picod2 => {
322                clk_mode = PsramClkMode::PsramClkModeNorm;
323                psram_io.psram_clk_io = PICO_PSRAM_CLK_IO;
324                psram_io.psram_cs_io = PICO_PSRAM_CS_IO;
325            }
326            crate::efuse::ChipType::Esp32Picod4 => {
327                panic!("PSRAM is unsupported on this chip");
328            }
329            crate::efuse::ChipType::Esp32Picov302 => {
330                clk_mode = PsramClkMode::PsramClkModeNorm;
331                psram_io.psram_clk_io = PICO_V3_02_PSRAM_CLK_IO;
332                psram_io.psram_cs_io = PICO_V3_02_PSRAM_CS_IO;
333            }
334            crate::efuse::ChipType::Unknown => {
335                panic!("Unknown chip type. PSRAM is not supported");
336            }
337        }
338
339        let spiconfig = unsafe { esp_rom_efuse_get_flash_gpio_info() };
340        if spiconfig == ESP_ROM_EFUSE_FLASH_DEFAULT_SPI {
341            psram_io.flash_clk_io = SPI_IOMUX_PIN_NUM_CLK;
342            psram_io.flash_cs_io = SPI_IOMUX_PIN_NUM_CS;
343            psram_io.psram_spiq_sd0_io = PSRAM_SPIQ_SD0_IO;
344            psram_io.psram_spid_sd1_io = PSRAM_SPID_SD1_IO;
345            psram_io.psram_spiwp_sd3_io = PSRAM_SPIWP_SD3_IO;
346            psram_io.psram_spihd_sd2_io = PSRAM_SPIHD_SD2_IO;
347        } else if spiconfig == ESP_ROM_EFUSE_FLASH_DEFAULT_HSPI {
348            psram_io.flash_clk_io = FLASH_HSPI_CLK_IO;
349            psram_io.flash_cs_io = FLASH_HSPI_CS_IO;
350            psram_io.psram_spiq_sd0_io = PSRAM_HSPI_SPIQ_SD0_IO;
351            psram_io.psram_spid_sd1_io = PSRAM_HSPI_SPID_SD1_IO;
352            psram_io.psram_spiwp_sd3_io = PSRAM_HSPI_SPIWP_SD3_IO;
353            psram_io.psram_spihd_sd2_io = PSRAM_HSPI_SPIHD_SD2_IO;
354        } else if chip == crate::efuse::ChipType::Esp32Picov302 {
355            psram_io.flash_clk_io = efuse_spiconfig_ret(
356                spiconfig,
357                EFUSE_SPICONFIG_RET_SPICLK_MASK,
358                EFUSE_SPICONFIG_RET_SPICLK_SHIFT,
359            );
360            psram_io.flash_cs_io = efuse_spiconfig_ret(
361                spiconfig,
362                EFUSE_SPICONFIG_RET_SPICS0_MASK,
363                EFUSE_SPICONFIG_RET_SPICS0_SHIFT,
364            );
365            psram_io.psram_spiq_sd0_io = efuse_spiconfig_ret(
366                spiconfig,
367                EFUSE_SPICONFIG_RET_SPIQ_MASK,
368                EFUSE_SPICONFIG_RET_SPIQ_SHIFT,
369            );
370            psram_io.psram_spid_sd1_io = efuse_spiconfig_ret(
371                spiconfig,
372                EFUSE_SPICONFIG_RET_SPID_MASK,
373                EFUSE_SPICONFIG_RET_SPID_SHIFT,
374            );
375            psram_io.psram_spihd_sd2_io = efuse_spiconfig_ret(
376                spiconfig,
377                EFUSE_SPICONFIG_RET_SPIHD_MASK,
378                EFUSE_SPICONFIG_RET_SPIHD_SHIFT,
379            );
380            psram_io.psram_spiwp_sd3_io = PICO_V3_02_PSRAM_SPIWP_SD3_IO;
381        } else {
382            panic!("Getting Flash/PSRAM pins from efuse is not supported");
383            // psram_io.flash_clk_io = EFUSE_SPICONFIG_RET_SPICLK(spiconfig);
384            // psram_io.flash_cs_io = EFUSE_SPICONFIG_RET_SPICS0(spiconfig);
385            // psram_io.psram_spiq_sd0_io = EFUSE_SPICONFIG_RET_SPIQ(spiconfig);
386            // psram_io.psram_spid_sd1_io = EFUSE_SPICONFIG_RET_SPID(spiconfig);
387            // psram_io.psram_spihd_sd2_io =
388            // EFUSE_SPICONFIG_RET_SPIHD(spiconfig);
389            // psram_io.psram_spiwp_sd3_io = bootloader_flash_get_wp_pin();
390        }
391        info!("PS-RAM pins {:?}", &psram_io);
392
393        unsafe {
394            SPI0::regs().ext3().modify(|_, w| w.bits(0x1));
395            SPI1::regs()
396                .user()
397                .modify(|_, w| w.usr_prep_hold().clear_bit());
398        }
399
400        psram_spi_init(mode, clk_mode);
401
402        match mode {
403            PsramCacheSpeed::PsramCacheF80mS80m => unsafe {
404                esp_rom_gpio_connect_out_signal(
405                    psram_io.psram_clk_io as u32,
406                    SPICLK_OUT_IDX,
407                    false,
408                    false,
409                );
410            },
411            _ => unsafe {
412                if clk_mode == PsramClkMode::PsramClkModeDclk {
413                    // We need to delay CLK to the PSRAM with respect to the clock signal as output
414                    // by the SPI peripheral. We do this by routing it signal to
415                    // signal 224/225, which are used as a loopback; the extra run through
416                    // the GPIO matrix causes the delay. We use GPIO20 (which is not in any package
417                    // but has pad logic in silicon) as a temporary pad for
418                    // this. So the signal path is: SPI CLK --> GPIO28 -->
419                    // signal224(in then out) --> internal GPIO29 --> signal225(in then out) -->
420                    // GPIO17(PSRAM CLK)
421                    esp_rom_gpio_connect_out_signal(
422                        PSRAM_INTERNAL_IO_28,
423                        SPICLK_OUT_IDX,
424                        false,
425                        false,
426                    );
427                    esp_rom_gpio_connect_in_signal(PSRAM_INTERNAL_IO_28, SIG_IN_FUNC224_IDX, false);
428                    esp_rom_gpio_connect_out_signal(
429                        PSRAM_INTERNAL_IO_29,
430                        SIG_IN_FUNC224_IDX,
431                        false,
432                        false,
433                    );
434                    esp_rom_gpio_connect_in_signal(PSRAM_INTERNAL_IO_29, SIG_IN_FUNC225_IDX, false);
435                    esp_rom_gpio_connect_out_signal(
436                        psram_io.psram_clk_io as u32,
437                        SIG_IN_FUNC225_IDX,
438                        false,
439                        false,
440                    );
441                } else {
442                    esp_rom_gpio_connect_out_signal(
443                        psram_io.psram_clk_io as u32,
444                        SPICLK_OUT_IDX,
445                        false,
446                        false,
447                    );
448                }
449            },
450        }
451
452        let extra_dummy = psram_gpio_config(&psram_io, mode);
453        info!("extra dummy = {}", extra_dummy);
454
455        // psram_is_32mbit_ver0 would need special handling here
456
457        unsafe {
458            esp_rom_gpio_connect_out_signal(PSRAM_INTERNAL_IO_28, SIG_GPIO_OUT_IDX, false, false);
459            esp_rom_gpio_connect_out_signal(PSRAM_INTERNAL_IO_29, SIG_GPIO_OUT_IDX, false, false);
460            esp_rom_gpio_connect_out_signal(
461                psram_io.psram_clk_io as u32,
462                SPICLK_OUT_IDX,
463                false,
464                false,
465            );
466        }
467
468        // Update cs timing according to psram driving method.
469        psram_set_cs_timing_spi1(mode, clk_mode);
470        psram_set_cs_timing_spi0(mode, clk_mode); // SPI_CACHE_PORT
471        psram_enable_qio_mode_spi1(clk_mode, mode);
472
473        let psram_vaddr_mode = config.psram_vaddr_mode;
474        info!("PS-RAM vaddrmode = {:?}", psram_vaddr_mode);
475
476        psram_cache_init(mode, psram_vaddr_mode, clk_mode, extra_dummy);
477    }
478
479    // register initialization for sram cache params and r/w commands
480    fn psram_cache_init(
481        psram_cache_mode: PsramCacheSpeed,
482        vaddrmode: PsramVaddrMode,
483        clk_mode: PsramClkMode,
484        extra_dummy: u32,
485    ) {
486        unsafe {
487            let spi = SPI0::regs();
488            info!(
489                "PS-RAM cache_init, psram_cache_mode={:?}, extra_dummy={}, clk_mode={:?}",
490                psram_cache_mode, extra_dummy, clk_mode
491            );
492            match psram_cache_mode {
493                PsramCacheSpeed::PsramCacheF80mS80m => {
494                    // flash 1 div clk,80+40;
495                    // There's no register on bit 31. No information about it in IDF, nor TRM,
496                    // so just doing it in this way.
497                    spi.date().modify(|r, w| {
498                        let current_bits = r.bits();
499                        let new_bits = current_bits & !((1 << 31) | (1 << 30));
500                        w.bits(new_bits)
501                    });
502                    // pre clk div , ONLY IF SPI/ SRAM@ DIFFERENT SPEED,JUST
503                    // FOR SPI0. FLASH DIV
504                    // 2+SRAM DIV4
505                }
506                PsramCacheSpeed::PsramCacheF80mS40m => {
507                    spi.clock().modify(|_, w| w.clk_equ_sysclk().clear_bit());
508                    spi.clock().modify(|_, w| w.clkdiv_pre().bits(0));
509                    spi.clock().modify(|_, w| w.clkcnt_n().bits(1));
510                    spi.clock().modify(|_, w| w.clkcnt_h().bits(0));
511                    spi.clock().modify(|_, w| w.clkcnt_l().bits(1));
512
513                    spi.date().modify(|r, w| {
514                        let current_bits = r.bits();
515                        let new_bits = (current_bits | (1 << 31)) & !(1 << 30);
516                        w.bits(new_bits)
517                    });
518                }
519                _ => {
520                    spi.date().modify(|r, w| {
521                        let current_bits = r.bits();
522                        let new_bits = current_bits & !((1 << 31) | (1 << 30));
523                        w.bits(new_bits)
524                    });
525                }
526            }
527
528            spi.cache_sctrl()
529                .modify(|_, w| w.usr_sram_dio().clear_bit()); // disable dio mode for cache command
530            spi.cache_sctrl().modify(|_, w| w.usr_sram_qio().set_bit()); // enable qio mode for cache command
531            spi.cache_sctrl()
532                .modify(|_, w| w.cache_sram_usr_rcmd().set_bit()); // enable cache read command
533            spi.cache_sctrl()
534                .modify(|_, w| w.cache_sram_usr_wcmd().set_bit()); // enable cache write command
535            spi.cache_sctrl()
536                .modify(|_, w| w.sram_addr_bitlen().bits(23)); // write address for cache command.
537            spi.cache_sctrl()
538                .modify(|_, w| w.usr_rd_sram_dummy().set_bit()); // enable cache read dummy
539
540            // config sram cache r/w command
541            spi.sram_drd_cmd()
542                .modify(|_, w| w.cache_sram_usr_rd_cmd_bitlen().bits(7));
543            spi.sram_drd_cmd().modify(|_, w| {
544                w.cache_sram_usr_rd_cmd_value()
545                    .bits(PSRAM_FAST_READ_QUAD as u16)
546            });
547            spi.sram_dwr_cmd()
548                .modify(|_, w| w.cache_sram_usr_wr_cmd_bitlen().bits(7));
549            spi.sram_dwr_cmd().modify(|_, w| {
550                w.cache_sram_usr_wr_cmd_value()
551                    .bits(PSRAM_QUAD_WRITE as u16)
552            });
553
554            // dummy, psram cache : 40m--+1dummy; 80m--+2dummy
555            spi.cache_sctrl().modify(|_, w| {
556                w.sram_dummy_cyclelen()
557                    .bits((PSRAM_FAST_READ_QUAD_DUMMY + extra_dummy) as u8)
558            });
559
560            match psram_cache_mode {
561                PsramCacheSpeed::PsramCacheF80mS80m => (), // in this mode , no delay is needed
562                _ => {
563                    if clk_mode == PsramClkMode::PsramClkModeDclk {
564                        spi.sram_drd_cmd()
565                            .modify(|_, w| w.cache_sram_usr_rd_cmd_bitlen().bits(15)); // read command length, 2 bytes(1byte for delay),sending in qio mode in
566                        // cache
567                        spi.sram_drd_cmd().modify(|_, w| {
568                            w.cache_sram_usr_rd_cmd_value()
569                                .bits((PSRAM_FAST_READ_QUAD << 8) as u16)
570                        }); // read command value,(0x00 for delay,0xeb for cmd)
571
572                        spi.sram_dwr_cmd()
573                            .modify(|_, w| w.cache_sram_usr_wr_cmd_bitlen().bits(15)); // write command length,2 bytes(1byte for delay,send in qio mode in cache)
574                        spi.sram_dwr_cmd().modify(|_, w| {
575                            w.cache_sram_usr_wr_cmd_value()
576                                .bits((PSRAM_QUAD_WRITE << 8) as u16)
577                        }); // write command value,(0x00 for delay)
578                        spi.cache_sctrl().modify(|_, w| {
579                            w.sram_dummy_cyclelen()
580                                .bits((PSRAM_FAST_READ_QUAD_DUMMY + extra_dummy) as u8)
581                        }); // dummy, psram cache : 40m--+1dummy; 80m--+2dummy
582                    }
583                }
584            }
585
586            let dport = DPORT::regs();
587
588            dport
589                .pro_cache_ctrl()
590                .modify(|_, w| w.pro_dram_hl().clear_bit().pro_dram_split().clear_bit());
591            dport
592                .app_cache_ctrl()
593                .modify(|_, w| w.app_dram_hl().clear_bit().app_dram_split().clear_bit());
594            if vaddrmode == PsramVaddrMode::LowHigh {
595                dport
596                    .pro_cache_ctrl()
597                    .modify(|_, w| w.pro_dram_hl().set_bit());
598                dport
599                    .app_cache_ctrl()
600                    .modify(|_, w| w.app_dram_hl().set_bit());
601            } else if vaddrmode == PsramVaddrMode::Evenodd {
602                dport
603                    .pro_cache_ctrl()
604                    .modify(|_, w| w.pro_dram_split().set_bit());
605                dport
606                    .app_cache_ctrl()
607                    .modify(|_, w| w.app_dram_split().set_bit());
608            }
609
610            // use Dram1 to visit ext sram. cache page mode : 1 -->16k  4 -->2k
611            // 0-->32k,(accord with the settings in cache_sram_mmu_set)
612            dport.pro_cache_ctrl1().modify(|_, w| {
613                w.pro_cache_mask_dram1()
614                    .clear_bit()
615                    .pro_cache_mask_opsdram()
616                    .clear_bit()
617            });
618            dport
619                .pro_cache_ctrl1()
620                .modify(|_, w| w.pro_cmmu_sram_page_mode().bits(0));
621
622            // use Dram1 to visit ext sram. cache page mode : 1 -->16k  4 -->2k
623            // 0-->32k,(accord with the settings in cache_sram_mmu_set)
624            dport.app_cache_ctrl1().modify(|_, w| {
625                w.app_cache_mask_dram1()
626                    .clear_bit()
627                    .app_cache_mask_opsdram()
628                    .clear_bit()
629            });
630            dport
631                .app_cache_ctrl1()
632                .modify(|_, w| w.app_cmmu_sram_page_mode().bits(0));
633
634            // ENABLE SPI0 CS1 TO PSRAM(CS0--FLASH; CS1--SRAM)
635            spi.pin().modify(|_, w| w.cs1_dis().clear_bit());
636        }
637    }
638
639    // spi param init for psram
640    #[ram]
641    fn psram_spi_init(
642        // psram_spi_num_t spi_num = PSRAM_SPI_1,
643        mode: PsramCacheSpeed,
644        clk_mode: PsramClkMode,
645    ) {
646        unsafe {
647            let spi = SPI1::regs();
648            // We need to clear last bit of INT_EN field here.
649            spi.slave().modify(|_, w| w.trans_inten().clear_bit());
650            // SPI_CPOL & SPI_CPHA
651            spi.pin().modify(|_, w| w.ck_idle_edge().clear_bit());
652            spi.user().modify(|_, w| w.ck_out_edge().clear_bit());
653            // SPI bit order
654            spi.ctrl().modify(|_, w| w.wr_bit_order().clear_bit());
655            spi.ctrl().modify(|_, w| w.rd_bit_order().clear_bit());
656            // SPI bit order
657            spi.user().modify(|_, w| w.doutdin().clear_bit());
658            // May be not must to do.
659            spi.user1().modify(|_, w| w.bits(0));
660            // SPI mode type
661            spi.slave().modify(|_, w| w.mode().clear_bit());
662
663            let ptr = SPI1_W0_REG as *mut u32;
664            for i in 0..16 {
665                ptr.offset(i).write_volatile(0);
666            }
667
668            psram_set_cs_timing_spi1(mode, clk_mode);
669        }
670    }
671
672    fn psram_set_cs_timing_spi1(psram_cache_mode: PsramCacheSpeed, clk_mode: PsramClkMode) {
673        unsafe {
674            let spi = SPI1::regs();
675            if clk_mode == PsramClkMode::PsramClkModeNorm {
676                spi.user().modify(|_, w| w.cs_hold().set_bit());
677                spi.user().modify(|_, w| w.cs_setup().set_bit());
678
679                spi.ctrl2().modify(|_, w| {
680                    w.hold_time()
681                        .bits(psram_cs_hold_time_from_psram_speed(psram_cache_mode) as u8)
682                });
683
684                // Set cs time.
685                spi.ctrl2().modify(|_, w| w.setup_time().bits(0));
686            } else {
687                spi.user().modify(|_, w| w.cs_hold().clear_bit());
688                spi.user().modify(|_, w| w.cs_setup().clear_bit());
689            }
690        }
691    }
692
693    fn psram_set_cs_timing_spi0(psram_cache_mode: PsramCacheSpeed, clk_mode: PsramClkMode) {
694        unsafe {
695            let spi = SPI0::regs();
696            if clk_mode == PsramClkMode::PsramClkModeNorm {
697                spi.user().modify(|_, w| w.cs_hold().set_bit());
698                spi.user().modify(|_, w| w.cs_setup().set_bit());
699
700                spi.ctrl2().modify(|_, w| {
701                    w.hold_time()
702                        .bits(psram_cs_hold_time_from_psram_speed(psram_cache_mode) as u8)
703                });
704
705                // Set cs time.
706                spi.ctrl2().modify(|_, w| w.setup_time().bits(0));
707            } else {
708                spi.user().modify(|_, w| w.cs_hold().clear_bit());
709                spi.user().modify(|_, w| w.cs_setup().clear_bit());
710            }
711        }
712    }
713
714    #[derive(Default, Debug, Copy, Clone, PartialEq)]
715    struct PsramCmd {
716        cmd: u16,             // Command value
717        cmd_bit_len: u16,     // Command byte length
718        addr: u32,            // Address value
719        addr_bit_len: u16,    // Address byte length
720        tx_data: *const u32,  // Point to send data buffer
721        tx_data_bit_len: u16, // Send data byte length.
722        rx_data: *mut u32,    // Point to recevie data buffer
723        rx_data_bit_len: u16, // Recevie Data byte length.
724        dummy_bit_len: u32,
725    }
726
727    const PSRAM_ENTER_QMODE: u32 = 0x35;
728
729    // enter QPI mode
730    #[ram]
731    fn psram_enable_qio_mode_spi1(clk_mode: PsramClkMode, psram_mode: PsramCacheSpeed) {
732        let mut ps_cmd: PsramCmd = PsramCmd::default();
733        let addr: u32 = PSRAM_ENTER_QMODE << 24;
734
735        ps_cmd.cmd_bit_len = 0;
736        if clk_mode == PsramClkMode::PsramClkModeDclk {
737            match psram_mode {
738                PsramCacheSpeed::PsramCacheF80mS80m => (),
739                _ => {
740                    ps_cmd.cmd_bit_len = 2;
741                }
742            }
743        }
744        ps_cmd.cmd = 0;
745        ps_cmd.addr = addr;
746        ps_cmd.addr_bit_len = 8;
747        ps_cmd.tx_data = core::ptr::null();
748        ps_cmd.tx_data_bit_len = 0;
749        ps_cmd.rx_data = core::ptr::null_mut();
750        ps_cmd.rx_data_bit_len = 0;
751        ps_cmd.dummy_bit_len = 0;
752        let (backup_usr, backup_usr1, backup_usr2) = psram_cmd_config_spi1(&ps_cmd);
753        psram_cmd_recv_start_spi1(core::ptr::null_mut(), 0, PsramCmdMode::PsramCmdQpi);
754        psram_cmd_end_spi1(backup_usr, backup_usr1, backup_usr2);
755    }
756
757    #[ram]
758    fn psram_cmd_end_spi1(backup_usr: u32, backup_usr1: u32, backup_usr2: u32) {
759        unsafe {
760            let spi = SPI1::regs();
761            while spi.cmd().read().usr().bit_is_set() {}
762
763            spi.user().write(|w| w.bits(backup_usr));
764            spi.user1().write(|w| w.bits(backup_usr1));
765            spi.user2().write(|w| w.bits(backup_usr2));
766        }
767    }
768
769    // setup spi command/addr/data/dummy in user mode
770    #[ram]
771    fn psram_cmd_config_spi1(p_in_data: &PsramCmd) -> (u32, u32, u32) {
772        unsafe {
773            let spi = SPI1::regs();
774            while spi.cmd().read().usr().bit_is_set() {}
775
776            let backup_usr = spi.user().read().bits();
777            let backup_usr1 = spi.user1().read().bits();
778            let backup_usr2 = spi.user2().read().bits();
779
780            // Set command by user.
781            if p_in_data.cmd_bit_len != 0 {
782                // Max command length 16 bits.
783                spi.user2().modify(|_, w| {
784                    w.usr_command_bitlen()
785                        .bits((p_in_data.cmd_bit_len - 1) as u8)
786                });
787                // Enable command
788                spi.user().modify(|_, w| w.usr_command().set_bit());
789                // Load command,bit15-0 is cmd value.
790                spi.user2()
791                    .modify(|_, w| w.usr_command_value().bits(p_in_data.cmd));
792            } else {
793                spi.user().modify(|_, w| w.usr_command().clear_bit());
794                spi.user2().modify(|_, w| w.usr_command_bitlen().bits(0));
795            }
796            // Set Address by user.
797            if p_in_data.addr_bit_len != 0 {
798                spi.user1()
799                    .modify(|_, w| w.usr_addr_bitlen().bits((p_in_data.addr_bit_len - 1) as u8));
800                // Enable address
801                spi.user().modify(|_, w| w.usr_addr().set_bit());
802                // Set address
803                spi.addr().modify(|_, w| w.bits(p_in_data.addr));
804            } else {
805                spi.user().modify(|_, w| w.usr_addr().clear_bit());
806                spi.user1().modify(|_, w| w.usr_addr_bitlen().bits(0));
807            }
808            // Set data by user.
809            let p_tx_val = p_in_data.tx_data;
810            if p_in_data.tx_data_bit_len != 0 {
811                // Enable MOSI
812                spi.user().modify(|_, w| w.usr_mosi().set_bit());
813                // Load send buffer
814                let len = p_in_data.tx_data_bit_len.div_ceil(32);
815                if !p_tx_val.is_null() {
816                    for i in 0..len {
817                        spi.w(i as usize)
818                            .write(|w| w.bits(p_tx_val.offset(i as isize).read_volatile()));
819                    }
820                }
821                // Set data send buffer length.Max data length 64 bytes.
822                spi.mosi_dlen().modify(|_, w| {
823                    w.usr_mosi_dbitlen()
824                        .bits((p_in_data.tx_data_bit_len - 1) as u32)
825                });
826            } else {
827                spi.user().modify(|_, w| w.usr_mosi().clear_bit());
828                spi.mosi_dlen().modify(|_, w| w.usr_mosi_dbitlen().bits(0));
829            }
830            // Set rx data by user.
831            if p_in_data.rx_data_bit_len != 0 {
832                // Enable MISO
833                spi.user().modify(|_, w| w.usr_miso().set_bit());
834                // Set data send buffer length.Max data length 64 bytes.
835                spi.miso_dlen().modify(|_, w| {
836                    w.usr_miso_dbitlen()
837                        .bits((p_in_data.rx_data_bit_len - 1) as u32)
838                });
839            } else {
840                spi.user().modify(|_, w| w.usr_miso().clear_bit());
841                spi.miso_dlen().modify(|_, w| w.usr_miso_dbitlen().bits(0));
842            }
843            if p_in_data.dummy_bit_len != 0 {
844                spi.user().modify(|_, w| w.usr_dummy().set_bit()); // dummy en
845                spi.user1().modify(|_, w| {
846                    w.usr_dummy_cyclelen()
847                        .bits((p_in_data.dummy_bit_len - 1) as u8)
848                }); // DUMMY
849            } else {
850                spi.user().modify(|_, w| w.usr_dummy().clear_bit()); // dummy dis
851                spi.user1().modify(|_, w| w.usr_dummy_cyclelen().bits(0)); // DUMMY
852            }
853
854            (backup_usr, backup_usr1, backup_usr2)
855        }
856    }
857
858    #[derive(Debug, Clone, Copy, PartialEq)]
859    enum PsramCmdMode {
860        PsramCmdQpi,
861        PsramCmdSpi,
862    }
863
864    // start sending cmd/addr and optionally, receiving data
865    #[ram]
866    fn psram_cmd_recv_start_spi1(
867        p_rx_data: *mut u32,
868        rx_data_len_words: usize,
869        cmd_mode: PsramCmdMode,
870    ) {
871        unsafe {
872            let spi = SPI1::regs();
873            // get cs1
874            spi.pin().modify(|_, w| w.cs1_dis().clear_bit());
875            spi.pin().modify(|_, w| w.cs0_dis().set_bit());
876
877            let mode_backup: u32 = (spi.user().read().bits() >> SPI_FWRITE_DUAL_S) & 0xf;
878            let rd_mode_backup: u32 = spi.ctrl().read().bits()
879                & (SPI_FREAD_DIO_M | SPI_FREAD_DUAL_M | SPI_FREAD_QUAD_M | SPI_FREAD_QIO_M);
880
881            if cmd_mode == PsramCmdMode::PsramCmdSpi {
882                psram_set_basic_write_mode_spi1();
883                psram_set_basic_read_mode_spi1();
884            } else if cmd_mode == PsramCmdMode::PsramCmdQpi {
885                psram_set_qio_write_mode_spi1();
886                psram_set_qio_read_mode_spi1();
887            }
888
889            // Wait for SPI0 to idle
890            while SPI1::regs().ext2().read().bits() != 0 {}
891
892            // DPORT_SET_PERI_REG_MASK(DPORT_HOST_INF_SEL_REG, 1 << 14);
893            DPORT::regs()
894                .host_inf_sel()
895                .modify(|r, w| w.bits(r.bits() | (1 << 14)));
896
897            // Start send data
898            spi.cmd().modify(|_, w| w.usr().set_bit());
899            while spi.cmd().read().usr().bit_is_set() {}
900
901            // DPORT_CLEAR_PERI_REG_MASK(DPORT_HOST_INF_SEL_REG, 1 << 14);
902            DPORT::regs()
903                .host_inf_sel()
904                .modify(|r, w| w.bits(r.bits() & !(1 << 14)));
905
906            // recover spi mode
907            // TODO: get back to this, why writing on `0xf` address?
908            set_peri_reg_bits(
909                SPI1_USER_REG,
910                if !p_rx_data.is_null() {
911                    SPI_FWRITE_DUAL_M
912                } else {
913                    0xf
914                },
915                mode_backup,
916                SPI_FWRITE_DUAL_S,
917            );
918
919            spi.ctrl().modify(|_, w| {
920                w.fread_dio().clear_bit();
921                w.fread_dual().clear_bit();
922                w.fread_quad().clear_bit();
923                w.fread_qio().clear_bit()
924            });
925            spi.ctrl().modify(|r, w| w.bits(r.bits() | rd_mode_backup));
926
927            // return cs to cs0
928            spi.pin().modify(|_, w| w.cs1_dis().set_bit());
929            spi.pin().modify(|_, w| w.cs0_dis().clear_bit());
930
931            if !p_rx_data.is_null() {
932                // Read data out
933                for i in 0..rx_data_len_words {
934                    p_rx_data.add(i).write_volatile(spi.w(i).read().bits());
935                }
936            }
937        }
938    }
939
940    // set basic SPI write mode
941    fn psram_set_basic_write_mode_spi1() {
942        SPI1::regs().user().modify(|_, w| {
943            w.fwrite_qio().clear_bit();
944            w.fwrite_dio().clear_bit();
945            w.fwrite_quad().clear_bit();
946            w.fwrite_dual().clear_bit()
947        });
948    }
949
950    // set QPI write mode
951    fn psram_set_qio_write_mode_spi1() {
952        SPI1::regs().user().modify(|_, w| {
953            w.fwrite_qio().set_bit();
954            w.fwrite_dio().clear_bit();
955            w.fwrite_quad().clear_bit();
956            w.fwrite_dual().clear_bit()
957        });
958    }
959
960    // set QPI read mode
961    fn psram_set_qio_read_mode_spi1() {
962        SPI1::regs().ctrl().modify(|_, w| {
963            w.fread_qio().set_bit();
964            w.fread_quad().clear_bit();
965            w.fread_dual().clear_bit();
966            w.fread_dio().clear_bit()
967        });
968    }
969
970    // set SPI read mode
971    fn psram_set_basic_read_mode_spi1() {
972        SPI1::regs().ctrl().modify(|_, w| {
973            w.fread_qio().clear_bit();
974            w.fread_quad().clear_bit();
975            w.fread_dual().clear_bit();
976            w.fread_dio().clear_bit()
977        });
978    }
979
980    // psram gpio init , different working frequency we have different solutions
981    fn psram_gpio_config(psram_io: &PsramIo, mode: PsramCacheSpeed) -> u32 {
982        unsafe {
983            let spi = SPI0::regs();
984            let g_rom_spiflash_dummy_len_plus_ptr = addr_of_mut!(g_rom_spiflash_dummy_len_plus);
985
986            #[derive(Debug, Clone, Copy)]
987            enum Field {
988                McuSel,
989                FunDrv,
990            }
991
992            macro_rules! apply_to_field {
993                ($w:ident, $field:expr, $bits:expr) => {
994                    match $field {
995                        Field::McuSel => $w.mcu_sel().bits($bits),
996                        Field::FunDrv => $w.fun_drv().bits($bits),
997                    }
998                };
999            }
1000
1001            fn configure_gpio(gpio: u8, field: Field, bits: u8) {
1002                unsafe {
1003                    let ptr = crate::gpio::io_mux_reg(gpio);
1004
1005                    ptr.modify(|_, w| apply_to_field!(w, field, bits));
1006                }
1007            }
1008
1009            let spi_cache_dummy;
1010            let rd_mode_reg = spi.ctrl().read().bits();
1011            if (rd_mode_reg & SPI_FREAD_QIO_M) != 0 {
1012                spi_cache_dummy = SPI0_R_QIO_DUMMY_CYCLELEN;
1013            } else if (rd_mode_reg & SPI_FREAD_DIO_M) != 0 {
1014                spi_cache_dummy = SPI0_R_DIO_DUMMY_CYCLELEN;
1015                spi.user1()
1016                    .modify(|_, w| w.usr_addr_bitlen().bits(SPI0_R_DIO_ADDR_BITSLEN as u8));
1017            } else {
1018                spi_cache_dummy = SPI0_R_FAST_DUMMY_CYCLELEN;
1019            }
1020
1021            let extra_dummy;
1022
1023            match mode {
1024                PsramCacheSpeed::PsramCacheF80mS40m => {
1025                    extra_dummy = PSRAM_IO_MATRIX_DUMMY_40M;
1026
1027                    g_rom_spiflash_dummy_len_plus_ptr
1028                        .offset(_SPI_CACHE_PORT as isize)
1029                        .write_volatile(PSRAM_IO_MATRIX_DUMMY_80M);
1030                    g_rom_spiflash_dummy_len_plus_ptr
1031                        .offset(_SPI_FLASH_PORT as isize)
1032                        .write_volatile(PSRAM_IO_MATRIX_DUMMY_40M);
1033
1034                    spi.user1().modify(|_, w| {
1035                        w.usr_dummy_cyclelen()
1036                            .bits(spi_cache_dummy as u8 + PSRAM_IO_MATRIX_DUMMY_80M)
1037                    }); // DUMMY
1038
1039                    esp_rom_spiflash_config_clk(_SPI_80M_CLK_DIV, _SPI_CACHE_PORT);
1040                    esp_rom_spiflash_config_clk(_SPI_40M_CLK_DIV, _SPI_FLASH_PORT);
1041
1042                    // set drive ability for clock
1043
1044                    configure_gpio(psram_io.flash_clk_io, Field::FunDrv, 3);
1045                    configure_gpio(psram_io.psram_clk_io, Field::FunDrv, 2);
1046                }
1047                PsramCacheSpeed::PsramCacheF80mS80m => {
1048                    extra_dummy = PSRAM_IO_MATRIX_DUMMY_80M;
1049                    g_rom_spiflash_dummy_len_plus_ptr
1050                        .offset(_SPI_CACHE_PORT as isize)
1051                        .write_volatile(PSRAM_IO_MATRIX_DUMMY_80M);
1052                    g_rom_spiflash_dummy_len_plus_ptr
1053                        .offset(_SPI_FLASH_PORT as isize)
1054                        .write_volatile(PSRAM_IO_MATRIX_DUMMY_80M);
1055
1056                    spi.user1().modify(|_, w| {
1057                        w.usr_dummy_cyclelen()
1058                            .bits(spi_cache_dummy as u8 + PSRAM_IO_MATRIX_DUMMY_80M)
1059                    }); // DUMMY
1060
1061                    esp_rom_spiflash_config_clk(_SPI_80M_CLK_DIV, _SPI_CACHE_PORT);
1062                    esp_rom_spiflash_config_clk(_SPI_80M_CLK_DIV, _SPI_FLASH_PORT);
1063
1064                    // set drive ability for clock
1065                    configure_gpio(psram_io.flash_clk_io, Field::FunDrv, 3);
1066                    configure_gpio(psram_io.psram_clk_io, Field::FunDrv, 3);
1067                }
1068                PsramCacheSpeed::PsramCacheF40mS40m => {
1069                    extra_dummy = PSRAM_IO_MATRIX_DUMMY_40M;
1070
1071                    g_rom_spiflash_dummy_len_plus_ptr
1072                        .offset(_SPI_CACHE_PORT as isize)
1073                        .write_volatile(PSRAM_IO_MATRIX_DUMMY_40M);
1074                    g_rom_spiflash_dummy_len_plus_ptr
1075                        .offset(_SPI_FLASH_PORT as isize)
1076                        .write_volatile(PSRAM_IO_MATRIX_DUMMY_40M);
1077
1078                    spi.user1().modify(|_, w| {
1079                        w.usr_dummy_cyclelen()
1080                            .bits(spi_cache_dummy as u8 + PSRAM_IO_MATRIX_DUMMY_40M)
1081                    }); // DUMMY
1082
1083                    esp_rom_spiflash_config_clk(_SPI_40M_CLK_DIV, _SPI_CACHE_PORT);
1084                    esp_rom_spiflash_config_clk(_SPI_40M_CLK_DIV, _SPI_FLASH_PORT);
1085
1086                    // set drive ability for clock
1087                    configure_gpio(psram_io.flash_clk_io, Field::FunDrv, 2);
1088                    configure_gpio(psram_io.psram_clk_io, Field::FunDrv, 2);
1089                }
1090            }
1091
1092            spi.user().modify(|_, w| w.usr_dummy().set_bit()); // dummy enable
1093
1094            // In bootloader, all the signals are already configured,
1095            // We keep the following code in case the bootloader is some older version.
1096
1097            esp_rom_gpio_connect_out_signal(
1098                psram_io.flash_cs_io as u32,
1099                SPICS0_OUT_IDX,
1100                false,
1101                false,
1102            );
1103            esp_rom_gpio_connect_out_signal(
1104                psram_io.psram_cs_io as u32,
1105                SPICS1_OUT_IDX,
1106                false,
1107                false,
1108            );
1109            esp_rom_gpio_connect_out_signal(
1110                psram_io.psram_spiq_sd0_io as u32,
1111                SPIQ_OUT_IDX,
1112                false,
1113                false,
1114            );
1115            esp_rom_gpio_connect_in_signal(psram_io.psram_spiq_sd0_io as u32, SPIQ_IN_IDX, false);
1116            esp_rom_gpio_connect_out_signal(
1117                psram_io.psram_spid_sd1_io as u32,
1118                SPID_OUT_IDX,
1119                false,
1120                false,
1121            );
1122            esp_rom_gpio_connect_in_signal(psram_io.psram_spid_sd1_io as u32, SPID_IN_IDX, false);
1123            esp_rom_gpio_connect_out_signal(
1124                psram_io.psram_spiwp_sd3_io as u32,
1125                SPIWP_OUT_IDX,
1126                false,
1127                false,
1128            );
1129            esp_rom_gpio_connect_in_signal(psram_io.psram_spiwp_sd3_io as u32, SPIWP_IN_IDX, false);
1130            esp_rom_gpio_connect_out_signal(
1131                psram_io.psram_spihd_sd2_io as u32,
1132                SPIHD_OUT_IDX,
1133                false,
1134                false,
1135            );
1136            esp_rom_gpio_connect_in_signal(psram_io.psram_spihd_sd2_io as u32, SPIHD_IN_IDX, false);
1137
1138            // select pin function gpio
1139            if (psram_io.flash_clk_io == SPI_IOMUX_PIN_NUM_CLK)
1140                && (psram_io.flash_clk_io != psram_io.psram_clk_io)
1141            {
1142                // flash clock signal should come from IO MUX.
1143                configure_gpio(
1144                    psram_io.flash_clk_io,
1145                    Field::McuSel,
1146                    FUNC_SD_CLK_SPICLK as u8,
1147                );
1148            } else {
1149                // flash clock signal should come from GPIO matrix.
1150                configure_gpio(psram_io.flash_clk_io, Field::McuSel, PIN_FUNC_GPIO as u8);
1151            }
1152            configure_gpio(psram_io.flash_cs_io, Field::McuSel, PIN_FUNC_GPIO as u8);
1153            configure_gpio(psram_io.psram_cs_io, Field::McuSel, PIN_FUNC_GPIO as u8);
1154            configure_gpio(psram_io.psram_clk_io, Field::McuSel, PIN_FUNC_GPIO as u8);
1155            configure_gpio(
1156                psram_io.psram_spiq_sd0_io,
1157                Field::McuSel,
1158                PIN_FUNC_GPIO as u8,
1159            );
1160            configure_gpio(
1161                psram_io.psram_spid_sd1_io,
1162                Field::McuSel,
1163                PIN_FUNC_GPIO as u8,
1164            );
1165            configure_gpio(
1166                psram_io.psram_spihd_sd2_io,
1167                Field::McuSel,
1168                PIN_FUNC_GPIO as u8,
1169            );
1170            configure_gpio(
1171                psram_io.psram_spiwp_sd3_io,
1172                Field::McuSel,
1173                PIN_FUNC_GPIO as u8,
1174            );
1175
1176            let flash_id: u32 = g_rom_flashchip.device_id;
1177            info!("Flash-ID = {}", flash_id);
1178            info!("Flash size = {}", g_rom_flashchip.chip_size);
1179
1180            if flash_id == FLASH_ID_GD25LQ32C {
1181                // Set drive ability for 1.8v flash in 80Mhz.
1182                configure_gpio(psram_io.flash_cs_io, Field::FunDrv, 3);
1183                configure_gpio(psram_io.flash_clk_io, Field::FunDrv, 3);
1184                configure_gpio(psram_io.psram_cs_io, Field::FunDrv, 3);
1185                configure_gpio(psram_io.psram_clk_io, Field::FunDrv, 3);
1186                configure_gpio(psram_io.psram_spiq_sd0_io, Field::FunDrv, 3);
1187                configure_gpio(psram_io.psram_spid_sd1_io, Field::FunDrv, 3);
1188                configure_gpio(psram_io.psram_spihd_sd2_io, Field::FunDrv, 3);
1189                configure_gpio(psram_io.psram_spiwp_sd3_io, Field::FunDrv, 3);
1190            }
1191
1192            extra_dummy as u32
1193        }
1194    }
1195
1196    fn set_peri_reg_bits(reg: u32, bitmap: u32, value: u32, shift: u32) {
1197        unsafe {
1198            (reg as *mut u32).write_volatile(
1199                ((reg as *mut u32).read_volatile() & !(bitmap << shift))
1200                    | ((value & bitmap) << shift),
1201            );
1202        }
1203    }
1204}