spi_flash_wrap.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /*
  2. * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <stdint.h>
  7. #include <stdbool.h>
  8. #include "sdkconfig.h"
  9. #include "esp_err.h"
  10. #include "esp_log.h"
  11. #include "spi_flash_defs.h"
  12. #include "esp_rom_sys.h"
  13. #include "esp_rom_spiflash.h"
  14. #include "spi_flash_override.h"
  15. #include "esp_private/spi_flash_os.h"
  16. // TODO: These dependencies will be removed after remove bootloader_flash to G0.IDF-4609
  17. #include "bootloader_flash_override.h"
  18. #include "bootloader_flash_priv.h"
  19. /***********************************************************************************
  20. * Flash wrap feature (also called burst read on some flash chips)
  21. *
  22. * Different flash chips enter wrap (burst read) mode in different strategies.
  23. * 1. Command 0xC0 + 8 Bytes.
  24. * 2. Command 0x77 + 24 dummy + 8 Bytes.
  25. **********************************************************************************/
  26. #if SOC_SPI_MEM_SUPPORT_WRAP
  27. const static char *FLASH_WRAP_TAG = "flash wrap";
  28. // TODO: This function will be changed after remove bootloader_flash to G0.IDF-4609
  29. extern uint32_t bootloader_flash_execute_command_common(
  30. uint8_t command,
  31. uint32_t addr_len, uint32_t address,
  32. uint8_t dummy_len,
  33. uint8_t mosi_len, uint32_t mosi_data,
  34. uint8_t miso_len);
  35. esp_err_t spi_flash_wrap_probe_c0(uint32_t flash_id)
  36. {
  37. esp_err_t ret = ESP_OK;
  38. switch (flash_id) {
  39. /* The flash listed here should enter the wrap with command 0xC0 */
  40. case 0xC22018:
  41. break;
  42. default:
  43. ret = ESP_ERR_NOT_FOUND;
  44. break;
  45. }
  46. return ret;
  47. }
  48. /**
  49. * @brief Burst read with command 0xC0 + 8 Bytes
  50. *
  51. * |------------|-----------------------------|
  52. * | data | wrap depth |
  53. * | 00h | 8 |
  54. * | 01h | 16 |
  55. * | 02h | 32 |
  56. * | 03h | 64 |
  57. * |------------|-----------------------------|
  58. */
  59. esp_err_t spi_flash_wrap_enable_c0(spi_flash_wrap_size_t wrap_size)
  60. {
  61. uint8_t wrap_code = (uint8_t) (__builtin_ctz(wrap_size) - 3);
  62. bootloader_flash_execute_command_common(CMD_BURST_RD, 0, 0, 0, 8, wrap_code, 0);
  63. return ESP_OK;
  64. }
  65. /**
  66. * @brief Burst read with command 0x77 + 24 Dummy + 8 Bytes
  67. *
  68. * |-------------------|-----------------------------|
  69. * | data(W6,W5) | wrap depth |
  70. * | 00h | 8 |
  71. * | 01h | 16 |
  72. * | 02h | 32 |
  73. * | 03h | 64 |
  74. * |-------------------|-----------------------------|
  75. */
  76. esp_err_t spi_flash_wrap_enable_77(spi_flash_wrap_size_t wrap_size)
  77. {
  78. uint8_t wrap_code = (uint8_t) (((__builtin_ctz(wrap_size) - 3) * 2) << 4);
  79. // According to the special format, we need enable QIO_FWRITE for command 77h and clear it after this command is done.
  80. REG_SET_BIT(SPI_MEM_USER_REG(1), SPI_MEM_FWRITE_QIO);
  81. bootloader_flash_execute_command_common(CMD_WRAP, 0, 0, 6, 8, wrap_code, 0);
  82. REG_CLR_BIT(SPI_MEM_USER_REG(1), SPI_MEM_FWRITE_QIO);
  83. return ESP_OK;
  84. }
  85. /**
  86. * @brief Burst read is cleared by setting 0x1xh,
  87. * so we set 0x10 to disable this feature.
  88. */
  89. esp_err_t spi_flash_wrap_clear_c0(void)
  90. {
  91. bootloader_flash_execute_command_common(CMD_BURST_RD, 0, 0, 0, 8, 0x10, 0);
  92. return ESP_OK;
  93. }
  94. /**
  95. * @brief Burst read is cleared by setting W4 bit 1,
  96. * so we set 0x10 to disable this feature.
  97. */
  98. esp_err_t spi_flash_wrap_clear_77(void)
  99. {
  100. // According to the special format, we need enable QIO_FWRITE for command 77h and clear it after this command is done.
  101. REG_SET_BIT(SPI_MEM_USER_REG(1), SPI_MEM_FWRITE_QIO);
  102. bootloader_flash_execute_command_common(CMD_WRAP, 0, 0, 6, 8, 0x10, 0);
  103. REG_CLR_BIT(SPI_MEM_USER_REG(1), SPI_MEM_FWRITE_QIO);
  104. return ESP_OK;
  105. }
  106. const spi_flash_wrap_info_t __attribute__((weak)) spi_flash_wrap_list[] = {
  107. /* method probe chip wrap set chip wrap clear */
  108. {"C0H+8B", spi_flash_wrap_probe_c0, spi_flash_wrap_enable_c0, spi_flash_wrap_clear_c0},
  109. {"default", NULL, spi_flash_wrap_enable_77, spi_flash_wrap_clear_77},
  110. };
  111. static const spi_flash_wrap_info_t *chip_wrap = NULL;
  112. esp_err_t spi_flash_wrap_probe(void)
  113. {
  114. uint32_t flash_chip_id = g_rom_flashchip.device_id;
  115. const spi_flash_wrap_info_t *chip = spi_flash_wrap_list;
  116. esp_err_t ret = ESP_OK;
  117. while (chip->probe) {
  118. ret = chip->probe(flash_chip_id);
  119. if (ret == ESP_OK) {
  120. break;
  121. }
  122. chip++;
  123. }
  124. chip_wrap = chip;
  125. return ret;
  126. }
  127. esp_err_t spi_flash_wrap_enable(spi_flash_wrap_size_t wrap_size)
  128. {
  129. return chip_wrap->chip_wrap_set(wrap_size);
  130. }
  131. esp_err_t spi_flash_wrap_disable(void)
  132. {
  133. return chip_wrap->chip_wrap_clr();
  134. }
  135. bool spi_flash_support_wrap_size(uint32_t wrap_size)
  136. {
  137. // Only QIO mode supports wrap.
  138. if (!REG_GET_BIT(SPI_MEM_CTRL_REG(0), SPI_MEM_FREAD_QIO)) {
  139. ESP_EARLY_LOGE(FLASH_WRAP_TAG, "flash wrap is only supported in QIO mode");
  140. abort();
  141. }
  142. // Only following size can be wrapped.
  143. switch (wrap_size) {
  144. case 0:
  145. case 8:
  146. case 16:
  147. case 32:
  148. case 64:
  149. return true;
  150. default:
  151. return false;
  152. }
  153. }
  154. #endif // SOC_SPI_MEM_SUPPORT_WRAP