flash.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /* Motenpoche
  2. *
  3. * (c) 2023 Daniele Lacamera <root@danielinux.net>
  4. *
  5. *
  6. * Motenpoche is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Motenpoche is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
  19. *
  20. */
  21. #include <stdio.h>
  22. #include <stdint.h>
  23. #include "hardware/gpio.h"
  24. #include "flash.h"
  25. #include "cryptoengine.h"
  26. #include "bsp/board.h"
  27. #define MDID 0x90
  28. #define RDSR 0x05
  29. #define WRSR 0x01
  30. # define ST_BUSY (1 << 0)
  31. # define ST_WEL (1 << 1)
  32. # define ST_BP0 (1 << 2)
  33. # define ST_BP1 (1 << 3)
  34. # define ST_BP2 (1 << 4)
  35. # define ST_BP3 (1 << 5)
  36. # define ST_AAI (1 << 6)
  37. # define ST_BRO (1 << 7)
  38. #define WREN 0x06
  39. #define WRDI 0x04
  40. #define SECTOR_ERASE 0x20
  41. #define BYTE_READ 0x03
  42. #define BYTE_WRITE 0x02
  43. #define EWSR 0x50
  44. #define EBSY 0x70
  45. #define DBSY 0x80
  46. #define SPI_FLASH_CS_PIN 5
  47. static spi_inst_t *SPI = NULL;
  48. static void write_address(uint32_t address)
  49. {
  50. uint8_t a0 = (uint8_t)((address & 0xFF0000) >> 16),
  51. a1 = (uint8_t)((address & 0xFF00) >> 8),
  52. a2 = (uint8_t)((address & 0xFF));
  53. spi_write_blocking(SPI, &a0, 1);
  54. spi_write_blocking(SPI, &a1, 1);
  55. spi_write_blocking(SPI, &a2, 1);
  56. }
  57. static uint8_t read_status(void)
  58. {
  59. uint8_t status;
  60. uint8_t rdsr = RDSR;
  61. gpio_put(SPI_FLASH_CS_PIN, 0);
  62. spi_write_blocking(SPI, &rdsr, 1);
  63. spi_read_blocking(SPI, 0xFF, &status, 1);
  64. gpio_put(SPI_FLASH_CS_PIN, 1);
  65. return status;
  66. }
  67. uint8_t flash_read_status(void)
  68. {
  69. return read_status();
  70. }
  71. static void spi_cmd(uint8_t cmd)
  72. {
  73. gpio_put(SPI_FLASH_CS_PIN, 0);
  74. spi_write_blocking(SPI, &cmd, 1);
  75. gpio_put(SPI_FLASH_CS_PIN, 1);
  76. }
  77. #ifndef GREEN_LED
  78. #define GREEN_LED 16
  79. #endif
  80. volatile uint8_t flash_status;
  81. static void flash_write_enable(void)
  82. {
  83. do {
  84. spi_cmd(WREN);
  85. flash_status = read_status();
  86. } while ((flash_status & ST_WEL) == 0);
  87. }
  88. static void flash_write_disable(void)
  89. {
  90. spi_cmd(WRDI);
  91. }
  92. static void wait_busy(void)
  93. {
  94. do {
  95. flash_status = read_status();
  96. } while((flash_status & ST_BUSY) != 0);
  97. }
  98. static int spi_flash_write_sb(uint32_t address, const void *data, int len)
  99. {
  100. const uint8_t *buf = data;
  101. uint8_t verify = 0;
  102. int j = 0;
  103. wait_busy();
  104. if (len < 1)
  105. return -1;
  106. while (len > 0) {
  107. uint8_t cmd = BYTE_WRITE;
  108. flash_write_enable();
  109. gpio_put(SPI_FLASH_CS_PIN, 0);
  110. spi_write_blocking(SPI, &cmd, 1);
  111. write_address(address);
  112. spi_write_blocking(SPI, &buf[j], 1);
  113. gpio_put(SPI_FLASH_CS_PIN, 1);
  114. wait_busy();
  115. j++;
  116. len--;
  117. address++;
  118. }
  119. return 0;
  120. }
  121. /* --- */
  122. static uint16_t spi_flash_probe(void)
  123. {
  124. uint8_t manuf, product, cmd[2];
  125. int i;
  126. wait_busy();
  127. gpio_put(SPI_FLASH_CS_PIN, 0);
  128. cmd[0] = MDID;
  129. spi_write_blocking(SPI, cmd, 1);
  130. write_address(0);
  131. spi_read_blocking(SPI, 0xFF, &manuf, 1);
  132. spi_read_blocking(SPI, 0xFF, &product, 1);
  133. gpio_put(SPI_FLASH_CS_PIN, 1);
  134. wait_busy();
  135. flash_write_enable();
  136. gpio_put(SPI_FLASH_CS_PIN, 0);
  137. cmd[0] = WRSR;
  138. cmd[1] = 0x00;
  139. spi_write_blocking(SPI, cmd, 2);
  140. gpio_put(SPI_FLASH_CS_PIN, 1);
  141. return (uint16_t)(manuf << 8 | product);
  142. }
  143. uint16_t flash_init(spi_inst_t *spi)
  144. {
  145. uint16_t ret;
  146. //uint32_t mgc = VAULT_MAGIC - 1;
  147. SPI = spi;
  148. ret = spi_flash_probe();
  149. return ret;
  150. }
  151. int flash_sector_erase(uint32_t address)
  152. {
  153. uint8_t cmd;
  154. address &= (~(SPI_FLASH_SECTOR_SIZE - 1));
  155. wait_busy();
  156. flash_write_enable();
  157. gpio_put(SPI_FLASH_CS_PIN, 0);
  158. cmd = SECTOR_ERASE;
  159. spi_write_blocking(SPI, &cmd, 1);
  160. write_address(address);
  161. gpio_put(SPI_FLASH_CS_PIN, 1);
  162. wait_busy();
  163. return 0;
  164. }
  165. int flash_read(uint32_t address, void *data, int len)
  166. {
  167. uint8_t *buf = data, cmd;
  168. int i = 0;
  169. wait_busy();
  170. gpio_put(SPI_FLASH_CS_PIN, 0);
  171. cmd = BYTE_READ;
  172. spi_write_blocking(SPI, &cmd, 1);
  173. write_address(address);
  174. spi_read_blocking(SPI, 0xFF, buf, len);
  175. gpio_put(SPI_FLASH_CS_PIN, 1);
  176. return len;
  177. }
  178. int flash_write(uint32_t address, const void *data, int len)
  179. {
  180. int ret;
  181. ret = spi_flash_write_sb(address, data, len);
  182. wait_busy();
  183. return ret;
  184. }
  185. static uint8_t flash_sector_write_cache[SPI_FLASH_SECTOR_SIZE];
  186. int flash_write_svc(struct vault_service *svc, int idx)
  187. {
  188. const int svc_per_sector = SPI_FLASH_SECTOR_SIZE / SVC_SIZE;
  189. uint32_t addr = SVC_FLASH_OFFSET + SVC_SIZE * idx;
  190. uint32_t sector = addr / SPI_FLASH_SECTOR_SIZE;
  191. uint32_t offset = addr - (sector * SPI_FLASH_SECTOR_SIZE);
  192. flash_read(sector * SPI_FLASH_SECTOR_SIZE, flash_sector_write_cache,
  193. SPI_FLASH_SECTOR_SIZE);
  194. memcpy(flash_sector_write_cache + offset, (uint8_t *)svc, SVC_SIZE);
  195. flash_sector_erase(sector * SPI_FLASH_SECTOR_SIZE);
  196. flash_write(sector * SPI_FLASH_SECTOR_SIZE, flash_sector_write_cache,
  197. SPI_FLASH_SECTOR_SIZE);
  198. return 0;
  199. }