]> granicus.if.org Git - esp-idf/commitdiff
feature(psram): add support for 64MBit psram of 1.8v and 3.3v.
authorWangjialin <wangjialin@espressif.com>
Wed, 4 Jul 2018 03:43:30 +0000 (11:43 +0800)
committerWangjialin <wangjialin@espressif.com>
Tue, 10 Jul 2018 06:24:59 +0000 (14:24 +0800)
1. Add reading psram EID.
2. Configure different clock mode for different EID.
3. add API to get psram size and voltage.
4. Remove unnecessary VSPI claim.

For 32MBit@1.8V and 64MBit@3.3V psram, there should be 2 extra clock cycles after CS get high level.
For 64MBit@1.8 psram, we can just use standard SPI protocol to drive the psram. We also need to increase the HOLD time for CS in this case.

EID for psram:
32MBit 1.8v: 0x20
64MBit 1.8v: 0x26
64MBit 3.3v: 0x46

components/esp32/include/esp_spiram.h
components/esp32/spiram.c
components/esp32/spiram_psram.c
components/esp32/spiram_psram.h

index 9663dcddcbd35659bb43c1c305460efd1f6e8c7d..aafd85cee88dde48175b9da80775dd4744d8d522 100644 (file)
 
 #include <stddef.h>
 #include <stdint.h>
+#include <stdbool.h>
 #include "esp_err.h"
 
+typedef enum {
+    ESP_SPIRAM_VOLT_3V3 = 0,       /*!< SPI RAM voltage is 3.3v */
+    ESP_SPIRAM_VOLT_1V8 = 1,       /*!< SPI RAM voltage is 1.8v */
+    ESP_SPIRAM_VOLT_INVALID,       /*!< SPI RAM voltage is invalid*/
+} esp_spiram_volt_t;
+
+typedef enum {
+    ESP_SPIRAM_SIZE_32MBITS = 0,   /*!< SPI RAM size is 32 MBits */
+    ESP_SPIRAM_SIZE_64MBITS = 1,   /*!< SPI RAM size is 64 MBits */
+    ESP_SPIRAM_SIZE_INVALID,       /*!< SPI RAM size is invalid */
+} esp_spiram_size_t;
+
+/**
+ * @brief get SPI RAM voltage
+ * @return
+ *     - ESP_SPIRAM_VOLT_INVALID if SPI RAM not enabled or not valid.
+ *     - SPI RAM voltage
+ */
+esp_spiram_volt_t esp_spiram_get_chip_volt();
+
+/**
+ * @brief get SPI RAM size
+ * @return
+ *     - ESP_SPIRAM_SIZE_INVALID if SPI RAM not enabled or not valid
+ *     - SPI RAM size
+ */
+esp_spiram_size_t esp_spiram_get_chip_size();
+
 /**
  * @brief Initialize spiram interface/hardware. Normally called from cpu_start.c.
  *
index dccc3bc33e0328420c818ef2ff038fb601d7df21..21fade5be64198ee72da600f0e1cce429e05078b 100644 (file)
@@ -23,6 +23,7 @@ we add more types of external RAM memory, this can be made into a more intellige
 #include "sdkconfig.h"
 #include "esp_attr.h"
 #include "esp_err.h"
+#include "esp_spiram.h"
 #include "spiram_psram.h"
 #include "esp_log.h"
 #include "freertos/FreeRTOS.h"
@@ -102,6 +103,39 @@ void IRAM_ATTR esp_spiram_init_cache()
 #endif
 }
 
+esp_spiram_volt_t esp_spiram_get_chip_volt()
+{
+    if (!spiram_inited) {
+        ESP_LOGE(TAG, "SPI RAM not initialized");
+        return ESP_SPIRAM_VOLT_INVALID;
+    }
+    psram_volt_t volt = psram_get_volt();
+    switch (volt) {
+        case PSRAM_VOLT_1V8:
+            return ESP_SPIRAM_VOLT_1V8;
+        case PSRAM_VOLT_3V3:
+            return ESP_SPIRAM_VOLT_3V3;
+        default:
+            return ESP_SPIRAM_VOLT_INVALID;
+    }
+}
+
+esp_spiram_size_t esp_spiram_get_chip_size()
+{
+    if (!spiram_inited) {
+        ESP_LOGE(TAG, "SPI RAM not initialized");
+        return ESP_SPIRAM_SIZE_INVALID;
+    }
+    psram_size_t psram_size = psram_get_size();
+    switch (psram_size) {
+        case PSRAM_SIZE_32MBITS:
+            return ESP_SPIRAM_SIZE_32MBITS;
+        case PSRAM_SIZE_64MBITS:
+            return ESP_SPIRAM_SIZE_64MBITS;
+        default:
+            return ESP_SPIRAM_SIZE_INVALID;
+    }
+}
 
 esp_err_t esp_spiram_init()
 {
index ed20375da8ed4337ae773cb42ffe36b9e8842d02..2aa3b422bb172fb56f87bc77cb0ce564697f7dc9 100644 (file)
 #include "soc/rtc.h"
 
 //Commands for PSRAM chip
-#define PSRAM_READ              0x03
-#define PSRAM_FAST_READ         0x0B
-#define PSRAM_FAST_READ_DUMMY   0x3
-#define PSRAM_FAST_READ_QUAD    0xEB
-#define PSRAM_WRITE             0x02
-#define PSRAM_QUAD_WRITE        0x38
-#define PSRAM_ENTER_QMODE       0x35
-#define PSRAM_EXIT_QMODE        0xF5
-#define PSRAM_RESET_EN          0x66
-#define PSRAM_RESET             0x99
-#define PSRAM_SET_BURST_LEN     0xC0
-#define PSRAM_DEVICE_ID         0x9F
-
-#if CONFIG_SPIRAM_TYPE_ESPPSRAM32
-
-#define PSRAM_MFG_ID_M          0xff
-#define PSRAM_MFG_ID_S             8
-#define PSRAM_MFG_ID_V          0x5d
-
-#endif
+#define PSRAM_READ                 0x03
+#define PSRAM_FAST_READ            0x0B
+#define PSRAM_FAST_READ_DUMMY      0x3
+#define PSRAM_FAST_READ_QUAD       0xEB
+#define PSRAM_FAST_READ_QUAD_DUMMY 0x5
+#define PSRAM_WRITE                0x02
+#define PSRAM_QUAD_WRITE           0x38
+#define PSRAM_ENTER_QMODE          0x35
+#define PSRAM_EXIT_QMODE           0xF5
+#define PSRAM_RESET_EN             0x66
+#define PSRAM_RESET                0x99
+#define PSRAM_SET_BURST_LEN        0xC0
+#define PSRAM_DEVICE_ID            0x9F
+
+typedef enum {
+    PSRAM_EID_32MBIT_1V8 = 0x20,    /*!< psram EID for 32MBit 1.8V */
+    PSRAM_EID_64MBIT_1V8 = 0x26,    /*!< psram EID for 64MBit 1.8V */
+    PSRAM_EID_64MBIT_3V3 = 0x46,    /*!< psram EID for 64MBit 3.3V */
+} psram_type_t;
+
+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;
+
+#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)
+#define PSRAM_IS_1V8(id)       ((PSRAM_EID(id) == PSRAM_EID_32MBIT_1V8) || (PSRAM_EID(id) == PSRAM_EID_64MBIT_1V8))
+#define PSRAM_IS_3V3(id)       (PSRAM_EID(id) == PSRAM_EID_64MBIT_3V3)
+#define PSRAM_IS_64MBIT(id)    ((PSRAM_EID(id) == PSRAM_EID_64MBIT_3V3) || (PSRAM_EID(id) == PSRAM_EID_64MBIT_1V8))
+#define PSRAM_IS_32MBIT(id)    (PSRAM_EID(id) == PSRAM_EID_32MBIT_1V8)
 
 // IO-pins for PSRAM. These need to be in the VDD_SIO power domain because all chips we
 // currently support are 1.8V parts.
@@ -94,6 +112,8 @@ typedef enum {
 } 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[];
@@ -280,7 +300,7 @@ static int psram_cmd_config(psram_spi_num_t spi_num, psram_cmd_t* pInData)
     return 0;
 }
 
-void psram_cmd_end(int spi_num) {
+static void psram_cmd_end(int spi_num) {
     while (READ_PERI_REG(SPI_CMD_REG(spi_num)) & SPI_USR);
     WRITE_PERI_REG(SPI_USER_REG(spi_num), backup_usr[spi_num]);
     WRITE_PERI_REG(SPI_USER1_REG(spi_num), backup_usr1[spi_num]);
@@ -292,17 +312,19 @@ static void psram_disable_qio_mode(psram_spi_num_t spi_num)
 {
     psram_cmd_t ps_cmd;
     uint32_t cmd_exit_qpi;
-    switch (s_psram_mode) {
-        case PSRAM_CACHE_F80M_S80M:
-            cmd_exit_qpi = PSRAM_EXIT_QMODE;
-            ps_cmd.txDataBitLen = 8;
-            break;
-        case PSRAM_CACHE_F80M_S40M:
-        case PSRAM_CACHE_F40M_S40M:
-        default:
-            cmd_exit_qpi = PSRAM_EXIT_QMODE << 8;
-            ps_cmd.txDataBitLen = 16;
-            break;
+    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_F80M_S80M:
+                break;
+            case PSRAM_CACHE_F80M_S40M:
+            case PSRAM_CACHE_F40M_S40M:
+            default:
+                cmd_exit_qpi = PSRAM_EXIT_QMODE << 8;
+                ps_cmd.txDataBitLen = 16;
+                break;
+        }
     }
     ps_cmd.txData = &cmd_exit_qpi;
     ps_cmd.cmd = 0;
@@ -322,29 +344,34 @@ 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 addr = (PSRAM_DEVICE_ID << 24) | 0;
-    uint32_t dummy_bits = 0;
+    uint32_t dummy_bits = 0 + extra_dummy;
     psram_cmd_t ps_cmd;
-    switch (s_psram_mode) {
-        case PSRAM_CACHE_F80M_S80M:
-            dummy_bits = 0 + extra_dummy;
-            ps_cmd.cmdBitLen = 0;
-            break;
-        case PSRAM_CACHE_F80M_S40M:
-        case PSRAM_CACHE_F40M_S40M:
-        default:
-            dummy_bits = 0 + extra_dummy;
-            ps_cmd.cmdBitLen = 2;   //this two bits is used to delay 2 clock cycle
-            break;
+
+    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_F80M_S80M:
+                break;
+            case PSRAM_CACHE_F80M_S40M:
+            case PSRAM_CACHE_F40M_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.cmd = 0;
     ps_cmd.addr = &addr;
-    ps_cmd.addrBitLen = 4 * 8;
     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);
@@ -356,15 +383,18 @@ 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;
-    switch (s_psram_mode) {
-        case PSRAM_CACHE_F80M_S80M:
-            ps_cmd.cmdBitLen = 0;
-            break;
-        case PSRAM_CACHE_F80M_S40M:
-        case PSRAM_CACHE_F40M_S40M:
-        default:
-            ps_cmd.cmdBitLen = 2;
-            break;
+
+    ps_cmd.cmdBitLen = 0;
+    if (s_clk_mode == PSRAM_CLK_MODE_DCLK) {
+        switch (s_psram_mode) {
+            case PSRAM_CACHE_F80M_S80M:
+                break;
+            case PSRAM_CACHE_F80M_S40M:
+            case PSRAM_CACHE_F40M_S40M:
+            default:
+                ps_cmd.cmdBitLen = 2;
+                break;
+        }
     }
     ps_cmd.cmd = 0;
     ps_cmd.addr = &addr;
@@ -491,6 +521,28 @@ static void IRAM_ATTR psram_gpio_config(psram_cache_mode_t mode)
     PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
 }
 
+psram_volt_t psram_get_volt()
+{
+    if (PSRAM_IS_1V8(s_psram_id)) {
+        return PSRAM_VOLT_1V8;
+    } else if (PSRAM_IS_3V3(s_psram_id)) {
+        return PSRAM_VOLT_3V3;
+    } else {
+        return PSRAM_VOLT_MAX;
+    }
+}
+
+psram_size_t psram_get_size()
+{
+    if (PSRAM_IS_32MBIT(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
 {
@@ -507,17 +559,6 @@ esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vad
         return ESP_FAIL;
     }
 
-    /*   note: If the third mode(80Mhz+80Mhz) is enabled, VSPI port will be occupied by the system,
-         Application code should never touch VSPI hardware in this case.  We try to stop applications
-         from doing this using the drivers by claiming the port for ourselves*/
-    if (mode == PSRAM_CACHE_F80M_S80M) {
-        periph_module_enable(PERIPH_VSPI_MODULE);
-        bool r=spicommon_periph_claim(VSPI_HOST);
-        if (!r) {
-            return ESP_ERR_INVALID_STATE;
-        }
-    }
-
     WRITE_PERI_REG(GPIO_ENABLE_W1TC_REG, BIT(PSRAM_CLK_IO) | BIT(PSRAM_CS_IO));   //DISABLE OUPUT FOR IO16/17
     assert(mode < PSRAM_CACHE_MAX && "we don't support any other mode for now.");
     s_psram_mode = mode;
@@ -532,21 +573,7 @@ esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vad
             psram_spi_init(PSRAM_SPI_1, mode);
             CLEAR_PERI_REG_MASK(SPI_USER_REG(PSRAM_SPI_1), SPI_CS_HOLD);
             gpio_matrix_out(PSRAM_CS_IO, SPICS1_OUT_IDX, 0, 0);
-            gpio_matrix_out(PSRAM_CLK_IO, VSPICLK_OUT_IDX, 0, 0);
-            //use spi3 clock,but use spi1 data/cs wires
-            //We get a solid 80MHz clock from SPI3 by setting it up, starting a transaction, waiting until it 
-            //is in progress, then cutting the clock (but not the reset!) to that peripheral.
-            WRITE_PERI_REG(SPI_ADDR_REG(PSRAM_SPI_3), 32 << 24);
-            WRITE_PERI_REG(SPI_CLOCK_REG(PSRAM_SPI_3), SPI_CLK_EQU_SYSCLK_M);   //SET 80M AND CLEAR OTHERS
-            SET_PERI_REG_MASK(SPI_CMD_REG(PSRAM_SPI_3), SPI_FLASH_READ_M);
-            uint32_t spi_status;
-            while (1) {
-                spi_status = READ_PERI_REG(SPI_EXT2_REG(PSRAM_SPI_3));
-                if (spi_status != 0 && spi_status != 1) {
-                    DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI3_CLK_EN);
-                    break;
-                }
-            }
+            gpio_matrix_out(PSRAM_CLK_IO, SPICLK_OUT_IDX, 0, 0);
             break;
         case PSRAM_CACHE_F80M_S40M:
         case PSRAM_CACHE_F40M_S40M:
@@ -585,27 +612,58 @@ esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vad
     PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[PSRAM_CS_IO], PIN_FUNC_GPIO);
     PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[PSRAM_CLK_IO], PIN_FUNC_GPIO);
 
+    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) {
-        #if CONFIG_SPIRAM_TYPE_ESPPSRAM32
+    if (flash_id == FLASH_ID_GD25LQ32C && PSRAM_IS_1V8(s_psram_id)) {
         // Set drive ability for 1.8v flash in 80Mhz.
-        SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA0_U, FUN_DRV, 3, FUN_DRV_S);
-        SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA1_U, FUN_DRV, 3, FUN_DRV_S);
-        SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA2_U, FUN_DRV, 3, FUN_DRV_S);
-        SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA3_U, FUN_DRV, 3, FUN_DRV_S);
-        SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CMD_U, FUN_DRV, 3, FUN_DRV_S);
-        SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, 3, FUN_DRV_S);
-        SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[PSRAM_CS_IO], FUN_DRV, 3, FUN_DRV_S);
-        SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[PSRAM_CLK_IO], FUN_DRV, 3, FUN_DRV_S);
-        #endif
+        SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA0_U,      FUN_DRV_V, 3, FUN_DRV_S);
+        SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA1_U,      FUN_DRV_V, 3, FUN_DRV_S);
+        SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA2_U,      FUN_DRV_V, 3, FUN_DRV_S);
+        SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA3_U,      FUN_DRV_V, 3, FUN_DRV_S);
+        SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CMD_U,        FUN_DRV_V, 3, FUN_DRV_S);
+        SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U,        FUN_DRV_V, 3, FUN_DRV_S);
+        SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[PSRAM_CS_IO],  FUN_DRV_V, 3, FUN_DRV_S);
+        SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[PSRAM_CLK_IO], FUN_DRV_V, 3, FUN_DRV_S);
     }
-    uint32_t id;
-    psram_read_id(&id);
-    if (((id >> PSRAM_MFG_ID_S) & PSRAM_MFG_ID_M) != PSRAM_MFG_ID_V) {
-        return ESP_FAIL;
+    if (PSRAM_EID(s_psram_id) == PSRAM_EID_64MBIT_1V8) {
+        // 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;
+        gpio_matrix_out(PSRAM_INTERNAL_IO_28, SIG_GPIO_OUT_IDX, 0, 0);
+        gpio_matrix_out(PSRAM_INTERNAL_IO_29, SIG_GPIO_OUT_IDX, 0, 0);
+        gpio_matrix_out(PSRAM_CLK_IO, SPICLK_OUT_IDX, 0, 0);
+    } else if (PSRAM_EID(s_psram_id) == PSRAM_EID_32MBIT_1V8 || PSRAM_EID(s_psram_id) == PSRAM_EID_64MBIT_3V3) {
+        s_clk_mode = PSRAM_CLK_MODE_DCLK;
+        if (mode == PSRAM_CACHE_F80M_S80M) {
+            /*   note: If the third mode(80Mhz+80Mhz) is enabled for 32MBit 1V8 psram and 64MBit 3.3v psram,
+                 VSPI port will be occupied by the system.
+                 Application code should never touch VSPI hardware in this case.  We try to stop applications
+                 from doing this using the drivers by claiming the port for ourselves*/
+            periph_module_enable(PERIPH_VSPI_MODULE);
+            bool r=spicommon_periph_claim(VSPI_HOST);
+            if (!r) {
+                return ESP_ERR_INVALID_STATE;
+            }
+            gpio_matrix_out(PSRAM_CLK_IO, VSPICLK_OUT_IDX, 0, 0);
+            //use spi3 clock,but use spi1 data/cs wires
+            //We get a solid 80MHz clock from SPI3 by setting it up, starting a transaction, waiting until it
+            //is in progress, then cutting the clock (but not the reset!) to that peripheral.
+            WRITE_PERI_REG(SPI_ADDR_REG(PSRAM_SPI_3), 32 << 24);
+            WRITE_PERI_REG(SPI_CLOCK_REG(PSRAM_SPI_3), SPI_CLK_EQU_SYSCLK_M);   //SET 80M AND CLEAR OTHERS
+            SET_PERI_REG_MASK(SPI_CMD_REG(PSRAM_SPI_3), SPI_FLASH_READ_M);
+            uint32_t spi_status;
+            while (1) {
+                spi_status = READ_PERI_REG(SPI_EXT2_REG(PSRAM_SPI_3));
+                if (spi_status != 0 && spi_status != 1) {
+                    DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI3_CLK_EN);
+                    break;
+                }
+            }
+        }
     }
     psram_enable_qio_mode(PSRAM_SPI_1);
-
     psram_cache_init(mode, vaddrmode);
     return ESP_OK;
 }
@@ -624,27 +682,15 @@ static void IRAM_ATTR psram_cache_init(psram_cache_mode_t psram_cache_mode, psra
             CLEAR_PERI_REG_MASK(SPI_DATE_REG(0), BIT(31));   //flash 1 div clk,80+40;
             CLEAR_PERI_REG_MASK(SPI_DATE_REG(0), BIT(30)); //pre clk div , ONLY IF SPI/SRAM@ DIFFERENT SPEED,JUST FOR SPI0. FLASH DIV 2+SRAM DIV4
             WRITE_PERI_REG(SPI_CLOCK_REG(0), SPI_CLK_EQU_SYSCLK_M);   //SET 1DIV CLOCK AND RESET OTHER PARAMS
-            SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_USR_RD_SRAM_DUMMY_M);   //enable cache read dummy
-            SET_PERI_REG_BITS(SPI_CACHE_SCTRL_REG(0), SPI_SRAM_DUMMY_CYCLELEN_V, PSRAM_FAST_READ_DUMMY + extra_dummy,
-                    SPI_SRAM_DUMMY_CYCLELEN_S); //dummy, psram cache :  40m--+1dummy,80m--+2dummy
-            SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_CACHE_SRAM_USR_RCMD_M); //enable user mode for cache read command
             break;
         case PSRAM_CACHE_F80M_S40M:
             SET_PERI_REG_MASK(SPI_DATE_REG(0), BIT(31)); //flash 1 div clk
             CLEAR_PERI_REG_MASK(SPI_DATE_REG(0), BIT(30)); //pre clk div , ONLY IF SPI/SRAM@ DIFFERENT SPEED,JUST FOR SPI0.
-            SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_USR_RD_SRAM_DUMMY_M); //enable cache read dummy
-            SET_PERI_REG_BITS(SPI_CACHE_SCTRL_REG(0), SPI_SRAM_DUMMY_CYCLELEN_V, PSRAM_FAST_READ_DUMMY + extra_dummy,
-                    SPI_SRAM_DUMMY_CYCLELEN_S); //dummy, psram cache :  40m--+1dummy,80m--+2dummy
-            SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_CACHE_SRAM_USR_RCMD_M); //enable user mode for cache read command
             break;
         case PSRAM_CACHE_F40M_S40M:
         default:
             CLEAR_PERI_REG_MASK(SPI_DATE_REG(0), BIT(31)); //flash 1 div clk
             CLEAR_PERI_REG_MASK(SPI_DATE_REG(0), BIT(30)); //pre clk div
-            SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_USR_RD_SRAM_DUMMY_M); //enable cache read dummy
-            SET_PERI_REG_BITS(SPI_CACHE_SCTRL_REG(0), SPI_SRAM_DUMMY_CYCLELEN_V, PSRAM_FAST_READ_DUMMY + extra_dummy,
-                    SPI_SRAM_DUMMY_CYCLELEN_S); //dummy, psram cache :  40m--+1dummy,80m--+2dummy
-            SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_CACHE_SRAM_USR_RCMD_M); //enable user mode for cache read command
             break;
     }
     SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_CACHE_SRAM_USR_WCMD_M);     // cache write command enable
@@ -652,30 +698,38 @@ static void IRAM_ATTR psram_cache_init(psram_cache_mode_t psram_cache_mode, psra
     SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_USR_SRAM_QIO_M);     //enable qio mode for cache command
     CLEAR_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_USR_SRAM_DIO_M);     //disable dio mode for cache command
 
+    SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_USR_RD_SRAM_DUMMY_M);   //enable cache read dummy
+    SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_CACHE_SRAM_USR_RCMD_M); //enable user mode for cache read command
+    SET_PERI_REG_BITS(SPI_SRAM_DWR_CMD_REG(0), SPI_CACHE_SRAM_USR_WR_CMD_BITLEN, 7,
+            SPI_CACHE_SRAM_USR_WR_CMD_BITLEN_S);
+    SET_PERI_REG_BITS(SPI_SRAM_DWR_CMD_REG(0), SPI_CACHE_SRAM_USR_WR_CMD_VALUE, PSRAM_QUAD_WRITE,
+            SPI_CACHE_SRAM_USR_WR_CMD_VALUE_S); //0x38
+    SET_PERI_REG_BITS(SPI_SRAM_DRD_CMD_REG(0), SPI_CACHE_SRAM_USR_RD_CMD_BITLEN_V, 7,
+            SPI_CACHE_SRAM_USR_RD_CMD_BITLEN_S);
+    SET_PERI_REG_BITS(SPI_SRAM_DRD_CMD_REG(0), SPI_CACHE_SRAM_USR_RD_CMD_VALUE_V, PSRAM_FAST_READ_QUAD,
+            SPI_CACHE_SRAM_USR_RD_CMD_VALUE_S); //0x0b
+    SET_PERI_REG_BITS(SPI_CACHE_SCTRL_REG(0), SPI_SRAM_DUMMY_CYCLELEN_V, PSRAM_FAST_READ_QUAD_DUMMY + extra_dummy,
+            SPI_SRAM_DUMMY_CYCLELEN_S); //dummy, psram cache :  40m--+1dummy,80m--+2dummy
 
     //config sram cache r/w command
     switch (psram_cache_mode) {
         case PSRAM_CACHE_F80M_S80M: //in this mode , no delay is needed
-            SET_PERI_REG_BITS(SPI_SRAM_DWR_CMD_REG(0), SPI_CACHE_SRAM_USR_WR_CMD_BITLEN, 7,
-                    SPI_CACHE_SRAM_USR_WR_CMD_BITLEN_S);
-            SET_PERI_REG_BITS(SPI_SRAM_DWR_CMD_REG(0), SPI_CACHE_SRAM_USR_WR_CMD_VALUE, PSRAM_QUAD_WRITE,
-                    SPI_CACHE_SRAM_USR_WR_CMD_VALUE_S); //0x38
-            SET_PERI_REG_BITS(SPI_SRAM_DRD_CMD_REG(0), SPI_CACHE_SRAM_USR_RD_CMD_BITLEN_V, 7,
-                    SPI_CACHE_SRAM_USR_RD_CMD_BITLEN_S);
-            SET_PERI_REG_BITS(SPI_SRAM_DRD_CMD_REG(0), SPI_CACHE_SRAM_USR_RD_CMD_VALUE_V, PSRAM_FAST_READ,
-                    SPI_CACHE_SRAM_USR_RD_CMD_VALUE_S); //0x0b
             break;
         case PSRAM_CACHE_F80M_S40M: //is sram is @40M, need 2 cycles of delay
         case PSRAM_CACHE_F40M_S40M:
         default:
-            SET_PERI_REG_BITS(SPI_SRAM_DRD_CMD_REG(0), SPI_CACHE_SRAM_USR_RD_CMD_BITLEN_V, 15,
-                    SPI_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_SRAM_DRD_CMD_REG(0), SPI_CACHE_SRAM_USR_RD_CMD_VALUE_V, ((PSRAM_FAST_READ) << 8),
-                    SPI_CACHE_SRAM_USR_RD_CMD_VALUE_S); //0x0b, read command value,(0x00 for delay,0x0b for cmd)
-            SET_PERI_REG_BITS(SPI_SRAM_DWR_CMD_REG(0), SPI_CACHE_SRAM_USR_WR_CMD_BITLEN, 15,
-                    SPI_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_SRAM_DWR_CMD_REG(0), SPI_CACHE_SRAM_USR_WR_CMD_VALUE, ((PSRAM_QUAD_WRITE) << 8),
-                    SPI_CACHE_SRAM_USR_WR_CMD_VALUE_S); //0x38, write command value,(0x00 for delay)
+            if (s_clk_mode == PSRAM_CLK_MODE_DCLK) {
+                SET_PERI_REG_BITS(SPI_SRAM_DRD_CMD_REG(0), SPI_CACHE_SRAM_USR_RD_CMD_BITLEN_V, 15,
+                        SPI_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_SRAM_DRD_CMD_REG(0), SPI_CACHE_SRAM_USR_RD_CMD_VALUE_V, ((PSRAM_FAST_READ_QUAD) << 8),
+                        SPI_CACHE_SRAM_USR_RD_CMD_VALUE_S); //0x0b, read command value,(0x00 for delay,0x0b for cmd)
+                SET_PERI_REG_BITS(SPI_SRAM_DWR_CMD_REG(0), SPI_CACHE_SRAM_USR_WR_CMD_BITLEN, 15,
+                        SPI_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_SRAM_DWR_CMD_REG(0), SPI_CACHE_SRAM_USR_WR_CMD_VALUE, ((PSRAM_QUAD_WRITE) << 8),
+                        SPI_CACHE_SRAM_USR_WR_CMD_VALUE_S); //0x38, write command value,(0x00 for delay)
+                SET_PERI_REG_BITS(SPI_CACHE_SCTRL_REG(0), SPI_SRAM_DUMMY_CYCLELEN_V, PSRAM_FAST_READ_QUAD_DUMMY + extra_dummy,
+                        SPI_SRAM_DUMMY_CYCLELEN_S); //dummy, psram cache :  40m--+1dummy,80m--+2dummy
+            }
             break;
     }
 
@@ -698,6 +752,11 @@ static void IRAM_ATTR psram_cache_init(psram_cache_mode_t psram_cache_mode, psra
 
     CLEAR_PERI_REG_MASK(SPI_PIN_REG(0), SPI_CS1_DIS_M); //ENABLE SPI0 CS1 TO PSRAM(CS0--FLASH; CS1--SRAM)
 
+    if (s_clk_mode == PSRAM_CLK_MODE_NORM) {    //different
+        SET_PERI_REG_MASK(SPI_USER_REG(0), SPI_CS_HOLD);
+        // Set cs time.
+        SET_PERI_REG_BITS(SPI_CTRL2_REG(0), SPI_SETUP_TIME_V, 1, SPI_SETUP_TIME_S);
+    }
 }
 
 #endif // CONFIG_SPIRAM_SUPPORT
index 10de4e1d6c02e20abe7d356837e2176d94d874f5..1756eed73ddef67b74d6bb6a7534325af14a884d 100644 (file)
@@ -26,6 +26,17 @@ typedef enum {
     PSRAM_CACHE_MAX,
 } psram_cache_mode_t;
 
+typedef enum {
+    PSRAM_VOLT_3V3 = 0,
+    PSRAM_VOLT_1V8 = 1,
+    PSRAM_VOLT_MAX,
+} psram_volt_t;
+
+typedef enum {
+    PSRAM_SIZE_32MBITS = 0,
+    PSRAM_SIZE_64MBITS = 1,
+    PSRAM_SIZE_MAX,
+} psram_size_t;
 
 /*
 See the TRM, chapter PID/MPU/MMU, header 'External RAM' for the definitions of these modes.
@@ -34,12 +45,29 @@ Important is that NORMAL works with the app CPU cache disabled, but gives huge c
 issues when both app and pro CPU are enabled. LOWHIGH and EVENODD do not have these coherency
 issues but cannot be used when the app CPU cache is disabled.
 */
+
 typedef enum {
     PSRAM_VADDR_MODE_NORMAL=0, ///< App and pro CPU use their own flash cache for external RAM access
     PSRAM_VADDR_MODE_LOWHIGH,  ///< App and pro CPU share external RAM caches: pro CPU has low 2M, app CPU has high 2M
     PSRAM_VADDR_MODE_EVENODD,  ///< App and pro CPU share external RAM caches: pro CPU does even 32yte ranges, app does odd ones.
 } psram_vaddr_mode_t;
 
+/**
+ * @brief get psram voltage
+ * @return
+ *     - PSRAM_VOLT_MAX if psram not enabled or not valid.
+ *     - PSRAM voltage
+ */
+psram_volt_t psram_get_volt();
+
+/**
+ * @brief get psram size
+ * @return
+ *     - PSRAM_SIZE_MAX if psram not enabled or not valid
+ *     - PSRAM size
+ */
+psram_size_t psram_get_size();
+
 /**
  * @brief psram cache enable function
  *