From fad639f0d4e0dddc60a1289cc71deccd7a76e815 Mon Sep 17 00:00:00 2001 From: Wangjialin Date: Fri, 10 Jan 2020 19:31:30 +0800 Subject: [PATCH] feature(psram): update psram initialization. 1. use spi functions in rom 2. remove unnecessary GPIO configurations. 3. remove unnecessary dummy settings. 4. enable dummy out function 5. flash and psram have independent timing setting registers. 6. no need to set 1.9v for LDO in 80Mhz 7. set IO driver ability to 1 by default. 8. no need to use GPIO matrix on esp32s2, IO MUX is recommended 9. enable spi clock mode and IO mode settings --- .../src/bootloader_flash_config_esp32s2beta.c | 57 +- .../src/esp32s2beta/bootloader_esp32s2beta.c | 68 +- components/esp32s2beta/Kconfig | 31 + components/esp32s2beta/spiram_psram.c | 1021 ++++++----------- components/esp32s2beta/spiram_psram.h | 5 +- .../include/esp32s2beta/rom/opi_flash.h | 291 +++++ .../include/esp32s2beta/rom/spi_flash.h | 8 +- .../soc/esp32s2beta/include/soc/io_mux_reg.h | 1 + 8 files changed, 714 insertions(+), 768 deletions(-) create mode 100644 components/esp_rom/include/esp32s2beta/rom/opi_flash.h diff --git a/components/bootloader_support/src/bootloader_flash_config_esp32s2beta.c b/components/bootloader_support/src/bootloader_flash_config_esp32s2beta.c index 8967971215..32d8906612 100644 --- a/components/bootloader_support/src/bootloader_flash_config_esp32s2beta.c +++ b/components/bootloader_support/src/bootloader_flash_config_esp32s2beta.c @@ -41,12 +41,12 @@ void bootloader_flash_update_id() void IRAM_ATTR bootloader_flash_cs_timing_config() { - SET_PERI_REG_MASK(SPI_USER_REG(0), SPI_CS_HOLD_M | SPI_CS_SETUP_M); - SET_PERI_REG_BITS(SPI_CTRL2_REG(0), SPI_CS_HOLD_TIME_V, 1, SPI_CS_HOLD_TIME_S); - SET_PERI_REG_BITS(SPI_CTRL2_REG(0), SPI_CS_SETUP_TIME_V, 0, SPI_CS_SETUP_TIME_S); - SET_PERI_REG_MASK(SPI_USER_REG(1), SPI_CS_HOLD_M | SPI_CS_SETUP_M); - SET_PERI_REG_BITS(SPI_CTRL2_REG(1), SPI_CS_HOLD_TIME_V, 1, SPI_CS_HOLD_TIME_S); - SET_PERI_REG_BITS(SPI_CTRL2_REG(1), SPI_CS_SETUP_TIME_V, 0, SPI_CS_SETUP_TIME_S); + SET_PERI_REG_MASK(SPI_MEM_USER_REG(0), SPI_MEM_CS_HOLD_M | SPI_MEM_CS_SETUP_M); + SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_HOLD_TIME_V, 0, SPI_MEM_CS_HOLD_TIME_S); + SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_SETUP_TIME_V, 0, SPI_MEM_CS_SETUP_TIME_S); + SET_PERI_REG_MASK(SPI_MEM_USER_REG(1), SPI_MEM_CS_HOLD_M | SPI_MEM_CS_SETUP_M); + SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(1), SPI_MEM_CS_HOLD_TIME_V, 1, SPI_MEM_CS_HOLD_TIME_S); + SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(1), SPI_MEM_CS_SETUP_TIME_V, 0, SPI_MEM_CS_SETUP_TIME_S); } void IRAM_ATTR bootloader_flash_clock_config(const esp_image_header_t* pfhdr) @@ -71,43 +71,14 @@ void IRAM_ATTR bootloader_flash_clock_config(const esp_image_header_t* pfhdr) esp_rom_spiflash_config_clk(spi_clk_div, 0); } +void IRAM_ATTR bootloader_flash_set_dummy_out(void) +{ + REG_SET_BIT(SPI_MEM_CTRL_REG(0), SPI_MEM_FDUMMY_OUT | SPI_MEM_D_POL | SPI_MEM_Q_POL); + REG_SET_BIT(SPI_MEM_CTRL_REG(1), SPI_MEM_FDUMMY_OUT | SPI_MEM_D_POL | SPI_MEM_Q_POL); +} + void IRAM_ATTR bootloader_flash_dummy_config(const esp_image_header_t* pfhdr) { - int spi_cache_dummy = 0; - int drv = 2; - switch (pfhdr->spi_mode) { - case ESP_IMAGE_SPI_MODE_QIO: - spi_cache_dummy = SPI0_R_QIO_DUMMY_CYCLELEN; - break; - case ESP_IMAGE_SPI_MODE_DIO: - spi_cache_dummy = SPI0_R_DIO_DUMMY_CYCLELEN; //qio 3 - break; - case ESP_IMAGE_SPI_MODE_QOUT: - case ESP_IMAGE_SPI_MODE_DOUT: - default: - spi_cache_dummy = SPI0_R_FAST_DUMMY_CYCLELEN; - break; - } - - /* dummy_len_plus values defined in ROM for SPI flash configuration */ - extern uint8_t g_rom_spiflash_dummy_len_plus[]; - switch (pfhdr->spi_speed) { - case ESP_IMAGE_SPI_SPEED_80M: - g_rom_spiflash_dummy_len_plus[0] = FLASH_IO_MATRIX_DUMMY_80M; - g_rom_spiflash_dummy_len_plus[1] = FLASH_IO_MATRIX_DUMMY_80M; - SET_PERI_REG_BITS(SPI_MEM_USER1_REG(0), SPI_MEM_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + FLASH_IO_MATRIX_DUMMY_80M, - SPI_MEM_USR_DUMMY_CYCLELEN_S); //DUMMY - drv = 3; - break; - case ESP_IMAGE_SPI_SPEED_40M: - g_rom_spiflash_dummy_len_plus[0] = FLASH_IO_MATRIX_DUMMY_40M; - g_rom_spiflash_dummy_len_plus[1] = FLASH_IO_MATRIX_DUMMY_40M; - SET_PERI_REG_BITS(SPI_MEM_USER1_REG(0), SPI_MEM_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + FLASH_IO_MATRIX_DUMMY_40M, - SPI_MEM_USR_DUMMY_CYCLELEN_S); //DUMMY - break; - default: - break; - } - - bootloader_configure_spi_pins(drv); + bootloader_configure_spi_pins(1); + bootloader_flash_set_dummy_out(); } diff --git a/components/bootloader_support/src/esp32s2beta/bootloader_esp32s2beta.c b/components/bootloader_support/src/esp32s2beta/bootloader_esp32s2beta.c index df399b31a0..e0fa0ceb68 100644 --- a/components/bootloader_support/src/esp32s2beta/bootloader_esp32s2beta.c +++ b/components/bootloader_support/src/esp32s2beta/bootloader_esp32s2beta.c @@ -40,52 +40,38 @@ #include "soc/extmem_reg.h" #include "soc/rtc.h" #include "soc/spi_periph.h" +#include static const char *TAG = "boot.esp32s2"; - -#define FLASH_CLK_IO SPI_CLK_GPIO_NUM -#define FLASH_CS_IO SPI_CS0_GPIO_NUM -#define FLASH_SPIQ_IO SPI_Q_GPIO_NUM -#define FLASH_SPID_IO SPI_D_GPIO_NUM -#define FLASH_SPIWP_IO SPI_WP_GPIO_NUM -#define FLASH_SPIHD_IO SPI_HD_GPIO_NUM - void bootloader_configure_spi_pins(int drv) { const uint32_t spiconfig = ets_efuse_get_spiconfig(); - if (spiconfig == EFUSE_SPICONFIG_SPI_DEFAULTS) { - gpio_matrix_out(FLASH_CS_IO, SPICS0_OUT_IDX, 0, 0); - gpio_matrix_out(FLASH_SPIQ_IO, SPIQ_OUT_IDX, 0, 0); - gpio_matrix_in(FLASH_SPIQ_IO, SPIQ_IN_IDX, 0); - gpio_matrix_out(FLASH_SPID_IO, SPID_OUT_IDX, 0, 0); - gpio_matrix_in(FLASH_SPID_IO, SPID_IN_IDX, 0); - gpio_matrix_out(FLASH_SPIWP_IO, SPIWP_OUT_IDX, 0, 0); - gpio_matrix_in(FLASH_SPIWP_IO, SPIWP_IN_IDX, 0); - gpio_matrix_out(FLASH_SPIHD_IO, SPIHD_OUT_IDX, 0, 0); - gpio_matrix_in(FLASH_SPIHD_IO, SPIHD_IN_IDX, 0); - //select pin function gpio - PIN_FUNC_SELECT(PERIPHS_IO_MUX_SPIHD_U, PIN_FUNC_GPIO); - PIN_FUNC_SELECT(PERIPHS_IO_MUX_SPIWP_U, PIN_FUNC_GPIO); - PIN_FUNC_SELECT(PERIPHS_IO_MUX_SPICS0_U, PIN_FUNC_GPIO); - PIN_FUNC_SELECT(PERIPHS_IO_MUX_SPIQ_U, PIN_FUNC_GPIO); - PIN_FUNC_SELECT(PERIPHS_IO_MUX_SPID_U, PIN_FUNC_GPIO); - // flash clock signal should come from IO MUX. - // set drive ability for clock - PIN_FUNC_SELECT(PERIPHS_IO_MUX_SPICLK_U, FUNC_SPICLK_SPICLK); - SET_PERI_REG_BITS(PERIPHS_IO_MUX_SPICLK_U, FUN_DRV, drv, FUN_DRV_S); - -#if CONFIG_SPIRAM_TYPE_ESPPSRAM32 || CONFIG_SPIRAM_TYPE_ESPPSRAM64 - uint32_t flash_id = g_rom_flashchip.device_id; - if (flash_id == FLASH_ID_GD25LQ32C) { - // Set drive ability for 1.8v flash in 80Mhz. - SET_PERI_REG_BITS(PERIPHS_IO_MUX_SPIHD_U, FUN_DRV, 3, FUN_DRV_S); - SET_PERI_REG_BITS(PERIPHS_IO_MUX_SPIWP_U, FUN_DRV, 3, FUN_DRV_S); - SET_PERI_REG_BITS(PERIPHS_IO_MUX_SPICS0_U, FUN_DRV, 3, FUN_DRV_S); - SET_PERI_REG_BITS(PERIPHS_IO_MUX_SPICLK_U, FUN_DRV, 3, FUN_DRV_S); - SET_PERI_REG_BITS(PERIPHS_IO_MUX_SPIQ_U, FUN_DRV, 3, FUN_DRV_S); - SET_PERI_REG_BITS(PERIPHS_IO_MUX_SPID_U, FUN_DRV, 3, FUN_DRV_S); - } -#endif + uint8_t wp_pin = ets_efuse_get_wp_pad(); + uint8_t clk_gpio_num = SPI_CLK_GPIO_NUM; + uint8_t q_gpio_num = SPI_Q_GPIO_NUM; + uint8_t d_gpio_num = SPI_D_GPIO_NUM; + uint8_t cs0_gpio_num = SPI_CS0_GPIO_NUM; + uint8_t hd_gpio_num = SPI_HD_GPIO_NUM; + uint8_t wp_gpio_num = SPI_WP_GPIO_NUM; + if (spiconfig == 0) { + + } else { + clk_gpio_num = spiconfig & 0x3f; + q_gpio_num = (spiconfig >> 6) & 0x3f; + d_gpio_num = (spiconfig >> 12) & 0x3f; + cs0_gpio_num = (spiconfig >> 18) & 0x3f; + hd_gpio_num = (spiconfig >> 24) & 0x3f; + wp_gpio_num = wp_pin; + } + gpio_pad_set_drv(clk_gpio_num, drv); + gpio_pad_set_drv(q_gpio_num, drv); + gpio_pad_set_drv(d_gpio_num, drv); + gpio_pad_set_drv(cs0_gpio_num, drv); + if (hd_gpio_num <= MAX_PAD_GPIO_NUM) { + gpio_pad_set_drv(hd_gpio_num, drv); + } + if (wp_gpio_num <= MAX_PAD_GPIO_NUM) { + gpio_pad_set_drv(wp_gpio_num, drv); } } diff --git a/components/esp32s2beta/Kconfig b/components/esp32s2beta/Kconfig index a2e7d6f1f7..cc68c99058 100644 --- a/components/esp32s2beta/Kconfig +++ b/components/esp32s2beta/Kconfig @@ -152,6 +152,37 @@ menu "ESP32S2-specific" default 4194304 if SPIRAM_TYPE_ESPPSRAM32 default 8388608 if SPIRAM_TYPE_ESPPSRAM64 default 0 + menu "PSRAM clock and cs IO for ESP32S2" + depends on ESP32S2_SPIRAM_SUPPORT + config DEFAULT_PSRAM_CLK_IO + int "PSRAM CLK IO number" + range 0 33 + default 30 + help + The PSRAM CLOCK IO can be any unused GPIO, user can config it based on hardware design. + + config DEFAULT_PSRAM_CS_IO + int "PSRAM CS IO number" + range 0 33 + default 26 + help + The PSRAM CS IO can be any unused GPIO, user can config it based on hardware design. + endmenu + config SPIRAM_SPIWP_SD3_PIN + int "SPI PSRAM WP(SD3) Pin when customising pins via eFuse (read help)" + depends on ESPTOOLPY_FLASHMODE_DIO || ESPTOOLPY_FLASHMODE_DOUT + range 0 33 + default 28 + help + This value is ignored unless flash mode is set to DIO or DOUT and the SPI flash pins have been + overriden by setting the eFuses SPI_PAD_CONFIG_xxx. + + Different from esp32 chip, on esp32s2, the WP pin would also be defined in efuse. This value would only + be used if the WP pin recorded in efuse SPI_PAD_CONFIG_xxx is invalid. + + When flash mode is set to QIO or QOUT, the PSRAM WP pin will be set as the value configured in + bootloader. + config SPIRAM_FETCH_INSTRUCTIONS bool "Cache fetch instructions from SPI RAM" diff --git a/components/esp32s2beta/spiram_psram.c b/components/esp32s2beta/spiram_psram.c index 3c9a599f39..49501b094e 100644 --- a/components/esp32s2beta/spiram_psram.c +++ b/components/esp32s2beta/spiram_psram.c @@ -26,16 +26,23 @@ #include "spiram_psram.h" #include "esp32s2beta/rom/ets_sys.h" #include "esp32s2beta/rom/spi_flash.h" +#include "esp32s2beta/rom/opi_flash.h" #include "esp32s2beta/rom/gpio.h" #include "esp32s2beta/rom/cache.h" -#include "soc/io_mux_reg.h" +#include "esp32s2beta/rom/efuse.h" #include "soc/dport_reg.h" +#include "soc/efuse_periph.h" +#include "soc/spi_caps.h" +#include "soc/io_mux_reg.h" #include "soc/apb_ctrl_reg.h" #include "soc/gpio_sig_map.h" #include "soc/efuse_reg.h" +#include "soc/soc.h" #include "driver/gpio.h" +#include "driver/spi_common_internal.h" #include "driver/spi_common.h" #include "driver/periph_ctrl.h" +#include "bootloader_common.h" #if CONFIG_SPIRAM #include "soc/rtc.h" @@ -54,438 +61,228 @@ #define PSRAM_RESET 0x99 #define PSRAM_SET_BURST_LEN 0xC0 #define PSRAM_DEVICE_ID 0x9F - -typedef enum { - PSRAM_CLK_MODE_NORM = 0, /*!< Normal SPI mode */ - PSRAM_CLK_MODE_DCLK = 1, /*!< Two extra clock cycles after CS is set high level */ -} psram_clk_mode_t; - +// ID #define PSRAM_ID_KGD_M 0xff #define PSRAM_ID_KGD_S 8 #define PSRAM_ID_KGD 0x5d #define PSRAM_ID_EID_M 0xff #define PSRAM_ID_EID_S 16 -#define PSRAM_KGD(id) (((id) >> PSRAM_ID_KGD_S) & PSRAM_ID_KGD_M) -#define PSRAM_EID(id) (((id) >> PSRAM_ID_EID_S) & PSRAM_ID_EID_M) -#define PSRAM_IS_VALID(id) (PSRAM_KGD(id) == PSRAM_ID_KGD) +// Use the [7:5](bit7~bit5) of EID to distinguish the psram size: +// +// BIT7 | BIT6 | BIT5 | SIZE(MBIT) +// ------------------------------------- +// 0 | 0 | 0 | 16 +// 0 | 0 | 1 | 32 +// 0 | 1 | 0 | 64 +#define PSRAM_EID_SIZE_M 0x07 +#define PSRAM_EID_SIZE_S 5 -// PSRAM_EID = 0x26 or 0x4x ----> 64MBit psram -// PSRAM_EID = 0x20 ------------> 32MBit psram -#define PSRAM_IS_64MBIT(id) ((PSRAM_EID(id) == 0x26) || ((PSRAM_EID(id) & 0xf0) == 0x40)) +#define PSRAM_KGD(id) (((id) >> PSRAM_ID_KGD_S) & PSRAM_ID_KGD_M) +#define PSRAM_EID(id) (((id) >> PSRAM_ID_EID_S) & PSRAM_ID_EID_M) +#define PSRAM_SIZE_ID(id) ((PSRAM_EID(id) >> PSRAM_EID_SIZE_S) & PSRAM_EID_SIZE_M) +#define PSRAM_IS_VALID(id) (PSRAM_KGD(id) == PSRAM_ID_KGD) + +// For the old version 32Mbit psram, using the spicial driver */ #define PSRAM_IS_32MBIT_VER0(id) (PSRAM_EID(id) == 0x20) +#define PSRAM_IS_64MBIT_TRIAL(id) (PSRAM_EID(id) == 0x26) -// IO-pins for PSRAM. These need to be in the VDD_SIO power domain because all chips we -// currently support are 1.8V parts. +// IO-pins for PSRAM. // WARNING: PSRAM shares all but the CS and CLK pins with the flash, so these defines // hardcode the flash pins as well, making this code incompatible with either a setup // that has the flash on non-standard pins or ESP32s with built-in flash. -#define FLASH_CLK_IO SPI_CLK_GPIO_NUM //Psram clock is a delayed version of this in 40MHz mode -#define FLASH_CS_IO SPI_CS0_GPIO_NUM -#define PSRAM_CS_IO 26 -#define PSRAM_SPIQ_IO SPI_Q_GPIO_NUM -#define PSRAM_SPID_IO SPI_D_GPIO_NUM -#define PSRAM_SPIWP_IO SPI_WP_GPIO_NUM -#define PSRAM_SPIHD_IO SPI_HD_GPIO_NUM -#define PSRAM_INTERNAL_IO_28 28 -#define PSRAM_INTERNAL_IO_29 29 +#define FLASH_CLK_IO SPI_CLK_GPIO_NUM +#define FLASH_CS_IO SPI_CS0_GPIO_NUM +// PSRAM clock and cs IO should be configured based on hardware design. +#define PSRAM_CLK_IO CONFIG_DEFAULT_PSRAM_CLK_IO // Default value is 30 +#define PSRAM_CS_IO CONFIG_DEFAULT_PSRAM_CS_IO // Default value is 26 +#define PSRAM_SPIQ_SD0_IO SPI_Q_GPIO_NUM +#define PSRAM_SPID_SD1_IO SPI_D_GPIO_NUM +#define PSRAM_SPIWP_SD3_IO SPI_WP_GPIO_NUM +#define PSRAM_SPIHD_SD2_IO SPI_HD_GPIO_NUM + +#define CS_PSRAM_SEL SPI_MEM_CS1_DIS_M +#define CS_FLASH_SEL SPI_MEM_CS0_DIS_M + #define PSRAM_IO_MATRIX_DUMMY_20M 0 #define PSRAM_IO_MATRIX_DUMMY_40M 0 #define PSRAM_IO_MATRIX_DUMMY_80M 0 +#define _SPI_CACHE_PORT 0 +#define _SPI_FLASH_PORT 1 +#define _SPI_80M_CLK_DIV 1 +#define _SPI_40M_CLK_DIV 2 +#define _SPI_20M_CLK_DIV 4 -#define _SPI_CACHE_PORT 0 -#define _SPI_FLASH_PORT 1 -#define _SPI_80M_CLK_DIV 1 -#define _SPI_40M_CLK_DIV 2 -#define _SPI_20M_CLK_DIV 4 +typedef enum { + PSRAM_CLK_MODE_NORM = 0, /*!< Normal SPI mode */ + PSRAM_CLK_MODE_A1C, /*!< ONE extra clock cycles after CS is set high level */ + PSRAM_CLK_MODE_A2C, /*!< Two extra clock cycles after CS is set high level */ + PSRAM_CLK_MODE_ALON, /*!< clock always on */ + PSRAM_CLK_MODE_MAX, +} psram_clk_mode_t; -static const char* TAG = "psram"; + +typedef enum { + PSRAM_EID_SIZE_16MBITS = 0, + PSRAM_EID_SIZE_32MBITS = 1, + PSRAM_EID_SIZE_64MBITS = 2, +} psram_eid_size_t; + +typedef struct { + uint8_t flash_clk_io; + uint8_t flash_cs_io; + uint8_t psram_clk_io; + uint8_t psram_cs_io; + uint8_t psram_spiq_sd0_io; + uint8_t psram_spid_sd1_io; + uint8_t psram_spiwp_sd3_io; + uint8_t psram_spihd_sd2_io; +} psram_io_t; + +#define PSRAM_IO_CONF_DEFAULT() { \ + .flash_clk_io = FLASH_CLK_IO, \ + .flash_cs_io = FLASH_CS_IO, \ + .psram_clk_io = PSRAM_CLK_IO, \ + .psram_cs_io = PSRAM_CS_IO, \ + .psram_spiq_sd0_io = PSRAM_SPIQ_SD0_IO, \ + .psram_spid_sd1_io = PSRAM_SPID_SD1_IO, \ + .psram_spiwp_sd3_io = PSRAM_SPIWP_SD3_IO, \ + .psram_spihd_sd2_io = PSRAM_SPIHD_SD2_IO, \ +} + +//static const char* TAG = "psram"; typedef enum { PSRAM_SPI_1 = 0x1, - PSRAM_SPI_2, - PSRAM_SPI_3, + /* PSRAM_SPI_2, */ + /* PSRAM_SPI_3, */ PSRAM_SPI_MAX , } psram_spi_num_t; -static psram_cache_mode_t s_psram_mode = PSRAM_CACHE_MAX; -static psram_clk_mode_t s_clk_mode = PSRAM_CLK_MODE_DCLK; -static uint32_t s_psram_id = 0; - -/* dummy_len_plus values defined in ROM for SPI flash configuration */ -extern uint8_t g_rom_spiflash_dummy_len_plus[]; -static int extra_dummy = 0; typedef enum { PSRAM_CMD_QPI, PSRAM_CMD_SPI, } psram_cmd_mode_t; -typedef struct { - uint16_t cmd; /*!< Command value */ - uint16_t cmdBitLen; /*!< Command byte length*/ - uint32_t *addr; /*!< Point to address value*/ - uint16_t addrBitLen; /*!< Address byte length*/ - uint32_t *txData; /*!< Point to send data buffer*/ - uint16_t txDataBitLen; /*!< Send data byte length.*/ - uint32_t *rxData; /*!< Point to recevie data buffer*/ - uint16_t rxDataBitLen; /*!< Recevie Data byte length.*/ - uint32_t dummyBitLen; -} psram_cmd_t; +typedef esp_rom_spi_cmd_t psram_cmd_t; +static uint32_t s_psram_id = 0; static void IRAM_ATTR psram_cache_init(psram_cache_mode_t psram_cache_mode, psram_vaddr_mode_t vaddrmode); +extern void esp_rom_spi_set_op_mode(int spi_num, esp_rom_spiflash_read_mode_t mode); -static void psram_clear_spi_fifo(psram_spi_num_t spi_num) +static void psram_set_op_mode(int spi_num, psram_cmd_mode_t mode) { - int i; - for (i = 0; i < 16; i++) { - WRITE_PERI_REG(SPI_MEM_W0_REG(spi_num)+i*4, 0); + if (mode == PSRAM_CMD_QPI) { + esp_rom_spi_set_op_mode(spi_num, ESP_ROM_SPIFLASH_QIO_MODE); + SET_PERI_REG_MASK(SPI_MEM_CTRL_REG(spi_num), SPI_MEM_FCMD_QUAD_M); + } else if (mode == PSRAM_CMD_SPI) { + esp_rom_spi_set_op_mode(spi_num, ESP_ROM_SPIFLASH_SLOWRD_MODE); } } - -//set basic SPI write mode -static void psram_set_basic_write_mode(psram_spi_num_t spi_num) +static void _psram_exec_cmd(int spi_num, + uint32_t cmd, int cmd_bit_len, + uint32_t addr, int addr_bit_len, + int dummy_bits, + uint8_t* mosi_data, int mosi_bit_len, + uint8_t* miso_data, int miso_bit_len) { - CLEAR_PERI_REG_MASK(SPI_MEM_USER_REG(spi_num), SPI_MEM_FWRITE_QIO); - CLEAR_PERI_REG_MASK(SPI_MEM_CTRL_REG(spi_num), SPI_MEM_FCMD_QUAD_M); - CLEAR_PERI_REG_MASK(SPI_MEM_USER_REG(spi_num), SPI_MEM_FWRITE_DIO); - CLEAR_PERI_REG_MASK(SPI_MEM_USER_REG(spi_num), SPI_MEM_FWRITE_QUAD); - CLEAR_PERI_REG_MASK(SPI_MEM_USER_REG(spi_num), SPI_MEM_FWRITE_DUAL); + esp_rom_spi_cmd_t conf; + uint32_t _addr = addr; + conf.addr = &_addr; + conf.addrBitLen = addr_bit_len; + conf.cmd = cmd; + conf.cmdBitLen = cmd_bit_len; + conf.dummyBitLen = dummy_bits; // There is a hardware approach on chip723 + conf.txData = (uint32_t*) mosi_data; + conf.txDataBitLen = mosi_bit_len; + conf.rxData = (uint32_t*) miso_data; + conf.rxDataBitLen = miso_bit_len; + esp_rom_spi_cmd_config(spi_num, &conf); } -//set QPI write mode -static void psram_set_qio_write_mode(psram_spi_num_t spi_num) + +void psram_exec_cmd(int spi_num, psram_cmd_mode_t mode, + uint32_t cmd, int cmd_bit_len, + uint32_t addr, int addr_bit_len, + int dummy_bits, + uint8_t* mosi_data, int mosi_bit_len, + uint8_t* miso_data, int miso_bit_len, + uint32_t cs_mask, + bool is_write_erase_operation) { - SET_PERI_REG_MASK(SPI_MEM_USER_REG(spi_num), SPI_MEM_FWRITE_QIO); - SET_PERI_REG_MASK(SPI_MEM_CTRL_REG(spi_num), SPI_MEM_FCMD_QUAD_M); - CLEAR_PERI_REG_MASK(SPI_MEM_USER_REG(spi_num), SPI_MEM_FWRITE_DIO); - CLEAR_PERI_REG_MASK(SPI_MEM_USER_REG(spi_num), SPI_MEM_FWRITE_QUAD); - CLEAR_PERI_REG_MASK(SPI_MEM_USER_REG(spi_num), SPI_MEM_FWRITE_DUAL); -} -//set QPI read mode -static void psram_set_qio_read_mode(psram_spi_num_t spi_num) -{ - SET_PERI_REG_MASK(SPI_MEM_CTRL_REG(spi_num), SPI_MEM_FREAD_QIO); - SET_PERI_REG_MASK(SPI_MEM_CTRL_REG(spi_num), SPI_MEM_FCMD_QUAD_M); - CLEAR_PERI_REG_MASK(SPI_MEM_CTRL_REG(spi_num), SPI_MEM_FREAD_QUAD); - CLEAR_PERI_REG_MASK(SPI_MEM_CTRL_REG(spi_num), SPI_MEM_FREAD_DUAL); - CLEAR_PERI_REG_MASK(SPI_MEM_CTRL_REG(spi_num), SPI_MEM_FREAD_DIO); -} -//set SPI read mode -static void psram_set_basic_read_mode(psram_spi_num_t spi_num) -{ - CLEAR_PERI_REG_MASK(SPI_MEM_CTRL_REG(spi_num), SPI_MEM_FREAD_QIO); - CLEAR_PERI_REG_MASK(SPI_MEM_CTRL_REG(spi_num), SPI_MEM_FCMD_QUAD_M); - CLEAR_PERI_REG_MASK(SPI_MEM_CTRL_REG(spi_num), SPI_MEM_FREAD_QUAD); - CLEAR_PERI_REG_MASK(SPI_MEM_CTRL_REG(spi_num), SPI_MEM_FREAD_DUAL); - CLEAR_PERI_REG_MASK(SPI_MEM_CTRL_REG(spi_num), SPI_MEM_FREAD_DIO); + uint32_t backup_usr = READ_PERI_REG(SPI_MEM_USER_REG(spi_num)); + uint32_t backup_usr1 = READ_PERI_REG(SPI_MEM_USER1_REG(spi_num)); + uint32_t backup_usr2 = READ_PERI_REG(SPI_MEM_USER2_REG(spi_num)); + uint32_t backup_ctrl = READ_PERI_REG(SPI_MEM_CTRL_REG(spi_num)); + psram_set_op_mode(spi_num, mode); + _psram_exec_cmd(spi_num, cmd, cmd_bit_len, addr, addr_bit_len, + dummy_bits, mosi_data, mosi_bit_len, miso_data, miso_bit_len); + esp_rom_spi_cmd_start(spi_num, miso_data, miso_bit_len / 8, cs_mask, is_write_erase_operation); + + WRITE_PERI_REG(SPI_MEM_USER_REG(spi_num), backup_usr); + WRITE_PERI_REG(SPI_MEM_USER1_REG(spi_num), backup_usr1); + WRITE_PERI_REG(SPI_MEM_USER2_REG(spi_num), backup_usr2); + WRITE_PERI_REG(SPI_MEM_CTRL_REG(spi_num), backup_ctrl); } - -//start sending cmd/addr and optionally, receiving data -static void IRAM_ATTR psram_cmd_recv_start(psram_spi_num_t spi_num, uint32_t* pRxData, uint16_t rxByteLen, - psram_cmd_mode_t cmd_mode) -{ - //get cs1 - CLEAR_PERI_REG_MASK(SPI_MEM_MISC_REG(PSRAM_SPI_1), SPI_MEM_CS1_DIS_M); - SET_PERI_REG_MASK(SPI_MEM_MISC_REG(PSRAM_SPI_1), SPI_MEM_CS0_DIS_M); - - uint32_t mode_backup = (READ_PERI_REG(SPI_MEM_USER_REG(spi_num)) >> SPI_MEM_FWRITE_DUAL_S) & 0xf; -#ifdef FAKE_QPI - uint32_t rd_mode_backup = READ_PERI_REG(SPI_MEM_CTRL_REG(spi_num)) & (SPI_MEM_FREAD_DIO_M | SPI_MEM_FREAD_DUAL_M | SPI_MEM_FREAD_QUAD_M | SPI_MEM_FREAD_QIO_M); -#else - uint32_t rd_mode_backup = READ_PERI_REG(SPI_MEM_CTRL_REG(spi_num)) & (SPI_MEM_FREAD_DIO_M | SPI_MEM_FREAD_DUAL_M | SPI_MEM_FREAD_QUAD_M | SPI_MEM_FREAD_QIO_M | SPI_MEM_FCMD_QUAD); -#endif - if (cmd_mode == PSRAM_CMD_SPI) { - psram_set_basic_write_mode(spi_num); - psram_set_basic_read_mode(spi_num); - } else if (cmd_mode == PSRAM_CMD_QPI) { - psram_set_qio_write_mode(spi_num); - psram_set_qio_read_mode(spi_num); - } - - // Start send data - SET_PERI_REG_MASK(SPI_MEM_CMD_REG(spi_num), SPI_MEM_USR); - while ((READ_PERI_REG(SPI_MEM_CMD_REG(spi_num)) & SPI_MEM_USR)); - - //recover spi mode - SET_PERI_REG_BITS(SPI_MEM_USER_REG(spi_num), (pRxData?SPI_MEM_FWRITE_DUAL_M:0xf), mode_backup, SPI_MEM_FWRITE_DUAL_S); -#ifdef FAKE_QPI - CLEAR_PERI_REG_MASK(SPI_MEM_CTRL_REG(spi_num), (SPI_MEM_FREAD_DIO_M|SPI_MEM_FREAD_DUAL_M|SPI_MEM_FREAD_QUAD_M|SPI_MEM_FREAD_QIO_M)); -#else - CLEAR_PERI_REG_MASK(SPI_MEM_CTRL_REG(spi_num), (SPI_MEM_FREAD_DIO_M|SPI_MEM_FREAD_DUAL_M|SPI_MEM_FREAD_QUAD_M|SPI_MEM_FREAD_QIO_M|SPI_MEM_FCMD_QUAD)); -#endif - SET_PERI_REG_MASK(SPI_MEM_CTRL_REG(spi_num), rd_mode_backup); - - //return cs to cs0 - SET_PERI_REG_MASK(SPI_MEM_MISC_REG(PSRAM_SPI_1), SPI_MEM_CS1_DIS_M); - CLEAR_PERI_REG_MASK(SPI_MEM_MISC_REG(PSRAM_SPI_1), SPI_MEM_CS0_DIS_M); - - if (pRxData) { - int idx = 0; - // Read data out - do { - *pRxData++ = READ_PERI_REG(SPI_MEM_W0_REG(spi_num) + (idx << 2)); - } while (++idx < ((rxByteLen / 4) + ((rxByteLen % 4) ? 1 : 0))); - } -} - -static uint32_t backup_usr[3]; -static uint32_t backup_usr1[3]; -static uint32_t backup_usr2[3]; - - - -//setup spi command/addr/data/dummy in user mode -static int psram_cmd_config(psram_spi_num_t spi_num, psram_cmd_t* pInData) -{ - while (READ_PERI_REG(SPI_MEM_CMD_REG(spi_num)) & SPI_MEM_USR); - backup_usr[spi_num]=READ_PERI_REG(SPI_MEM_USER_REG(spi_num)); - backup_usr1[spi_num]=READ_PERI_REG(SPI_MEM_USER1_REG(spi_num)); - backup_usr2[spi_num]=READ_PERI_REG(SPI_MEM_USER2_REG(spi_num)); - // Set command by user. - if (pInData->cmdBitLen != 0) { - // Max command length 16 bits. - SET_PERI_REG_BITS(SPI_MEM_USER2_REG(spi_num), SPI_MEM_USR_COMMAND_BITLEN, pInData->cmdBitLen - 1, - SPI_MEM_USR_COMMAND_BITLEN_S); - // Enable command - SET_PERI_REG_MASK(SPI_MEM_USER_REG(spi_num), SPI_MEM_USR_COMMAND); - // Load command,bit15-0 is cmd value. - SET_PERI_REG_BITS(SPI_MEM_USER2_REG(spi_num), SPI_MEM_USR_COMMAND_VALUE, pInData->cmd, SPI_MEM_USR_COMMAND_VALUE_S); - } else { - CLEAR_PERI_REG_MASK(SPI_MEM_USER_REG(spi_num), SPI_MEM_USR_COMMAND); - SET_PERI_REG_BITS(SPI_MEM_USER2_REG(spi_num), SPI_MEM_USR_COMMAND_BITLEN, 0, SPI_MEM_USR_COMMAND_BITLEN_S); - } - // Set Address by user. - if (pInData->addrBitLen != 0) { - SET_PERI_REG_BITS(SPI_MEM_USER1_REG(spi_num), SPI_MEM_USR_ADDR_BITLEN, (pInData->addrBitLen - 1), SPI_MEM_USR_ADDR_BITLEN_S); - // Enable address - SET_PERI_REG_MASK(SPI_MEM_USER_REG(spi_num), SPI_MEM_USR_ADDR); - // Set address - WRITE_PERI_REG(SPI_MEM_ADDR_REG(spi_num), *pInData->addr); - } else { - CLEAR_PERI_REG_MASK(SPI_MEM_USER_REG(spi_num), SPI_MEM_USR_ADDR); - SET_PERI_REG_BITS(SPI_MEM_USER1_REG(spi_num), SPI_MEM_USR_ADDR_BITLEN, 0, SPI_MEM_USR_ADDR_BITLEN_S); - } - // Set data by user. - uint32_t* p_tx_val = pInData->txData; - if (pInData->txDataBitLen != 0) { - // Enable MOSI - SET_PERI_REG_MASK(SPI_MEM_USER_REG(spi_num), SPI_MEM_USR_MOSI); - // Load send buffer - int len = (pInData->txDataBitLen + 31) / 32; - if (p_tx_val != NULL) { - memcpy((void*)SPI_MEM_W0_REG(spi_num), p_tx_val, len * 4); - } - // Set data send buffer length.Max data length 64 bytes. - SET_PERI_REG_BITS(SPI_MEM_MOSI_DLEN_REG(spi_num), SPI_MEM_USR_MOSI_DBITLEN, (pInData->txDataBitLen - 1), - SPI_MEM_USR_MOSI_DBITLEN_S); - } else { - CLEAR_PERI_REG_MASK(SPI_MEM_USER_REG(spi_num), SPI_MEM_USR_MOSI); - SET_PERI_REG_BITS(SPI_MEM_MOSI_DLEN_REG(spi_num), SPI_MEM_USR_MOSI_DBITLEN, 0, SPI_MEM_USR_MOSI_DBITLEN_S); - } - // Set rx data by user. - if (pInData->rxDataBitLen != 0) { - // Enable MOSI - SET_PERI_REG_MASK(SPI_MEM_USER_REG(spi_num), SPI_MEM_USR_MISO); - // Set data send buffer length.Max data length 64 bytes. - SET_PERI_REG_BITS(SPI_MEM_MISO_DLEN_REG(spi_num), SPI_MEM_USR_MISO_DBITLEN, (pInData->rxDataBitLen - 1), - SPI_MEM_USR_MISO_DBITLEN_S); - } else { - CLEAR_PERI_REG_MASK(SPI_MEM_USER_REG(spi_num), SPI_MEM_USR_MISO); - SET_PERI_REG_BITS(SPI_MEM_MISO_DLEN_REG(spi_num), SPI_MEM_USR_MISO_DBITLEN, 0, SPI_MEM_USR_MISO_DBITLEN_S); - } - if (pInData->dummyBitLen != 0) { - SET_PERI_REG_MASK(SPI_MEM_USER_REG(PSRAM_SPI_1), SPI_MEM_USR_DUMMY); // dummy en - SET_PERI_REG_BITS(SPI_MEM_USER1_REG(PSRAM_SPI_1), SPI_MEM_USR_DUMMY_CYCLELEN_V, pInData->dummyBitLen - 1, - SPI_MEM_USR_DUMMY_CYCLELEN_S); //DUMMY - } else { - CLEAR_PERI_REG_MASK(SPI_MEM_USER_REG(PSRAM_SPI_1), SPI_MEM_USR_DUMMY); // dummy en - SET_PERI_REG_BITS(SPI_MEM_USER1_REG(PSRAM_SPI_1), SPI_MEM_USR_DUMMY_CYCLELEN_V, 0, SPI_MEM_USR_DUMMY_CYCLELEN_S); //DUMMY - } - return 0; -} - -void psram_cmd_end(int spi_num) { - while (READ_PERI_REG(SPI_MEM_CMD_REG(spi_num)) & SPI_MEM_USR); - WRITE_PERI_REG(SPI_MEM_USER_REG(spi_num), backup_usr[spi_num]); - WRITE_PERI_REG(SPI_MEM_USER1_REG(spi_num), backup_usr1[spi_num]); - WRITE_PERI_REG(SPI_MEM_USER2_REG(spi_num), backup_usr2[spi_num]); -} - -#ifdef FAKE_QPI //exit QPI mode(set back to SPI mode) -static void psram_disable_qio_mode(psram_spi_num_t spi_num) +static void psram_disable_qio_mode(int spi_num) { - psram_cmd_t ps_cmd; - uint32_t cmd_exit_qpi; - cmd_exit_qpi = PSRAM_EXIT_QMODE; - ps_cmd.txDataBitLen = 8; - if (s_clk_mode == PSRAM_CLK_MODE_DCLK) { - switch (s_psram_mode) { - case PSRAM_CACHE_S80M: - break; - case PSRAM_CACHE_S40M: - default: - cmd_exit_qpi = PSRAM_EXIT_QMODE << 8; - ps_cmd.txDataBitLen = 16; - break; - } - } - ps_cmd.txData = &cmd_exit_qpi; - ps_cmd.cmd = 0; - ps_cmd.cmdBitLen = 0; - ps_cmd.addr = 0; - ps_cmd.addrBitLen = 0; - ps_cmd.rxData = NULL; - ps_cmd.rxDataBitLen = 0; - ps_cmd.dummyBitLen = 0; - psram_cmd_config(spi_num, &ps_cmd); - psram_cmd_recv_start(spi_num, NULL, 0, PSRAM_CMD_QPI); - psram_cmd_end(spi_num); + psram_exec_cmd(spi_num, PSRAM_CMD_QPI, + PSRAM_EXIT_QMODE, 8, /* command and command bit len*/ + 0, 0, /* address and address bit len*/ + 0, /* dummy bit len */ + NULL, 0, /* tx data and tx bit len*/ + NULL, 0, /* rx data and rx bit len*/ + CS_PSRAM_SEL, /* cs bit mask*/ + false); /* whether is program/erase operation */ } -//read psram id -static void psram_read_id(uint32_t* dev_id) -{ - psram_spi_num_t spi_num = PSRAM_SPI_1; - psram_disable_qio_mode(spi_num); - uint32_t dummy_bits = 0 + extra_dummy; - psram_cmd_t ps_cmd; - - uint32_t addr = 0; - ps_cmd.addrBitLen = 3 * 8; - ps_cmd.cmd = PSRAM_DEVICE_ID; - ps_cmd.cmdBitLen = 8; - if (s_clk_mode == PSRAM_CLK_MODE_DCLK) { - switch (s_psram_mode) { - case PSRAM_CACHE_S80M: - break; - case PSRAM_CACHE_S40M: - default: - ps_cmd.cmdBitLen = 2; //this two bits is used to delay 2 clock cycle - ps_cmd.cmd = 0; - addr = (PSRAM_DEVICE_ID << 24) | 0; - ps_cmd.addrBitLen = 4 * 8; - break; - } - } - ps_cmd.addr = &addr; - ps_cmd.txDataBitLen = 0; - ps_cmd.txData = NULL; - ps_cmd.rxDataBitLen = 4 * 8; - ps_cmd.rxData = dev_id; - ps_cmd.dummyBitLen = dummy_bits; - - psram_cmd_config(spi_num, &ps_cmd); - psram_clear_spi_fifo(spi_num); - psram_cmd_recv_start(spi_num, ps_cmd.rxData, ps_cmd.rxDataBitLen / 8, PSRAM_CMD_SPI); - psram_cmd_end(spi_num); -} - -//enter QPI mode -static esp_err_t IRAM_ATTR psram_enable_qio_mode(psram_spi_num_t spi_num) -{ - psram_cmd_t ps_cmd; - uint32_t addr = (PSRAM_ENTER_QMODE << 24) | 0; - - ps_cmd.cmdBitLen = 0; - if (s_clk_mode == PSRAM_CLK_MODE_DCLK) { - switch (s_psram_mode) { - case PSRAM_CACHE_S80M: - break; - case PSRAM_CACHE_S40M: - default: - ps_cmd.cmdBitLen = 2; - break; - } - } - ps_cmd.cmd = 0; - ps_cmd.addr = &addr; - ps_cmd.addrBitLen = 8; - ps_cmd.txData = NULL; - ps_cmd.txDataBitLen = 0; - ps_cmd.rxData = NULL; - ps_cmd.rxDataBitLen = 0; - ps_cmd.dummyBitLen = 0; - psram_cmd_config(spi_num, &ps_cmd); - psram_cmd_recv_start(spi_num, NULL, 0, PSRAM_CMD_SPI); - psram_cmd_end(spi_num); - return ESP_OK; -} -#else /* FAKE_QPI */ -//exit QPI mode(set back to SPI mode) -static void psram_disable_qio_mode(psram_spi_num_t spi_num) -{ - psram_cmd_t ps_cmd; - ps_cmd.txData = NULL; - ps_cmd.txDataBitLen = 0; - ps_cmd.cmd = PSRAM_EXIT_QMODE; - ps_cmd.cmdBitLen = 8; - ps_cmd.addr = 0; - ps_cmd.addrBitLen = 0; - ps_cmd.rxData = NULL; - ps_cmd.rxDataBitLen = 0; - ps_cmd.dummyBitLen = 0; - psram_cmd_config(spi_num, &ps_cmd); - psram_cmd_recv_start(spi_num, NULL, 0, PSRAM_CMD_QPI); - psram_cmd_end(spi_num); -} - - //switch psram burst length(32 bytes or 1024 bytes) //datasheet says it should be 1024 bytes by default -static void psram_set_wrap_burst_length(psram_spi_num_t spi_num, psram_cmd_mode_t mode) +static void psram_set_wrap_burst_length(int spi_num, psram_cmd_mode_t mode) { - psram_cmd_t ps_cmd; - ps_cmd.cmd = 0xC0; - ps_cmd.cmdBitLen = 8; - ps_cmd.addr = 0; - ps_cmd.addrBitLen = 0; - ps_cmd.txData = NULL; - ps_cmd.txDataBitLen = 0; - ps_cmd.rxData = NULL; - ps_cmd.rxDataBitLen = 0; - ps_cmd.dummyBitLen = 0; - psram_cmd_config(spi_num, &ps_cmd); - psram_cmd_recv_start(spi_num, NULL, 0, mode); - psram_cmd_end(spi_num); + psram_exec_cmd(spi_num, mode, + PSRAM_SET_BURST_LEN, 8, /* command and command bit len*/ + 0, 0, /* address and address bit len*/ + 0, /* dummy bit len */ + NULL, 0, /* tx data and tx bit len*/ + NULL, 0, /* rx data and rx bit len*/ + CS_PSRAM_SEL, /* cs bit mask*/ + false); /* whether is program/erase operation */ } //send reset command to psram, in spi mode -static void psram_reset_mode(psram_spi_num_t spi_num) +static void psram_reset_mode(int spi_num) { - psram_cmd_t ps_cmd; - ps_cmd.txData = NULL; - ps_cmd.txDataBitLen = 0; - ps_cmd.addr = NULL; - ps_cmd.addrBitLen = 0; - ps_cmd.cmd = PSRAM_RESET_EN; - ps_cmd.cmdBitLen = 8; - ps_cmd.rxData = NULL; - ps_cmd.rxDataBitLen = 0; - ps_cmd.dummyBitLen = 0; - psram_cmd_config(spi_num, &ps_cmd); - psram_cmd_recv_start(spi_num, NULL, 0, PSRAM_CMD_SPI); - psram_cmd_end(spi_num); + psram_exec_cmd(spi_num, PSRAM_CMD_SPI, + PSRAM_RESET_EN, 8, /* command and command bit len*/ + 0, 0, /* address and address bit len*/ + 0, /* dummy bit len */ + NULL, 0, /* tx data and tx bit len*/ + NULL, 0, /* rx data and rx bit len*/ + CS_PSRAM_SEL, /* cs bit mask*/ + false); /* whether is program/erase operation */ - memset(&ps_cmd, 0, sizeof(ps_cmd)); - ps_cmd.txData = NULL; - ps_cmd.txDataBitLen = 0; - ps_cmd.addr = NULL; - ps_cmd.addrBitLen = 0; - ps_cmd.cmd = PSRAM_RESET; - ps_cmd.cmdBitLen = 8; - ps_cmd.rxData = NULL; - ps_cmd.rxDataBitLen = 0; - ps_cmd.dummyBitLen = 0; - psram_cmd_config(spi_num, &ps_cmd); - psram_cmd_recv_start(spi_num, NULL, 0, PSRAM_CMD_SPI); - psram_cmd_end(spi_num); + psram_exec_cmd(spi_num, PSRAM_CMD_SPI, + PSRAM_RESET, 8, /* command and command bit len*/ + 0, 0, /* address and address bit len*/ + 0, /* dummy bit len */ + NULL, 0, /* tx data and tx bit len*/ + NULL, 0, /* rx data and rx bit len*/ + CS_PSRAM_SEL, /* cs bit mask*/ + false); /* whether is program/erase operation */ } esp_err_t psram_enable_wrap(uint32_t wrap_size) { + static int current_wrap_size = 0; + if (current_wrap_size == wrap_size) { + return ESP_OK; + } switch (wrap_size) { case 32: + case 0: psram_set_wrap_burst_length(PSRAM_SPI_1, PSRAM_CMD_QPI); + current_wrap_size = wrap_size; return ESP_OK; case 16: case 64: @@ -508,275 +305,173 @@ bool psram_support_wrap_size(uint32_t wrap_size) } +//read psram id static void psram_read_id(uint32_t* dev_id) { - psram_spi_num_t spi_num = PSRAM_SPI_1; + int spi_num = PSRAM_SPI_1; psram_disable_qio_mode(spi_num); - uint32_t dummy_bits = 0; - uint32_t addr = 0; - psram_cmd_t ps_cmd; - switch (s_psram_mode) { - case PSRAM_CACHE_S80M: - dummy_bits = 0 + extra_dummy; - break; - case PSRAM_CACHE_S40M: - case PSRAM_CACHE_S26M: - case PSRAM_CACHE_S20M: - default: - dummy_bits = 0 + extra_dummy; - break; - } - ps_cmd.cmd = PSRAM_DEVICE_ID; - ps_cmd.cmdBitLen = 8; - ps_cmd.addr = &addr; - ps_cmd.addrBitLen = 24; - ps_cmd.txDataBitLen = 0; - ps_cmd.txData = NULL; - ps_cmd.rxDataBitLen = 3 * 8; - ps_cmd.rxData = dev_id; - ps_cmd.dummyBitLen = dummy_bits; - psram_cmd_config(spi_num, &ps_cmd); - psram_clear_spi_fifo(spi_num); - psram_cmd_recv_start(spi_num, ps_cmd.rxData, ps_cmd.rxDataBitLen / 8, PSRAM_CMD_SPI); - psram_cmd_end(spi_num); + psram_exec_cmd(spi_num, PSRAM_CMD_SPI, + PSRAM_DEVICE_ID, 8, /* command and command bit len*/ + 0, 24, /* address and address bit len*/ + 0, /* dummy bit len */ + NULL, 0, /* tx data and tx bit len*/ + (uint8_t*) dev_id, 24, /* rx data and rx bit len*/ + CS_PSRAM_SEL, /* cs bit mask*/ + false); /* whether is program/erase operation */ } //enter QPI mode -static esp_err_t IRAM_ATTR psram_enable_qio_mode(psram_spi_num_t spi_num) +static void IRAM_ATTR psram_enable_qio_mode(int spi_num) { - psram_cmd_t ps_cmd; - ps_cmd.cmd = PSRAM_ENTER_QMODE; - ps_cmd.cmdBitLen = 8; //this two bits is used to delay 2 clock cycle - ps_cmd.addr = NULL; - ps_cmd.addrBitLen = 0; - ps_cmd.txData = NULL; - ps_cmd.txDataBitLen = 0; - ps_cmd.rxData = NULL; - ps_cmd.rxDataBitLen = 0; - ps_cmd.dummyBitLen = 0; - psram_cmd_config(spi_num, &ps_cmd); - psram_cmd_recv_start(spi_num, NULL, 0, PSRAM_CMD_SPI); - psram_cmd_end(spi_num); - return ESP_OK; + psram_exec_cmd(spi_num, PSRAM_CMD_SPI, + PSRAM_ENTER_QMODE, 8, /* command and command bit len*/ + 0, 0, /* address and address bit len*/ + 0, /* dummy bit len */ + NULL, 0, /* tx data and tx bit len*/ + NULL, 0, /* rx data and rx bit len*/ + CS_PSRAM_SEL, /* cs bit mask*/ + false); /* whether is program/erase operation */ } -#endif /* FAKE_QPI */ -//spi param init for psram -void IRAM_ATTR psram_spi_init(psram_spi_num_t spi_num, psram_cache_mode_t mode) +static void psram_set_spi1_cmd_cs_timing(psram_clk_mode_t clk_mode) { - uint8_t k; - SET_PERI_REG_MASK(SPI_MEM_USER_REG(spi_num), SPI_MEM_CS_SETUP); -#warning "psram_spi_init: part of configuration missing for esp32s2beta" -#if 0 - // SPI_CPOL & SPI_CPHA - CLEAR_PERI_REG_MASK(SPI_MEM_MISC_REG(spi_num), SPI_MEM_CK_IDLE_EDGE); - CLEAR_PERI_REG_MASK(SPI_MEM_USER_REG(spi_num), SPI_MEM_CK_OUT_EDGE); - // SPI bit order - CLEAR_PERI_REG_MASK(SPI_MEM_CTRL_REG(spi_num), SPI_MEM_WR_BIT_ORDER); - CLEAR_PERI_REG_MASK(SPI_MEM_CTRL_REG(spi_num), SPI_MEM_RD_BIT_ORDER); - // SPI bit order - CLEAR_PERI_REG_MASK(SPI_MEM_USER_REG(spi_num), SPI_MEM_DOUTDIN); -#endif - // May be not must to do. - WRITE_PERI_REG(SPI_MEM_USER1_REG(spi_num), 0); -#if 0 - // SPI mode type - CLEAR_PERI_REG_MASK(SPI_MEM_SLAVE_REG(spi_num), SPI_MEM_SLAVE_MODE); -#endif - // Set SPI speed for non-80M mode. (80M mode uses APB clock directly.) - if (mode!=PSRAM_CACHE_S80M) { - k = 2; //Main divider. Divide by 2 so we get 40MHz - //clear bit 31, set SPI clock div - CLEAR_PERI_REG_MASK(SPI_MEM_CLOCK_REG(spi_num), SPI_MEM_CLK_EQU_SYSCLK); - WRITE_PERI_REG(SPI_MEM_CLOCK_REG(spi_num), - (((k - 1) & SPI_MEM_CLKCNT_N) << SPI_MEM_CLKCNT_N_S) | - ((((k + 1) / 2 - 1) & SPI_MEM_CLKCNT_H) << SPI_MEM_CLKCNT_H_S) | //50% duty cycle - (((k - 1) & SPI_MEM_CLKCNT_L) << SPI_MEM_CLKCNT_L_S)); + if (clk_mode == PSRAM_CLK_MODE_NORM) { + // SPI1 Flash Operation port + SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(_SPI_FLASH_PORT), SPI_MEM_CS_HOLD_TIME_V, 1, SPI_MEM_CS_HOLD_TIME_S); + SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(_SPI_FLASH_PORT), SPI_MEM_CS_SETUP_TIME_V, 0, SPI_MEM_CS_SETUP_TIME_S); + SET_PERI_REG_MASK(SPI_MEM_USER_REG(_SPI_FLASH_PORT), SPI_MEM_CS_HOLD_M | SPI_MEM_CS_SETUP_M); + } else { + SET_PERI_REG_MASK(SPI_MEM_USER_REG(_SPI_FLASH_PORT), SPI_MEM_CS_HOLD_M | SPI_MEM_CS_SETUP_M); + } +} + +static void psram_set_spi0_cache_cs_timing(psram_clk_mode_t clk_mode) +{ + if (clk_mode == PSRAM_CLK_MODE_NORM) { + // SPI0 SRAM Cache port + SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_AC_REG(_SPI_CACHE_PORT), SPI_MEM_SPI_SMEM_CS_HOLD_TIME_V, 1, SPI_MEM_SPI_SMEM_CS_HOLD_TIME_S); + SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_AC_REG(_SPI_CACHE_PORT), SPI_MEM_SPI_SMEM_CS_SETUP_TIME_V, 0, SPI_MEM_SPI_SMEM_CS_SETUP_TIME_S); + SET_PERI_REG_MASK(SPI_MEM_SPI_SMEM_AC_REG(_SPI_CACHE_PORT), SPI_MEM_SPI_SMEM_CS_HOLD_M | SPI_MEM_SPI_SMEM_CS_SETUP_M); + // SPI0 Flash Cache port + SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(_SPI_CACHE_PORT), SPI_MEM_CS_HOLD_TIME_V, 0, SPI_MEM_CS_HOLD_TIME_S); + SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(_SPI_CACHE_PORT), SPI_MEM_CS_SETUP_TIME_V, 0, SPI_MEM_CS_SETUP_TIME_S); + SET_PERI_REG_MASK(SPI_MEM_USER_REG(_SPI_CACHE_PORT), SPI_MEM_CS_HOLD_M | SPI_MEM_CS_SETUP_M); + } else { + CLEAR_PERI_REG_MASK(SPI_MEM_USER_REG(_SPI_CACHE_PORT), SPI_CS_HOLD_M | SPI_CS_SETUP_M); + } +} + +//psram gpio init , different working frequency we have different solutions +static void IRAM_ATTR psram_gpio_config(psram_cache_mode_t mode) +{ + psram_io_t psram_io = PSRAM_IO_CONF_DEFAULT(); + const uint32_t spiconfig = ets_efuse_get_spiconfig(); + if (spiconfig == EFUSE_SPICONFIG_SPI_DEFAULTS) { + /* FLASH pins(except wp / hd) are all configured via IO_MUX in rom. */ + } else { + // FLASH pins are all configured via GPIO matrix in ROM. + psram_io.flash_clk_io = EFUSE_SPICONFIG_RET_SPICLK(spiconfig); + psram_io.flash_cs_io = EFUSE_SPICONFIG_RET_SPICS0(spiconfig); + psram_io.psram_spiq_sd0_io = EFUSE_SPICONFIG_RET_SPIQ(spiconfig); + psram_io.psram_spid_sd1_io = EFUSE_SPICONFIG_RET_SPID(spiconfig); + psram_io.psram_spihd_sd2_io = EFUSE_SPICONFIG_RET_SPIHD(spiconfig); + psram_io.psram_spiwp_sd3_io = ets_efuse_get_wp_pad(); + } + + #if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_FLASHMODE_QOUT + // WP/HD already configured in bootloader. + psram_io.psram_spiwp_sd3_io = (psram_io.psram_spiwp_sd3_io <= MAX_PAD_GPIO_NUM ? psram_io.psram_spiwp_sd3_io : CONFIG_BOOTLOADER_SPI_WP_PIN); + #else + + psram_io.psram_spiwp_sd3_io = (psram_io.psram_spiwp_sd3_io <= MAX_PAD_GPIO_NUM ? psram_io.psram_spiwp_sd3_io : CONFIG_SPIRAM_SPIWP_SD3_PIN); + esp_rom_spiflash_select_qio_pins(psram_io.psram_spiwp_sd3_io, spiconfig); + #endif +} + +psram_size_t psram_get_size(void) +{ + if ((PSRAM_SIZE_ID(s_psram_id) == PSRAM_EID_SIZE_64MBITS) || PSRAM_IS_64MBIT_TRIAL(s_psram_id)) { + return PSRAM_SIZE_64MBITS; + } else if (PSRAM_SIZE_ID(s_psram_id) == PSRAM_EID_SIZE_32MBITS) { + return PSRAM_SIZE_32MBITS; + } else if (PSRAM_SIZE_ID(s_psram_id) == PSRAM_EID_SIZE_16MBITS) { + return PSRAM_SIZE_16MBITS; + } else { + return PSRAM_SIZE_MAX; + } + return PSRAM_SIZE_MAX; +} + +//used in UT only +bool psram_is_32mbit_ver0(void) +{ + return PSRAM_IS_32MBIT_VER0(s_psram_id); +} + +static void psram_set_clk_mode(int spi_num, psram_clk_mode_t clk_mode) +{ + if (spi_num == _SPI_CACHE_PORT) { + REG_SET_FIELD(SPI_MEM_SRAM_CMD_REG(0), SPI_MEM_SCLK_MODE, clk_mode); + } else if (spi_num == _SPI_FLASH_PORT) { + REG_SET_FIELD(SPI_MEM_CTRL1_REG(1), SPI_MEM_CLK_MODE, clk_mode); } - // Enable MOSI - SET_PERI_REG_MASK(SPI_MEM_USER_REG(spi_num), SPI_MEM_CS_SETUP | SPI_MEM_CS_HOLD | SPI_MEM_USR_MOSI); - memset((void*)SPI_MEM_W0_REG(spi_num), 0, 16 * 4); } /* * Psram mode init will overwrite original flash speed mode, so that it is possible to change psram and flash speed after OTA. * Flash read mode(QIO/QOUT/DIO/DOUT) will not be changed in app bin. It is decided by bootloader, OTA can not change this mode. */ -static void IRAM_ATTR psram_gpio_config(psram_cache_mode_t mode) -{ - int spi_cache_dummy = 0; - uint32_t rd_mode_reg = READ_PERI_REG(SPI_MEM_CTRL_REG(0)); - if (rd_mode_reg & (SPI_MEM_FREAD_QIO_M | SPI_MEM_FREAD_DIO_M)) { - spi_cache_dummy = SPI0_R_QIO_DUMMY_CYCLELEN; - } else if (rd_mode_reg & (SPI_MEM_FREAD_QUAD_M | SPI_MEM_FREAD_DUAL_M)) { - spi_cache_dummy = SPI0_R_FAST_DUMMY_CYCLELEN; - } else { - spi_cache_dummy = SPI0_R_FAST_DUMMY_CYCLELEN; - } - // In bootloader, all the signals are already configured, - // We keep the following code in case the bootloader is some older version. - gpio_matrix_out(FLASH_CS_IO, SPICS0_OUT_IDX, 0, 0); - gpio_matrix_out(PSRAM_SPIQ_IO, SPIQ_OUT_IDX, 0, 0); - gpio_matrix_in(PSRAM_SPIQ_IO, SPIQ_IN_IDX, 0); - gpio_matrix_out(PSRAM_SPID_IO, SPID_OUT_IDX, 0, 0); - gpio_matrix_in(PSRAM_SPID_IO, SPID_IN_IDX, 0); - gpio_matrix_out(PSRAM_SPIWP_IO, SPIWP_OUT_IDX, 0, 0); - gpio_matrix_in(PSRAM_SPIWP_IO, SPIWP_IN_IDX, 0); - gpio_matrix_out(PSRAM_SPIHD_IO, SPIHD_OUT_IDX, 0, 0); - gpio_matrix_in(PSRAM_SPIHD_IO, SPIHD_IN_IDX, 0); - -#warning "psram_gpio_config: parts not implemented for esp32s2beta" - - switch (mode) { - case PSRAM_CACHE_S40M: - extra_dummy = PSRAM_IO_MATRIX_DUMMY_40M; - break; - case PSRAM_CACHE_S80M: - extra_dummy = PSRAM_IO_MATRIX_DUMMY_80M; -#if 0 - g_rom_spiflash_dummy_len_plus[_SPI_CACHE_PORT] = PSRAM_IO_MATRIX_DUMMY_80M; - g_rom_spiflash_dummy_len_plus[_SPI_FLASH_PORT] = PSRAM_IO_MATRIX_DUMMY_80M; - SET_PERI_REG_BITS(SPI_MEM_USER1_REG(_SPI_CACHE_PORT), SPI_MEM_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + PSRAM_IO_MATRIX_DUMMY_80M, SPI_MEM_USR_DUMMY_CYCLELEN_S); //DUMMY - - CLEAR_PERI_REG_MASK(PERIPHS_SPI_FLASH_CTRL, SPI_MEM_FREAD_QIO | SPI_MEM_FREAD_QUAD | SPI_MEM_FREAD_DIO | SPI_MEM_FREAD_DUAL | SPI_MEM_FASTRD_MODE); - esp_rom_spiflash_config_clk(_SPI_80M_CLK_DIV, _SPI_CACHE_PORT); - CLEAR_PERI_REG_MASK(PERIPHS_SPI_FLASH_CTRL, SPI_MEM_FREAD_QIO | SPI_MEM_FREAD_QUAD | SPI_MEM_FREAD_DIO | SPI_MEM_FREAD_DUAL | SPI_MEM_FASTRD_MODE); - esp_rom_spiflash_config_clk(_SPI_80M_CLK_DIV, _SPI_FLASH_PORT); - -#endif - break; - case PSRAM_CACHE_S26M: - case PSRAM_CACHE_S20M: - extra_dummy = PSRAM_IO_MATRIX_DUMMY_20M; -#if 0 - g_rom_spiflash_dummy_len_plus[_SPI_CACHE_PORT] = PSRAM_IO_MATRIX_DUMMY_20M; - g_rom_spiflash_dummy_len_plus[_SPI_FLASH_PORT] = PSRAM_IO_MATRIX_DUMMY_20M; - SET_PERI_REG_BITS(SPI_MEM_USER1_REG(_SPI_CACHE_PORT), SPI_MEM_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + PSRAM_IO_MATRIX_DUMMY_20M, SPI_MEM_USR_DUMMY_CYCLELEN_S); //DUMMY - - CLEAR_PERI_REG_MASK(PERIPHS_SPI_FLASH_CTRL, SPI_MEM_FREAD_QIO | SPI_MEM_FREAD_QUAD | SPI_MEM_FREAD_DIO | SPI_MEM_FREAD_DUAL | SPI_MEM_FASTRD_MODE); - esp_rom_spiflash_config_clk(_SPI_20M_CLK_DIV, _SPI_CACHE_PORT); - CLEAR_PERI_REG_MASK(PERIPHS_SPI_FLASH_CTRL, SPI_MEM_FREAD_QIO | SPI_MEM_FREAD_QUAD | SPI_MEM_FREAD_DIO | SPI_MEM_FREAD_DUAL | SPI_MEM_FASTRD_MODE); - esp_rom_spiflash_config_clk(_SPI_20M_CLK_DIV, _SPI_FLASH_PORT); -#endif - - default: - break; - } - SET_PERI_REG_MASK(SPI_MEM_USER_REG(0), SPI_MEM_USR_DUMMY); // dummy en - //select pin function gpio - PIN_FUNC_SELECT(PERIPHS_IO_MUX_SPIHD_U, PIN_FUNC_GPIO); - PIN_FUNC_SELECT(PERIPHS_IO_MUX_SPIWP_U, PIN_FUNC_GPIO); - PIN_FUNC_SELECT(PERIPHS_IO_MUX_SPICS0_U, PIN_FUNC_GPIO); - PIN_FUNC_SELECT(PERIPHS_IO_MUX_SPIQ_U, PIN_FUNC_GPIO); - PIN_FUNC_SELECT(PERIPHS_IO_MUX_SPID_U, PIN_FUNC_GPIO); - // flash clock signal should come from IO MUX. - // set drive ability for clock - PIN_FUNC_SELECT(PERIPHS_IO_MUX_SPICLK_U, FUNC_SPICLK_SPICLK); -} - -psram_size_t psram_get_size(void) -{ - if (PSRAM_IS_32MBIT_VER0(s_psram_id)) { - return PSRAM_SIZE_32MBITS; - } else if (PSRAM_IS_64MBIT(s_psram_id)) { - return PSRAM_SIZE_64MBITS; - } else { - return PSRAM_SIZE_MAX; - } -} - -//psram gpio init , different working frequency we have different solutions esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vaddrmode) //psram init { - assert(mode < PSRAM_CACHE_MAX && "we don't support any other mode for now."); - s_psram_mode = mode; - - periph_module_enable(PERIPH_SPI_MODULE); - -#warning "psram_enable: some code disabled for esp32s2beta" -#if 0 - WRITE_PERI_REG(SPI_MEM_EXT3_REG(0), 0x1); - CLEAR_PERI_REG_MASK(SPI_MEM_USER_REG(PSRAM_SPI_1), SPI_MEM_USR_PREP_HOLD_M); -#endif - - - switch (mode) { - case PSRAM_CACHE_S80M: - case PSRAM_CACHE_S40M: - case PSRAM_CACHE_S26M: - case PSRAM_CACHE_S20M: - default: - psram_spi_init(PSRAM_SPI_1, mode); - CLEAR_PERI_REG_MASK(SPI_MEM_USER_REG(PSRAM_SPI_1), SPI_MEM_CS_HOLD); - gpio_matrix_out(PSRAM_CS_IO, SPICS1_OUT_IDX, 0, 0); -#ifdef FAKE_QPI - /* We need to delay CLK to the PSRAM with respect to the clock signal as output by the SPI peripheral. - We do this by routing it signal to signal 220/221, which are used as a loopback; the extra run through - the GPIO matrix causes the delay. We use GPIO20 (which is not in any package but has pad logic in - silicon) as a temporary pad for this. So the signal path is: - SPI CLK --> GPIO28 --> signal220(in then out) --> internal GPIO29 --> signal221(in then out) --> GPIO17(PSRAM CLK) - */ - gpio_matrix_out(PSRAM_INTERNAL_IO_28, SPICLK_OUT_IDX, 0, 0); - gpio_matrix_in(PSRAM_INTERNAL_IO_28, SIG_IN_FUNC220_IDX, 0); - gpio_matrix_out(PSRAM_INTERNAL_IO_29, SIG_IN_FUNC220_IDX, 0, 0); - gpio_matrix_in(PSRAM_INTERNAL_IO_29, SIG_IN_FUNC221_IDX, 0); - gpio_matrix_out(PSRAM_CLK_IO, SIG_IN_FUNC221_IDX, 0, 0); -#else - REG_SET_FIELD(SPI_MEM_SRAM_CMD_REG(0), SPI_MEM_SCLK_MODE, 1); - REG_SET_FIELD(SPI_MEM_CTRL1_REG(1), SPI_MEM_CLK_MODE, 1); -#endif - - break; - } - - #if CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V - // For flash 80Mhz, we must update ldo voltage in case older version of bootloader didn't do this. - rtc_vddsdio_config_t cfg = rtc_vddsdio_get_config(); - if (cfg.enable == 1 && cfg.tieh == RTC_VDDSDIO_TIEH_1_8V) { // VDDSDIO regulator is enabled @ 1.8V - cfg.drefh = 3; - cfg.drefm = 3; - cfg.drefl = 3; - cfg.force = 1; - rtc_vddsdio_set_config(cfg); - ets_delay_us(10); // wait for regulator to become stable - } - #endif - CLEAR_PERI_REG_MASK(SPI_MEM_USER_REG(PSRAM_SPI_1), SPI_MEM_CS_SETUP_M); + // GPIO related settings psram_gpio_config(mode); - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[PSRAM_CS_IO], PIN_FUNC_GPIO); - psram_read_id(&s_psram_id); + + /* SPI1: set spi1 clk mode, in order to send commands on SPI1 */ + /* SPI1: set cs timing(hold time) in order to send commands on SPI1 */ + psram_set_clk_mode(_SPI_FLASH_PORT, PSRAM_CLK_MODE_A1C); + psram_set_spi1_cmd_cs_timing(PSRAM_CLK_MODE_A1C); + psram_read_id(&s_psram_id); if (!PSRAM_IS_VALID(s_psram_id)) { return ESP_FAIL; } - uint32_t flash_id = g_rom_flashchip.device_id; - if (flash_id == FLASH_ID_GD25LQ32C) { - // Set drive ability for 1.8v flash in 80Mhz. - SET_PERI_REG_BITS(PERIPHS_IO_MUX_SPIHD_U, FUN_DRV, 3, FUN_DRV_S); - SET_PERI_REG_BITS(PERIPHS_IO_MUX_SPIWP_U, FUN_DRV, 3, FUN_DRV_S); - SET_PERI_REG_BITS(PERIPHS_IO_MUX_SPICS0_U, FUN_DRV, 3, FUN_DRV_S); - SET_PERI_REG_BITS(PERIPHS_IO_MUX_SPICLK_U, FUN_DRV, 3, FUN_DRV_S); - SET_PERI_REG_BITS(PERIPHS_IO_MUX_SPIQ_U, FUN_DRV, 3, FUN_DRV_S); - SET_PERI_REG_BITS(PERIPHS_IO_MUX_SPID_U, FUN_DRV, 3, FUN_DRV_S); - SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[PSRAM_CS_IO], FUN_DRV, 3, FUN_DRV_S); + + psram_clk_mode_t clk_mode = PSRAM_CLK_MODE_MAX; + if (psram_is_32mbit_ver0()) { + clk_mode = PSRAM_CLK_MODE_A1C; + // SPI1: keep clock mode and cs timing for spi1 + } else { + // For other psram, we don't need any extra clock cycles after cs get back to high level + clk_mode = PSRAM_CLK_MODE_NORM; + // SPI1: set clock mode and cs timing to normal mode + psram_set_clk_mode(_SPI_FLASH_PORT, PSRAM_CLK_MODE_NORM); + psram_set_spi1_cmd_cs_timing(PSRAM_CLK_MODE_NORM); } - if (PSRAM_IS_64MBIT(s_psram_id)) { - // For this psram, we don't need any extra clock cycles after cs get back to high level - s_clk_mode = PSRAM_CLK_MODE_NORM; - REG_SET_FIELD(SPI_MEM_SRAM_CMD_REG(0), SPI_MEM_SCLK_MODE, 0); - REG_SET_FIELD(SPI_MEM_CTRL1_REG(1), SPI_MEM_CLK_MODE, 0); - } else if (PSRAM_IS_32MBIT_VER0(s_psram_id)) { - s_clk_mode = PSRAM_CLK_MODE_DCLK; - if (mode == PSRAM_CACHE_S80M) { - } - } - psram_reset_mode(PSRAM_SPI_1); + + /* SPI1: send psram reset command */ + /* SPI1: send QPI enable command */ + psram_reset_mode(PSRAM_SPI_1); psram_enable_qio_mode(PSRAM_SPI_1); + + // after sending commands, set spi1 clock mode and cs timing to normal mode. + // since all the operations are sent via SPI0 Cache + /* SPI1: set clock mode to normal mode. */ + /* SPI1: set cs timing to normal */ + psram_set_clk_mode(_SPI_FLASH_PORT, PSRAM_CLK_MODE_NORM); + psram_set_spi1_cmd_cs_timing(PSRAM_CLK_MODE_NORM); + + /* SPI0: set spi0 clock mode */ + /* SPI0: set spi0 flash/cache cs timing */ + psram_set_clk_mode(_SPI_CACHE_PORT, clk_mode); + psram_set_spi0_cache_cs_timing(clk_mode); + + // SPI0: init SPI commands for Cache psram_cache_init(mode, vaddrmode); + return ESP_OK; } -static void IRAM_ATTR psram_clock_set(psram_spi_num_t spi_num, int8_t freqdiv) +static void IRAM_ATTR psram_clock_set(int spi_num, int8_t freqdiv) { uint32_t freqbits; if (1 >= freqdiv) { @@ -790,8 +485,37 @@ static void IRAM_ATTR psram_clock_set(psram_spi_num_t spi_num, int8_t freqdiv) //register initialization for sram cache params and r/w commands static void IRAM_ATTR psram_cache_init(psram_cache_mode_t psram_cache_mode, psram_vaddr_mode_t vaddrmode) { - SET_PERI_REG_MASK(SPI_MEM_CACHE_SCTRL_REG(0), SPI_MEM_USR_RD_SRAM_DUMMY_M); //enable cache read dummy - SET_PERI_REG_MASK(SPI_MEM_CACHE_SCTRL_REG(0), SPI_MEM_CACHE_SRAM_USR_RCMD_M); //enable user mode for cache read command + int extra_dummy = 0; + switch (psram_cache_mode) { + case PSRAM_CACHE_S80M: + psram_clock_set(0, 1); + extra_dummy = PSRAM_IO_MATRIX_DUMMY_80M; + break; + case PSRAM_CACHE_S40M: + psram_clock_set(0, 2); + extra_dummy = PSRAM_IO_MATRIX_DUMMY_40M; + break; + case PSRAM_CACHE_S26M: + psram_clock_set(0, 3); + extra_dummy = PSRAM_IO_MATRIX_DUMMY_20M; + break; + case PSRAM_CACHE_S20M: + psram_clock_set(0, 4); + extra_dummy = PSRAM_IO_MATRIX_DUMMY_20M; + break; + default: + psram_clock_set(0, 2); + break; + } + + CLEAR_PERI_REG_MASK(SPI_MEM_CACHE_SCTRL_REG(0), SPI_MEM_USR_SRAM_DIO_M); //disable dio mode for cache command + SET_PERI_REG_MASK(SPI_MEM_CACHE_SCTRL_REG(0), SPI_MEM_USR_SRAM_QIO_M); //enable qio mode for cache command + SET_PERI_REG_MASK(SPI_MEM_CACHE_SCTRL_REG(0), SPI_MEM_CACHE_SRAM_USR_RCMD_M); //enable cache read command + SET_PERI_REG_MASK(SPI_MEM_CACHE_SCTRL_REG(0), SPI_MEM_CACHE_SRAM_USR_WCMD_M); //enable cache write command + SET_PERI_REG_BITS(SPI_MEM_CACHE_SCTRL_REG(0), SPI_MEM_SRAM_ADDR_BITLEN_V, 23, SPI_MEM_SRAM_ADDR_BITLEN_S); //write address for cache command. + SET_PERI_REG_MASK(SPI_MEM_CACHE_SCTRL_REG(0), SPI_MEM_USR_RD_SRAM_DUMMY_M); //enable cache read dummy + + //config sram cache r/w command SET_PERI_REG_BITS(SPI_MEM_SRAM_DWR_CMD_REG(0), SPI_MEM_CACHE_SRAM_USR_WR_CMD_BITLEN, 7, SPI_MEM_CACHE_SRAM_USR_WR_CMD_BITLEN_S); SET_PERI_REG_BITS(SPI_MEM_SRAM_DWR_CMD_REG(0), SPI_MEM_CACHE_SRAM_USR_WR_CMD_VALUE, PSRAM_QUAD_WRITE, @@ -803,58 +527,6 @@ static void IRAM_ATTR psram_cache_init(psram_cache_mode_t psram_cache_mode, psra SET_PERI_REG_BITS(SPI_MEM_CACHE_SCTRL_REG(0), SPI_MEM_SRAM_RDUMMY_CYCLELEN_V, PSRAM_FAST_READ_QUAD_DUMMY + extra_dummy, SPI_MEM_SRAM_RDUMMY_CYCLELEN_S); //dummy, psram cache : 40m--+1dummy,80m--+2dummy - switch (psram_cache_mode) { - case PSRAM_CACHE_S80M: - psram_clock_set(0, 1); - break; - case PSRAM_CACHE_S40M: - psram_clock_set(0, 2); - break; - case PSRAM_CACHE_S26M: - psram_clock_set(0, 3); - break; - case PSRAM_CACHE_S20M: - psram_clock_set(0, 4); - break; - default: - psram_clock_set(0, 2); - break; - } - SET_PERI_REG_MASK(SPI_MEM_CACHE_SCTRL_REG(0), SPI_MEM_CACHE_SRAM_USR_WCMD_M); // cache write command enable - SET_PERI_REG_BITS(SPI_MEM_CACHE_SCTRL_REG(0), SPI_MEM_SRAM_ADDR_BITLEN_V, 23, SPI_MEM_SRAM_ADDR_BITLEN_S); //write address for cache command. - SET_PERI_REG_MASK(SPI_MEM_CACHE_SCTRL_REG(0), SPI_MEM_USR_SRAM_QIO_M); //enable qio mode for cache command - CLEAR_PERI_REG_MASK(SPI_MEM_CACHE_SCTRL_REG(0), SPI_MEM_USR_SRAM_DIO_M); //disable dio mode for cache command - - //config sram cache r/w command - switch (psram_cache_mode) { - case PSRAM_CACHE_S80M: //in this mode , no delay is needed - break; - case PSRAM_CACHE_S40M: //is sram is @40M, need 2 cycles of delay - case PSRAM_CACHE_S26M: - case PSRAM_CACHE_S20M: - default: -#ifdef FAKE_QPI - SET_PERI_REG_BITS(SPI_MEM_SRAM_DRD_CMD_REG(0), SPI_MEM_CACHE_SRAM_USR_RD_CMD_BITLEN_V, 15, - SPI_MEM_CACHE_SRAM_USR_RD_CMD_BITLEN_S); //read command length, 2 bytes(1byte for delay),sending in qio mode in cache - SET_PERI_REG_BITS(SPI_MEM_SRAM_DRD_CMD_REG(0), SPI_MEM_CACHE_SRAM_USR_RD_CMD_VALUE_V, ((PSRAM_FAST_READ_QUAD) << 8), - SPI_MEM_CACHE_SRAM_USR_RD_CMD_VALUE_S); //0x0b, read command value,(0x00 for delay,0x0b for cmd) - SET_PERI_REG_BITS(SPI_MEM_SRAM_DWR_CMD_REG(0), SPI_MEM_CACHE_SRAM_USR_WR_CMD_BITLEN, 15, - SPI_MEM_CACHE_SRAM_USR_WR_CMD_BITLEN_S); //write command length,2 bytes(1byte for delay,send in qio mode in cache) - SET_PERI_REG_BITS(SPI_MEM_SRAM_DWR_CMD_REG(0), SPI_MEM_CACHE_SRAM_USR_WR_CMD_VALUE, ((PSRAM_QUAD_WRITE) << 8), - SPI_MEM_CACHE_SRAM_USR_WR_CMD_VALUE_S); //0x38, write command value,(0x00 for delay) -#else - SET_PERI_REG_BITS(SPI_MEM_SRAM_DRD_CMD_REG(0), SPI_MEM_CACHE_SRAM_USR_RD_CMD_BITLEN_V, 7, - SPI_MEM_CACHE_SRAM_USR_RD_CMD_BITLEN_S); //read command length, 2 bytes(1byte for delay),sending in qio mode in cache - SET_PERI_REG_BITS(SPI_MEM_SRAM_DRD_CMD_REG(0), SPI_MEM_CACHE_SRAM_USR_RD_CMD_VALUE_V, PSRAM_FAST_READ_QUAD, - SPI_MEM_CACHE_SRAM_USR_RD_CMD_VALUE_S); //0x0b, read command value,(0x00 for delay,0x0b for cmd) - SET_PERI_REG_BITS(SPI_MEM_SRAM_DWR_CMD_REG(0), SPI_MEM_CACHE_SRAM_USR_WR_CMD_BITLEN, 7, - SPI_MEM_CACHE_SRAM_USR_WR_CMD_BITLEN_S); //write command length,2 bytes(1byte for delay,send in qio mode in cache) - SET_PERI_REG_BITS(SPI_MEM_SRAM_DWR_CMD_REG(0), SPI_MEM_CACHE_SRAM_USR_WR_CMD_VALUE, PSRAM_QUAD_WRITE, - SPI_MEM_CACHE_SRAM_USR_WR_CMD_VALUE_S); //0x38, write command value,(0x00 for delay) -#endif - break; - } - #if !CONFIG_FREERTOS_UNICORE DPORT_CLEAR_PERI_REG_MASK(DPORT_PRO_CACHE_CTRL_REG, DPORT_PRO_DRAM_HL|DPORT_PRO_DRAM_SPLIT); DPORT_CLEAR_PERI_REG_MASK(DPORT_APP_CACHE_CTRL_REG, DPORT_APP_DRAM_HL|DPORT_APP_DRAM_SPLIT); @@ -868,17 +540,6 @@ static void IRAM_ATTR psram_cache_init(psram_cache_mode_t psram_cache_mode, psra #endif Cache_Resume_DCache(0); - CLEAR_PERI_REG_MASK(SPI_MEM_MISC_REG(0), SPI_MEM_CS1_DIS_M); //ENABLE SPI0 CS1 TO PSRAM(CS0--FLASH; CS1--SRAM) - if (s_clk_mode == PSRAM_CLK_MODE_NORM) { //different - REG_SET_FIELD(SPI_MEM_SRAM_CMD_REG(0), SPI_MEM_SCLK_MODE, 0); - REG_SET_FIELD(SPI_MEM_CTRL1_REG(1), SPI_MEM_CLK_MODE, 0); - - SET_PERI_REG_MASK(SPI_MEM_USER_REG(0), SPI_MEM_CS_HOLD); - // Set cs time. - SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_HOLD_TIME_V, 1, SPI_MEM_CS_HOLD_TIME_S); - } else { - CLEAR_PERI_REG_MASK(SPI_MEM_USER_REG(0), SPI_MEM_CS_HOLD | SPI_MEM_CS_SETUP); - } } #endif // CONFIG_SPIRAM diff --git a/components/esp32s2beta/spiram_psram.h b/components/esp32s2beta/spiram_psram.h index b357b8807e..ea7908f030 100644 --- a/components/esp32s2beta/spiram_psram.h +++ b/components/esp32s2beta/spiram_psram.h @@ -28,8 +28,9 @@ typedef enum { } psram_cache_mode_t; typedef enum { - PSRAM_SIZE_32MBITS = 0, - PSRAM_SIZE_64MBITS = 1, + PSRAM_SIZE_16MBITS = 0, + PSRAM_SIZE_32MBITS = 1, + PSRAM_SIZE_64MBITS = 2, PSRAM_SIZE_MAX, } psram_size_t; diff --git a/components/esp_rom/include/esp32s2beta/rom/opi_flash.h b/components/esp_rom/include/esp32s2beta/rom/opi_flash.h new file mode 100644 index 0000000000..ee2490bed4 --- /dev/null +++ b/components/esp_rom/include/esp32s2beta/rom/opi_flash.h @@ -0,0 +1,291 @@ +/* + * copyright (c) Espressif System 2019 + * + */ + +#ifndef _ROM_OPI_FLASH_H_ +#define _ROM_OPI_FLASH_H_ +#include +#include +#include +#include "spi_flash.h" + +typedef struct { + uint16_t cmd; /*!< Command value */ + uint16_t cmdBitLen; /*!< Command byte length*/ + uint32_t *addr; /*!< Point to address value*/ + uint32_t addrBitLen; /*!< Address byte length*/ + uint32_t *txData; /*!< Point to send data buffer*/ + uint32_t txDataBitLen; /*!< Send data byte length.*/ + uint32_t *rxData; /*!< Point to recevie data buffer*/ + uint32_t rxDataBitLen; /*!< Recevie Data byte length.*/ + uint32_t dummyBitLen; +} esp_rom_spi_cmd_t; + +#define ESP_ROM_OPIFLASH_MUX_TAKE() +#define ESP_ROM_OPIFLASH_MUX_GIVE() +#define ESP_ROM_OPIFLASH_SEL_CS0 (BIT(0)) +#define ESP_ROM_OPIFLASH_SEL_CS1 (BIT(1)) + +// Definition of MX25UM25645G Octa Flash +// SPI status register +#define ESP_ROM_SPIFLASH_BUSY_FLAG BIT0 +#define ESP_ROM_SPIFLASH_WRENABLE_FLAG BIT1 +#define ESP_ROM_SPIFLASH_BP0 BIT2 +#define ESP_ROM_SPIFLASH_BP1 BIT3 +#define ESP_ROM_SPIFLASH_BP2 BIT4 +#define ESP_ROM_SPIFLASH_WR_PROTECT (ESP_ROM_SPIFLASH_BP0|ESP_ROM_SPIFLASH_BP1|ESP_ROM_SPIFLASH_BP2) +#define ESP_ROM_SPIFLASH_QE BIT9 + +#define FLASH_OP_MODE_RDCMD_DOUT 0x3B +#define ESP_ROM_FLASH_SECTOR_SIZE 0x1000 +#define ESP_ROM_FLASH_BLOCK_SIZE_64K 0x10000 +#define ESP_ROM_FLASH_PAGE_SIZE 256 + +// FLASH commands +#define ROM_FLASH_CMD_RDID 0x9F +#define ROM_FLASH_CMD_WRSR 0x01 +#define ROM_FLASH_CMD_WRSR2 0x31 /* Not all SPI flash uses this command */ +#define ROM_FLASH_CMD_WREN 0x06 +#define ROM_FLASH_CMD_WRDI 0x04 +#define ROM_FLASH_CMD_RDSR 0x05 +#define ROM_FLASH_CMD_RDSR2 0x35 /* Not all SPI flash uses this command */ +#define ROM_FLASH_CMD_ERASE_SEC 0x20 +#define ROM_FLASH_CMD_ERASE_BLK_32K 0x52 +#define ROM_FLASH_CMD_ERASE_BLK_64K 0xD8 +#define ROM_FLASH_CMD_OTPEN 0x3A /* Enable OTP mode, not all SPI flash uses this command */ +#define ROM_FLASH_CMD_RSTEN 0x66 +#define ROM_FLASH_CMD_RST 0x99 + +#define ROM_FLASH_CMD_SE4B 0x21 +#define ROM_FLASH_CMD_SE4B_OCT 0xDE21 +#define ROM_FLASH_CMD_BE4B 0xDC +#define ROM_FLASH_CMD_BE4B_OCT 0x23DC +#define ROM_FLASH_CMD_RSTEN_OCT 0x9966 +#define ROM_FLASH_CMD_RST_OCT 0x6699 + +#define ROM_FLASH_CMD_FSTRD4B_STR 0x13EC +#define ROM_FLASH_CMD_FSTRD4B_DTR 0x11EE +#define ROM_FLASH_CMD_FSTRD4B 0x0C +#define ROM_FLASH_CMD_PP4B 0x12 +#define ROM_FLASH_CMD_PP4B_OCT 0xED12 + +#define ROM_FLASH_CMD_RDID_OCT 0x609F +#define ROM_FLASH_CMD_WREN_OCT 0xF906 +#define ROM_FLASH_CMD_RDSR_OCT 0xFA05 +#define ROM_FLASH_CMD_RDCR2 0x71 +#define ROM_FLASH_CMD_RDCR2_OCT 0x8E71 +#define ROM_FLASH_CMD_WRCR2 0x72 +#define ROM_FLASH_CMD_WRCR2_OCT 0x8D72 + +// Definitions for GigaDevice GD25LX256E Flash +#define ROM_FLASH_CMD_RDFSR_GD 0x70 +#define ROM_FLASH_CMD_RD_GD 0x03 +#define ROM_FLASH_CMD_RD4B_GD 0x13 +#define ROM_FLASH_CMD_FSTRD_GD 0x0B +#define ROM_FLASH_CMD_FSTRD4B_GD 0x0C +#define ROM_FLASH_CMD_FSTRD_OOUT_GD 0x8B +#define ROM_FLASH_CMD_FSTRD4B_OOUT_GD 0x7C +#define ROM_FLASH_CMD_FSTRD_OIOSTR_GD 0xCB +#define ROM_FLASH_CMD_FSTRD4B_OIOSTR_GD 0xCC +#define ROM_FLASH_CMD_FSTRD4B_OIODTR_GD 0xFD + +#define ROM_FLASH_CMD_PP_GD 0x02 +#define ROM_FLASH_CMD_PP4B_GD 0x12 +#define ROM_FLASH_CMD_PP_OOUT_GD 0x82 +#define ROM_FLASH_CMD_PP4B_OOUT_GD 0x84 +#define ROM_FLASH_CMD_PP_OIO_GD 0xC2 +#define ROM_FLASH_CMD_PP4B_OIOSTR_GD 0x8E + +#define ROM_FLASH_CMD_SE_GD 0x20 +#define ROM_FLASH_CMD_SE4B_GD 0x21 +#define ROM_FLASH_CMD_BE32K_GD 0x52 +#define ROM_FLASH_CMD_BE32K4B_GD 0x5C +#define ROM_FLASH_CMD_BE64K_GD 0xD8 +#define ROM_FLASH_CMD_BE64K4B_GD 0xDC + +#define ROM_FLASH_CMD_EN4B_GD 0xB7 +#define ROM_FLASH_CMD_DIS4B_GD 0xE9 + +// spi user mode command config + +/** + * @brief Config the spi user command + * @param spi_num spi port + * @param pcmd pointer to accept the spi command struct + */ +void esp_rom_spi_cmd_config(int spi_num, esp_rom_spi_cmd_t* pcmd); + +/** + * @brief Start a spi user command sequence + * @param spi_num spi port + * @param rx_buf buffer pointer to receive data + * @param rx_len receive data length in byte + * @param cs_en_mask decide which cs to use, 0 for cs0, 1 for cs1 + * @param is_write_erase to indicate whether this is a write or erase operation, since the CPU would check permission + */ +void esp_rom_spi_cmd_start(int spi_num, uint8_t* rx_buf, uint16_t rx_len, uint8_t cs_en_mask, bool is_write_erase); + +/** + * @brief Config opi flash pads according to efuse settings. + */ +void esp_rom_opiflash_pin_config(void); + +// set SPI read/write mode +/** + * @brief Set SPI operation mode + * @param spi_num spi port + * @param mode Flash Read Mode + */ +void esp_rom_spi_set_op_mode(int spi_num, esp_rom_spiflash_read_mode_t mode); + +/** + * @brief Set data swap mode in DTR(DDR) mode + * @param spi_num spi port + * @param wr_swap to decide whether to swap fifo data in dtr write operation + * @param rd_swap to decide whether to swap fifo data in dtr read operation + */ +void esp_rom_spi_set_dtr_swap_mode(int spi, bool wr_swap, bool rd_swap); + + +/** + * @brief to send reset command in spi/opi-str/opi-dtr mode(for MX25UM25645G) + * @param spi_num spi port + */ +void esp_rom_opiflash_mode_reset(int spi_num); + +#if 0 +// MX25UM25645G opi flash interface +/** + * @brief To execute a flash operation command + * @param spi_num spi port + * @param mode Flash Read Mode + * @param cmd data to send in command field + * @param cmd_bit_len bit length of command field + * @param addr data to send in address field + * @param addr_bit_len bit length of address field + * @param dummy_bits bit length of dummy field + * @param mosi_data data buffer to be sent in mosi field + * @param mosi_bit_len bit length of data buffer to be sent in mosi field + * @param miso_data data buffer to accept data in miso field + * @param miso_bit_len bit length of data buffer to accept data in miso field + * @param cs_mark decide which cs pin to use. 0: cs0, 1: cs1 + * @param is_write_erase_operation to indicate whether this a write or erase flash operation + */ +void esp_rom_opiflash_exec_cmd(int spi_num, esp_rom_spiflash_read_mode_t mode, + uint32_t cmd, int cmd_bit_len, + uint32_t addr, int addr_bit_len, + int dummy_bits, + uint8_t* mosi_data, int mosi_bit_len, + uint8_t* miso_data, int miso_bit_len, + uint32_t cs_mask, + bool is_write_erase_operation); + +/** + * @brief send reset command to opi flash + * @param spi_num spi port + * @param mode Flash Operation Mode + */ +void esp_rom_opiflash_soft_reset(int spi_num, esp_rom_spiflash_read_mode_t mode); + +/** + * @brief to read opi flash ID(for MX25UM25645G) + * @param spi_num spi port + * @param mode Flash Operation Mode + * @return opi flash id + */ +uint32_t esp_rom_opiflash_read_id(int spi_num, esp_rom_spiflash_read_mode_t mode); + +/** + * @brief to read opi flash status register(for MX25UM25645G) + * @param spi_num spi port + * @param mode Flash Operation Mode + * @return opi flash status value + */ +uint8_t esp_rom_opiflash_rdsr(int spi_num, esp_rom_spiflash_read_mode_t mode); + +/** + * @brief wait opi flash status register to be idle + * @param spi_num spi port + * @param mode Flash Operation Mode + */ +void esp_rom_opiflash_wait_idle(int spi_num, esp_rom_spiflash_read_mode_t mode); + +/** + * @brief to read the config register2(for MX25UM25645G) + * @param spi_num spi port + * @param mode Flash Operation Mode + * @param addr the address of configure register + * @return value of config register2 + */ +uint8_t esp_rom_opiflash_rdcr2(int spi_num, esp_rom_spiflash_read_mode_t mode, uint32_t addr); + +/** + * @brief to write the config register2(for MX25UM25645G) + * @param spi_num spi port + * @param mode Flash Operation Mode + * @param addr the address of config register + * @param val the value to write + */ +void esp_rom_opiflash_wrcr2(int spi_num, esp_rom_spiflash_read_mode_t mode, uint32_t addr, uint8_t val); + +/** + * @brief to erase flash sector(for MX25UM25645G) + * @param spi_num spi port + * @param address the sector address to be erased + * @param mode Flash operation mode + * @return flash operation result + */ +esp_rom_spiflash_result_t esp_rom_opiflash_erase_sector(int spi_num, uint32_t address, esp_rom_spiflash_read_mode_t mode); + +/** + * @brief to erase flash block(for MX25UM25645G) + * @param spi_num spi port + * @param address the block address to be erased + * @param mode Flash operation mode + * @return flash operation result + */ +esp_rom_spiflash_result_t esp_rom_opiflash_erase_block_64k(int spi_num, uint32_t address, esp_rom_spiflash_read_mode_t mode); + +/** + * @brief to erase a flash area define by start address and length(for MX25UM25645G) + * @param spi_num spi port + * @param start_addr the start address to be erased + * @param area_len the erea length to be erased + * @param mode flash operation mode + * @return flash operation result + */ +esp_rom_spiflash_result_t esp_rom_opiflash_erase_area(int spi_num, uint32_t start_addr, uint32_t area_len, esp_rom_spiflash_read_mode_t mode); + +/** + * @brief to read data from opi flash(for MX25UM25645G) + * @param spi_num spi port + * @param mode flash operation mode + * @param flash_addr flash address to read data from + * @param data_addr data buffer to accept the data + * @param len data length to be read + * @return flash operation result + */ +esp_rom_spiflash_result_t esp_rom_opiflash_read(int spi_num, esp_rom_spiflash_read_mode_t mode, uint32_t flash_addr, uint8_t *data_addr, int len); + +/** + * @brief to write data to opi flash(for MX25UM25645G) + * @param spi_num spi port + * @param mode flash operation mode + * @param flash_addr flash address to write data to + * @param data_addr data buffer to write to flash + * @param len data length to write + * @return flash operation result + */ +esp_rom_spiflash_result_t esp_rom_opiflash_write(int spi_num, esp_rom_spiflash_read_mode_t mode, uint32_t flash_addr, uint8_t *data_addr, uint32_t len); + +/** + * @brief to set opi flash operation mode(for MX25UM25645G) + * @param spi_num spi port + * @param cur_mode current operation mode + * @param target the target operation mode to be set + */ +void esp_rom_opiflash_set_mode(int spi_num, esp_rom_spiflash_read_mode_t cur_mode, esp_rom_spiflash_read_mode_t target_mode); +#endif + +#endif diff --git a/components/esp_rom/include/esp32s2beta/rom/spi_flash.h b/components/esp_rom/include/esp32s2beta/rom/spi_flash.h index 47441ec646..5d2a261fd8 100644 --- a/components/esp_rom/include/esp32s2beta/rom/spi_flash.h +++ b/components/esp_rom/include/esp32s2beta/rom/spi_flash.h @@ -19,7 +19,6 @@ #include #include "esp_attr.h" - #include "soc/spi_mem_reg.h" #ifdef __cplusplus @@ -125,7 +124,12 @@ typedef enum { ESP_ROM_SPIFLASH_DIO_MODE, ESP_ROM_SPIFLASH_DOUT_MODE, ESP_ROM_SPIFLASH_FASTRD_MODE, - ESP_ROM_SPIFLASH_SLOWRD_MODE + ESP_ROM_SPIFLASH_SLOWRD_MODE, + ESP_ROM_SPIFASH_OPI_STR_MODE, + ESP_ROM_SPIFASH_OPI_DTR_MODE, + ESP_ROM_SPIFASH_OOUT_MODE, + ESP_ROM_SPIFASH_OIO_STR_MODE, + ESP_ROM_SPIFASH_OIO_DTR_MODE, } esp_rom_spiflash_read_mode_t; typedef enum { diff --git a/components/soc/esp32s2beta/include/soc/io_mux_reg.h b/components/soc/esp32s2beta/include/soc/io_mux_reg.h index 5a79e8e4ad..b9de086724 100644 --- a/components/soc/esp32s2beta/include/soc/io_mux_reg.h +++ b/components/soc/esp32s2beta/include/soc/io_mux_reg.h @@ -139,6 +139,7 @@ #define U0RXD_GPIO_NUM 44 #define U0TXD_GPIO_NUM 43 +#define SPI_CS1_GPIO_NUM 26 #define SPI_HD_GPIO_NUM 27 #define SPI_WP_GPIO_NUM 28 #define SPI_CS0_GPIO_NUM 29