cwespressif commented on code in PR #10625:
URL: https://github.com/apache/nuttx/pull/10625#discussion_r1325833299


##########
arch/xtensa/src/esp32s3/esp32s3_spi_timing.c:
##########
@@ -238,129 +349,1232 @@ static void IRAM_ATTR set_flash_clock(uint8_t spi_num, 
uint32_t freqdiv)
     }
 }
 
+#if ESP32S3_SPI_TIMING_FLASH_TUNING || ESP32S3_SPI_TIMING_PSRAM_TUNING
+
 /****************************************************************************
- * Public Functions
+ * Name: init_spi1_for_tuning
+ *
+ * Description:
+ *   Initialize SPI1 for timing tuning.
+ *
+ * Input Parameters:
+ *   is_flash - is flash or not
+ *
+ * Returned Value:
+ *   None.
+ *
  ****************************************************************************/
 
+static void init_spi1_for_tuning(bool is_flash)
+{
+  /* Set SPI1 core clock. SPI0 and SPI1 share the register for core clock.
+   * So we only set SPI0 here.
+   */
+
+  REG_SET_FIELD(SPI_MEM_CORE_CLK_SEL_REG(0),
+                SPI_MEM_CORE_CLK_SEL,
+                DEFAULT_CORE_CLK_REG);
+
+  /* Set SPI1 module clock as required */
+
+  if (is_flash)
+    {
+      set_flash_clock(1, FLASH_CLOCK_DIVIDER);
+
+      /* Enable Flash HCLK */
+
+      REG_SET_BIT(SPI_MEM_TIMING_CALI_REG(0), SPI_MEM_TIMING_CLK_ENA);
+    }
+  else
+    {
+      /* We use SPI1 Flash to tune PSRAM, PSRAM timing related regs
+       * do nothing on SPI1
+       */
+
+      set_flash_clock(1, PSRAM_CLOCK_DIVIDER);
+
+      /* Enable PSRAM HCLK */
+
+      REG_SET_BIT(SPI_MEM_SPI_SMEM_TIMING_CALI_REG(0),
+                  SPI_MEM_SPI_SMEM_TIMING_CLK_ENA);
+    }
+}
+
 /****************************************************************************
- * Name: esp32s3_spi_timing_set_pin_drive_strength
+ * Name: get_dummy
  *
  * Description:
- *   Make SPI all GPIO strength to be 3 under default clock.
+ *   Get dummy cycle length
  *
  * Input Parameters:
  *   None
  *
  * Returned Value:
+ *   Dummy cycle length.
+ *
+ ****************************************************************************/
+
+static uint32_t get_dummy(void)
+{
+  uint32_t ctrl_reg = READ_PERI_REG(SPI_MEM_CTRL_REG(0));
+  if (ctrl_reg & MSPI_TIMING_LL_FLASH_OCT_MASK)
+    {
+      DEBUGASSERT(0);
+      return 0;
+    }
+
+#if ESP32S3_SPI_FLASH_HPM_ENABLE
+  /* HPM is not enabled */
+
+  DEBUGASSERT();
+  return 0;
+#endif
+  switch (ctrl_reg & MSPI_TIMING_LL_FLASH_QUAD_MASK)
+    {
+      case MSPI_TIMING_LL_FLASH_QIO_MODE_MASK:
+        return SPI1_R_QIO_DUMMY_CYCLELEN;
+      case MSPI_TIMING_LL_FLASH_DIO_MODE_MASK:
+        return SPI1_R_DIO_DUMMY_CYCLELEN;
+      case MSPI_TIMING_LL_FLASH_QUAD_MODE_MASK:
+      case MSPI_TIMING_LL_FLASH_DUAL_MODE_MASK:
+      case MSPI_TIMING_LL_FLASH_FAST_MODE_MASK:
+        return SPI1_R_FAST_DUMMY_CYCLELEN;
+      default:
+        DEBUGASSERT(0);
+        return 0;
+    }
+}
+
+/****************************************************************************
+ * Name: set_flash_extra_dummy
+ *
+ * Description:
+ *   Set MSPI Flash extra dummy
+ *
+ * Input Parameters:
+ *   spi_num     - SPI0 / 1
+ *   extra_dummy - extra dummy
+ *
+ * Returned Value:
  *   None.
  *
  ****************************************************************************/
 
-void esp32s3_spi_timing_set_pin_drive_strength(void)
+static void set_flash_extra_dummy(uint8_t spi_num, uint8_t extra_dummy)
 {
-  const uint32_t regs[] =
+#ifdef CONFIG_ESP32S3_FLASH_MODE_OCT
+  if (extra_dummy > 0)
     {
-      IO_MUX_GPIO27_REG,
-      IO_MUX_GPIO28_REG,
-      IO_MUX_GPIO31_REG,
-      IO_MUX_GPIO32_REG,
-      IO_MUX_GPIO33_REG,
-      IO_MUX_GPIO34_REG,
-      IO_MUX_GPIO35_REG,
-      IO_MUX_GPIO36_REG,
-      IO_MUX_GPIO37_REG
-    };
+      SET_PERI_REG_MASK(SPI_MEM_TIMING_CALI_REG(spi_num),
+                        SPI_MEM_TIMING_CALI_M);
+      SET_PERI_REG_BITS(SPI_MEM_TIMING_CALI_REG(spi_num),
+                        SPI_MEM_EXTRA_DUMMY_CYCLELEN_V,
+                        extra_dummy,
+                        SPI_MEM_EXTRA_DUMMY_CYCLELEN_S);
+    }
+  else
+    {
+      CLEAR_PERI_REG_MASK(SPI_MEM_TIMING_CALI_REG(spi_num),
+                          SPI_MEM_TIMING_CALI_M);
+      SET_PERI_REG_BITS(SPI_MEM_TIMING_CALI_REG(spi_num),
+                        SPI_MEM_EXTRA_DUMMY_CYCLELEN_V, 0,
+                        SPI_MEM_EXTRA_DUMMY_CYCLELEN_S);
+    }
 
-  /* Set default clock */
+  return;
+#endif
+  if (g_flash_extra_dummy[spi_num] == NOT_INIT_INT)
+    {
+      g_flash_extra_dummy[spi_num] = g_spiflash_dummy_len_plus[spi_num];
+    }
 
-  SET_PERI_REG_MASK(SPI_MEM_DATE_REG(0), SPI_MEM_SPICLK_PAD_DRV_CTL_EN);
-  REG_SET_FIELD(SPI_MEM_DATE_REG(0), SPI_MEM_SPI_SMEM_SPICLK_FUN_DRV, 3);
-  REG_SET_FIELD(SPI_MEM_DATE_REG(0), SPI_MEM_SPI_FMEM_SPICLK_FUN_DRV, 3);
+  g_spiflash_dummy_len_plus[spi_num] = g_flash_extra_dummy[(int)spi_num] +
+                                       extra_dummy;
 
-  /* Set default mspi d0 ~ d7, dqs pin drive strength */
+  /* Only Quad Flash will run into this branch. */
 
-  for (int i = 0; i < nitems(regs); i++)
+  uint32_t dummy = get_dummy();
+
+  /* Set MSPI Quad Flash dummy */
+
+  SET_PERI_REG_MASK(SPI_MEM_USER_REG(spi_num), SPI_MEM_USR_DUMMY);
+  SET_PERI_REG_BITS(SPI_MEM_USER1_REG(spi_num), SPI_MEM_USR_DUMMY_CYCLELEN_V,
+  dummy + g_spiflash_dummy_len_plus[spi_num], SPI_MEM_USR_DUMMY_CYCLELEN_S);
+}
+
+/****************************************************************************
+ * Name: set_psram_extra_dummy
+ *
+ * Description:
+ *   Set MSPI PSRAM extra dummy
+ *
+ * Input Parameters:
+ *   spi_num     - SPI0 / 1
+ *   extra_dummy - extra dummy
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+static void set_psram_extra_dummy(uint8_t spi_num, uint8_t extra_dummy)
+{
+#if CONFIG_ESP32S3_SPIRAM_MODE_OCT
+
+  /* Set MSPI Octal PSRAM extra dummy */
+
+  if (extra_dummy > 0)
     {
-      PIN_SET_DRV(regs[i], 3);
+      SET_PERI_REG_MASK(SPI_MEM_SPI_SMEM_TIMING_CALI_REG(spi_num),
+                        SPI_MEM_SPI_SMEM_TIMING_CALI_M);
+      SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_TIMING_CALI_REG(spi_num),
+                        SPI_MEM_SPI_SMEM_EXTRA_DUMMY_CYCLELEN_V,
+                        extra_dummy,
+                        SPI_MEM_SPI_SMEM_EXTRA_DUMMY_CYCLELEN_S);
+    }
+  else
+    {
+      CLEAR_PERI_REG_MASK(SPI_MEM_SPI_SMEM_TIMING_CALI_REG(spi_num),
+                          SPI_MEM_SPI_SMEM_TIMING_CALI_M);
+      SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_TIMING_CALI_REG(spi_num),
+                        SPI_MEM_SPI_SMEM_EXTRA_DUMMY_CYCLELEN_V, 0,
+                        SPI_MEM_SPI_SMEM_EXTRA_DUMMY_CYCLELEN_S);
     }
+
+#elif CONFIG_ESP32S3_SPIRAM_MODE_QUAD
+
+  /* Set MSPI QUAD PSRAM dummy.
+   * HW workaround: Use normal dummy register to set extra dummy, the
+   * calibration dedicated extra dummy register doesn't work for quad mode
+   */
+
+  SET_PERI_REG_MASK(SPI_MEM_CACHE_SCTRL_REG(spi_num),
+                    SPI_MEM_USR_RD_SRAM_DUMMY_M);
+  SET_PERI_REG_BITS(SPI_MEM_CACHE_SCTRL_REG(spi_num),
+                    SPI_MEM_SRAM_RDUMMY_CYCLELEN_V,
+                   (QPI_PSRAM_FAST_READ_DUMMY + extra_dummy - 1),
+                    SPI_MEM_SRAM_RDUMMY_CYCLELEN_S);
+#endif
 }
 
 /****************************************************************************
- * Name: esp32s3_spi_timing_set_mspi_high_speed
+ * Name: set_flash_din_mode_num
  *
  * Description:
- *   Make MSPI work under the frequency as users set, may add certain
- *   delays to MSPI RX direction to meet timing requirements.
+ *   Set MSPI Flash Din Mode and Din Num
  *
  * Input Parameters:
- *   spi1 - Select whether to control SPI1
+ *   spi_num  - SPI0 / 1
+ *   din_mode - Din mode
+ *   din_num  - Din num
  *
  * Returned Value:
  *   None.
  *
  ****************************************************************************/
 
-void IRAM_ATTR esp32s3_spi_timing_set_mspi_high_speed(bool spi1)
+static void set_flash_din_mode_num(uint8_t spi_num, uint8_t din_mode,
+                                   uint8_t din_num)
 {
-  uint32_t flash_div = FLASH_CLOCK_DIVIDER;
-  uint32_t psram_div = PSRAM_CLOCK_DIVIDER;
+  /* Set MSPI Flash din mode */
 
-  /* Set SPI0 & 1 core clock */
+  uint32_t reg_val = (REG_READ(SPI_MEM_DIN_MODE_REG(spi_num)) &
+      (~(SPI_MEM_DIN0_MODE_M | SPI_MEM_DIN1_MODE_M | SPI_MEM_DIN2_MODE_M |
+         SPI_MEM_DIN3_MODE_M | SPI_MEM_DIN4_MODE_M | SPI_MEM_DIN5_MODE_M |
+         SPI_MEM_DIN6_MODE_M | SPI_MEM_DIN7_MODE_M | SPI_MEM_DINS_MODE_M))) |
+      (din_mode << SPI_MEM_DIN0_MODE_S) | (din_mode << SPI_MEM_DIN1_MODE_S) |
+      (din_mode << SPI_MEM_DIN2_MODE_S) | (din_mode << SPI_MEM_DIN3_MODE_S) |
+      (din_mode << SPI_MEM_DIN4_MODE_S) | (din_mode << SPI_MEM_DIN5_MODE_S) |
+      (din_mode << SPI_MEM_DIN6_MODE_S) | (din_mode << SPI_MEM_DIN7_MODE_S) |
+      (din_mode << SPI_MEM_DINS_MODE_S);
+  REG_WRITE(SPI_MEM_DIN_MODE_REG(spi_num), reg_val);
 
-  REG_SET_FIELD(SPI_MEM_CORE_CLK_SEL_REG(0),
-                SPI_MEM_CORE_CLK_SEL,
-                DEFAULT_CORE_CLK_REG);
+  /* Set MSPI Flash din num */
 
-  set_flash_clock(0, flash_div);
-  if (spi1)
+  reg_val = (REG_READ(SPI_MEM_DIN_NUM_REG(spi_num)) &
+      (~(SPI_MEM_DIN0_NUM_M | SPI_MEM_DIN1_NUM_M | SPI_MEM_DIN2_NUM_M |
+         SPI_MEM_DIN3_NUM_M | SPI_MEM_DIN4_NUM_M | SPI_MEM_DIN5_NUM_M |
+         SPI_MEM_DIN6_NUM_M | SPI_MEM_DIN7_NUM_M | SPI_MEM_DINS_NUM_M))) |
+      (din_num << SPI_MEM_DIN0_NUM_S) | (din_num << SPI_MEM_DIN1_NUM_S) |
+      (din_num << SPI_MEM_DIN2_NUM_S) | (din_num << SPI_MEM_DIN3_NUM_S) |
+      (din_num << SPI_MEM_DIN4_NUM_S) | (din_num << SPI_MEM_DIN5_NUM_S) |
+      (din_num << SPI_MEM_DIN6_NUM_S) | (din_num << SPI_MEM_DIN7_NUM_S) |
+      (din_num << SPI_MEM_DINS_NUM_S);
+  REG_WRITE(SPI_MEM_DIN_NUM_REG(spi_num), reg_val);
+}
+
+/****************************************************************************
+ * Name: set_psram_din_mode_num
+ *
+ * Description:
+ *   Set MSPI PSRAM Din Mode and Din Num
+ *
+ * Input Parameters:
+ *   spi_num  - SPI0 / 1
+ *   din_mode - Din mode
+ *   din_num  - Din num
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+static void set_psram_din_mode_num(uint8_t spi_num, uint8_t din_mode,
+                                   uint8_t din_num)
+{
+  /* Set MSPI PSRAM din mode */
+
+  uint32_t reg_val = (REG_READ(SPI_MEM_SPI_SMEM_DIN_MODE_REG(spi_num)) &
+      (~(SPI_MEM_SPI_SMEM_DIN0_MODE_M | SPI_MEM_SPI_SMEM_DIN1_MODE_M |
+         SPI_MEM_SPI_SMEM_DIN2_MODE_M | SPI_MEM_SPI_SMEM_DIN3_MODE_M |
+         SPI_MEM_SPI_SMEM_DIN4_MODE_M | SPI_MEM_SPI_SMEM_DIN5_MODE_M |
+         SPI_MEM_SPI_SMEM_DIN6_MODE_M | SPI_MEM_SPI_SMEM_DIN7_MODE_M |
+         SPI_MEM_SPI_SMEM_DINS_MODE_M))) |
+         (din_mode << SPI_MEM_SPI_SMEM_DIN0_MODE_S) |
+         (din_mode << SPI_MEM_SPI_SMEM_DIN1_MODE_S) |
+         (din_mode << SPI_MEM_SPI_SMEM_DIN2_MODE_S) |
+         (din_mode << SPI_MEM_SPI_SMEM_DIN3_MODE_S) |
+         (din_mode << SPI_MEM_SPI_SMEM_DIN4_MODE_S) |
+         (din_mode << SPI_MEM_SPI_SMEM_DIN5_MODE_S) |
+         (din_mode << SPI_MEM_SPI_SMEM_DIN6_MODE_S) |
+         (din_mode << SPI_MEM_SPI_SMEM_DIN7_MODE_S) |
+         (din_mode << SPI_MEM_SPI_SMEM_DINS_MODE_S);
+  REG_WRITE(SPI_MEM_SPI_SMEM_DIN_MODE_REG(spi_num), reg_val);
+
+  /* Set MSPI PSRAM din num */
+
+  reg_val = (REG_READ(SPI_MEM_SPI_SMEM_DIN_NUM_REG(spi_num)) &
+      (~(SPI_MEM_SPI_SMEM_DIN0_NUM_M | SPI_MEM_SPI_SMEM_DIN1_NUM_M |
+         SPI_MEM_SPI_SMEM_DIN2_NUM_M | SPI_MEM_SPI_SMEM_DIN3_NUM_M |
+         SPI_MEM_SPI_SMEM_DIN4_NUM_M | SPI_MEM_SPI_SMEM_DIN5_NUM_M |
+         SPI_MEM_SPI_SMEM_DIN6_NUM_M | SPI_MEM_SPI_SMEM_DIN7_NUM_M |
+         SPI_MEM_SPI_SMEM_DINS_NUM_M))) |
+         (din_num << SPI_MEM_SPI_SMEM_DIN0_NUM_S) |
+         (din_num << SPI_MEM_SPI_SMEM_DIN1_NUM_S) |
+         (din_num << SPI_MEM_SPI_SMEM_DIN2_NUM_S) |
+         (din_num << SPI_MEM_SPI_SMEM_DIN3_NUM_S) |
+         (din_num << SPI_MEM_SPI_SMEM_DIN4_NUM_S) |
+         (din_num << SPI_MEM_SPI_SMEM_DIN5_NUM_S) |
+         (din_num << SPI_MEM_SPI_SMEM_DIN6_NUM_S) |
+         (din_num << SPI_MEM_SPI_SMEM_DIN7_NUM_S) |
+         (din_num << SPI_MEM_SPI_SMEM_DINS_NUM_S);
+  REG_WRITE(SPI_MEM_SPI_SMEM_DIN_NUM_REG(spi_num), reg_val);
+}
+
+#if ESP32S3_SPI_TIMING_FLASH_TUNING
+
+/****************************************************************************
+ * Name: config_flash_read_data
+ *
+ * Description:
+ *   Configure Flash to read data via SPI1h
+ *
+ * Input Parameters:
+ *   buf  - data buffer pointer
+ *   addr - target address value
+ *   len  - data length
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+static void config_flash_read_data(uint8_t *buf, uint32_t addr, uint32_t len)
+{
+#ifdef CONFIG_ESP32S3_FLASH_MODE_OCT
+  /* Clear MSPI hw fifo */
+
+  for (int i = 0; i < 16; i++)
     {
-      set_flash_clock(1, flash_div);
+      REG_WRITE(SPI_MEM_W0_REG(1) + i * 4, 0);

Review Comment:
   Already replaced, REG_WRITE is the same as putreg32.



##########
arch/xtensa/src/esp32s3/esp32s3_spi_timing.c:
##########
@@ -238,129 +349,1232 @@ static void IRAM_ATTR set_flash_clock(uint8_t spi_num, 
uint32_t freqdiv)
     }
 }
 
+#if ESP32S3_SPI_TIMING_FLASH_TUNING || ESP32S3_SPI_TIMING_PSRAM_TUNING
+
 /****************************************************************************
- * Public Functions
+ * Name: init_spi1_for_tuning
+ *
+ * Description:
+ *   Initialize SPI1 for timing tuning.
+ *
+ * Input Parameters:
+ *   is_flash - is flash or not
+ *
+ * Returned Value:
+ *   None.
+ *
  ****************************************************************************/
 
+static void init_spi1_for_tuning(bool is_flash)
+{
+  /* Set SPI1 core clock. SPI0 and SPI1 share the register for core clock.
+   * So we only set SPI0 here.
+   */
+
+  REG_SET_FIELD(SPI_MEM_CORE_CLK_SEL_REG(0),
+                SPI_MEM_CORE_CLK_SEL,
+                DEFAULT_CORE_CLK_REG);
+
+  /* Set SPI1 module clock as required */
+
+  if (is_flash)
+    {
+      set_flash_clock(1, FLASH_CLOCK_DIVIDER);
+
+      /* Enable Flash HCLK */
+
+      REG_SET_BIT(SPI_MEM_TIMING_CALI_REG(0), SPI_MEM_TIMING_CLK_ENA);
+    }
+  else
+    {
+      /* We use SPI1 Flash to tune PSRAM, PSRAM timing related regs
+       * do nothing on SPI1
+       */
+
+      set_flash_clock(1, PSRAM_CLOCK_DIVIDER);
+
+      /* Enable PSRAM HCLK */
+
+      REG_SET_BIT(SPI_MEM_SPI_SMEM_TIMING_CALI_REG(0),
+                  SPI_MEM_SPI_SMEM_TIMING_CLK_ENA);
+    }
+}
+
 /****************************************************************************
- * Name: esp32s3_spi_timing_set_pin_drive_strength
+ * Name: get_dummy
  *
  * Description:
- *   Make SPI all GPIO strength to be 3 under default clock.
+ *   Get dummy cycle length
  *
  * Input Parameters:
  *   None
  *
  * Returned Value:
+ *   Dummy cycle length.
+ *
+ ****************************************************************************/
+
+static uint32_t get_dummy(void)
+{
+  uint32_t ctrl_reg = READ_PERI_REG(SPI_MEM_CTRL_REG(0));
+  if (ctrl_reg & MSPI_TIMING_LL_FLASH_OCT_MASK)
+    {
+      DEBUGASSERT(0);
+      return 0;
+    }
+
+#if ESP32S3_SPI_FLASH_HPM_ENABLE
+  /* HPM is not enabled */
+
+  DEBUGASSERT();
+  return 0;
+#endif
+  switch (ctrl_reg & MSPI_TIMING_LL_FLASH_QUAD_MASK)
+    {
+      case MSPI_TIMING_LL_FLASH_QIO_MODE_MASK:
+        return SPI1_R_QIO_DUMMY_CYCLELEN;
+      case MSPI_TIMING_LL_FLASH_DIO_MODE_MASK:
+        return SPI1_R_DIO_DUMMY_CYCLELEN;
+      case MSPI_TIMING_LL_FLASH_QUAD_MODE_MASK:
+      case MSPI_TIMING_LL_FLASH_DUAL_MODE_MASK:
+      case MSPI_TIMING_LL_FLASH_FAST_MODE_MASK:
+        return SPI1_R_FAST_DUMMY_CYCLELEN;
+      default:
+        DEBUGASSERT(0);
+        return 0;
+    }
+}
+
+/****************************************************************************
+ * Name: set_flash_extra_dummy
+ *
+ * Description:
+ *   Set MSPI Flash extra dummy
+ *
+ * Input Parameters:
+ *   spi_num     - SPI0 / 1
+ *   extra_dummy - extra dummy
+ *
+ * Returned Value:
  *   None.
  *
  ****************************************************************************/
 
-void esp32s3_spi_timing_set_pin_drive_strength(void)
+static void set_flash_extra_dummy(uint8_t spi_num, uint8_t extra_dummy)
 {
-  const uint32_t regs[] =
+#ifdef CONFIG_ESP32S3_FLASH_MODE_OCT
+  if (extra_dummy > 0)
     {
-      IO_MUX_GPIO27_REG,
-      IO_MUX_GPIO28_REG,
-      IO_MUX_GPIO31_REG,
-      IO_MUX_GPIO32_REG,
-      IO_MUX_GPIO33_REG,
-      IO_MUX_GPIO34_REG,
-      IO_MUX_GPIO35_REG,
-      IO_MUX_GPIO36_REG,
-      IO_MUX_GPIO37_REG
-    };
+      SET_PERI_REG_MASK(SPI_MEM_TIMING_CALI_REG(spi_num),
+                        SPI_MEM_TIMING_CALI_M);
+      SET_PERI_REG_BITS(SPI_MEM_TIMING_CALI_REG(spi_num),
+                        SPI_MEM_EXTRA_DUMMY_CYCLELEN_V,
+                        extra_dummy,
+                        SPI_MEM_EXTRA_DUMMY_CYCLELEN_S);
+    }
+  else
+    {
+      CLEAR_PERI_REG_MASK(SPI_MEM_TIMING_CALI_REG(spi_num),
+                          SPI_MEM_TIMING_CALI_M);
+      SET_PERI_REG_BITS(SPI_MEM_TIMING_CALI_REG(spi_num),
+                        SPI_MEM_EXTRA_DUMMY_CYCLELEN_V, 0,
+                        SPI_MEM_EXTRA_DUMMY_CYCLELEN_S);
+    }
 
-  /* Set default clock */
+  return;
+#endif
+  if (g_flash_extra_dummy[spi_num] == NOT_INIT_INT)
+    {
+      g_flash_extra_dummy[spi_num] = g_spiflash_dummy_len_plus[spi_num];
+    }
 
-  SET_PERI_REG_MASK(SPI_MEM_DATE_REG(0), SPI_MEM_SPICLK_PAD_DRV_CTL_EN);
-  REG_SET_FIELD(SPI_MEM_DATE_REG(0), SPI_MEM_SPI_SMEM_SPICLK_FUN_DRV, 3);
-  REG_SET_FIELD(SPI_MEM_DATE_REG(0), SPI_MEM_SPI_FMEM_SPICLK_FUN_DRV, 3);
+  g_spiflash_dummy_len_plus[spi_num] = g_flash_extra_dummy[(int)spi_num] +
+                                       extra_dummy;
 
-  /* Set default mspi d0 ~ d7, dqs pin drive strength */
+  /* Only Quad Flash will run into this branch. */
 
-  for (int i = 0; i < nitems(regs); i++)
+  uint32_t dummy = get_dummy();
+
+  /* Set MSPI Quad Flash dummy */
+
+  SET_PERI_REG_MASK(SPI_MEM_USER_REG(spi_num), SPI_MEM_USR_DUMMY);
+  SET_PERI_REG_BITS(SPI_MEM_USER1_REG(spi_num), SPI_MEM_USR_DUMMY_CYCLELEN_V,
+  dummy + g_spiflash_dummy_len_plus[spi_num], SPI_MEM_USR_DUMMY_CYCLELEN_S);
+}
+
+/****************************************************************************
+ * Name: set_psram_extra_dummy
+ *
+ * Description:
+ *   Set MSPI PSRAM extra dummy
+ *
+ * Input Parameters:
+ *   spi_num     - SPI0 / 1
+ *   extra_dummy - extra dummy
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+static void set_psram_extra_dummy(uint8_t spi_num, uint8_t extra_dummy)
+{
+#if CONFIG_ESP32S3_SPIRAM_MODE_OCT
+
+  /* Set MSPI Octal PSRAM extra dummy */
+
+  if (extra_dummy > 0)
     {
-      PIN_SET_DRV(regs[i], 3);
+      SET_PERI_REG_MASK(SPI_MEM_SPI_SMEM_TIMING_CALI_REG(spi_num),
+                        SPI_MEM_SPI_SMEM_TIMING_CALI_M);
+      SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_TIMING_CALI_REG(spi_num),
+                        SPI_MEM_SPI_SMEM_EXTRA_DUMMY_CYCLELEN_V,
+                        extra_dummy,
+                        SPI_MEM_SPI_SMEM_EXTRA_DUMMY_CYCLELEN_S);
+    }
+  else
+    {
+      CLEAR_PERI_REG_MASK(SPI_MEM_SPI_SMEM_TIMING_CALI_REG(spi_num),
+                          SPI_MEM_SPI_SMEM_TIMING_CALI_M);
+      SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_TIMING_CALI_REG(spi_num),
+                        SPI_MEM_SPI_SMEM_EXTRA_DUMMY_CYCLELEN_V, 0,
+                        SPI_MEM_SPI_SMEM_EXTRA_DUMMY_CYCLELEN_S);
     }
+
+#elif CONFIG_ESP32S3_SPIRAM_MODE_QUAD
+
+  /* Set MSPI QUAD PSRAM dummy.
+   * HW workaround: Use normal dummy register to set extra dummy, the
+   * calibration dedicated extra dummy register doesn't work for quad mode
+   */
+
+  SET_PERI_REG_MASK(SPI_MEM_CACHE_SCTRL_REG(spi_num),
+                    SPI_MEM_USR_RD_SRAM_DUMMY_M);
+  SET_PERI_REG_BITS(SPI_MEM_CACHE_SCTRL_REG(spi_num),
+                    SPI_MEM_SRAM_RDUMMY_CYCLELEN_V,
+                   (QPI_PSRAM_FAST_READ_DUMMY + extra_dummy - 1),
+                    SPI_MEM_SRAM_RDUMMY_CYCLELEN_S);
+#endif
 }
 
 /****************************************************************************
- * Name: esp32s3_spi_timing_set_mspi_high_speed
+ * Name: set_flash_din_mode_num
  *
  * Description:
- *   Make MSPI work under the frequency as users set, may add certain
- *   delays to MSPI RX direction to meet timing requirements.
+ *   Set MSPI Flash Din Mode and Din Num
  *
  * Input Parameters:
- *   spi1 - Select whether to control SPI1
+ *   spi_num  - SPI0 / 1
+ *   din_mode - Din mode
+ *   din_num  - Din num
  *
  * Returned Value:
  *   None.
  *
  ****************************************************************************/
 
-void IRAM_ATTR esp32s3_spi_timing_set_mspi_high_speed(bool spi1)
+static void set_flash_din_mode_num(uint8_t spi_num, uint8_t din_mode,
+                                   uint8_t din_num)
 {
-  uint32_t flash_div = FLASH_CLOCK_DIVIDER;
-  uint32_t psram_div = PSRAM_CLOCK_DIVIDER;
+  /* Set MSPI Flash din mode */
 
-  /* Set SPI0 & 1 core clock */
+  uint32_t reg_val = (REG_READ(SPI_MEM_DIN_MODE_REG(spi_num)) &
+      (~(SPI_MEM_DIN0_MODE_M | SPI_MEM_DIN1_MODE_M | SPI_MEM_DIN2_MODE_M |
+         SPI_MEM_DIN3_MODE_M | SPI_MEM_DIN4_MODE_M | SPI_MEM_DIN5_MODE_M |
+         SPI_MEM_DIN6_MODE_M | SPI_MEM_DIN7_MODE_M | SPI_MEM_DINS_MODE_M))) |
+      (din_mode << SPI_MEM_DIN0_MODE_S) | (din_mode << SPI_MEM_DIN1_MODE_S) |
+      (din_mode << SPI_MEM_DIN2_MODE_S) | (din_mode << SPI_MEM_DIN3_MODE_S) |
+      (din_mode << SPI_MEM_DIN4_MODE_S) | (din_mode << SPI_MEM_DIN5_MODE_S) |
+      (din_mode << SPI_MEM_DIN6_MODE_S) | (din_mode << SPI_MEM_DIN7_MODE_S) |
+      (din_mode << SPI_MEM_DINS_MODE_S);
+  REG_WRITE(SPI_MEM_DIN_MODE_REG(spi_num), reg_val);
 
-  REG_SET_FIELD(SPI_MEM_CORE_CLK_SEL_REG(0),
-                SPI_MEM_CORE_CLK_SEL,
-                DEFAULT_CORE_CLK_REG);
+  /* Set MSPI Flash din num */
 
-  set_flash_clock(0, flash_div);
-  if (spi1)
+  reg_val = (REG_READ(SPI_MEM_DIN_NUM_REG(spi_num)) &
+      (~(SPI_MEM_DIN0_NUM_M | SPI_MEM_DIN1_NUM_M | SPI_MEM_DIN2_NUM_M |
+         SPI_MEM_DIN3_NUM_M | SPI_MEM_DIN4_NUM_M | SPI_MEM_DIN5_NUM_M |
+         SPI_MEM_DIN6_NUM_M | SPI_MEM_DIN7_NUM_M | SPI_MEM_DINS_NUM_M))) |
+      (din_num << SPI_MEM_DIN0_NUM_S) | (din_num << SPI_MEM_DIN1_NUM_S) |
+      (din_num << SPI_MEM_DIN2_NUM_S) | (din_num << SPI_MEM_DIN3_NUM_S) |
+      (din_num << SPI_MEM_DIN4_NUM_S) | (din_num << SPI_MEM_DIN5_NUM_S) |
+      (din_num << SPI_MEM_DIN6_NUM_S) | (din_num << SPI_MEM_DIN7_NUM_S) |
+      (din_num << SPI_MEM_DINS_NUM_S);
+  REG_WRITE(SPI_MEM_DIN_NUM_REG(spi_num), reg_val);
+}
+
+/****************************************************************************
+ * Name: set_psram_din_mode_num
+ *
+ * Description:
+ *   Set MSPI PSRAM Din Mode and Din Num
+ *
+ * Input Parameters:
+ *   spi_num  - SPI0 / 1
+ *   din_mode - Din mode
+ *   din_num  - Din num
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+static void set_psram_din_mode_num(uint8_t spi_num, uint8_t din_mode,
+                                   uint8_t din_num)
+{
+  /* Set MSPI PSRAM din mode */
+
+  uint32_t reg_val = (REG_READ(SPI_MEM_SPI_SMEM_DIN_MODE_REG(spi_num)) &
+      (~(SPI_MEM_SPI_SMEM_DIN0_MODE_M | SPI_MEM_SPI_SMEM_DIN1_MODE_M |
+         SPI_MEM_SPI_SMEM_DIN2_MODE_M | SPI_MEM_SPI_SMEM_DIN3_MODE_M |
+         SPI_MEM_SPI_SMEM_DIN4_MODE_M | SPI_MEM_SPI_SMEM_DIN5_MODE_M |
+         SPI_MEM_SPI_SMEM_DIN6_MODE_M | SPI_MEM_SPI_SMEM_DIN7_MODE_M |
+         SPI_MEM_SPI_SMEM_DINS_MODE_M))) |
+         (din_mode << SPI_MEM_SPI_SMEM_DIN0_MODE_S) |
+         (din_mode << SPI_MEM_SPI_SMEM_DIN1_MODE_S) |
+         (din_mode << SPI_MEM_SPI_SMEM_DIN2_MODE_S) |
+         (din_mode << SPI_MEM_SPI_SMEM_DIN3_MODE_S) |
+         (din_mode << SPI_MEM_SPI_SMEM_DIN4_MODE_S) |
+         (din_mode << SPI_MEM_SPI_SMEM_DIN5_MODE_S) |
+         (din_mode << SPI_MEM_SPI_SMEM_DIN6_MODE_S) |
+         (din_mode << SPI_MEM_SPI_SMEM_DIN7_MODE_S) |
+         (din_mode << SPI_MEM_SPI_SMEM_DINS_MODE_S);
+  REG_WRITE(SPI_MEM_SPI_SMEM_DIN_MODE_REG(spi_num), reg_val);
+
+  /* Set MSPI PSRAM din num */
+
+  reg_val = (REG_READ(SPI_MEM_SPI_SMEM_DIN_NUM_REG(spi_num)) &
+      (~(SPI_MEM_SPI_SMEM_DIN0_NUM_M | SPI_MEM_SPI_SMEM_DIN1_NUM_M |
+         SPI_MEM_SPI_SMEM_DIN2_NUM_M | SPI_MEM_SPI_SMEM_DIN3_NUM_M |
+         SPI_MEM_SPI_SMEM_DIN4_NUM_M | SPI_MEM_SPI_SMEM_DIN5_NUM_M |
+         SPI_MEM_SPI_SMEM_DIN6_NUM_M | SPI_MEM_SPI_SMEM_DIN7_NUM_M |
+         SPI_MEM_SPI_SMEM_DINS_NUM_M))) |
+         (din_num << SPI_MEM_SPI_SMEM_DIN0_NUM_S) |
+         (din_num << SPI_MEM_SPI_SMEM_DIN1_NUM_S) |
+         (din_num << SPI_MEM_SPI_SMEM_DIN2_NUM_S) |
+         (din_num << SPI_MEM_SPI_SMEM_DIN3_NUM_S) |
+         (din_num << SPI_MEM_SPI_SMEM_DIN4_NUM_S) |
+         (din_num << SPI_MEM_SPI_SMEM_DIN5_NUM_S) |
+         (din_num << SPI_MEM_SPI_SMEM_DIN6_NUM_S) |
+         (din_num << SPI_MEM_SPI_SMEM_DIN7_NUM_S) |
+         (din_num << SPI_MEM_SPI_SMEM_DINS_NUM_S);
+  REG_WRITE(SPI_MEM_SPI_SMEM_DIN_NUM_REG(spi_num), reg_val);
+}
+
+#if ESP32S3_SPI_TIMING_FLASH_TUNING
+
+/****************************************************************************
+ * Name: config_flash_read_data
+ *
+ * Description:
+ *   Configure Flash to read data via SPI1h
+ *
+ * Input Parameters:
+ *   buf  - data buffer pointer
+ *   addr - target address value
+ *   len  - data length
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+static void config_flash_read_data(uint8_t *buf, uint32_t addr, uint32_t len)
+{
+#ifdef CONFIG_ESP32S3_FLASH_MODE_OCT
+  /* Clear MSPI hw fifo */
+
+  for (int i = 0; i < 16; i++)
     {
-      set_flash_clock(1, flash_div);
+      REG_WRITE(SPI_MEM_W0_REG(1) + i * 4, 0);
     }
 
-  set_psram_clock(0, psram_div);
+  esp_rom_opiflash_read_raw(addr, buf, len);
+#else
+  esp_rom_spiflash_read(addr, (uint32_t *)buf, len);
+#endif
 }
 
 /****************************************************************************
- * Name: esp32s3_spi_timing_set_mspi_low_speed
+ * Name: config_flash_set_tuning_regs
  *
  * Description:
- *   Make MSPI work under 20MHz and remove the timing tuning required delays.
+ *   Tune Flash timing registers for SPI1 accessing Flash
  *
  * Input Parameters:
- *   spi1 - Select whether to control SPI1
+ *   params - tuning timing parameters pointer
  *
  * Returned Value:
  *   None.
  *
  ****************************************************************************/
 
-void IRAM_ATTR esp32s3_spi_timing_set_mspi_low_speed(bool spi1)
+static void config_flash_set_tuning_regs(const tuning_param_s *params)
 {
-  /**
-   * Here we are going to set the SPI1 frequency to be 20MHz,
-   * so we need to set SPI1 din_num and din_mode regs.
-   *
-   * Because SPI0 and SPI1 share the din_num and din_mode regs,
-   * but if we clear SPI1 din_num and din_mode to 0 and SPI0 flash
-   * module clock is still in high freq, it may not work correctly.
-   *
-   * Therefore, we need to set both the SPI0 and SPI1 and related
-   * timing tuning regs to be 20MHz.
+  /* SPI_MEM_DINx_MODE(1), SPI_MEM_DINx_NUM(1) are meaningless SPI0 and SPI1
+   * share SPI_MEM_DINx_MODE(0), SPI_MEM_DINx_NUM(0) for FLASH timing tuning
+   * We use SPI1 to get the best Flash timing tuning (mode and num) config
    */
 
-  /* Set SPIMEM core clock as 80MHz, and set SPI1 and SPI0 clock
-   * to be 20MHz by setting clock division as 4
-   */
+  set_flash_din_mode_num(0, params->spi_din_mode, params->spi_din_num);
+  set_flash_extra_dummy(1, params->extra_dummy_len);
+}
 
-  REG_SET_FIELD(SPI_MEM_CORE_CLK_SEL_REG(0),
-                SPI_MEM_CORE_CLK_SEL,
-                CORE_CLK_REG_SEL_80M);
+/****************************************************************************
+ * Name: get_flash_tuning_configs
+ *
+ * Description:
+ *   Get FLASH tuning configuration.
+ *
+ * Input Parameters:
+ *   config - tuning timing configuration pointer
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
 
-  set_flash_clock(0, 4);
-  if (spi1)
-    {
-      /* After tuning, won't touch SPI1 again */
+static void get_flash_tuning_configs(tuning_config_s *config)
+{
+#if MSPI_TIMING_FLASH_DTR_MODE
+#  define FLASH_MODE  DTR_MODE
+#else
+#  define FLASH_MODE  STR_MODE
+#endif
 
-      set_flash_clock(1, 4);
+#if CONFIG_ESP32S3_FLASH_FREQ_20M
+    *config = MSPI_TIMING_FLASH_GET_TUNING_CONFIG(
+                ESP32S3_SPI_TIMING_CORE_CLK, 20, FLASH_MODE);
+#elif CONFIG_ESP32S3_FLASH_FREQ_40M
+    *config = MSPI_TIMING_FLASH_GET_TUNING_CONFIG(
+                ESP32S3_SPI_TIMING_CORE_CLK, 40, FLASH_MODE);
+#elif CONFIG_ESP32S3_FLASH_FREQ_80M
+    *config = MSPI_TIMING_FLASH_GET_TUNING_CONFIG(
+                ESP32S3_SPI_TIMING_CORE_CLK, 80, FLASH_MODE);
+#elif CONFIG_ESP32S3_FLASH_FREQ_120M
+    *config = MSPI_TIMING_FLASH_GET_TUNING_CONFIG(
+                ESP32S3_SPI_TIMING_CORE_CLK, 120, FLASH_MODE);
+#endif
+
+#undef FLASH_MODE
+}
+#endif
+
+#if ESP32S3_SPI_TIMING_PSRAM_TUNING
+
+/****************************************************************************
+ * Name: psram_read_data
+ *
+ * Description:
+ *   Configure PSRAM to read data via SPI1.
+ *
+ * Input Parameters:
+ *   buf  - data buffer pointer
+ *   addr - target address value
+ *   len  - data length
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+static void psram_read_data(uint8_t *buf, uint32_t addr, uint32_t len)
+{
+#if CONFIG_ESP32S3_SPIRAM_MODE_OCT
+
+  /* Clear MSPI hw fifo */
+
+  for (int i = 0; i < 16; i++)
+    {
+      REG_WRITE(SPI_MEM_W0_REG(1) + i * 4, 0);
     }
+
+  esp_rom_opiflash_exec_cmd(1, ESP_ROM_SPIFLASH_OPI_DTR_MODE,
+                            OPI_PSRAM_SYNC_READ, 16,
+                            addr, 32,
+                            OCT_PSRAM_RD_DUMMY_NUM,
+                            NULL, 0,
+                            buf, len * 8,
+                            BIT(1),
+                            false);
+#elif CONFIG_ESP32S3_SPIRAM_MODE_QUAD
+  psram_exec_cmd(1, 0,
+                 QPI_PSRAM_FAST_READ, 8,
+                 addr, 24,
+                 QPI_PSRAM_FAST_READ_DUMMY + g_psram_extra_dummy,
+                 NULL, 0,
+                 buf, len * 8,
+                 SPI_MEM_CS1_DIS_M,
+                 false);
+#endif
+}
+
+/****************************************************************************
+ * Name: psram_write_data
+ *
+ * Description:
+ *   Configure PSRAM to write data via SPI1.
+ *
+ * Input Parameters:
+ *   buf  - data buffer pointer
+ *   addr - target address value
+ *   len  - data length
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+static void psram_write_data(uint8_t *buf, uint32_t addr, uint32_t len)
+{
+#if CONFIG_ESP32S3_SPIRAM_MODE_OCT
+  esp_rom_opiflash_exec_cmd(1, ESP_ROM_SPIFLASH_OPI_DTR_MODE,
+                            OPI_PSRAM_SYNC_WRITE, 16,
+                            addr, 32,
+                            OCT_PSRAM_WR_DUMMY_NUM,
+                            buf, len * 8,
+                            NULL, 0,
+                            BIT(1),
+                            false);
+#elif CONFIG_ESP32S3_SPIRAM_MODE_QUAD
+  psram_exec_cmd(1, 0,
+                 QPI_PSRAM_WRITE, 8,  /* command and command bit len */
+                 addr, 24,            /* address and address bit len */
+                 0,                   /* dummy bit len */
+                 buf, len * 8,        /* tx data and tx bit len */
+                 NULL, 0,             /* rx data and rx bit len */
+                 SPI_MEM_CS1_DIS_M,   /* cs bit mask */
+                 false);              /* whether is program/erase operation */
+#endif
+}
+
+/****************************************************************************
+ * Name: config_psram_read_write_data
+ *
+ * Description:
+ *   Configure PSRAM to read or write data via SPI1.
+ *
+ * Input Parameters:
+ *   buf     - data buffer pointer
+ *   addr    - target address value
+ *   len     - data length
+ *   is_read - is read or write
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+static void config_psram_read_write_data(uint8_t *buf, uint32_t addr,
+                                         uint32_t len, bool is_read)
+{
+  while (len)

Review Comment:
   Done



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to