spi_flash.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. /*
  2. * Copyright (c) 2019-2020, Broadcom
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <stdbool.h>
  7. #include <stddef.h>
  8. #include <stdint.h>
  9. #include <common/debug.h>
  10. #include <drivers/delay_timer.h>
  11. #include <errno.h>
  12. #include <sf.h>
  13. #include <spi.h>
  14. #define SPI_FLASH_CMD_LEN 4
  15. #define QSPI_WAIT_TIMEOUT_US 200000U /* usec */
  16. #define FINFO(jedec_id, ext_id, _sector_size, _n_sectors, _page_size, _flags) \
  17. .id = { \
  18. ((jedec_id) >> 16) & 0xff, \
  19. ((jedec_id) >> 8) & 0xff, \
  20. (jedec_id) & 0xff, \
  21. ((ext_id) >> 8) & 0xff, \
  22. (ext_id) & 0xff, \
  23. }, \
  24. .id_len = (!(jedec_id) ? 0 : (3 + ((ext_id) ? 2 : 0))), \
  25. .sector_size = (_sector_size), \
  26. .n_sectors = (_n_sectors), \
  27. .page_size = _page_size, \
  28. .flags = (_flags),
  29. /* SPI/QSPI flash device params structure */
  30. const struct spi_flash_info spi_flash_ids[] = {
  31. {"W25Q64CV", FINFO(0xef4017, 0x0, 64 * 1024, 128, 256, WR_QPP | SECT_4K)},
  32. {"W25Q64DW", FINFO(0xef6017, 0x0, 64 * 1024, 128, 256, WR_QPP | SECT_4K)},
  33. {"W25Q32", FINFO(0xef4016, 0x0, 64 * 1024, 64, 256, SECT_4K)},
  34. {"MX25l3205D", FINFO(0xc22016, 0x0, 64 * 1024, 64, 256, SECT_4K)},
  35. };
  36. static void spi_flash_addr(uint32_t addr, uint8_t *cmd)
  37. {
  38. /*
  39. * cmd[0] holds a SPI Flash command, stored earlier
  40. * cmd[1/2/3] holds 24bit flash address
  41. */
  42. cmd[1] = addr >> 16;
  43. cmd[2] = addr >> 8;
  44. cmd[3] = addr >> 0;
  45. }
  46. static const struct spi_flash_info *spi_flash_read_id(void)
  47. {
  48. const struct spi_flash_info *info;
  49. uint8_t id[SPI_FLASH_MAX_ID_LEN];
  50. int ret;
  51. ret = spi_flash_cmd(CMD_READ_ID, id, SPI_FLASH_MAX_ID_LEN);
  52. if (ret < 0) {
  53. ERROR("SF: Error %d reading JEDEC ID\n", ret);
  54. return NULL;
  55. }
  56. for (info = spi_flash_ids; info->name != NULL; info++) {
  57. if (info->id_len) {
  58. if (!memcmp(info->id, id, info->id_len))
  59. return info;
  60. }
  61. }
  62. printf("SF: unrecognized JEDEC id bytes: %02x, %02x, %02x\n",
  63. id[0], id[1], id[2]);
  64. return NULL;
  65. }
  66. /* Enable writing on the SPI flash */
  67. static inline int spi_flash_cmd_write_enable(struct spi_flash *flash)
  68. {
  69. return spi_flash_cmd(CMD_WRITE_ENABLE, NULL, 0);
  70. }
  71. static int spi_flash_cmd_wait(struct spi_flash *flash)
  72. {
  73. uint8_t cmd;
  74. uint32_t i;
  75. uint8_t status;
  76. int ret;
  77. i = 0;
  78. while (1) {
  79. cmd = CMD_RDSR;
  80. ret = spi_flash_cmd_read(&cmd, 1, &status, 1);
  81. if (ret < 0) {
  82. ERROR("SF: cmd wait failed\n");
  83. break;
  84. }
  85. if (!(status & STATUS_WIP))
  86. break;
  87. i++;
  88. if (i >= QSPI_WAIT_TIMEOUT_US) {
  89. ERROR("SF: cmd wait timeout\n");
  90. ret = -1;
  91. break;
  92. }
  93. udelay(1);
  94. }
  95. return ret;
  96. }
  97. static int spi_flash_write_common(struct spi_flash *flash, const uint8_t *cmd,
  98. size_t cmd_len, const void *buf,
  99. size_t buf_len)
  100. {
  101. int ret;
  102. ret = spi_flash_cmd_write_enable(flash);
  103. if (ret < 0) {
  104. ERROR("SF: enabling write failed\n");
  105. return ret;
  106. }
  107. ret = spi_flash_cmd_write(cmd, cmd_len, buf, buf_len);
  108. if (ret < 0) {
  109. ERROR("SF: write cmd failed\n");
  110. return ret;
  111. }
  112. ret = spi_flash_cmd_wait(flash);
  113. if (ret < 0) {
  114. ERROR("SF: write timed out\n");
  115. return ret;
  116. }
  117. return ret;
  118. }
  119. static int spi_flash_read_common(const uint8_t *cmd, size_t cmd_len,
  120. void *data, size_t data_len)
  121. {
  122. int ret;
  123. ret = spi_flash_cmd_read(cmd, cmd_len, data, data_len);
  124. if (ret < 0) {
  125. ERROR("SF: read cmd failed\n");
  126. return ret;
  127. }
  128. return ret;
  129. }
  130. int spi_flash_read(struct spi_flash *flash, uint32_t offset,
  131. uint32_t len, void *data)
  132. {
  133. uint32_t read_len = 0, read_addr;
  134. uint8_t cmd[SPI_FLASH_CMD_LEN];
  135. int ret;
  136. ret = spi_claim_bus();
  137. if (ret) {
  138. ERROR("SF: unable to claim SPI bus\n");
  139. return ret;
  140. }
  141. cmd[0] = CMD_READ_NORMAL;
  142. while (len) {
  143. read_addr = offset;
  144. read_len = MIN(flash->page_size, (len - read_len));
  145. spi_flash_addr(read_addr, cmd);
  146. ret = spi_flash_read_common(cmd, sizeof(cmd), data, read_len);
  147. if (ret < 0) {
  148. ERROR("SF: read failed\n");
  149. break;
  150. }
  151. offset += read_len;
  152. len -= read_len;
  153. data += read_len;
  154. }
  155. SPI_DEBUG("SF read done\n");
  156. spi_release_bus();
  157. return ret;
  158. }
  159. int spi_flash_write(struct spi_flash *flash, uint32_t offset,
  160. uint32_t len, void *buf)
  161. {
  162. unsigned long byte_addr, page_size;
  163. uint8_t cmd[SPI_FLASH_CMD_LEN];
  164. uint32_t chunk_len, actual;
  165. uint32_t write_addr;
  166. int ret;
  167. ret = spi_claim_bus();
  168. if (ret) {
  169. ERROR("SF: unable to claim SPI bus\n");
  170. return ret;
  171. }
  172. page_size = flash->page_size;
  173. cmd[0] = flash->write_cmd;
  174. for (actual = 0; actual < len; actual += chunk_len) {
  175. write_addr = offset;
  176. byte_addr = offset % page_size;
  177. chunk_len = MIN(len - actual,
  178. (uint32_t)(page_size - byte_addr));
  179. spi_flash_addr(write_addr, cmd);
  180. SPI_DEBUG("SF:0x%p=>cmd:{0x%02x 0x%02x%02x%02x} chunk_len:%d\n",
  181. buf + actual, cmd[0], cmd[1],
  182. cmd[2], cmd[3], chunk_len);
  183. ret = spi_flash_write_common(flash, cmd, sizeof(cmd),
  184. buf + actual, chunk_len);
  185. if (ret < 0) {
  186. ERROR("SF: write cmd failed\n");
  187. break;
  188. }
  189. offset += chunk_len;
  190. }
  191. SPI_DEBUG("SF write done\n");
  192. spi_release_bus();
  193. return ret;
  194. }
  195. int spi_flash_erase(struct spi_flash *flash, uint32_t offset, uint32_t len)
  196. {
  197. uint8_t cmd[SPI_FLASH_CMD_LEN];
  198. uint32_t erase_size, erase_addr;
  199. int ret;
  200. erase_size = flash->erase_size;
  201. if (offset % erase_size || len % erase_size) {
  202. ERROR("SF: Erase offset/length not multiple of erase size\n");
  203. return -1;
  204. }
  205. ret = spi_claim_bus();
  206. if (ret) {
  207. ERROR("SF: unable to claim SPI bus\n");
  208. return ret;
  209. }
  210. cmd[0] = flash->erase_cmd;
  211. while (len) {
  212. erase_addr = offset;
  213. spi_flash_addr(erase_addr, cmd);
  214. SPI_DEBUG("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1],
  215. cmd[2], cmd[3], erase_addr);
  216. ret = spi_flash_write_common(flash, cmd, sizeof(cmd), NULL, 0);
  217. if (ret < 0) {
  218. ERROR("SF: erase failed\n");
  219. break;
  220. }
  221. offset += erase_size;
  222. len -= erase_size;
  223. }
  224. SPI_DEBUG("sf erase done\n");
  225. spi_release_bus();
  226. return ret;
  227. }
  228. int spi_flash_probe(struct spi_flash *flash)
  229. {
  230. const struct spi_flash_info *info = NULL;
  231. int ret;
  232. ret = spi_claim_bus();
  233. if (ret) {
  234. ERROR("SF: Unable to claim SPI bus\n");
  235. ERROR("SF: probe failed\n");
  236. return ret;
  237. }
  238. info = spi_flash_read_id();
  239. if (!info)
  240. goto probe_fail;
  241. INFO("Flash Name: %s sectors %x, sec size %x\n",
  242. info->name, info->n_sectors,
  243. info->sector_size);
  244. flash->size = info->n_sectors * info->sector_size;
  245. flash->sector_size = info->sector_size;
  246. flash->page_size = info->page_size;
  247. flash->flags = info->flags;
  248. flash->read_cmd = CMD_READ_NORMAL;
  249. flash->write_cmd = CMD_PAGE_PROGRAM;
  250. flash->erase_cmd = CMD_ERASE_64K;
  251. flash->erase_size = ERASE_SIZE_64K;
  252. probe_fail:
  253. spi_release_bus();
  254. return ret;
  255. }