spiflash.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531
  1. #include "compiler.h"
  2. #include "zlib.h"
  3. #include "spiflash.h"
  4. struct spz_stream;
  5. typedef struct spz_stream spz_stream;
  6. struct spz_stream {
  7. z_stream zs;
  8. const struct spiflash *flash;
  9. int (*read_data)(spz_stream *); /* Routine to get more data */
  10. int (*end_data)(z_stream *); /* Termination routine for zlib */
  11. int err; /* Error code to return */
  12. bool eoi; /* Reached end of input */
  13. uint8_t *optr; /* Output data pointer into obuf */
  14. /* Note: available output data ends at zs->next_out */
  15. uint8_t *ibuf; /* Input buffer if compressed */
  16. uint8_t *obuf; /* Output buffer */
  17. uint8_t *vbuf; /* Readback/verify buffer */
  18. };
  19. static int spiflash_read_data(spz_stream *spz)
  20. {
  21. int rv;
  22. if (spz->eoi)
  23. return 0;
  24. spz->zs.next_in = NULL;
  25. spz->zs.avail_in = 0;
  26. rv = spz->flash->ops->read_data(spz->flash->cookie,
  27. spz->ibuf, SPIFLASH_BLOCK_SIZE);
  28. if (rv != SPIFLASH_BLOCK_SIZE)
  29. spz->eoi = true;
  30. if (rv < 0) {
  31. if (!spz->err)
  32. spz->err = rv;
  33. return 0;
  34. }
  35. spz->zs.next_in = spz->ibuf;
  36. spz->zs.avail_in = rv;
  37. return rv;
  38. }
  39. static int read_data_raw(spz_stream *spz)
  40. {
  41. int rlen;
  42. if (spz->eoi)
  43. return Z_STREAM_END;
  44. rlen = spiflash_read_data(spz);
  45. if (rlen < 0)
  46. return rlen; /* Error! */
  47. spz->optr = spz->ibuf;
  48. spz->zs.next_out = spz->ibuf + rlen;
  49. spz->zs.avail_out = SPIFLASH_BLOCK_SIZE - rlen;
  50. return spz->eoi ? Z_STREAM_END : Z_OK;
  51. }
  52. static int read_data_inflate(spz_stream *spz)
  53. {
  54. int rv = Z_STREAM_END;
  55. spz->optr = spz->zs.next_out = spz->obuf;
  56. spz->zs.avail_out = SPIFLASH_BLOCK_SIZE;
  57. while (spz->zs.avail_out) {
  58. if (!spz->zs.avail_in && !spz->eoi) {
  59. int rlen = spiflash_read_data(spz);
  60. spz->zs.next_in = spz->ibuf;
  61. spz->zs.avail_in = rlen;
  62. }
  63. rv = inflate(&spz->zs, Z_SYNC_FLUSH);
  64. if (rv == Z_OK || (rv == Z_BUF_ERROR && !spz->eoi))
  65. continue;
  66. if (rv != Z_STREAM_END) {
  67. if (!spz->err)
  68. spz->err = rv >= 0 ? Z_STREAM_ERROR : rv;
  69. }
  70. break;
  71. }
  72. if (rv != Z_OK) {
  73. /* Z_STREAM_END or error */
  74. inflateEnd(&spz->zs);
  75. }
  76. return rv;
  77. }
  78. static void *spz_malloc(spz_stream *spz, size_t bytes)
  79. {
  80. void *p = malloc(bytes);
  81. if (!p && !spz->err) {
  82. spz->err = Z_MEM_ERROR;
  83. }
  84. return p;
  85. }
  86. int spiflash_data_init(spz_stream *spz, const struct spiflash *flash)
  87. {
  88. int rlen;
  89. int rv = Z_OK;
  90. uint8_t *rdbuf = NULL;
  91. memset(spz, 0, sizeof *spz);
  92. spz->flash = flash;
  93. spz->ibuf = spz_malloc(spz, SPIFLASH_BLOCK_SIZE);
  94. if (!spz->ibuf)
  95. goto err;
  96. spz->vbuf = spz_malloc(spz, SPIFLASH_BLOCK_SIZE);
  97. if (!spz->vbuf)
  98. goto err;
  99. rlen = spiflash_read_data(spz);
  100. if (rlen >= 14 && !memcmp(spz->ibuf, "\37\213\10", 3)) {
  101. /* It is a gzip file */
  102. spz->zs.next_in = spz->ibuf;
  103. spz->zs.avail_in = rlen;
  104. spz->read_data = read_data_inflate;
  105. spz->obuf = spz_malloc(spz, SPIFLASH_BLOCK_SIZE);
  106. if (!spz->obuf)
  107. goto err;
  108. rv = inflateInit2(&spz->zs, 16 + 15); /* gzip, max window size */
  109. if (rv != Z_OK) {
  110. spz->err = rv;
  111. goto err;
  112. }
  113. spz->end_data = inflateEnd;
  114. } else {
  115. /* Assume it is a raw binary; input buffer is output buffer */
  116. spz->optr = spz->ibuf;
  117. spz->zs.next_out = spz->ibuf + rlen;
  118. spz->zs.avail_out = SPIFLASH_BLOCK_SIZE - rlen;
  119. rv = spz->eoi ? Z_STREAM_END : Z_OK;
  120. }
  121. err:
  122. return spz->err ? spz->err : rv;
  123. }
  124. static void spiflash_data_cleanup(spz_stream *spz)
  125. {
  126. if (!spz)
  127. return;
  128. if (spz->end_data)
  129. spz->end_data(&spz->zs);
  130. if (spz->vbuf)
  131. free(spz->vbuf);
  132. if (spz->obuf)
  133. free(spz->obuf);
  134. if (spz->ibuf)
  135. free(spz->ibuf);
  136. }
  137. /*
  138. * Set up a command header with an address according to the SPI
  139. * addressing mode. Returns a pointer to the first byte past the
  140. * address.
  141. */
  142. static void *spiflash_setup_addrcmd(const struct spiflash *flash,
  143. uint32_t addr,
  144. uint8_t cmd24, uint8_t cmd32,
  145. void *cmdbuf)
  146. {
  147. enum spiflash_addr_mode mode = flash->param->addr;
  148. uint8_t *cmd = cmdbuf;
  149. if (!mode)
  150. mode = addr < (1 << 24) ? SPIFLASH_ADDR_24BIT : SPIFLASH_ADDR_32BIT;
  151. if (mode == SPIFLASH_ADDR_24BIT) {
  152. addr <<= 8;
  153. *cmd++ = cmd24;
  154. } else {
  155. *cmd++ = cmd32;
  156. *cmd++ = addr >> 24;
  157. }
  158. *cmd++ = addr >> 16;
  159. *cmd++ = addr >> 8;
  160. *cmd++ = addr;
  161. return cmd;
  162. }
  163. static int spiflash_wait_ready(const struct spiflash *flash, int delay)
  164. {
  165. uint8_t cmd = 0x05; /* Read Status Register 1 */
  166. uint8_t sr1 = 0;
  167. int rv;
  168. do {
  169. flash->ops->yield(flash->cookie, delay);
  170. rv = flash->ops->spi_read(flash->cookie, &cmd, 1,
  171. &sr1, 1, flash->param->tshsl);
  172. if (rv)
  173. return rv;
  174. } while (sr1 & 0x01); /* Busy bit set? */
  175. return 0;
  176. }
  177. int spiflash_read(const struct spiflash *flash,
  178. uint32_t addr, void *buffer, size_t len)
  179. {
  180. uint8_t cmdbuf[6];
  181. uint8_t *cmd;
  182. /*
  183. * 13h = Fast Read
  184. * 0Ch = Fast Read with 4-Byte Address
  185. */
  186. cmd = spiflash_setup_addrcmd(flash, addr, 0x13, 0x0c, cmdbuf);
  187. *cmd++ = 0; /* Dummy bits */
  188. return flash->ops->spi_read(flash->cookie, cmdbuf, cmd - cmdbuf,
  189. buffer, len, flash->param->tshsl1);
  190. }
  191. static int spiflash_write_enable(const struct spiflash *flash)
  192. {
  193. const uint8_t cmd = 0x06; /* 06h = Write Enable */
  194. return flash->ops->spi_write(flash->cookie, &cmd, 1, NULL, 0,
  195. flash->param->tshsl);
  196. }
  197. static int spiflash_program(const struct spiflash *flash,
  198. uint32_t addr, const void *buffer, size_t len)
  199. {
  200. uint8_t cmdbuf[5];
  201. uint8_t *cmd;
  202. int rv;
  203. rv = spiflash_write_enable(flash);
  204. if (rv)
  205. return rv;
  206. /*
  207. * 02h = Page Program
  208. * 12h = Page Program with 4-Byte Address
  209. */
  210. cmd = spiflash_setup_addrcmd(flash, addr, 0x02, 0x12, cmdbuf);
  211. rv = flash->ops->spi_write(flash->cookie, cmdbuf, cmd - cmdbuf,
  212. buffer, len, flash->param->tshsl2);
  213. if (rv)
  214. return rv;
  215. return spiflash_wait_ready(flash, flash->param->tpp);
  216. }
  217. /*
  218. * Erase up to (long bits) sectors, using block erase if possible.
  219. */
  220. static int spiflash_erase(const struct spiflash *flash,
  221. uint32_t addr, unsigned long sector_mask)
  222. {
  223. uint8_t cmdbuf[5];
  224. uint8_t *cmd;
  225. uint8_t cmd24, cmd32;
  226. uint32_t nextaddr;
  227. int rv;
  228. int delay;
  229. const uint32_t block_mask = SPIFLASH_BLOCK_SIZE - 1;
  230. const unsigned long block_sectors = block_mask >> SPIFLASH_SECTOR_SHIFT;
  231. while (sector_mask) {
  232. if (((sector_mask & block_sectors) == block_sectors) &&
  233. !(addr & block_mask)) {
  234. /*
  235. * D8h = 64KB Block Erase
  236. * DCh = 64K Block Erase with 4-Byte Address
  237. */
  238. cmd24 = 0xd8; cmd32 = 0xdc;
  239. delay = flash->param->tbe2;
  240. nextaddr = addr + SPIFLASH_BLOCK_SIZE;
  241. sector_mask >>= 16;
  242. } else {
  243. if (sector_mask & 1) {
  244. /*
  245. * 20h = Sector Erase
  246. * 21h = Sector Erase with 4-Byte Address
  247. */
  248. cmd24 = 0x20; cmd32 = 0x21;
  249. delay = flash->param->tse;
  250. nextaddr = addr + SPIFLASH_SECTOR_SIZE;
  251. sector_mask >>= 1;
  252. } else {
  253. addr += SPIFLASH_SECTOR_SIZE;
  254. sector_mask >>= 1;
  255. continue; /* Skip sector */
  256. }
  257. }
  258. rv = spiflash_write_enable(flash);
  259. if (rv)
  260. return rv;
  261. cmd = spiflash_setup_addrcmd(flash, addr, cmd24, cmd32, cmdbuf);
  262. rv = flash->ops->spi_write(flash->cookie, cmdbuf, cmd - cmdbuf,
  263. NULL, 0, flash->param->tshsl2);
  264. if (rv)
  265. return rv;
  266. rv = spiflash_wait_ready(flash, delay);
  267. if (rv)
  268. return rv;
  269. addr = nextaddr;
  270. }
  271. return 0;
  272. }
  273. /*
  274. * from: current flash contents
  275. * to: desired flash contents
  276. *
  277. * These are assumed to be aligned full block buffers
  278. */
  279. enum flashmem_status {
  280. FMS_DONE, /* All done, no programming needed */
  281. FMS_PROGRAM, /* Can be programmed */
  282. FMS_ERASE, /* Needs erase before programming */
  283. FMS_NOTCHECKED /* Not checked yet */
  284. };
  285. static enum flashmem_status
  286. spiflash_memcmp(const void *from, const void *to, size_t len)
  287. {
  288. const uint32_t *pf = from;
  289. const uint32_t *pt = to;
  290. const uint32_t *pfend = (const uint32_t *)((const char *)from + len);
  291. uint32_t notok = 0;
  292. uint32_t notprog = 0;
  293. while (pf < pfend) {
  294. uint32_t f = *pf++;
  295. uint32_t t = *pt++;
  296. notok |= f ^ t; /* Need programming if any data mismatch */
  297. notprog |= ~f & t; /* Need erasing if any 0 -> 1 */
  298. }
  299. return notprog ? FMS_ERASE : notok ? FMS_PROGRAM : FMS_DONE;
  300. }
  301. /*
  302. * Check a block for sectors which need erasing and pages which need
  303. * programming; the prog_mask is 256 bits long and so span multiple words.
  304. *
  305. * The input is spz->optr, and the existing flash content is written
  306. * to spz->vptr.
  307. *
  308. */
  309. static int spiflash_check_block(spz_stream *spz, uint32_t addr,
  310. uint32_t *erase_mask, uint32_t *prog_mask)
  311. {
  312. int rv;
  313. const uint8_t *p, *q;
  314. unsigned int page;
  315. rv = spiflash_read(spz->flash, addr, spz->vbuf, SPIFLASH_BLOCK_SIZE);
  316. if (rv) {
  317. if (!spz->err)
  318. spz->err = rv;
  319. return rv;
  320. }
  321. p = spz->optr;
  322. q = spz->vbuf;
  323. for (page = 0; page < SPIFLASH_BLOCK_SIZE/SPIFLASH_PAGE_SIZE; page++) {
  324. enum flashmem_status status;
  325. switch (spiflash_memcmp(p, q, SPIFLASH_PAGE_SIZE)) {
  326. case FMS_ERASE:
  327. *erase_mask |= UINT32_C(1) <<
  328. (page >> (SPIFLASH_SECTOR_SHIFT-SPIFLASH_PAGE_SHIFT));
  329. break;
  330. case FMS_PROGRAM:
  331. prog_mask[page >> 5] |= UINT32_C(1) << (page & 31);
  332. break;
  333. default:
  334. /* Nothing to do! */
  335. break;
  336. }
  337. p += SPIFLASH_PAGE_SIZE;
  338. q += SPIFLASH_PAGE_SIZE;
  339. }
  340. return 0;
  341. }
  342. int spiflash_flash_file(const struct spiflash *flash, uint32_t addr)
  343. {
  344. spz_stream _spz;
  345. spz_stream * const spz = &_spz; /* For consistency in notation */
  346. int rv;
  347. bool eof;
  348. enum flashmem_status fs;
  349. rv = spiflash_data_init(spz, flash);
  350. eof = rv != Z_OK;
  351. while (!eof && !spz->err) {
  352. unsigned int bytes = spz->zs.next_out - spz->optr;
  353. unsigned int padding;
  354. if (bytes < SPIFLASH_BLOCK_SIZE) {
  355. int rv;
  356. rv = spz->read_data(spz);
  357. eof = rv != Z_OK || spz->err;
  358. bytes = spz->zs.next_out - spz->optr;
  359. if (!bytes)
  360. break;
  361. padding = -bytes & (SPIFLASH_BLOCK_SIZE-1);
  362. if (padding > spz->zs.avail_out) {
  363. /* This should never happen */
  364. padding = spz->zs.avail_out;
  365. }
  366. if (padding) {
  367. memset(spz->zs.next_out, 0xff, padding);
  368. spz->zs.avail_out -= padding;
  369. bytes += padding;
  370. }
  371. }
  372. uint32_t erase_mask;
  373. uint32_t prog_mask[SPIFLASH_BLOCK_SIZE >> (SPIFLASH_PAGE_SHIFT+5)];
  374. rv = spiflash_check_block(spz, addr, &erase_mask, prog_mask);
  375. if (rv)
  376. break;
  377. if (erase_mask) {
  378. rv = spiflash_erase(spz->flash, addr, erase_mask);
  379. if (rv)
  380. break;
  381. rv = spiflash_check_block(spz, addr, &erase_mask, prog_mask);
  382. if (spz->err)
  383. break;
  384. if (erase_mask) {
  385. spz->err = SPIFLASH_ERR_ERASE_FAILED;
  386. break;
  387. }
  388. }
  389. unsigned int page;
  390. for (page = 0; page < (SPIFLASH_BLOCK_SIZE >> SPIFLASH_PAGE_SHIFT);
  391. page++) {
  392. uint32_t page_offs = page << SPIFLASH_PAGE_SHIFT;
  393. if (prog_mask[page >> 5] & (UINT32_C(1) << (page & 31))) {
  394. rv = spiflash_program(spz->flash, addr + page_offs,
  395. spz->optr + page_offs,
  396. SPIFLASH_PAGE_SIZE);
  397. if (rv) {
  398. spz->err = rv;
  399. break;
  400. }
  401. /* Read back data and verify */
  402. rv = spiflash_read(spz->flash, addr+page_offs,
  403. spz->vbuf + page_offs,
  404. SPIFLASH_PAGE_SIZE);
  405. if (rv) {
  406. spz->err = rv;
  407. break;
  408. }
  409. if (memcmp(spz->optr + page_offs, spz->vbuf + page_offs,
  410. SPIFLASH_PAGE_SIZE)) {
  411. spz->err = SPIFLASH_ERR_PROGRAM_FAILED;
  412. break;
  413. }
  414. }
  415. }
  416. spz->optr += SPIFLASH_BLOCK_SIZE;
  417. addr += SPIFLASH_BLOCK_SIZE;
  418. }
  419. if (spz->flash->ops->close_data)
  420. spz->flash->ops->close_data(spz->flash->cookie);
  421. spiflash_data_cleanup(spz);
  422. return spz->err;
  423. }
  424. /*
  425. * Read unique serial number from flash. Note: returns id in
  426. * bigendian ("network") byte order.
  427. */
  428. int spiflash_read_id(const struct spiflash *flash, void *id)
  429. {
  430. static const uint8_t read_unique_id[] = { 0x4b, 0, 0, 0, 0 };
  431. return flash->ops->spi_read(flash->cookie, read_unique_id,
  432. sizeof read_unique_id,
  433. id, SPIFLASH_ID_LEN, flash->param->tshsl);
  434. }
  435. /*
  436. * Read vendor and device ID from flash.
  437. */
  438. int spiflash_read_vdid(const struct spiflash *flash, void *vdid)
  439. {
  440. static const uint8_t read_vdid[] = { 0x90, 0, 0, 0 };
  441. return flash->ops->spi_read(flash->cookie, read_vdid,
  442. sizeof read_vdid,
  443. vdid, SPIFLASH_VDID_LEN, flash->param->tshsl);
  444. }