mspi_timing_by_mspi_delay.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626
  1. /*
  2. * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /**
  7. * @brief
  8. *
  9. * This file contains configuration APIs doing MSPI timing tuning by MSPI delay
  10. * This file will only be built, when `SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY == 1`
  11. */
  12. #include <sys/param.h>
  13. #include "sdkconfig.h"
  14. #include "string.h"
  15. #include "esp_attr.h"
  16. #include "esp_err.h"
  17. #include "esp_types.h"
  18. #include "esp_log.h"
  19. #include "soc/rtc.h"
  20. #include "hal/mspi_timing_tuning_ll.h"
  21. #include "hal/clk_tree_ll.h"
  22. #include "hal/regi2c_ctrl_ll.h"
  23. #include "mspi_timing_config.h"
  24. #include "mspi_timing_by_mspi_delay.h"
  25. #include "bootloader_flash.h"
  26. #include "esp32s3/rom/spi_flash.h"
  27. #include "esp32s3/rom/opi_flash.h"
  28. #define OPI_PSRAM_SYNC_READ 0x0000
  29. #define OPI_PSRAM_SYNC_WRITE 0x8080
  30. #define OCT_PSRAM_RD_DUMMY_NUM (2*(10-1))
  31. #define OCT_PSRAM_WR_DUMMY_NUM (2*(5-1))
  32. #define QPI_PSRAM_FAST_READ 0XEB
  33. #define QPI_PSRAM_WRITE 0X38
  34. #define QPI_PSRAM_FAST_READ_DUMMY 6
  35. #define NOT_INIT_INT 127
  36. /////////////////////////////////////////TIMING TUNING IS NEEDED//////////////////////////////////////////////
  37. //////////////////////////////////////////////////////////////////////////////////////////////////////////////
  38. #if MSPI_TIMING_FLASH_NEEDS_TUNING || MSPI_TIMING_PSRAM_NEEDS_TUNING
  39. const static char *TAG = "MSPI Timing";
  40. //If one of the FLASH / PSRAM or both of them need timing tuning, we should build following code
  41. typedef enum {
  42. PSRAM_CMD_QPI,
  43. PSRAM_CMD_SPI,
  44. } psram_cmd_mode_t;
  45. static uint8_t s_rom_flash_extra_dummy[2] = {NOT_INIT_INT, NOT_INIT_INT};
  46. #if CONFIG_SPIRAM_MODE_QUAD
  47. static uint8_t s_psram_extra_dummy;
  48. extern void psram_exec_cmd(int spi_num, psram_cmd_mode_t mode,
  49. uint32_t cmd, int cmd_bit_len,
  50. uint32_t addr, int addr_bit_len,
  51. int dummy_bits,
  52. uint8_t* mosi_data, int mosi_bit_len,
  53. uint8_t* miso_data, int miso_bit_len,
  54. uint32_t cs_mask,
  55. bool is_write_erase_operation);
  56. #endif
  57. //-------------------------------------FLASH timing tuning register config-------------------------------------//
  58. void mspi_timing_get_flash_tuning_configs(mspi_timing_config_t *config)
  59. {
  60. #if MSPI_TIMING_FLASH_DTR_MODE
  61. #define FLASH_MODE DTR_MODE
  62. #else //MSPI_TIMING_FLASH_STR_MODE
  63. #define FLASH_MODE STR_MODE
  64. #endif
  65. #if CONFIG_ESPTOOLPY_FLASHFREQ_80M
  66. *config = MSPI_TIMING_FLASH_GET_TUNING_CONFIG(MSPI_TIMING_CORE_CLOCK_MHZ, 80, FLASH_MODE);
  67. #elif CONFIG_ESPTOOLPY_FLASHFREQ_120M
  68. *config = MSPI_TIMING_FLASH_GET_TUNING_CONFIG(MSPI_TIMING_CORE_CLOCK_MHZ, 120, FLASH_MODE);
  69. #else
  70. assert(false && "should never reach here");
  71. #endif
  72. #undef FLASH_MODE
  73. }
  74. void mspi_timing_flash_init(uint32_t flash_freq_mhz)
  75. {
  76. mspi_timing_config_set_flash_clock(flash_freq_mhz, MSPI_TIMING_SPEED_MODE_NORMAL_PERF, true);
  77. //Power on HCLK
  78. mspi_timinng_ll_enable_flash_hclk(0);
  79. }
  80. static void s_set_flash_din_mode_num(uint8_t spi_num, uint8_t din_mode, uint8_t din_num)
  81. {
  82. mspi_timing_ll_set_flash_din_mode(spi_num, din_mode);
  83. mspi_timing_ll_set_flash_din_num(spi_num, din_num);
  84. }
  85. static uint32_t spi_timing_config_get_dummy(void)
  86. {
  87. mspi_timing_ll_flash_mode_t mode = mspi_timing_ll_get_flash_mode(0);
  88. if (mode == MSPI_TIMING_LL_FLASH_OPI_MODE) {
  89. abort();
  90. }
  91. #if CONFIG_SPI_FLASH_HPM_DC_ON
  92. if (spi_flash_hpm_dummy_adjust()) { // HPM-DC is enabled
  93. const spi_flash_hpm_dummy_conf_t *hpm_dummy = spi_flash_hpm_get_dummy();
  94. switch (mode) {
  95. case MSPI_TIMING_LL_FLASH_QIO_MODE:
  96. return hpm_dummy->qio_dummy - 1;
  97. case MSPI_TIMING_LL_FLASH_QUAD_MODE:
  98. return hpm_dummy->qout_dummy - 1;
  99. case MSPI_TIMING_LL_FLASH_DIO_MODE:
  100. return hpm_dummy->dio_dummy - 1;
  101. case MSPI_TIMING_LL_FLASH_DUAL_MODE:
  102. return hpm_dummy->dout_dummy - 1;
  103. case MSPI_TIMING_LL_FLASH_FAST_MODE:
  104. return hpm_dummy->fastrd_dummy - 1;
  105. case MSPI_TIMING_LL_FLASH_SLOW_MODE:
  106. return 0;
  107. default:
  108. abort();
  109. }
  110. } else
  111. #endif
  112. { // HPM-DC is not enabled
  113. switch (mode) {
  114. case MSPI_TIMING_LL_FLASH_QIO_MODE:
  115. return SPI1_R_QIO_DUMMY_CYCLELEN;
  116. case MSPI_TIMING_LL_FLASH_QUAD_MODE:
  117. return SPI1_R_FAST_DUMMY_CYCLELEN;
  118. case MSPI_TIMING_LL_FLASH_DIO_MODE:
  119. return SPI1_R_DIO_DUMMY_CYCLELEN;
  120. case MSPI_TIMING_LL_FLASH_DUAL_MODE:
  121. return SPI1_R_FAST_DUMMY_CYCLELEN;
  122. case MSPI_TIMING_LL_FLASH_FAST_MODE:
  123. return SPI1_R_FAST_DUMMY_CYCLELEN;
  124. case MSPI_TIMING_LL_FLASH_SLOW_MODE:
  125. return 0;
  126. default:
  127. abort();
  128. }
  129. }
  130. }
  131. static void s_set_flash_extra_dummy(uint8_t spi_num, uint8_t extra_dummy)
  132. {
  133. if (bootloader_flash_is_octal_mode_enabled()) {
  134. mspi_timing_ll_set_octal_flash_extra_dummy(spi_num, extra_dummy);
  135. return;
  136. }
  137. /**
  138. * HW workaround:
  139. * The `SPI_MEM_TIMING_CALI_REG` register is only used for OPI on 728
  140. * Here we only need to update this global variable for extra dummy. Since we use the ROM Flash API, which will set the dummy based on this.
  141. * We only initialise the SPI0. And leave the SPI1 for flash driver to configure.
  142. */
  143. if (s_rom_flash_extra_dummy[spi_num] == NOT_INIT_INT) {
  144. s_rom_flash_extra_dummy[spi_num] = g_rom_spiflash_dummy_len_plus[spi_num];
  145. }
  146. g_rom_spiflash_dummy_len_plus[spi_num] = s_rom_flash_extra_dummy[spi_num] + extra_dummy;
  147. // Only Quad Flash will run into this branch.
  148. uint32_t dummy = spi_timing_config_get_dummy();
  149. mspi_timing_ll_set_quad_flash_dummy(spi_num, dummy + g_rom_spiflash_dummy_len_plus[spi_num]);
  150. }
  151. void mspi_timing_config_flash_set_tuning_regs(const void *timing_params)
  152. {
  153. const mspi_timing_tuning_param_t *params = (const mspi_timing_tuning_param_t *)timing_params;
  154. /**
  155. * 1. SPI_MEM_DINx_MODE(1), SPI_MEM_DINx_NUM(1) are meaningless
  156. * SPI0 and SPI1 share the SPI_MEM_DINx_MODE(0), SPI_MEM_DINx_NUM(0) for FLASH timing tuning
  157. * 2. We use SPI1 to get the best Flash timing tuning (mode and num) config
  158. */
  159. s_set_flash_din_mode_num(0, params->spi_din_mode, params->spi_din_num);
  160. s_set_flash_extra_dummy(1, params->extra_dummy_len);
  161. }
  162. //-------------------------------------------FLASH Read/Write------------------------------------------//
  163. void mspi_timing_config_flash_read_data(uint8_t *buf, uint32_t addr, uint32_t len)
  164. {
  165. if (bootloader_flash_is_octal_mode_enabled()) {
  166. // note that in spi_flash_read API, there is a wait-idle stage, since flash can only be read in idle state.
  167. // but after we change the timing settings, we might not read correct idle status via RDSR.
  168. // so, here we should use a read API that won't check idle status.
  169. mspi_timing_ll_clear_fifo(1);
  170. esp_rom_opiflash_read_raw(addr, buf, len);
  171. } else {
  172. esp_rom_spiflash_read(addr, (uint32_t *)buf, len);
  173. }
  174. }
  175. //-------------------------------------PSRAM timing tuning register config-------------------------------------//
  176. void mspi_timing_get_psram_tuning_configs(mspi_timing_config_t *config)
  177. {
  178. #if MSPI_TIMING_PSRAM_DTR_MODE
  179. #define PSRAM_MODE DTR_MODE
  180. #else //MSPI_TIMING_PSRAM_STR_MODE
  181. #define PSRAM_MODE STR_MODE
  182. #endif
  183. #if CONFIG_SPIRAM_SPEED_80M
  184. *config = MSPI_TIMING_PSRAM_GET_TUNING_CONFIG(MSPI_TIMING_CORE_CLOCK_MHZ, 80, PSRAM_MODE);
  185. #elif CONFIG_SPIRAM_SPEED_120M
  186. *config = MSPI_TIMING_PSRAM_GET_TUNING_CONFIG(MSPI_TIMING_CORE_CLOCK_MHZ, 120, PSRAM_MODE);
  187. #else
  188. assert(false && "should never reach here");
  189. #endif
  190. #undef PSRAM_MODE
  191. }
  192. void mspi_timing_psram_init(uint32_t psram_freq_mhz)
  193. {
  194. mspi_timing_config_set_flash_clock(psram_freq_mhz, MSPI_TIMING_SPEED_MODE_NORMAL_PERF, true);
  195. //Power on HCLK
  196. mspi_timinng_ll_enable_psram_hclk(0);
  197. }
  198. static void s_set_psram_din_mode_num(uint8_t spi_num, uint8_t din_mode, uint8_t din_num)
  199. {
  200. mspi_timing_ll_set_psram_din_mode(spi_num, din_mode);
  201. mspi_timing_ll_set_psram_din_num(spi_num, din_num);
  202. }
  203. static void s_set_psram_extra_dummy(uint8_t spi_num, uint8_t extra_dummy)
  204. {
  205. #if CONFIG_SPIRAM_MODE_OCT
  206. mspi_timing_ll_set_octal_psram_extra_dummy(spi_num, extra_dummy);
  207. #elif CONFIG_SPIRAM_MODE_QUAD
  208. //HW workaround: Use normal dummy register to set extra dummy, the calibration dedicated extra dummy register doesn't work for quad mode
  209. mspi_timing_ll_set_quad_psram_dummy(spi_num, (QPI_PSRAM_FAST_READ_DUMMY + extra_dummy - 1));
  210. #endif
  211. }
  212. void mspi_timing_config_psram_set_tuning_regs(const void *timing_params)
  213. {
  214. const mspi_timing_tuning_param_t *params = (const mspi_timing_tuning_param_t *)timing_params;
  215. /**
  216. * 1. SPI_MEM_SPI_SMEM_DINx_MODE(1), SPI_MEM_SPI_SMEM_DINx_NUM(1) are meaningless
  217. * SPI0 and SPI1 share the SPI_MEM_SPI_SMEM_DINx_MODE(0), SPI_MEM_SPI_SMEM_DINx_NUM(0) for PSRAM timing tuning
  218. * 2. We use SPI1 to get the best PSRAM timing tuning (mode and num) config
  219. */
  220. s_set_psram_din_mode_num(0, params->spi_din_mode, params->spi_din_num);
  221. #if CONFIG_SPIRAM_MODE_OCT
  222. //On 728, for SPI1, flash and psram share the extra dummy register
  223. s_set_flash_extra_dummy(1, params->extra_dummy_len);
  224. #elif CONFIG_SPIRAM_MODE_QUAD
  225. //Update this `s_psram_extra_dummy`, the `s_psram_read_data` will set dummy according to this `s_psram_extra_dummy`
  226. s_psram_extra_dummy = params->extra_dummy_len;
  227. mspi_timing_ll_set_quad_flash_dummy(1, params->extra_dummy_len - 1);
  228. #endif
  229. }
  230. //-------------------------------------------PSRAM Read/Write------------------------------------------//
  231. static void s_psram_write_data(uint8_t *buf, uint32_t addr, uint32_t len)
  232. {
  233. #if CONFIG_SPIRAM_MODE_OCT
  234. esp_rom_opiflash_exec_cmd(1, ESP_ROM_SPIFLASH_OPI_DTR_MODE,
  235. OPI_PSRAM_SYNC_WRITE, 16,
  236. addr, 32,
  237. OCT_PSRAM_WR_DUMMY_NUM,
  238. buf, len * 8,
  239. NULL, 0,
  240. BIT(1),
  241. false);
  242. #elif CONFIG_SPIRAM_MODE_QUAD
  243. psram_exec_cmd(1, 0,
  244. QPI_PSRAM_WRITE, 8,
  245. addr, 24,
  246. 0,
  247. buf, len * 8,
  248. NULL, 0,
  249. SPI_MEM_CS1_DIS_M,
  250. false);
  251. #endif
  252. }
  253. static void s_psram_read_data(uint8_t *buf, uint32_t addr, uint32_t len)
  254. {
  255. #if CONFIG_SPIRAM_MODE_OCT
  256. mspi_timing_ll_clear_fifo(1);
  257. esp_rom_opiflash_exec_cmd(1, ESP_ROM_SPIFLASH_OPI_DTR_MODE,
  258. OPI_PSRAM_SYNC_READ, 16,
  259. addr, 32,
  260. OCT_PSRAM_RD_DUMMY_NUM,
  261. NULL, 0,
  262. buf, len * 8,
  263. BIT(1),
  264. false);
  265. #elif CONFIG_SPIRAM_MODE_QUAD
  266. psram_exec_cmd(1, 0,
  267. QPI_PSRAM_FAST_READ, 8,
  268. addr, 24,
  269. QPI_PSRAM_FAST_READ_DUMMY + s_psram_extra_dummy,
  270. NULL, 0,
  271. buf, len * 8,
  272. SPI_MEM_CS1_DIS_M,
  273. false);
  274. #endif
  275. }
  276. static void s_psram_execution(uint8_t *buf, uint32_t addr, uint32_t len, bool is_read)
  277. {
  278. while (len) {
  279. uint32_t length = MIN(len, 32);
  280. if (is_read) {
  281. s_psram_read_data(buf, addr, length);
  282. } else {
  283. s_psram_write_data(buf, addr, length);
  284. }
  285. addr += length;
  286. buf += length;
  287. len -= length;
  288. }
  289. }
  290. void mspi_timing_config_psram_write_data(uint8_t *buf, uint32_t addr, uint32_t len)
  291. {
  292. s_psram_execution(buf, addr, len, false);
  293. }
  294. void mspi_timing_config_psram_read_data(uint8_t *buf, uint32_t addr, uint32_t len)
  295. {
  296. s_psram_execution(buf, addr, len, true);
  297. }
  298. /*-------------------------------------------------------------------------------------------------
  299. * Best Timing Tuning Params Selection
  300. *-------------------------------------------------------------------------------------------------*/
  301. #if (MSPI_TIMING_FLASH_DTR_MODE || MSPI_TIMING_PSRAM_DTR_MODE) && (MSPI_TIMING_CORE_CLOCK_MHZ == 240)
  302. static bool get_working_pll_freq(const uint8_t *reference_data, bool is_flash, uint32_t *out_max_freq, uint32_t *out_min_freq)
  303. {
  304. uint8_t read_data[MSPI_TIMING_TEST_DATA_LEN] = {0};
  305. rtc_cpu_freq_config_t previous_config;
  306. rtc_clk_cpu_freq_get_config(&previous_config);
  307. uint32_t big_num = MSPI_TIMING_PLL_FREQ_SCAN_RANGE_MHZ_MAX * 2; //This number should be larger than MSPI_TIMING_PLL_FREQ_SCAN_RANGE_MHZ_MAX, for error handling
  308. uint32_t max_freq = 0;
  309. uint32_t min_freq = big_num;
  310. rtc_xtal_freq_t xtal_freq = rtc_clk_xtal_freq_get();
  311. for (int pll_mhz_tuning = MSPI_TIMING_PLL_FREQ_SCAN_RANGE_MHZ_MIN; pll_mhz_tuning <= MSPI_TIMING_PLL_FREQ_SCAN_RANGE_MHZ_MAX; pll_mhz_tuning += 8) {
  312. //bbpll calibration start
  313. regi2c_ctrl_ll_bbpll_calibration_start();
  314. /**
  315. * pll_mhz = xtal_mhz * (oc_div + 4) / (oc_ref_div + 1)
  316. */
  317. clk_ll_bbpll_set_frequency_for_mspi_tuning(xtal_freq, pll_mhz_tuning, ((pll_mhz_tuning / 4) - 4), 9);
  318. //wait calibration done
  319. while(!regi2c_ctrl_ll_bbpll_calibration_is_done());
  320. //bbpll calibration stop
  321. regi2c_ctrl_ll_bbpll_calibration_stop();
  322. memset(read_data, 0, MSPI_TIMING_TEST_DATA_LEN);
  323. if (is_flash) {
  324. mspi_timing_config_flash_read_data(read_data, MSPI_TIMING_FLASH_TEST_DATA_ADDR, MSPI_TIMING_TEST_DATA_LEN);
  325. } else {
  326. mspi_timing_config_psram_read_data(read_data, MSPI_TIMING_PSRAM_TEST_DATA_ADDR, MSPI_TIMING_TEST_DATA_LEN);
  327. }
  328. if (memcmp(read_data, reference_data, MSPI_TIMING_TEST_DATA_LEN) == 0) {
  329. max_freq = MAX(pll_mhz_tuning, max_freq);
  330. min_freq = MIN(pll_mhz_tuning, min_freq);
  331. //Continue to find successful cases
  332. continue;
  333. }
  334. if (max_freq != 0) {
  335. //The first fail case after successful case(s) is the end
  336. break;
  337. }
  338. //If no break, no successful case found, continue to find successful cases
  339. }
  340. //restore PLL config
  341. clk_ll_bbpll_set_freq_mhz(previous_config.source_freq_mhz);
  342. //bbpll calibration start
  343. regi2c_ctrl_ll_bbpll_calibration_start();
  344. //set pll
  345. clk_ll_bbpll_set_config(previous_config.source_freq_mhz, xtal_freq);
  346. //wait calibration done
  347. while(!regi2c_ctrl_ll_bbpll_calibration_is_done());
  348. //bbpll calibration stop
  349. regi2c_ctrl_ll_bbpll_calibration_stop();
  350. *out_max_freq = max_freq;
  351. *out_min_freq = min_freq;
  352. return (max_freq != 0);
  353. }
  354. #endif //Frequency Scanning
  355. static uint32_t s_select_best_tuning_config_dtr(const mspi_timing_config_t *configs, uint32_t consecutive_length, uint32_t end, const uint8_t *reference_data, bool is_flash)
  356. {
  357. #if (MSPI_TIMING_CORE_CLOCK_MHZ == 160)
  358. //Core clock 160M DTR best point scheme
  359. uint32_t best_point;
  360. //Define these magic number in macros in `spi_timing_config.h`. TODO: IDF-3663
  361. if (consecutive_length <= 2 || consecutive_length >= 6) {
  362. //tuning is FAIL, select default point, and generate a warning
  363. best_point = configs->default_config_id;
  364. ESP_EARLY_LOGW(TAG, "tuning fail, best point is fallen back to index %"PRIu32"", best_point);
  365. } else if (consecutive_length <= 4) {
  366. //consecutive length : 3 or 4
  367. best_point = end - 1;
  368. ESP_EARLY_LOGD(TAG, "tuning success, best point is index %"PRIu32"", best_point);
  369. } else {
  370. //consecutive point list length equals 5
  371. best_point = end - 2;
  372. ESP_EARLY_LOGD(TAG, "tuning success, best point is index %"PRIu32"", best_point);
  373. }
  374. return best_point;
  375. #elif (MSPI_TIMING_CORE_CLOCK_MHZ == 240)
  376. uint32_t best_point = 0;
  377. uint32_t current_point = end + 1 - consecutive_length;
  378. bool ret = false;
  379. //This `max_freq` is the max pll frequency that per MSPI timing tuning config can work
  380. uint32_t max_freq = 0;
  381. uint32_t temp_max_freq = 0;
  382. uint32_t temp_min_freq = 0;
  383. for (; current_point <= end; current_point++) {
  384. if (is_flash) {
  385. mspi_timing_config_flash_set_tuning_regs(&(configs->tuning_config_table[current_point]));
  386. } else {
  387. mspi_timing_config_psram_set_tuning_regs(&(configs->tuning_config_table[current_point]));
  388. }
  389. ret = get_working_pll_freq(reference_data, is_flash, &temp_max_freq, &temp_min_freq);
  390. if (ret && temp_min_freq <= MSPI_TIMING_PLL_FREQ_SCAN_THRESH_MHZ_LOW && temp_max_freq >= MSPI_TIMING_PLL_FREQ_SCAN_THRESH_MHZ_HIGH && temp_max_freq > max_freq) {
  391. max_freq = temp_max_freq;
  392. best_point = current_point;
  393. }
  394. ESP_EARLY_LOGD(TAG, "sample point %"PRIu32", max pll is %"PRIu32" mhz, min pll is %"PRIu32"\n", current_point, temp_max_freq, temp_min_freq);
  395. }
  396. if (max_freq == 0) {
  397. ESP_EARLY_LOGW(TAG, "freq scan tuning fail, best point is fallen back to index %"PRIu32"", end + 1 - consecutive_length);
  398. best_point = end + 1 - consecutive_length;
  399. } else {
  400. ESP_EARLY_LOGD(TAG, "freq scan success, max pll is %"PRIu32"mhz, best point is index %"PRIu32"", max_freq, best_point);
  401. }
  402. return best_point;
  403. #else
  404. //won't reach here
  405. abort();
  406. #endif
  407. }
  408. static uint32_t s_select_best_tuning_config_str(const mspi_timing_config_t *configs, uint32_t consecutive_length, uint32_t end)
  409. {
  410. #if (MSPI_TIMING_CORE_CLOCK_MHZ == 120 || MSPI_TIMING_CORE_CLOCK_MHZ == 240)
  411. //STR best point scheme
  412. uint32_t best_point;
  413. if (consecutive_length <= 2|| consecutive_length >= 5) {
  414. //tuning is FAIL, select default point, and generate a warning
  415. best_point = configs->default_config_id;
  416. ESP_EARLY_LOGW(TAG, "tuning fail, best point is fallen back to index %"PRIu32"", best_point);
  417. } else {
  418. //consecutive length : 3 or 4
  419. best_point = end - consecutive_length / 2;
  420. ESP_EARLY_LOGD(TAG, "tuning success, best point is index %"PRIu32"", best_point);
  421. }
  422. return best_point;
  423. #else
  424. //won't reach here
  425. abort();
  426. #endif
  427. }
  428. static uint32_t s_select_best_tuning_config(const mspi_timing_config_t *configs, uint32_t consecutive_length, uint32_t end, const uint8_t *reference_data, bool is_ddr, bool is_flash)
  429. {
  430. uint32_t best_point = 0;
  431. if (is_ddr) {
  432. best_point = s_select_best_tuning_config_dtr(configs, consecutive_length, end, reference_data, is_flash);
  433. } else {
  434. best_point = s_select_best_tuning_config_str(configs, consecutive_length, end);
  435. }
  436. return best_point;
  437. }
  438. uint32_t mspi_timing_flash_select_best_tuning_config(const void *configs, uint32_t consecutive_length, uint32_t end, const uint8_t *reference_data, bool is_ddr)
  439. {
  440. const mspi_timing_config_t *timing_configs = (const mspi_timing_config_t *)configs;
  441. uint32_t best_point = s_select_best_tuning_config(timing_configs, consecutive_length, end, reference_data, is_ddr, true);
  442. ESP_EARLY_LOGI(TAG, "Flash timing tuning index: %"PRIu32"", best_point);
  443. return best_point;
  444. }
  445. uint32_t mspi_timing_psram_select_best_tuning_config(const void *configs, uint32_t consecutive_length, uint32_t end, const uint8_t *reference_data, bool is_ddr)
  446. {
  447. const mspi_timing_config_t *timing_configs = (const mspi_timing_config_t *)configs;
  448. uint32_t best_point = s_select_best_tuning_config(timing_configs, consecutive_length, end, reference_data, is_ddr, false);
  449. ESP_EARLY_LOGI(TAG, "PSRAM timing tuning index: %"PRIu32"", best_point);
  450. return best_point;
  451. }
  452. static mspi_timing_tuning_param_t s_flash_best_timing_tuning_config;
  453. static mspi_timing_tuning_param_t s_psram_best_timing_tuning_config;
  454. void mspi_timing_flash_set_best_tuning_config(const void *timing_params)
  455. {
  456. const mspi_timing_tuning_param_t *params = (const mspi_timing_tuning_param_t *)timing_params;
  457. s_flash_best_timing_tuning_config = *params;
  458. }
  459. void mspi_timing_psram_set_best_tuning_config(const void *timing_params)
  460. {
  461. const mspi_timing_tuning_param_t *params = (const mspi_timing_tuning_param_t *)timing_params;
  462. s_psram_best_timing_tuning_config = *params;
  463. }
  464. /*-------------------------------------------------------------------------------------------------
  465. * Best Timing Tuning Params Clear / Set
  466. *-------------------------------------------------------------------------------------------------*/
  467. void mspi_timing_flash_config_clear_tuning_regs(bool control_both_mspi)
  468. {
  469. s_set_flash_din_mode_num(0, 0, 0); //SPI0 and SPI1 share the registers for flash din mode and num setting, so we only set SPI0's reg
  470. s_set_flash_extra_dummy(0, 0);
  471. //Won't touch SPI1 registers if not control_both_mspi
  472. if (control_both_mspi) {
  473. s_set_flash_extra_dummy(1, 0);
  474. }
  475. }
  476. void mspi_timing_flash_config_set_tuning_regs(bool control_both_mspi)
  477. {
  478. //SPI0 and SPI1 share the registers for flash din mode and num setting, so we only set SPI0's reg
  479. s_set_flash_din_mode_num(0, s_flash_best_timing_tuning_config.spi_din_mode, s_flash_best_timing_tuning_config.spi_din_num);
  480. s_set_flash_extra_dummy(0, s_flash_best_timing_tuning_config.extra_dummy_len);
  481. if (control_both_mspi) {
  482. s_set_flash_extra_dummy(1, s_flash_best_timing_tuning_config.extra_dummy_len);
  483. } else {
  484. //Won't touch SPI1 registers
  485. }
  486. }
  487. void mspi_timing_psram_config_clear_tuning_regs(bool control_both_mspi)
  488. {
  489. (void)control_both_mspi; //for compatibility
  490. s_set_psram_din_mode_num(0, 0, 0);
  491. s_set_psram_extra_dummy(0, 0);
  492. }
  493. void mspi_timing_psram_config_set_tuning_regs(bool control_both_mspi)
  494. {
  495. (void)control_both_mspi; //for compatibility
  496. s_set_psram_din_mode_num(0, s_psram_best_timing_tuning_config.spi_din_mode, s_psram_best_timing_tuning_config.spi_din_num);
  497. s_set_psram_extra_dummy(0, s_psram_best_timing_tuning_config.extra_dummy_len);
  498. }
  499. #endif //#if MSPI_TIMING_FLASH_NEEDS_TUNING || MSPI_TIMING_PSRAM_NEEDS_TUNING
  500. /*-------------------------------------------------------------------------------------------------
  501. * To let upper lay (spi_flash_timing_tuning.c) to know the necessary timing registers
  502. *-------------------------------------------------------------------------------------------------*/
  503. /**
  504. * Get the SPI1 Flash CS timing setting. The setup time and hold time are both realistic cycles.
  505. * @note On ESP32-S3, SPI0/1 share the Flash CS timing registers. Therefore, we should not change these values.
  506. * @note This function inform `spi_flash_timing_tuning.c` (driver layer) of the cycle,
  507. * and other component (esp_flash driver) should get these cycle and configure the registers accordingly.
  508. */
  509. void mspi_timing_config_get_cs_timing(uint8_t *setup_time, uint32_t *hold_time)
  510. {
  511. *setup_time = mspi_timing_ll_get_cs_setup_val(0);
  512. *hold_time = mspi_timing_ll_get_cs_hold_val(0);
  513. /**
  514. * The logic here is, if setup_en / hold_en is false, then we return the realistic cycle number,
  515. * which is 0. If true, then the realistic cycle number is (reg_value + 1)
  516. */
  517. if (mspi_timing_ll_is_cs_setup_enabled(0)) {
  518. *setup_time += 1;
  519. } else {
  520. *setup_time = 0;
  521. }
  522. if (mspi_timing_ll_is_cs_hold_enabled(0)) {
  523. *hold_time += 1;
  524. } else {
  525. *hold_time = 0;
  526. }
  527. }
  528. /**
  529. * Get the SPI1 Flash clock setting.
  530. * @note Similarly, this function inform `spi_flash_timing_tuning.c` (driver layer) of the clock setting,
  531. * and other component (esp_flash driver) should get these and configure the registers accordingly.
  532. */
  533. uint32_t mspi_timing_config_get_flash_clock_reg(void)
  534. {
  535. return mspi_timing_ll_get_clock_reg(1);
  536. }
  537. uint8_t mspi_timing_config_get_flash_extra_dummy(void)
  538. {
  539. #if MSPI_TIMING_FLASH_NEEDS_TUNING
  540. return s_flash_best_timing_tuning_config.extra_dummy_len;
  541. #else
  542. return 0;
  543. #endif
  544. }