s25f.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537
  1. /*
  2. * This file is part of the flashrom project.
  3. *
  4. * Copyright (C) 2014 Google Inc.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. *
  13. * Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in the
  15. * documentation and/or other materials provided with the distribution.
  16. *
  17. * Neither the name of Google or the names of contributors or
  18. * licensors may be used to endorse or promote products derived from this
  19. * software without specific prior written permission.
  20. *
  21. * This software is provided "AS IS," without a warranty of any kind.
  22. * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
  23. * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
  24. * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
  25. * GOOGLE INC AND ITS LICENSORS SHALL NOT BE LIABLE
  26. * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
  27. * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
  28. * GOOGLE OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
  29. * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
  30. * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
  31. * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
  32. * EVEN IF GOOGLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
  33. *
  34. * s25f.c - Helper functions for Spansion S25FL and S25FS SPI flash chips.
  35. * Uses 24 bit addressing for the FS chips and 32 bit addressing for the FL
  36. * chips (which is required by the overlayed sector size devices).
  37. * TODO: Implement fancy hybrid sector architecture helpers.
  38. */
  39. #include <string.h>
  40. #include "chipdrivers.h"
  41. #include "spi.h"
  42. #include "writeprotect.h"
  43. /*
  44. * RDAR and WRAR are supported on chips which have more than one set of status
  45. * and control registers and take an address of the register to read/write.
  46. * WRR, RDSR2, and RDCR are used on chips with a more limited set of control/
  47. * status registers.
  48. *
  49. * WRR is somewhat peculiar. It shares the same opcode as JEDEC_WRSR, and if
  50. * given one data byte (following the opcode) it acts the same way. If it's
  51. * given two data bytes, the first data byte overwrites status register 1
  52. * and the second data byte overwrites config register 1.
  53. */
  54. #define CMD_WRR 0x01
  55. #define CMD_WRDI 0x04
  56. #define CMD_RDSR2 0x07 /* note: read SR1 with JEDEC RDSR opcode */
  57. #define CMD_RDCR 0x35
  58. #define CMD_RDAR 0x65
  59. #define CMD_WRAR 0x71
  60. /* TODO: For now, commands which use an address assume 24-bit addressing */
  61. #define CMD_WRR_LEN 3
  62. #define CMD_WRDI_LEN 1
  63. #define CMD_RDAR_LEN 4
  64. #define CMD_WRAR_LEN 5
  65. #define CMD_RSTEN 0x66
  66. #define CMD_RST 0x99
  67. #define CR1NV_ADDR 0x000002
  68. #define CR1_BPNV_O (1 << 3)
  69. #define CR1_TBPROT_O (1 << 5)
  70. #define CR3NV_ADDR 0x000004
  71. #define CR3NV_20H_NV (1 << 3)
  72. /* See "Embedded Algorithm Performance Tables for additional timing specs. */
  73. #define T_W 145 * 1000 /* NV register write time (145ms) */
  74. #define T_RPH 35 /* Reset pulse hold time (35us) */
  75. #define S25FS_T_SE 145 * 1000 /* Sector Erase Time (145ms) */
  76. #define S25FL_T_SE 130 * 1000 /* Sector Erase Time (130ms) */
  77. static int s25f_legacy_software_reset(const struct flashctx *flash)
  78. {
  79. int result;
  80. struct spi_command cmds[] = {
  81. {
  82. .writecnt = 1,
  83. .writearr = (const unsigned char[]){ CMD_RSTEN },
  84. .readcnt = 0,
  85. .readarr = NULL,
  86. }, {
  87. .writecnt = 1,
  88. .writearr = (const unsigned char[]){ 0xf0 },
  89. .readcnt = 0,
  90. .readarr = NULL,
  91. }, {
  92. .writecnt = 0,
  93. .writearr = NULL,
  94. .readcnt = 0,
  95. .readarr = NULL,
  96. }};
  97. result = spi_send_multicommand(flash, cmds);
  98. if (result) {
  99. msg_cerr("%s failed during command execution\n", __func__);
  100. return result;
  101. }
  102. /* Allow time for reset command to execute. The datasheet specifies
  103. * Trph = 35us, double that to be safe. */
  104. programmer_delay(T_RPH * 2);
  105. return 0;
  106. }
  107. /* "Legacy software reset" is disabled by default on S25FS, use this instead. */
  108. static int s25fs_software_reset(struct flashctx *flash)
  109. {
  110. int result;
  111. struct spi_command cmds[] = {
  112. {
  113. .writecnt = 1,
  114. .writearr = (const unsigned char[]){ CMD_RSTEN },
  115. .readcnt = 0,
  116. .readarr = NULL,
  117. }, {
  118. .writecnt = 1,
  119. .writearr = (const unsigned char[]){ CMD_RST },
  120. .readcnt = 0,
  121. .readarr = NULL,
  122. }, {
  123. .writecnt = 0,
  124. .writearr = NULL,
  125. .readcnt = 0,
  126. .readarr = NULL,
  127. }};
  128. result = spi_send_multicommand(flash, cmds);
  129. if (result) {
  130. msg_cerr("%s failed during command execution\n", __func__);
  131. return result;
  132. }
  133. /* Allow time for reset command to execute. Double tRPH to be safe. */
  134. programmer_delay(T_RPH * 2);
  135. return 0;
  136. }
  137. static int s25f_poll_status(const struct flashctx *flash)
  138. {
  139. uint8_t tmp = spi_read_status_register(flash);
  140. while (tmp & JEDEC_RDSR_BIT_WIP) {
  141. /*
  142. * The WIP bit on S25F chips remains set to 1 if erase or
  143. * programming errors occur, so we must check for those
  144. * errors here. If an error is encountered, do a software
  145. * reset to clear WIP and other volatile bits, otherwise
  146. * the chip will be unresponsive to further commands.
  147. */
  148. if (tmp & JEDEC_RDSR_BIT_ERASE_ERR) {
  149. msg_cerr("Erase error occurred\n");
  150. s25f_legacy_software_reset(flash);
  151. return -1;
  152. }
  153. if (tmp & (1 << 6)) {
  154. msg_cerr("Programming error occurred\n");
  155. s25f_legacy_software_reset(flash);
  156. return -1;
  157. }
  158. programmer_delay(1000 * 10);
  159. tmp = spi_read_status_register(flash);
  160. }
  161. return 0;
  162. }
  163. /* "Read Any Register" instruction only supported on S25FS */
  164. static int s25fs_read_cr(const struct flashctx *flash, uint32_t addr)
  165. {
  166. int result;
  167. uint8_t cfg;
  168. /* By default, 8 dummy cycles are necessary for variable-latency
  169. commands such as RDAR (see CR2NV[3:0]). */
  170. unsigned char read_cr_cmd[] = {
  171. CMD_RDAR,
  172. (addr >> 16) & 0xff,
  173. (addr >> 8) & 0xff,
  174. (addr & 0xff),
  175. 0x00, 0x00, 0x00, 0x00,
  176. 0x00, 0x00, 0x00, 0x00,
  177. };
  178. result = spi_send_command(flash, sizeof(read_cr_cmd), 1, read_cr_cmd, &cfg);
  179. if (result) {
  180. msg_cerr("%s failed during command execution at address 0x%x\n",
  181. __func__, addr);
  182. return -1;
  183. }
  184. return cfg;
  185. }
  186. static int s25f_read_cr1(const struct flashctx *flash)
  187. {
  188. int result;
  189. uint8_t cfg;
  190. unsigned char read_cr_cmd[] = { CMD_RDCR };
  191. result = spi_send_command(flash, sizeof(read_cr_cmd), 1, read_cr_cmd, &cfg);
  192. if (result) {
  193. msg_cerr("%s failed during command execution\n", __func__);
  194. return -1;
  195. }
  196. return cfg;
  197. }
  198. /* "Write Any Register" instruction only supported on S25FS */
  199. static int s25fs_write_cr(const struct flashctx *flash,
  200. uint32_t addr, uint8_t data)
  201. {
  202. int result;
  203. struct spi_command cmds[] = {
  204. {
  205. .writecnt = JEDEC_WREN_OUTSIZE,
  206. .writearr = (const unsigned char[]){ JEDEC_WREN },
  207. .readcnt = 0,
  208. .readarr = NULL,
  209. }, {
  210. .writecnt = CMD_WRAR_LEN,
  211. .writearr = (const unsigned char[]){
  212. CMD_WRAR,
  213. (addr >> 16) & 0xff,
  214. (addr >> 8) & 0xff,
  215. (addr & 0xff),
  216. data
  217. },
  218. .readcnt = 0,
  219. .readarr = NULL,
  220. }, {
  221. .writecnt = 0,
  222. .writearr = NULL,
  223. .readcnt = 0,
  224. .readarr = NULL,
  225. }};
  226. result = spi_send_multicommand(flash, cmds);
  227. if (result) {
  228. msg_cerr("%s failed during command execution at address 0x%x\n",
  229. __func__, addr);
  230. return -1;
  231. }
  232. programmer_delay(T_W);
  233. return s25f_poll_status(flash);
  234. }
  235. static int s25f_write_cr1(const struct flashctx *flash, uint8_t data)
  236. {
  237. int result;
  238. struct spi_command cmds[] = {
  239. {
  240. .writecnt = JEDEC_WREN_OUTSIZE,
  241. .writearr = (const unsigned char[]){ JEDEC_WREN },
  242. .readcnt = 0,
  243. .readarr = NULL,
  244. }, {
  245. .writecnt = CMD_WRR_LEN,
  246. .writearr = (const unsigned char[]){
  247. CMD_WRR,
  248. spi_read_status_register(flash),
  249. data,
  250. },
  251. .readcnt = 0,
  252. .readarr = NULL,
  253. }, {
  254. .writecnt = 0,
  255. .writearr = NULL,
  256. .readcnt = 0,
  257. .readarr = NULL,
  258. }};
  259. result = spi_send_multicommand(flash, cmds);
  260. if (result) {
  261. msg_cerr("%s failed during command execution\n", __func__);
  262. return -1;
  263. }
  264. programmer_delay(T_W);
  265. return s25f_poll_status(flash);
  266. }
  267. static int s25fs_restore_cr3nv(struct flashctx *flash, uint8_t cfg)
  268. {
  269. int ret = 0;
  270. msg_cdbg("Restoring CR3NV value to 0x%02x\n", cfg);
  271. ret |= s25fs_write_cr(flash, CR3NV_ADDR, cfg);
  272. ret |= s25fs_software_reset(flash);
  273. return ret;
  274. }
  275. /* returns state of top/bottom block protection, or <0 to indicate error */
  276. static int s25f_get_tbprot_o(const struct flashctx *flash)
  277. {
  278. int cr1 = s25f_read_cr1(flash);
  279. if (cr1 < 0)
  280. return -1;
  281. /*
  282. * 1 = BP starts at bottom (low address)
  283. * 0 = BP start at top (high address)
  284. */
  285. return cr1 & CR1_TBPROT_O ? 1 : 0;
  286. }
  287. /* fills modifier_bits struct, returns 0 to indicate success */
  288. int s25f_get_modifier_bits(const struct flashctx *flash,
  289. struct generic_modifier_bits *m)
  290. {
  291. int tmp;
  292. memset(m, 0, sizeof(*m));
  293. tmp = s25f_get_tbprot_o(flash);
  294. if (tmp < 0)
  295. return -1;
  296. m->tb = tmp;
  297. return 0;
  298. }
  299. int s25f_set_modifier_bits(const struct flashctx *flash,
  300. struct generic_modifier_bits *m)
  301. {
  302. int cr1, cr1_orig;
  303. cr1 = cr1_orig = s25f_read_cr1(flash);
  304. if (cr1 < 0)
  305. return -1;
  306. /*
  307. * Clear BPNV so that setting BP2-0 in status register gets
  308. * written to non-volatile memory.
  309. *
  310. * For TBPROT:
  311. * 1 = BP starts at bottom (low address)
  312. * 0 = BP start at top (high address)
  313. */
  314. cr1 &= ~(CR1_BPNV_O | CR1_TBPROT_O);
  315. cr1 |= m->tb ? CR1_TBPROT_O : 0;
  316. if (cr1 != cr1_orig) {
  317. msg_cdbg("%s: setting cr1 bits to 0x%02x\n", __func__, cr1);
  318. if (s25f_write_cr1(flash, cr1) < 0)
  319. return -1;
  320. if (s25f_read_cr1(flash) != cr1) {
  321. msg_cerr("%s: failed to set CR1 value\n", __func__);
  322. return -1;
  323. }
  324. } else {
  325. msg_cdbg("%s: cr1 bits already match desired value: "
  326. "0x%02x\n", __func__, cr1);
  327. }
  328. return 0;
  329. }
  330. int s25fs_block_erase_d8(struct flashctx *flash,
  331. unsigned int addr, unsigned int blocklen)
  332. {
  333. unsigned char cfg;
  334. int result;
  335. static int cr3nv_checked = 0;
  336. struct spi_command erase_cmds[] = {
  337. {
  338. .writecnt = JEDEC_WREN_OUTSIZE,
  339. .writearr = (const unsigned char[]){ JEDEC_WREN },
  340. .readcnt = 0,
  341. .readarr = NULL,
  342. }, {
  343. .writecnt = JEDEC_BE_D8_OUTSIZE,
  344. .writearr = (const unsigned char[]){
  345. JEDEC_BE_D8,
  346. (addr >> 16) & 0xff,
  347. (addr >> 8) & 0xff,
  348. (addr & 0xff)
  349. },
  350. .readcnt = 0,
  351. .readarr = NULL,
  352. }, {
  353. .writecnt = 0,
  354. .writearr = NULL,
  355. .readcnt = 0,
  356. .readarr = NULL,
  357. }};
  358. /* Check if hybrid sector architecture is in use and, if so,
  359. * switch to uniform sectors. */
  360. if (!cr3nv_checked) {
  361. cfg = s25fs_read_cr(flash, CR3NV_ADDR);
  362. if (!(cfg & CR3NV_20H_NV)) {
  363. s25fs_write_cr(flash, CR3NV_ADDR, cfg | CR3NV_20H_NV);
  364. s25fs_software_reset(flash);
  365. cfg = s25fs_read_cr(flash, CR3NV_ADDR);
  366. if (!(cfg & CR3NV_20H_NV)) {
  367. msg_cerr("%s: Unable to enable uniform "
  368. "block sizes.\n", __func__);
  369. return 1;
  370. }
  371. msg_cdbg("\n%s: CR3NV updated (0x%02x -> 0x%02x)\n",
  372. __func__, cfg,
  373. s25fs_read_cr(flash, CR3NV_ADDR));
  374. /* Restore CR3V when flashrom exits */
  375. register_chip_restore(s25fs_restore_cr3nv, flash, cfg);
  376. }
  377. cr3nv_checked = 1;
  378. }
  379. result = spi_send_multicommand(flash, erase_cmds);
  380. if (result) {
  381. msg_cerr("%s failed during command execution at address 0x%x\n",
  382. __func__, addr);
  383. return result;
  384. }
  385. programmer_delay(S25FS_T_SE);
  386. return s25f_poll_status(flash);
  387. }
  388. int s25fl_block_erase(struct flashctx *flash,
  389. unsigned int addr, unsigned int blocklen)
  390. {
  391. int result;
  392. struct spi_command erase_cmds[] = {
  393. {
  394. .writecnt = JEDEC_WREN_OUTSIZE,
  395. .writearr = (const unsigned char[]){
  396. JEDEC_WREN
  397. },
  398. .readcnt = 0,
  399. .readarr = NULL,
  400. }, {
  401. .writecnt = JEDEC_BE_DC_OUTSIZE,
  402. .writearr = (const unsigned char[]){
  403. JEDEC_BE_DC,
  404. (addr >> 24) & 0xff,
  405. (addr >> 16) & 0xff,
  406. (addr >> 8) & 0xff,
  407. (addr & 0xff)
  408. },
  409. .readcnt = 0,
  410. .readarr = NULL,
  411. }, {
  412. .writecnt = 0,
  413. .readcnt = 0,
  414. }
  415. };
  416. result = spi_send_multicommand(flash, erase_cmds);
  417. if (result) {
  418. msg_cerr("%s failed during command execution at address 0x%x\n",
  419. __func__, addr);
  420. return result;
  421. }
  422. programmer_delay(S25FL_T_SE);
  423. return s25f_poll_status(flash);
  424. }
  425. int probe_spi_big_spansion(struct flashctx *flash)
  426. {
  427. static const unsigned char cmd = JEDEC_RDID;
  428. int ret;
  429. unsigned char dev_id[6]; /* We care only about 6 first bytes */
  430. ret = spi_send_command(flash, sizeof(cmd), sizeof(dev_id), &cmd, dev_id);
  431. if (!ret) {
  432. int i;
  433. for (i = 0; i < sizeof(dev_id); i++)
  434. msg_gdbg(" 0x%02x", dev_id[i]);
  435. msg_gdbg(".\n");
  436. if (dev_id[0] == flash->manufacture_id) {
  437. union {
  438. uint8_t array[4];
  439. uint32_t whole;
  440. } model_id;
  441. /*
  442. * The structure of the RDID output is as follows:
  443. *
  444. * offset value meaning
  445. * 00h 01h Manufacturer ID for Spansion
  446. * 01h 20h 128 Mb capacity
  447. * 01h 02h 256 Mb capacity
  448. * 02h 18h 128 Mb capacity
  449. * 02h 19h 256 Mb capacity
  450. * 03h 4Dh Full size of the RDID output (ignored)
  451. * 04h 00h FS: 256-kB physical sectors
  452. * 04h 01h FS: 64-kB physical sectors
  453. * 04h 00h FL: 256-kB physical sectors
  454. * 04h 01h FL: Mix of 64-kB and 4KB overlayed sectors
  455. * 05h 80h FL family
  456. * 05h 81h FS family
  457. *
  458. * Need to use bytes 1, 2, 4, and 5 to properly identify one of eight
  459. * possible chips:
  460. *
  461. * 2 types * 2 possible sizes * 2 possible sector layouts
  462. *
  463. */
  464. memcpy(model_id.array, dev_id + 1, 2);
  465. memcpy(model_id.array + 2, dev_id + 4, 2);
  466. if (be_to_cpu32(model_id.whole) == flash->model_id)
  467. return 1;
  468. }
  469. }
  470. return 0;
  471. }