memspi_host_driver.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. // Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include "soc/soc_caps.h"
  15. #include "spi_flash_defs.h"
  16. #include "memspi_host_driver.h"
  17. #include "string.h"
  18. #include "esp_log.h"
  19. #include "cache_utils.h"
  20. #include "esp_flash_partitions.h"
  21. #define SPI_FLASH_HAL_MAX_WRITE_BYTES 64
  22. #define SPI_FLASH_HAL_MAX_READ_BYTES 64
  23. DRAM_ATTR static const spi_flash_host_driver_t esp_flash_default_host = ESP_FLASH_DEFAULT_HOST_DRIVER();
  24. #if SOC_MEMSPI_IS_INDEPENDENT
  25. extern void spi_flash_hal_gpspi_poll_cmd_done(spi_flash_host_inst_t *host);
  26. extern esp_err_t spi_flash_hal_gpspi_device_config(spi_flash_host_inst_t *host);
  27. esp_err_t spi_flash_hal_gpspi_configure_host_io_mode(
  28. spi_flash_host_inst_t *host,
  29. uint32_t command,
  30. uint32_t addr_bitlen,
  31. int dummy_cyclelen_base,
  32. esp_flash_io_mode_t io_mode);
  33. extern esp_err_t spi_flash_hal_gpspi_common_command(spi_flash_host_inst_t *host, spi_flash_trans_t *trans);
  34. extern esp_err_t spi_flash_hal_gpspi_read(spi_flash_host_inst_t *host, void *buffer, uint32_t address, uint32_t read_len);
  35. extern uint32_t spi_flash_hal_gpspi_check_status(spi_flash_host_inst_t *host);
  36. extern bool spi_flash_hal_gpspi_supports_direct_write(spi_flash_host_inst_t *host, const void *p);
  37. extern bool spi_flash_hal_gpspi_supports_direct_read(spi_flash_host_inst_t *host, const void *p);
  38. /** Default configuration for GPSPI */
  39. static const spi_flash_host_driver_t esp_flash_gpspi_host = {
  40. .dev_config = spi_flash_hal_gpspi_device_config,
  41. .common_command = spi_flash_hal_gpspi_common_command,
  42. .read_id = memspi_host_read_id_hs,
  43. .erase_chip = memspi_host_erase_chip,
  44. .erase_sector = memspi_host_erase_sector,
  45. .erase_block = memspi_host_erase_block,
  46. .read_status = memspi_host_read_status_hs,
  47. .set_write_protect = memspi_host_set_write_protect,
  48. .supports_direct_write = spi_flash_hal_gpspi_supports_direct_write,
  49. .supports_direct_read = spi_flash_hal_gpspi_supports_direct_read,
  50. .program_page = memspi_host_program_page,
  51. .write_data_slicer = memspi_host_write_data_slicer,
  52. .read = spi_flash_hal_gpspi_read,
  53. .read_data_slicer = memspi_host_read_data_slicer,
  54. .host_status = spi_flash_hal_gpspi_check_status,
  55. .configure_host_io_mode = spi_flash_hal_gpspi_configure_host_io_mode,
  56. .poll_cmd_done = spi_flash_hal_gpspi_poll_cmd_done,
  57. .flush_cache = NULL,
  58. .check_suspend = NULL,
  59. .resume = spi_flash_hal_resume,
  60. .suspend = spi_flash_hal_suspend,
  61. };
  62. #endif
  63. esp_err_t memspi_host_init_pointers(memspi_host_inst_t *host, const memspi_host_config_t *cfg)
  64. {
  65. #if SOC_MEMSPI_IS_INDEPENDENT
  66. if (cfg->host_id == SPI1_HOST)
  67. host->inst.driver = &esp_flash_default_host;
  68. else {
  69. host->inst.driver = &esp_flash_gpspi_host;
  70. }
  71. #else
  72. host->inst.driver = &esp_flash_default_host;
  73. #endif
  74. esp_err_t err = spi_flash_hal_init(host, cfg);
  75. return err;
  76. }
  77. #ifndef CONFIG_SPI_FLASH_ROM_IMPL
  78. static const char TAG[] = "memspi";
  79. esp_err_t memspi_host_read_id_hs(spi_flash_host_inst_t *host, uint32_t *id)
  80. {
  81. uint32_t id_buf = 0;
  82. spi_flash_trans_t t = {
  83. .command = CMD_RDID,
  84. .miso_len = 3,
  85. .miso_data = ((uint8_t*) &id_buf),
  86. };
  87. host->driver->common_command(host, &t);
  88. uint32_t raw_flash_id = id_buf;
  89. ESP_EARLY_LOGV(TAG, "raw_chip_id: %X\n", raw_flash_id);
  90. if (raw_flash_id == 0xFFFFFF || raw_flash_id == 0) {
  91. ESP_EARLY_LOGE(TAG, "no response\n");
  92. return ESP_ERR_FLASH_NO_RESPONSE;
  93. }
  94. // Byte swap the flash id as it's usually written the other way around
  95. uint8_t mfg_id = raw_flash_id & 0xFF;
  96. uint16_t flash_id = (raw_flash_id >> 16) | (raw_flash_id & 0xFF00);
  97. *id = ((uint32_t)mfg_id << 16) | flash_id;
  98. ESP_EARLY_LOGV(TAG, "chip_id: %X\n", *id);
  99. return ESP_OK;
  100. }
  101. esp_err_t memspi_host_read_status_hs(spi_flash_host_inst_t *host, uint8_t *out_sr)
  102. {
  103. //NOTE: we do have a read id function, however it doesn't work in high freq
  104. uint32_t stat_buf = 0;
  105. spi_flash_trans_t t = {
  106. .command = CMD_RDSR,
  107. .miso_data = ((uint8_t*) &stat_buf),
  108. .miso_len = 1
  109. };
  110. esp_err_t err = host->driver->common_command(host, &t);
  111. if (err != ESP_OK) {
  112. return err;
  113. }
  114. *out_sr = stat_buf;
  115. return ESP_OK;
  116. }
  117. esp_err_t memspi_host_flush_cache(spi_flash_host_inst_t *host, uint32_t addr, uint32_t size)
  118. {
  119. if ((void*)((memspi_host_inst_t*)host)->spi == (void*) spi_flash_ll_get_hw(SPI1_HOST)) {
  120. spi_flash_check_and_flush_cache(addr, size);
  121. }
  122. return ESP_OK;
  123. }
  124. void memspi_host_erase_chip(spi_flash_host_inst_t *host)
  125. {
  126. spi_flash_trans_t t = { 0 };
  127. t.command = CMD_CHIP_ERASE;
  128. host->driver->common_command(host, &t);
  129. }
  130. // Only support 24bit address
  131. void memspi_host_erase_sector(spi_flash_host_inst_t *host, uint32_t start_address)
  132. {
  133. assert(start_address < 0x1000000);
  134. spi_flash_trans_t t = {
  135. .command = CMD_SECTOR_ERASE,
  136. .address_bitlen = 24,
  137. .address = start_address
  138. };
  139. host->driver->common_command(host, &t);
  140. }
  141. // Only support 24bit address
  142. void memspi_host_erase_block(spi_flash_host_inst_t *host, uint32_t start_address)
  143. {
  144. assert(start_address < 0x1000000);
  145. spi_flash_trans_t t = {
  146. .command = CMD_LARGE_BLOCK_ERASE,
  147. .address_bitlen = 24,
  148. .address = start_address,
  149. };
  150. host->driver->common_command(host, &t);
  151. }
  152. // Only support 24bit address
  153. void memspi_host_program_page(spi_flash_host_inst_t *host, const void *buffer, uint32_t address, uint32_t length)
  154. {
  155. assert(address + length <= 0x1000000);
  156. spi_flash_trans_t t = {
  157. .command = CMD_PROGRAM_PAGE,
  158. .address_bitlen = 24,
  159. .address = address,
  160. .mosi_len = length,
  161. .mosi_data = buffer
  162. };
  163. host->driver->common_command(host, &t);
  164. }
  165. esp_err_t memspi_host_read(spi_flash_host_inst_t *host, void *buffer, uint32_t address, uint32_t read_len)
  166. {
  167. spi_flash_trans_t t = {
  168. .command = CMD_READ,
  169. .address_bitlen = 24,
  170. .address = address,
  171. .miso_len = read_len,
  172. .miso_data = buffer
  173. };
  174. host->driver->common_command(host, &t);
  175. return ESP_OK;
  176. }
  177. esp_err_t memspi_host_set_write_protect(spi_flash_host_inst_t *host, bool wp)
  178. {
  179. spi_flash_trans_t t = {
  180. .command = wp ? CMD_WRDI : CMD_WREN
  181. };
  182. host->driver->common_command(host, &t);
  183. return ESP_OK;
  184. }
  185. // When encryption is enabled, etc. the data slicer may be complicated
  186. // This is the simple case where the hardware has no other requirements than the size and page boundary
  187. int memspi_host_write_data_slicer(spi_flash_host_inst_t *host, uint32_t address, uint32_t len, uint32_t *align_address, uint32_t page_size)
  188. {
  189. uint32_t slicer_flag = ((spi_flash_hal_context_t*)host)->slicer_flags;
  190. uint32_t align_addr = address;
  191. if (slicer_flag & SPI_FLASH_HOST_CONTEXT_SLICER_FLAG_DTR) {
  192. if (((align_addr % 2) != 0) && ((len % 2) != 0)) {
  193. align_addr -= 1;
  194. len += 1;
  195. } else if (((align_addr % 2) != 0) && ((len % 2) == 0)) {
  196. align_addr -= 1;
  197. len += 2;
  198. } else if (((align_addr % 2) == 0) && ((len % 2) != 0)) {
  199. len += 1;
  200. }
  201. }
  202. uint32_t end_bound = (align_addr/page_size + 1) * page_size;
  203. // Shouldn't program cross the page, or longer than SPI_FLASH_HAL_MAX_WRITE_BYTES
  204. uint32_t max_len = MIN(end_bound - align_addr, SPI_FLASH_HAL_MAX_WRITE_BYTES);
  205. *align_address = align_addr;
  206. return MIN(max_len, len);
  207. }
  208. int memspi_host_read_data_slicer(spi_flash_host_inst_t *host, uint32_t address, uint32_t len, uint32_t *align_address, uint32_t page_size)
  209. {
  210. // Shouldn't read longer than SPI_FLASH_HAL_MAX_READ_BYTES
  211. uint32_t slicer_flag = ((spi_flash_hal_context_t*)host)->slicer_flags;
  212. uint32_t align_addr = address;
  213. if (slicer_flag & SPI_FLASH_HOST_CONTEXT_SLICER_FLAG_DTR) {
  214. if (((align_addr % 2) != 0) && ((len % 2) != 0)) {
  215. align_addr -= 1;
  216. len += 1;
  217. } else if (((align_addr % 2) != 0) && ((len % 2) == 0)) {
  218. align_addr -= 1;
  219. len += 2;
  220. } else if (((align_addr % 2) == 0) && ((len % 2) != 0)) {
  221. len += 1;
  222. }
  223. }
  224. uint32_t max_len = SPI_FLASH_HAL_MAX_READ_BYTES;
  225. *align_address = align_addr;
  226. return MIN(max_len, len);
  227. }
  228. #endif // CONFIG_SPI_FLASH_ROM_IMPL