spi_flash_hpm_enable.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  1. /*
  2. * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <stdint.h>
  7. #include "sdkconfig.h"
  8. #include "esp_err.h"
  9. #include "esp_log.h"
  10. #include "spi_flash_defs.h"
  11. #include "esp_rom_sys.h"
  12. #include "esp_rom_spiflash.h"
  13. #include "spi_flash_override.h"
  14. // TODO: These dependencies will be removed after remove bootloader_flash to G0.IDF-4609
  15. #include "bootloader_flash_override.h"
  16. #include "bootloader_flash_priv.h"
  17. /*******************************************************************************
  18. * Flash high speed performance mode.
  19. * HPM: High performance mode.
  20. * HPF: High performance flag.
  21. *
  22. * Different flash chips might have different high performance strategy.
  23. * 1. Some flash chips send A3H to enable the HPM.
  24. * 2. Some flash chips write HPF bit in status register.
  25. * 3. Some flash chips adjust dummy cycles.
  26. * 4. Some flash chips do nothing.
  27. ******************************************************************************/
  28. /*
  29. * Note: This file should only be compiled when HPM_ON, which is only available when !CONFIG_ESPTOOLPY_OCT_FLASH.
  30. * However when HPM_ON, there are still some cases this file is not actually used:
  31. *
  32. * - !CONFIG_SPI_FLASH_UNDER_HIGH_FREQ:
  33. * It mean that the flash not running under frequency requires HPM. spi_flash_enable_high_performance_mode() still
  34. * called because caller shouldn't take care of the frequency.
  35. *
  36. * - bootloader_flash_is_octal_mode_enabled() == true:
  37. * This is possible when `CONFIG_ESPTOOLPY_FLASH_MODE_AUTO_DETECT` selected
  38. *
  39. * Octal Flash for now all support 120M. No need to enable HPM. The file is compiled, but will not actually run
  40. * into spi_flash_enable_high_performance_mode().
  41. */
  42. void spi_flash_hpm_get_dummy_generic(spi_flash_hpm_dummy_conf_t *dummy_conf);
  43. #if CONFIG_SPI_FLASH_UNDER_HIGH_FREQ
  44. #if CONFIG_SPI_FLASH_HPM_AUTO
  45. // This only happens on S3, where HPM_AUTO leads to HPM_ON
  46. #warning High Performance Mode (QSPI Flash > 80MHz) is optional feature that depends on flash model. Read Docs First!
  47. #endif
  48. const static char *HPM_TAG = "flash HPM";
  49. // TODO: This function will be changed after remove bootloader_flash to G0.IDF-4609
  50. extern uint32_t bootloader_flash_execute_command_common(
  51. uint8_t command,
  52. uint32_t addr_len, uint32_t address,
  53. uint8_t dummy_len,
  54. uint8_t mosi_len, uint32_t mosi_data,
  55. uint8_t miso_len);
  56. extern uint32_t IRAM_ATTR bootloader_flash_read_sfdp(uint32_t sfdp_addr, unsigned int miso_byte_num);
  57. //-----------------For flash chips which enter HPM via command-----------------------//
  58. /**
  59. * @brief Probe the chip whether use command to enable HPM mode. Take GD as an example:
  60. * Some GD send 0xA3 command to enable HPM mode of the flash.
  61. */
  62. static esp_err_t spi_flash_hpm_probe_chip_with_cmd(uint32_t flash_id)
  63. {
  64. esp_err_t ret = ESP_OK;
  65. uint32_t gd_sfdp;
  66. switch (flash_id) {
  67. /* The flash listed here should enter the HPM with command 0xA3 */
  68. case 0xC84016:
  69. case 0xC84017:
  70. // Read BYTE4 in SFDP, 0 means C series, 6 means E series
  71. gd_sfdp = bootloader_flash_read_sfdp(0x4, 1);
  72. if (gd_sfdp == 0x0) {
  73. break;
  74. } else {
  75. ret = ESP_ERR_NOT_FOUND;
  76. break;
  77. }
  78. default:
  79. ret = ESP_ERR_NOT_FOUND;
  80. break;
  81. }
  82. return ret;
  83. }
  84. static spi_flash_requirement_t spi_flash_hpm_chip_hpm_requirement_check_with_cmd(uint32_t flash_id, uint32_t freq_mhz, int voltage_mv, int temperautre)
  85. {
  86. // voltage and temperature are not been used now, to be completed in the future.
  87. (void)voltage_mv;
  88. (void)temperautre;
  89. spi_flash_requirement_t chip_cap = SPI_FLASH_HPM_UNNEEDED;
  90. if (freq_mhz > 80) {
  91. chip_cap = SPI_FLASH_HPM_CMD_NEEDED;
  92. }
  93. ESP_EARLY_LOGD(HPM_TAG, "HPM with command, status is %d", chip_cap);
  94. return chip_cap;
  95. }
  96. /**
  97. * @brief Send HPMEN command (A3H)
  98. */
  99. static void spi_flash_enable_high_performance_send_cmd(void)
  100. {
  101. uint32_t dummy = 24;
  102. bootloader_flash_execute_command_common(CMD_HPMEN, 0, 0, dummy, 0, 0, 0);
  103. // Delay for T(HPM) refering to datasheet.
  104. esp_rom_delay_us(20);
  105. }
  106. /**
  107. * @brief Check whether flash HPM has been enabled. According to flash datasheets, majorities of
  108. * HPF bit are at bit-5, sr-3. But some are not. Therefore, this function is only used for those
  109. * HPF bit is at bit-5, sr-3.
  110. */
  111. static esp_err_t spi_flash_high_performance_check_hpf_bit_5(void)
  112. {
  113. if((bootloader_read_status_8b_rdsr3() & (1 << 4)) == 0) {
  114. return ESP_FAIL;
  115. }
  116. return ESP_OK;
  117. }
  118. //-----------------For flash chips which enter HPM via adjust dummy-----------------------//
  119. #if CONFIG_SPI_FLASH_HPM_DC_ON
  120. /**
  121. * @brief Probe the chip whether adjust dummy to enable HPM mode. Take XMC as an example:
  122. * Adjust dummy bits to enable HPM mode of the flash. If XMC works under 80MHz, the dummy bits
  123. * might be 6, but when works under 120MHz, the dummy bits might be 10.
  124. */
  125. static esp_err_t spi_flash_hpm_probe_chip_with_dummy(uint32_t flash_id)
  126. {
  127. esp_err_t ret = ESP_OK;
  128. uint32_t gd_sfdp;
  129. switch (flash_id) {
  130. /* The flash listed here should enter the HPM by adjusting dummy cycles */
  131. // XMC chips.
  132. case 0x204017:
  133. case 0x204018:
  134. break;
  135. // GD chips.
  136. case 0xC84017:
  137. case 0xC84018:
  138. // Read BYTE4 in SFDP, 0 means C series, 6 means E series
  139. gd_sfdp = bootloader_flash_read_sfdp(0x4, 1);
  140. if (gd_sfdp == 0x6) {
  141. break;
  142. } else {
  143. ret = ESP_ERR_NOT_FOUND;
  144. break;
  145. }
  146. default:
  147. ret = ESP_ERR_NOT_FOUND;
  148. break;
  149. }
  150. return ret;
  151. }
  152. static spi_flash_requirement_t spi_flash_hpm_chip_hpm_requirement_check_with_dummy(uint32_t flash_id, uint32_t freq_mhz, int voltage_mv, int temperautre)
  153. {
  154. // voltage and temperature are not been used now, to be completed in the future.
  155. (void)voltage_mv;
  156. (void)temperautre;
  157. spi_flash_requirement_t chip_cap = SPI_FLASH_HPM_UNNEEDED;
  158. if (freq_mhz >= 104) {
  159. chip_cap = SPI_FLASH_HPM_DUMMY_NEEDED;
  160. }
  161. ESP_EARLY_LOGD(HPM_TAG, "HPM with dummy, status is %d", chip_cap);
  162. return chip_cap;
  163. }
  164. /**
  165. * @brief Adjust dummy cycles. This function modifies the Dummy Cycle Bits in SR3.
  166. * Usually, the bits are at bit-0, bit-1, sr-3 and set DC[1:0]=[1,1].
  167. *
  168. * @note Don't forget to adjust dummy configurations for MSPI, you can get the
  169. * correct dummy from interface `spi_flash_hpm_get_dummy`.
  170. */
  171. static void spi_flash_turn_high_performance_reconfig_dummy(void)
  172. {
  173. uint8_t old_status_3 = bootloader_read_status_8b_rdsr3();
  174. uint8_t new_status = (old_status_3 | 0x03);
  175. bootloader_execute_flash_command(CMD_WRENVSR, 0, 0, 0);
  176. bootloader_write_status_8b_wrsr3(new_status);
  177. esp_rom_spiflash_wait_idle(&g_rom_flashchip);
  178. }
  179. /**
  180. * @brief Check whether HPM has been enabled. This function checks the DC bits
  181. */
  182. static esp_err_t spi_flash_high_performance_check_dummy_sr(void)
  183. {
  184. if((bootloader_read_status_8b_rdsr3() & 0x03) == 0) {
  185. return ESP_FAIL;
  186. }
  187. return ESP_OK;
  188. }
  189. static void spi_flash_hpm_get_dummy_xmc(spi_flash_hpm_dummy_conf_t *dummy_conf)
  190. {
  191. dummy_conf->dio_dummy = SPI_FLASH_DIO_HPM_DUMMY_BITLEN;
  192. dummy_conf->dout_dummy = SPI_FLASH_DOUT_DUMMY_BITLEN;
  193. dummy_conf->qio_dummy = SPI_FLASH_QIO_HPM_DUMMY_BITLEN;
  194. dummy_conf->qout_dummy = SPI_FLASH_QOUT_DUMMY_BITLEN;
  195. dummy_conf->fastrd_dummy = SPI_FLASH_FASTRD_DUMMY_BITLEN;
  196. }
  197. #elif !CONFIG_SPI_FLASH_HPM_DC_DISABLE
  198. //This is because bootloader doesn't support this
  199. #warning HPM-DC, which helps to run some flash > 80MHz by adjusting dummy cycles, is no longer enabled by default.
  200. #warning To enable this feature, your bootloader needs to have the support for it (by explicitly selecting BOOTLOADER_FLASH_DC_AWARE).
  201. #warning If your bootloader does not support it, select SPI_FLASH_HPM_DC_DISABLE to suppress the warning. READ DOCS FIRST!
  202. #endif //CONFIG_SPI_FLASH_HPM_DC_ON
  203. //-----------------For flash chips which enter HPM via write status register-----------------------//
  204. /**
  205. * @brief Probe the chip whether to write status register to enable HPM mode. Take ZB as an example:
  206. * Write status register bits to enable HPM mode of the flash. If ZB works under 80MHz, the register value
  207. * would be 0, but when works under 120MHz, the register value would be 1.
  208. */
  209. static esp_err_t spi_flash_hpm_probe_chip_with_write_hpf_bit_5(uint32_t flash_id)
  210. {
  211. esp_err_t ret = ESP_OK;
  212. switch (flash_id) {
  213. /* The flash listed here should enter the HPM by adjusting dummy cycles */
  214. // ZB chips.
  215. case 0x5E4016:
  216. break;
  217. default:
  218. ret = ESP_ERR_NOT_FOUND;
  219. break;
  220. }
  221. return ret;
  222. }
  223. static spi_flash_requirement_t spi_flash_hpm_chip_hpm_requirement_check_with_write_hpf_bit_5(uint32_t flash_id, uint32_t freq_mhz, int voltage_mv, int temperautre)
  224. {
  225. // voltage and temperature are not been used now, to be completed in the future.
  226. (void)voltage_mv;
  227. (void)temperautre;
  228. spi_flash_requirement_t chip_cap = SPI_FLASH_HPM_UNNEEDED;
  229. if (freq_mhz >= 104) {
  230. chip_cap = SPI_FLASH_HPM_WRITE_SR_NEEDED;
  231. }
  232. ESP_EARLY_LOGD(HPM_TAG, "HPM with dummy, status is %d", chip_cap);
  233. return chip_cap;
  234. }
  235. /**
  236. * @brief Write bit 5 in status 3
  237. */
  238. static void spi_flash_turn_high_performance_write_hpf_bit_5(void)
  239. {
  240. uint8_t old_status_3 = bootloader_read_status_8b_rdsr3();
  241. uint8_t new_status = (old_status_3 | 0x10);
  242. bootloader_execute_flash_command(CMD_WRENVSR, 0, 0, 0);
  243. bootloader_write_status_8b_wrsr3(new_status);
  244. esp_rom_spiflash_wait_idle(&g_rom_flashchip);
  245. }
  246. //-----------------For flash chips which enter HPM with doing nothing-----------------------//
  247. /**
  248. * @brief Probe the chip whether to write status register to enable HPM mode. Take a GD chip as an example:
  249. * This chip (GD25LQ255E) supports maximum frequency to 133MHz by default. So, we don't need to do any extra
  250. * thing.
  251. */
  252. static esp_err_t spi_flash_hpm_probe_chip_with_doing_nothing(uint32_t flash_id)
  253. {
  254. esp_err_t ret = ESP_OK;
  255. switch (flash_id) {
  256. /* The flash listed here should enter the HPM by doing nothing */
  257. // GD25LQ255E.
  258. case 0xC86019:
  259. break;
  260. default:
  261. ret = ESP_ERR_NOT_FOUND;
  262. break;
  263. }
  264. return ret;
  265. }
  266. static spi_flash_requirement_t spi_flash_hpm_chip_hpm_requirement_check_with_doing_nothing(uint32_t flash_id, uint32_t freq_mhz, int voltage_mv, int temperautre)
  267. {
  268. // voltage and temperature are not been used now, to be completed in the future.
  269. (void)voltage_mv;
  270. (void)temperautre;
  271. spi_flash_requirement_t chip_cap = SPI_FLASH_HPM_UNNEEDED;
  272. ESP_EARLY_LOGD(HPM_TAG, "HPM by default, chip caps is %d", chip_cap);
  273. return chip_cap;
  274. }
  275. const spi_flash_hpm_info_t __attribute__((weak)) spi_flash_hpm_enable_list[] = {
  276. /* vendor, chip_id, freq_threshold, temperature threshold, operation for setting high performance, reading HPF status, get dummy */
  277. { "command", spi_flash_hpm_probe_chip_with_cmd, spi_flash_hpm_chip_hpm_requirement_check_with_cmd, spi_flash_enable_high_performance_send_cmd, spi_flash_high_performance_check_hpf_bit_5, spi_flash_hpm_get_dummy_generic },
  278. #if CONFIG_SPI_FLASH_HPM_DC_ON
  279. { "dummy", spi_flash_hpm_probe_chip_with_dummy, spi_flash_hpm_chip_hpm_requirement_check_with_dummy, spi_flash_turn_high_performance_reconfig_dummy, spi_flash_high_performance_check_dummy_sr, spi_flash_hpm_get_dummy_xmc},
  280. #endif //CONFIG_SPI_FLASH_HPM_DC_ON
  281. { "write sr3-bit5", spi_flash_hpm_probe_chip_with_write_hpf_bit_5, spi_flash_hpm_chip_hpm_requirement_check_with_write_hpf_bit_5, spi_flash_turn_high_performance_write_hpf_bit_5, spi_flash_high_performance_check_hpf_bit_5, spi_flash_hpm_get_dummy_generic},
  282. { "noting-to-do", spi_flash_hpm_probe_chip_with_doing_nothing, spi_flash_hpm_chip_hpm_requirement_check_with_doing_nothing, NULL, NULL, spi_flash_hpm_get_dummy_generic},
  283. // default: do nothing, but keep the dummy get function. The first item with NULL as its probe will be the fallback.
  284. { "NULL", NULL, NULL, NULL, NULL, spi_flash_hpm_get_dummy_generic},
  285. };
  286. static const spi_flash_hpm_info_t *chip_hpm = NULL;
  287. #if CONFIG_SPI_FLASH_HPM_DC_ON
  288. static bool s_hpm_dummy_changed = false;
  289. static spi_flash_hpm_dummy_conf_t s_dummy_conf;
  290. const spi_flash_hpm_dummy_conf_t *spi_flash_hpm_get_dummy(void)
  291. {
  292. chip_hpm->flash_get_dummy(&s_dummy_conf);
  293. return &s_dummy_conf;
  294. }
  295. bool spi_flash_hpm_dummy_adjust(void)
  296. {
  297. return s_hpm_dummy_changed;
  298. }
  299. #endif //CONFIG_SPI_FLASH_HPM_DC_ON
  300. #if CONFIG_ESPTOOLPY_FLASHFREQ_120M
  301. #define FLASH_FREQUENCY 120
  302. #endif
  303. esp_err_t spi_flash_enable_high_performance_mode(void)
  304. {
  305. uint32_t flash_chip_id = g_rom_flashchip.device_id;
  306. uint32_t flash_freq = FLASH_FREQUENCY;
  307. spi_flash_requirement_t hpm_requirement_check;
  308. // voltage and temperature has not been implemented, just leave an interface here. Complete in the future.
  309. int voltage = 0;
  310. int temperature = 0;
  311. #if CONFIG_SPI_FLASH_HPM_AUTO
  312. ESP_EARLY_LOGW(HPM_TAG, "HPM mode is optional feature that depends on flash model. Read Docs First!");
  313. #endif
  314. #if CONFIG_SPI_FLASH_HPM_DC_DISABLE
  315. // case 1: force disabled
  316. ESP_EARLY_LOGI(HPM_TAG, "w/o HPM-DC support");
  317. #elif CONFIG_SPI_FLASH_HPM_DC_ON
  318. // case 2: auto, and actually enabled
  319. ESP_EARLY_LOGI(HPM_TAG, "with HPM-DC support");
  320. #else
  321. // case 3: auto, but disabled (not supported by bootloader)
  322. ESP_EARLY_LOGW(HPM_TAG, "HPM mode with DC adjustment is disabled. Some flash models may not be supported. Read Docs First!");
  323. #endif
  324. const spi_flash_hpm_info_t *chip = spi_flash_hpm_enable_list;
  325. esp_err_t ret = ESP_OK;
  326. while (chip->probe) {
  327. ret = chip->probe(flash_chip_id);
  328. if (ret == ESP_OK) {
  329. break;
  330. }
  331. chip++;
  332. }
  333. chip_hpm = chip;
  334. /* When > 80 MHz, flash chips usually need special HPM support to run normally. The support is chip-specific. When
  335. * the chip is not in the known flash list, nothing will be done and there will be an warning.
  336. * When <= 80 MHz, it's assumed that all flash chips can run without chip-specific HPM support. This function will not be called and there will be no warning.
  337. */
  338. if (ret != ESP_OK) {
  339. ESP_EARLY_LOGW(HPM_TAG, "High performance mode of this flash model hasn't been supported.");
  340. return ret;
  341. }
  342. hpm_requirement_check = chip_hpm->chip_hpm_requirement_check(flash_chip_id, flash_freq, voltage, temperature);
  343. if ((hpm_requirement_check == SPI_FLASH_HPM_CMD_NEEDED) || (hpm_requirement_check == SPI_FLASH_HPM_DUMMY_NEEDED) || (hpm_requirement_check == SPI_FLASH_HPM_WRITE_SR_NEEDED)) {
  344. ESP_EARLY_LOGI(HPM_TAG, "Enabling flash high speed mode by %s", chip_hpm->method);
  345. chip_hpm->flash_hpm_enable();
  346. ESP_EARLY_LOGD(HPM_TAG, "Checking whether HPM has been executed");
  347. if (chip_hpm->flash_hpf_check() != ESP_OK) {
  348. ESP_EARLY_LOGE(HPM_TAG, "Flash high performance mode hasn't been executed successfully");
  349. return ESP_FAIL;
  350. }
  351. #if CONFIG_SPI_FLASH_HPM_DC_ON
  352. s_hpm_dummy_changed = (hpm_requirement_check == SPI_FLASH_HPM_DUMMY_NEEDED) ? true : false;
  353. #else
  354. assert(hpm_requirement_check != SPI_FLASH_HPM_DUMMY_NEEDED);
  355. #endif
  356. } else if (hpm_requirement_check == SPI_FLASH_HPM_BEYOND_LIMIT) {
  357. ESP_EARLY_LOGE(HPM_TAG, "Flash does not have the ability to raise to that frequency");
  358. return ESP_FAIL;
  359. }
  360. return ESP_OK;
  361. }
  362. #else
  363. //!CONFIG_SPI_FLASH_UNDER_HIGH_FREQ
  364. static spi_flash_hpm_dummy_conf_t s_dummy_conf;
  365. esp_err_t spi_flash_enable_high_performance_mode(void)
  366. {
  367. return ESP_OK;
  368. }
  369. const spi_flash_hpm_dummy_conf_t *spi_flash_hpm_get_dummy(void)
  370. {
  371. spi_flash_hpm_get_dummy_generic(&s_dummy_conf);
  372. return &s_dummy_conf;
  373. }
  374. bool spi_flash_hpm_dummy_adjust(void)
  375. {
  376. return false;
  377. }
  378. #endif //CONFIG_SPI_FLASH_UNDER_HIGH_FREQ
  379. //-----------------------generic functions-------------------------------------//
  380. /**
  381. * @brief Default dummy for almost all flash chips. If your flash does't need to reconfigure dummy,
  382. * just call this function.
  383. */
  384. void __attribute__((weak)) spi_flash_hpm_get_dummy_generic(spi_flash_hpm_dummy_conf_t *dummy_conf)
  385. {
  386. dummy_conf->dio_dummy = SPI_FLASH_DIO_DUMMY_BITLEN;
  387. dummy_conf->dout_dummy = SPI_FLASH_DOUT_DUMMY_BITLEN;
  388. dummy_conf->qio_dummy = SPI_FLASH_QIO_DUMMY_BITLEN;
  389. dummy_conf->qout_dummy = SPI_FLASH_QOUT_DUMMY_BITLEN;
  390. dummy_conf->fastrd_dummy = SPI_FLASH_FASTRD_DUMMY_BITLEN;
  391. }