spi_flash_hpm_enable.c 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  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. ******************************************************************************/
  27. #if CONFIG_ESPTOOLPY_FLASHFREQ_120M
  28. #define FLASH_FREQUENCY 120
  29. #elif CONFIG_ESPTOOLPY_FLASHFREQ_80M
  30. #define FLASH_FREQUENCY 80
  31. #elif CONFIG_ESPTOOLPY_FLASHFREQ_40M
  32. #define FLASH_FREQUENCY 40
  33. #elif CONFIG_ESPTOOLPY_FLASHFREQ_20M
  34. #define FLASH_FREQUENCY 20
  35. #endif
  36. const static char *HPM_TAG = "flash HPM";
  37. // TODO: This function will be changed after remove bootloader_flash to G0.IDF-4609
  38. extern uint32_t bootloader_flash_execute_command_common(
  39. uint8_t command,
  40. uint32_t addr_len, uint32_t address,
  41. uint8_t dummy_len,
  42. uint8_t mosi_len, uint32_t mosi_data,
  43. uint8_t miso_len);
  44. //-----------------For flash chips which enter HPM via command-----------------------//
  45. /**
  46. * @brief Probe the chip whether use command to enable HPM mode. Take GD as an example:
  47. * Some GD send 0xA3 command to enable HPM mode of the flash.
  48. */
  49. static esp_err_t spi_flash_hpm_probe_chip_with_cmd(uint32_t flash_id)
  50. {
  51. esp_err_t ret = ESP_OK;
  52. switch (flash_id) {
  53. /* The flash listed here should enter the HPM with command 0xA3 */
  54. case 0xC84016:
  55. case 0xC84017:
  56. break;
  57. default:
  58. ret = ESP_ERR_NOT_FOUND;
  59. break;
  60. }
  61. return ret;
  62. }
  63. 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)
  64. {
  65. // voltage and temperature are not been used now, to be completed in the future.
  66. (void)voltage_mv;
  67. (void)temperautre;
  68. spi_flash_requirement_t chip_cap = SPI_FLASH_HPM_UNNEEDED;
  69. switch (flash_id) {
  70. /* The flash listed here should enter the HPM with command 0xA3 */
  71. case 0xC84016:
  72. case 0xC84017:
  73. if (freq_mhz > 80) {
  74. chip_cap = SPI_FLASH_HPM_CMD_NEEDED;
  75. }
  76. break;
  77. default:
  78. chip_cap = SPI_FLASH_HPM_UNNEEDED;
  79. break;
  80. }
  81. return chip_cap;
  82. }
  83. /**
  84. * @brief Send HPMEN command (A3H)
  85. */
  86. static void spi_flash_enable_high_performance_send_cmd(void)
  87. {
  88. uint32_t dummy = 24;
  89. bootloader_flash_execute_command_common(CMD_HPMEN, 0, 0, dummy, 0, 0, 0);
  90. // Delay for T(HPM) refering to datasheet.
  91. esp_rom_delay_us(20);
  92. }
  93. /**
  94. * @brief Check whether flash HPM has been enabled. According to flash datasheets, majorities of
  95. * HPF bit are at bit-5, sr-3. But some are not. Therefore, this function is only used for those
  96. * HPF bit is at bit-5, sr-3.
  97. */
  98. static esp_err_t spi_flash_high_performance_check_hpf_bit_5(void)
  99. {
  100. if((bootloader_read_status_8b_rdsr3() & (1 << 4)) == 0) {
  101. return ESP_FAIL;
  102. }
  103. return ESP_OK;
  104. }
  105. //-----------------For flash chips which enter HPM via adjust dummy-----------------------//
  106. /**
  107. * @brief Probe the chip whether adjust dummy to enable HPM mode. Take XMC as an example:
  108. * Adjust dummy bits to enable HPM mode of the flash. If XMC works under 80MHz, the dummy bits
  109. * might be 6, but when works under 120MHz, the dummy bits might be 10.
  110. */
  111. static esp_err_t spi_flash_hpm_probe_chip_with_dummy(uint32_t flash_id)
  112. {
  113. esp_err_t ret = ESP_OK;
  114. switch (flash_id) {
  115. /* The flash listed here should enter the HPM by adjusting dummy cycles */
  116. // XMC chips.
  117. case 0x204017:
  118. case 0x204018:
  119. break;
  120. default:
  121. ret = ESP_ERR_NOT_FOUND;
  122. break;
  123. }
  124. return ret;
  125. }
  126. 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)
  127. {
  128. // voltage and temperature are not been used now, to be completed in the future.
  129. (void)voltage_mv;
  130. (void)temperautre;
  131. spi_flash_requirement_t chip_cap = SPI_FLASH_HPM_UNNEEDED;
  132. switch (flash_id) {
  133. /* The flash listed here should enter the HPM with command 0xA3 */
  134. case 0x204017:
  135. case 0x204018:
  136. if (freq_mhz >= 104) {
  137. chip_cap = SPI_FLASH_HPM_DUMMY_NEEDED;
  138. }
  139. break;
  140. default:
  141. chip_cap = SPI_FLASH_HPM_UNNEEDED;
  142. break;
  143. }
  144. return chip_cap;
  145. }
  146. /**
  147. * @brief Adjust dummy cycles. This function modifies the Dummy Cycle Bits in SR3.
  148. * Usually, the bits are at bit-0, bit-1, sr-3 and set DC[1:0]=[1,1].
  149. *
  150. * @note Don't forget to adjust dummy configurations for MSPI, you can get the
  151. * correct dummy from interface `spi_flash_hpm_get_dummy`.
  152. */
  153. static void spi_flash_turn_high_performance_reconfig_dummy(void)
  154. {
  155. uint8_t old_status_3 = bootloader_read_status_8b_rdsr3();
  156. uint8_t new_status = (old_status_3 | 0x03);
  157. bootloader_execute_flash_command(CMD_WRENVSR, 0, 0, 0);
  158. bootloader_write_status_8b_wrsr3(new_status);
  159. esp_rom_spiflash_wait_idle(&g_rom_flashchip);
  160. }
  161. /**
  162. * @brief Check whether HPM has been enabled. This function checks the DC bits
  163. */
  164. static esp_err_t spi_flash_high_performance_check_dummy_sr(void)
  165. {
  166. if((bootloader_read_status_8b_rdsr3() & 0x03) == 0) {
  167. return ESP_FAIL;
  168. }
  169. return ESP_OK;
  170. }
  171. static void spi_flash_hpm_get_dummy_xmc(spi_flash_hpm_dummy_conf_t *dummy_conf)
  172. {
  173. dummy_conf->dio_dummy = SPI_FLASH_DIO_HPM_DUMMY_BITLEN;
  174. dummy_conf->dout_dummy = SPI_FLASH_DOUT_DUMMY_BITLEN;
  175. dummy_conf->qio_dummy = SPI_FLASH_QIO_HPM_DUMMY_BITLEN;
  176. dummy_conf->qout_dummy = SPI_FLASH_QOUT_DUMMY_BITLEN;
  177. dummy_conf->fastrd_dummy = SPI_FLASH_FASTRD_DUMMY_BITLEN;
  178. }
  179. //-----------------------generic functions-------------------------------------//
  180. /**
  181. * @brief Default dummy for almost all flash chips. If your flash does't need to reconfigure dummy,
  182. * just call this function.
  183. */
  184. void __attribute__((weak)) spi_flash_hpm_get_dummy_generic(spi_flash_hpm_dummy_conf_t *dummy_conf)
  185. {
  186. dummy_conf->dio_dummy = SPI_FLASH_DIO_DUMMY_BITLEN;
  187. dummy_conf->dout_dummy = SPI_FLASH_DOUT_DUMMY_BITLEN;
  188. dummy_conf->qio_dummy = SPI_FLASH_QIO_DUMMY_BITLEN;
  189. dummy_conf->qout_dummy = SPI_FLASH_QOUT_DUMMY_BITLEN;
  190. dummy_conf->fastrd_dummy = SPI_FLASH_FASTRD_DUMMY_BITLEN;
  191. }
  192. const spi_flash_hpm_info_t __attribute__((weak)) spi_flash_hpm_enable_list[] = {
  193. /* vendor, chip_id, freq_threshold, temperature threshold, operation for setting high performance, reading HPF status, get dummy */
  194. { "GD", 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 },
  195. { "XMC", 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},
  196. // default: do nothing, but keep the dummy get function. The first item with NULL as its probe will be the fallback.
  197. { "NULL", NULL, NULL, NULL, NULL, spi_flash_hpm_get_dummy_generic},
  198. };
  199. static const spi_flash_hpm_info_t *chip_hpm = NULL;
  200. static spi_flash_hpm_dummy_conf_t dummy_conf;
  201. static bool hpm_dummy_changed = false;
  202. esp_err_t spi_flash_enable_high_performance_mode(void)
  203. {
  204. uint32_t flash_chip_id = g_rom_flashchip.device_id;
  205. uint32_t flash_freq = FLASH_FREQUENCY;
  206. spi_flash_requirement_t hpm_requirement_check;
  207. // voltage and temperature has not been implemented, just leave an interface here. Complete in the future.
  208. int voltage = 0;
  209. int temperature = 0;
  210. const spi_flash_hpm_info_t *chip = spi_flash_hpm_enable_list;
  211. esp_err_t ret = ESP_OK;
  212. while (chip->probe) {
  213. ret = chip->probe(flash_chip_id);
  214. if (ret == ESP_OK) {
  215. break;
  216. }
  217. chip++;
  218. }
  219. chip_hpm = chip;
  220. if (ret != ESP_OK) {
  221. #if (FLASH_FREQUENCY == 120)
  222. ESP_EARLY_LOGW(HPM_TAG, "Flash high performance mode hasn't been supported");
  223. #endif
  224. return ret;
  225. }
  226. hpm_requirement_check = chip_hpm->chip_hpm_requirement_check(flash_chip_id, flash_freq, voltage, temperature);
  227. if ((hpm_requirement_check == SPI_FLASH_HPM_CMD_NEEDED) || (hpm_requirement_check == SPI_FLASH_HPM_DUMMY_NEEDED)) {
  228. ESP_EARLY_LOGI(HPM_TAG, "Enabling high speed mode for chip %s", chip_hpm->manufacturer);
  229. chip_hpm->flash_hpm_enable();
  230. ESP_EARLY_LOGD(HPM_TAG, "Checking whether HPM has been executed");
  231. if (chip_hpm->flash_hpf_check() != ESP_OK) {
  232. ESP_EARLY_LOGE(HPM_TAG, "Flash high performance mode hasn't been executed successfully");
  233. return ESP_FAIL;
  234. }
  235. hpm_dummy_changed = (hpm_requirement_check == SPI_FLASH_HPM_DUMMY_NEEDED) ? true : false;
  236. } else if (hpm_requirement_check == SPI_FLASH_HPM_BEYOND_LIMIT) {
  237. ESP_EARLY_LOGE(HPM_TAG, "Flash does not have the ability to raise to that frequency");
  238. return ESP_FAIL;
  239. }
  240. return ESP_OK;
  241. }
  242. const spi_flash_hpm_dummy_conf_t *spi_flash_hpm_get_dummy(void)
  243. {
  244. chip_hpm->flash_get_dummy(&dummy_conf);
  245. return &dummy_conf;
  246. }
  247. bool spi_flash_hpm_dummy_adjust(void)
  248. {
  249. return hpm_dummy_changed;
  250. }