spi25_statusreg.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739
  1. /*
  2. * This file is part of the flashrom project.
  3. * It handles everything related to status registers of the JEDEC family 25.
  4. *
  5. * Copyright (C) 2007, 2008, 2009, 2010 Carl-Daniel Hailfinger
  6. * Copyright (C) 2008 coresystems GmbH
  7. * Copyright (C) 2008 Ronald Hoogenboom <ronald@zonnet.nl>
  8. * Copyright (C) 2012 Stefan Tauner
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; version 2 of the License.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  22. */
  23. #include "flash.h"
  24. #include "chipdrivers.h"
  25. #include "spi.h"
  26. /* === Generic functions === */
  27. int spi_write_status_enable(struct flashctx *flash)
  28. {
  29. static const unsigned char cmd[JEDEC_EWSR_OUTSIZE] = { JEDEC_EWSR };
  30. int result;
  31. /* Send EWSR (Enable Write Status Register). */
  32. result = spi_send_command(flash, sizeof(cmd), JEDEC_EWSR_INSIZE, cmd, NULL);
  33. if (result)
  34. msg_cerr("%s failed\n", __func__);
  35. return result;
  36. }
  37. static int spi_write_status_register_flag(struct flashctx *flash, int status, const unsigned char enable_opcode)
  38. {
  39. int result;
  40. int i = 0;
  41. /*
  42. * WRSR requires either EWSR or WREN depending on chip type.
  43. * The code below relies on the fact hat EWSR and WREN have the same
  44. * INSIZE and OUTSIZE.
  45. */
  46. struct spi_command cmds[] = {
  47. {
  48. .writecnt = JEDEC_WREN_OUTSIZE,
  49. .writearr = (const unsigned char[]){ enable_opcode },
  50. .readcnt = 0,
  51. .readarr = NULL,
  52. }, {
  53. .writecnt = JEDEC_WRSR_OUTSIZE,
  54. .writearr = (const unsigned char[]){ JEDEC_WRSR, (unsigned char) status },
  55. .readcnt = 0,
  56. .readarr = NULL,
  57. }, {
  58. .writecnt = 0,
  59. .writearr = NULL,
  60. .readcnt = 0,
  61. .readarr = NULL,
  62. }};
  63. result = spi_send_multicommand(flash, cmds);
  64. if (result) {
  65. msg_cerr("%s failed during command execution\n", __func__);
  66. /* No point in waiting for the command to complete if execution
  67. * failed.
  68. */
  69. return result;
  70. }
  71. /* WRSR performs a self-timed erase before the changes take effect.
  72. * This may take 50-85 ms in most cases, and some chips apparently
  73. * allow running RDSR only once. Therefore pick an initial delay of
  74. * 100 ms, then wait in 10 ms steps until a total of 5 s have elapsed.
  75. */
  76. programmer_delay(100 * 1000);
  77. while (spi_read_status_register(flash) & SPI_SR_WIP) {
  78. if (++i > 490) {
  79. msg_cerr("Error: WIP bit after WRSR never cleared\n");
  80. return TIMEOUT_ERROR;
  81. }
  82. programmer_delay(10 * 1000);
  83. }
  84. return 0;
  85. }
  86. int spi_write_status_register(struct flashctx *flash, int status)
  87. {
  88. int feature_bits = flash->chip->feature_bits;
  89. int ret = 1;
  90. if (!(feature_bits & (FEATURE_WRSR_WREN | FEATURE_WRSR_EWSR))) {
  91. msg_cdbg("Missing status register write definition, assuming "
  92. "EWSR is needed\n");
  93. feature_bits |= FEATURE_WRSR_EWSR;
  94. }
  95. if (feature_bits & FEATURE_WRSR_WREN)
  96. ret = spi_write_status_register_flag(flash, status, JEDEC_WREN);
  97. if (ret && (feature_bits & FEATURE_WRSR_EWSR))
  98. ret = spi_write_status_register_flag(flash, status, JEDEC_EWSR);
  99. return ret;
  100. }
  101. uint8_t spi_read_status_register(struct flashctx *flash)
  102. {
  103. static const unsigned char cmd[JEDEC_RDSR_OUTSIZE] = { JEDEC_RDSR };
  104. /* FIXME: No workarounds for driver/hardware bugs in generic code. */
  105. unsigned char readarr[2]; /* JEDEC_RDSR_INSIZE=1 but wbsio needs 2 */
  106. int ret;
  107. /* Read Status Register */
  108. ret = spi_send_command(flash, sizeof(cmd), sizeof(readarr), cmd, readarr);
  109. if (ret)
  110. msg_cerr("RDSR failed!\n");
  111. return readarr[0];
  112. }
  113. /* A generic block protection disable.
  114. * Tests if a protection is enabled with the block protection mask (bp_mask) and returns success otherwise.
  115. * Tests if the register bits are locked with the lock_mask (lock_mask).
  116. * Tests if a hardware protection is active (i.e. low pin/high bit value) with the write protection mask
  117. * (wp_mask) and bails out in that case.
  118. * If there are register lock bits set we try to disable them by unsetting those bits of the previous register
  119. * contents that are set in the lock_mask. We then check if removing the lock bits has worked and continue as if
  120. * they never had been engaged:
  121. * If the lock bits are out of the way try to disable engaged protections.
  122. * To support uncommon global unprotects (e.g. on most AT2[56]xx1(A)) unprotect_mask can be used to force
  123. * bits to 0 additionally to those set in bp_mask and lock_mask. Only bits set in unprotect_mask are potentially
  124. * preserved when doing the final unprotect.
  125. *
  126. * To sum up:
  127. * bp_mask: set those bits that correspond to the bits in the status register that indicate an active protection
  128. * (which should be unset after this function returns).
  129. * lock_mask: set the bits that correspond to the bits that lock changing the bits above.
  130. * wp_mask: set the bits that correspond to bits indicating non-software revocable protections.
  131. * unprotect_mask: set the bits that should be preserved if possible when unprotecting.
  132. */
  133. static int spi_disable_blockprotect_generic(struct flashctx *flash, uint8_t bp_mask, uint8_t lock_mask, uint8_t wp_mask, uint8_t unprotect_mask)
  134. {
  135. uint8_t status;
  136. int result;
  137. status = spi_read_status_register(flash);
  138. if ((status & bp_mask) == 0) {
  139. msg_cdbg2("Block protection is disabled.\n");
  140. return 0;
  141. }
  142. msg_cdbg("Some block protection in effect, disabling... ");
  143. if ((status & lock_mask) != 0) {
  144. msg_cdbg("\n\tNeed to disable the register lock first... ");
  145. if (wp_mask != 0 && (status & wp_mask) == 0) {
  146. msg_cerr("Hardware protection is active, disabling write protection is impossible.\n");
  147. return 1;
  148. }
  149. /* All bits except the register lock bit (often called SPRL, SRWD, WPEN) are readonly. */
  150. result = spi_write_status_register(flash, status & ~lock_mask);
  151. if (result) {
  152. msg_cerr("spi_write_status_register failed.\n");
  153. return result;
  154. }
  155. status = spi_read_status_register(flash);
  156. if ((status & lock_mask) != 0) {
  157. msg_cerr("Unsetting lock bit(s) failed.\n");
  158. return 1;
  159. }
  160. msg_cdbg("done.\n");
  161. }
  162. /* Global unprotect. Make sure to mask the register lock bit as well. */
  163. result = spi_write_status_register(flash, status & ~(bp_mask | lock_mask) & unprotect_mask);
  164. if (result) {
  165. msg_cerr("spi_write_status_register failed.\n");
  166. return result;
  167. }
  168. status = spi_read_status_register(flash);
  169. if ((status & bp_mask) != 0) {
  170. msg_cerr("Block protection could not be disabled!\n");
  171. flash->chip->printlock(flash);
  172. return 1;
  173. }
  174. msg_cdbg("disabled.\n");
  175. return 0;
  176. }
  177. /* A common block protection disable that tries to unset the status register bits masked by 0x3C. */
  178. int spi_disable_blockprotect(struct flashctx *flash)
  179. {
  180. return spi_disable_blockprotect_generic(flash, 0x3C, 0, 0, 0xFF);
  181. }
  182. /* A common block protection disable that tries to unset the status register bits masked by 0x0C (BP0-1) and
  183. * protected/locked by bit #7. Useful when bits 4-5 may be non-0). */
  184. int spi_disable_blockprotect_bp1_srwd(struct flashctx *flash)
  185. {
  186. return spi_disable_blockprotect_generic(flash, 0x0C, 1 << 7, 0, 0xFF);
  187. }
  188. /* A common block protection disable that tries to unset the status register bits masked by 0x1C (BP0-2) and
  189. * protected/locked by bit #7. Useful when bit #5 is neither a protection bit nor reserved (and hence possibly
  190. * non-0). */
  191. int spi_disable_blockprotect_bp2_srwd(struct flashctx *flash)
  192. {
  193. return spi_disable_blockprotect_generic(flash, 0x1C, 1 << 7, 0, 0xFF);
  194. }
  195. /* A common block protection disable that tries to unset the status register bits masked by 0x3C (BP0-3) and
  196. * protected/locked by bit #7. */
  197. int spi_disable_blockprotect_bp3_srwd(struct flashctx *flash)
  198. {
  199. return spi_disable_blockprotect_generic(flash, 0x3C, 1 << 7, 0, 0xFF);
  200. }
  201. /* A common block protection disable that tries to unset the status register bits masked by 0x7C (BP0-4) and
  202. * protected/locked by bit #7. */
  203. int spi_disable_blockprotect_bp4_srwd(struct flashctx *flash)
  204. {
  205. return spi_disable_blockprotect_generic(flash, 0x7C, 1 << 7, 0, 0xFF);
  206. }
  207. static void spi_prettyprint_status_register_hex(uint8_t status)
  208. {
  209. msg_cdbg("Chip status register is 0x%02x.\n", status);
  210. }
  211. /* Common highest bit: Status Register Write Disable (SRWD) or Status Register Protect (SRP). */
  212. static void spi_prettyprint_status_register_srwd(uint8_t status)
  213. {
  214. msg_cdbg("Chip status register: Status Register Write Disable (SRWD, SRP, ...) is %sset\n",
  215. (status & (1 << 7)) ? "" : "not ");
  216. }
  217. /* Common highest bit: Block Protect Write Disable (BPL). */
  218. static void spi_prettyprint_status_register_bpl(uint8_t status)
  219. {
  220. msg_cdbg("Chip status register: Block Protect Write Disable (BPL) is %sset\n",
  221. (status & (1 << 7)) ? "" : "not ");
  222. }
  223. /* Common lowest 2 bits: WEL and WIP. */
  224. static void spi_prettyprint_status_register_welwip(uint8_t status)
  225. {
  226. msg_cdbg("Chip status register: Write Enable Latch (WEL) is %sset\n",
  227. (status & (1 << 1)) ? "" : "not ");
  228. msg_cdbg("Chip status register: Write In Progress (WIP/BUSY) is %sset\n",
  229. (status & (1 << 0)) ? "" : "not ");
  230. }
  231. /* Common block protection (BP) bits. */
  232. static void spi_prettyprint_status_register_bp(uint8_t status, int bp)
  233. {
  234. switch (bp) {
  235. /* Fall through. */
  236. case 4:
  237. msg_cdbg("Chip status register: Block Protect 4 (BP4) is %sset\n",
  238. (status & (1 << 6)) ? "" : "not ");
  239. case 3:
  240. msg_cdbg("Chip status register: Block Protect 3 (BP3) is %sset\n",
  241. (status & (1 << 5)) ? "" : "not ");
  242. case 2:
  243. msg_cdbg("Chip status register: Block Protect 2 (BP2) is %sset\n",
  244. (status & (1 << 4)) ? "" : "not ");
  245. case 1:
  246. msg_cdbg("Chip status register: Block Protect 1 (BP1) is %sset\n",
  247. (status & (1 << 3)) ? "" : "not ");
  248. case 0:
  249. msg_cdbg("Chip status register: Block Protect 0 (BP0) is %sset\n",
  250. (status & (1 << 2)) ? "" : "not ");
  251. }
  252. }
  253. /* Unnamed bits. */
  254. void spi_prettyprint_status_register_bit(uint8_t status, int bit)
  255. {
  256. msg_cdbg("Chip status register: Bit %i is %sset\n", bit, (status & (1 << bit)) ? "" : "not ");
  257. }
  258. int spi_prettyprint_status_register_plain(struct flashctx *flash)
  259. {
  260. uint8_t status = spi_read_status_register(flash);
  261. spi_prettyprint_status_register_hex(status);
  262. return 0;
  263. }
  264. /* Print the plain hex value and the welwip bits only. */
  265. int spi_prettyprint_status_register_default_welwip(struct flashctx *flash)
  266. {
  267. uint8_t status = spi_read_status_register(flash);
  268. spi_prettyprint_status_register_hex(status);
  269. spi_prettyprint_status_register_welwip(status);
  270. return 0;
  271. }
  272. /* Works for many chips of the
  273. * AMIC A25L series
  274. * and MX MX25L512
  275. */
  276. int spi_prettyprint_status_register_bp1_srwd(struct flashctx *flash)
  277. {
  278. uint8_t status = spi_read_status_register(flash);
  279. spi_prettyprint_status_register_hex(status);
  280. spi_prettyprint_status_register_srwd(status);
  281. spi_prettyprint_status_register_bit(status, 6);
  282. spi_prettyprint_status_register_bit(status, 5);
  283. spi_prettyprint_status_register_bit(status, 4);
  284. spi_prettyprint_status_register_bp(status, 1);
  285. spi_prettyprint_status_register_welwip(status);
  286. return 0;
  287. }
  288. /* Works for many chips of the
  289. * AMIC A25L series
  290. * PMC Pm25LD series
  291. */
  292. int spi_prettyprint_status_register_bp2_srwd(struct flashctx *flash)
  293. {
  294. uint8_t status = spi_read_status_register(flash);
  295. spi_prettyprint_status_register_hex(status);
  296. spi_prettyprint_status_register_srwd(status);
  297. spi_prettyprint_status_register_bit(status, 6);
  298. spi_prettyprint_status_register_bit(status, 5);
  299. spi_prettyprint_status_register_bp(status, 2);
  300. spi_prettyprint_status_register_welwip(status);
  301. return 0;
  302. }
  303. /* Works for many chips of the
  304. * ST M25P series
  305. * MX MX25L series
  306. */
  307. int spi_prettyprint_status_register_bp3_srwd(struct flashctx *flash)
  308. {
  309. uint8_t status = spi_read_status_register(flash);
  310. spi_prettyprint_status_register_hex(status);
  311. spi_prettyprint_status_register_srwd(status);
  312. spi_prettyprint_status_register_bit(status, 6);
  313. spi_prettyprint_status_register_bp(status, 3);
  314. spi_prettyprint_status_register_welwip(status);
  315. return 0;
  316. }
  317. int spi_prettyprint_status_register_bp4_srwd(struct flashctx *flash)
  318. {
  319. uint8_t status = spi_read_status_register(flash);
  320. spi_prettyprint_status_register_hex(status);
  321. spi_prettyprint_status_register_srwd(status);
  322. spi_prettyprint_status_register_bp(status, 4);
  323. spi_prettyprint_status_register_welwip(status);
  324. return 0;
  325. }
  326. int spi_prettyprint_status_register_bp2_bpl(struct flashctx *flash)
  327. {
  328. uint8_t status = spi_read_status_register(flash);
  329. spi_prettyprint_status_register_hex(status);
  330. spi_prettyprint_status_register_bpl(status);
  331. spi_prettyprint_status_register_bit(status, 6);
  332. spi_prettyprint_status_register_bit(status, 5);
  333. spi_prettyprint_status_register_bp(status, 2);
  334. spi_prettyprint_status_register_welwip(status);
  335. return 0;
  336. }
  337. int spi_prettyprint_status_register_bp2_tb_bpl(struct flashctx *flash)
  338. {
  339. uint8_t status = spi_read_status_register(flash);
  340. spi_prettyprint_status_register_hex(status);
  341. spi_prettyprint_status_register_bpl(status);
  342. spi_prettyprint_status_register_bit(status, 6);
  343. msg_cdbg("Chip status register: Top/Bottom (TB) is %s\n", (status & (1 << 5)) ? "bottom" : "top");
  344. spi_prettyprint_status_register_bp(status, 2);
  345. spi_prettyprint_status_register_welwip(status);
  346. return 0;
  347. }
  348. /* === Amic ===
  349. * FIXME: spi_disable_blockprotect is incorrect but works fine for chips using
  350. * spi_prettyprint_status_register_bp1_srwd or
  351. * spi_prettyprint_status_register_bp2_srwd.
  352. * FIXME: spi_disable_blockprotect is incorrect and will fail for chips using
  353. * spi_prettyprint_status_register_amic_a25l032 if those have locks controlled
  354. * by the second status register.
  355. */
  356. int spi_prettyprint_status_register_amic_a25l032(struct flashctx *flash)
  357. {
  358. uint8_t status = spi_read_status_register(flash);
  359. spi_prettyprint_status_register_hex(status);
  360. spi_prettyprint_status_register_srwd(status);
  361. msg_cdbg("Chip status register: Sector Protect Size (SEC) is %i KB\n", (status & (1 << 6)) ? 4 : 64);
  362. msg_cdbg("Chip status register: Top/Bottom (TB) is %s\n", (status & (1 << 5)) ? "bottom" : "top");
  363. spi_prettyprint_status_register_bp(status, 2);
  364. spi_prettyprint_status_register_welwip(status);
  365. msg_cdbg("Chip status register 2 is NOT decoded!\n");
  366. return 0;
  367. }
  368. /* === Atmel === */
  369. static void spi_prettyprint_status_register_atmel_at25_wpen(uint8_t status)
  370. {
  371. msg_cdbg("Chip status register: Write Protect Enable (WPEN) is %sset\n",
  372. (status & (1 << 7)) ? "" : "not ");
  373. }
  374. static void spi_prettyprint_status_register_atmel_at25_srpl(uint8_t status)
  375. {
  376. msg_cdbg("Chip status register: Sector Protection Register Lock (SRPL) is %sset\n",
  377. (status & (1 << 7)) ? "" : "not ");
  378. }
  379. static void spi_prettyprint_status_register_atmel_at25_epewpp(uint8_t status)
  380. {
  381. msg_cdbg("Chip status register: Erase/Program Error (EPE) is %sset\n",
  382. (status & (1 << 5)) ? "" : "not ");
  383. msg_cdbg("Chip status register: WP# pin (WPP) is %sasserted\n",
  384. (status & (1 << 4)) ? "not " : "");
  385. }
  386. static void spi_prettyprint_status_register_atmel_at25_swp(uint8_t status)
  387. {
  388. msg_cdbg("Chip status register: Software Protection Status (SWP): ");
  389. switch (status & (3 << 2)) {
  390. case 0x0 << 2:
  391. msg_cdbg("no sectors are protected\n");
  392. break;
  393. case 0x1 << 2:
  394. msg_cdbg("some sectors are protected\n");
  395. /* FIXME: Read individual Sector Protection Registers. */
  396. break;
  397. case 0x3 << 2:
  398. msg_cdbg("all sectors are protected\n");
  399. break;
  400. default:
  401. msg_cdbg("reserved for future use\n");
  402. break;
  403. }
  404. }
  405. int spi_prettyprint_status_register_at25df(struct flashctx *flash)
  406. {
  407. uint8_t status = spi_read_status_register(flash);
  408. spi_prettyprint_status_register_hex(status);
  409. spi_prettyprint_status_register_atmel_at25_srpl(status);
  410. spi_prettyprint_status_register_bit(status, 6);
  411. spi_prettyprint_status_register_atmel_at25_epewpp(status);
  412. spi_prettyprint_status_register_atmel_at25_swp(status);
  413. spi_prettyprint_status_register_welwip(status);
  414. return 0;
  415. }
  416. int spi_prettyprint_status_register_at25df_sec(struct flashctx *flash)
  417. {
  418. /* FIXME: We should check the security lockdown. */
  419. msg_cdbg("Ignoring security lockdown (if present)\n");
  420. msg_cdbg("Ignoring status register byte 2\n");
  421. return spi_prettyprint_status_register_at25df(flash);
  422. }
  423. /* used for AT25F512, AT25F1024(A), AT25F2048 */
  424. int spi_prettyprint_status_register_at25f(struct flashctx *flash)
  425. {
  426. uint8_t status;
  427. status = spi_read_status_register(flash);
  428. spi_prettyprint_status_register_hex(status);
  429. spi_prettyprint_status_register_atmel_at25_wpen(status);
  430. spi_prettyprint_status_register_bit(status, 6);
  431. spi_prettyprint_status_register_bit(status, 5);
  432. spi_prettyprint_status_register_bit(status, 4);
  433. spi_prettyprint_status_register_bp(status, 1);
  434. spi_prettyprint_status_register_welwip(status);
  435. return 0;
  436. }
  437. int spi_prettyprint_status_register_at25f512a(struct flashctx *flash)
  438. {
  439. uint8_t status;
  440. status = spi_read_status_register(flash);
  441. spi_prettyprint_status_register_hex(status);
  442. spi_prettyprint_status_register_atmel_at25_wpen(status);
  443. spi_prettyprint_status_register_bit(status, 6);
  444. spi_prettyprint_status_register_bit(status, 5);
  445. spi_prettyprint_status_register_bit(status, 4);
  446. spi_prettyprint_status_register_bit(status, 3);
  447. spi_prettyprint_status_register_bp(status, 0);
  448. spi_prettyprint_status_register_welwip(status);
  449. return 0;
  450. }
  451. int spi_prettyprint_status_register_at25f512b(struct flashctx *flash)
  452. {
  453. uint8_t status = spi_read_status_register(flash);
  454. spi_prettyprint_status_register_hex(status);
  455. spi_prettyprint_status_register_atmel_at25_srpl(status);
  456. spi_prettyprint_status_register_bit(status, 6);
  457. spi_prettyprint_status_register_atmel_at25_epewpp(status);
  458. spi_prettyprint_status_register_bit(status, 3);
  459. spi_prettyprint_status_register_bp(status, 0);
  460. spi_prettyprint_status_register_welwip(status);
  461. return 0;
  462. }
  463. int spi_prettyprint_status_register_at25f4096(struct flashctx *flash)
  464. {
  465. uint8_t status;
  466. status = spi_read_status_register(flash);
  467. spi_prettyprint_status_register_hex(status);
  468. spi_prettyprint_status_register_atmel_at25_wpen(status);
  469. spi_prettyprint_status_register_bit(status, 6);
  470. spi_prettyprint_status_register_bit(status, 5);
  471. spi_prettyprint_status_register_bp(status, 2);
  472. spi_prettyprint_status_register_welwip(status);
  473. return 0;
  474. }
  475. int spi_prettyprint_status_register_at25fs010(struct flashctx *flash)
  476. {
  477. uint8_t status = spi_read_status_register(flash);
  478. spi_prettyprint_status_register_hex(status);
  479. spi_prettyprint_status_register_atmel_at25_wpen(status);
  480. msg_cdbg("Chip status register: Bit 6 / Block Protect 4 (BP4) is "
  481. "%sset\n", (status & (1 << 6)) ? "" : "not ");
  482. msg_cdbg("Chip status register: Bit 5 / Block Protect 3 (BP3) is "
  483. "%sset\n", (status & (1 << 5)) ? "" : "not ");
  484. spi_prettyprint_status_register_bit(status, 4);
  485. msg_cdbg("Chip status register: Bit 3 / Block Protect 1 (BP1) is "
  486. "%sset\n", (status & (1 << 3)) ? "" : "not ");
  487. msg_cdbg("Chip status register: Bit 2 / Block Protect 0 (BP0) is "
  488. "%sset\n", (status & (1 << 2)) ? "" : "not ");
  489. /* FIXME: Pretty-print detailed sector protection status. */
  490. spi_prettyprint_status_register_welwip(status);
  491. return 0;
  492. }
  493. int spi_prettyprint_status_register_at25fs040(struct flashctx *flash)
  494. {
  495. uint8_t status = spi_read_status_register(flash);
  496. spi_prettyprint_status_register_hex(status);
  497. spi_prettyprint_status_register_atmel_at25_wpen(status);
  498. spi_prettyprint_status_register_bp(status, 4);
  499. /* FIXME: Pretty-print detailed sector protection status. */
  500. spi_prettyprint_status_register_welwip(status);
  501. return 0;
  502. }
  503. int spi_prettyprint_status_register_at26df081a(struct flashctx *flash)
  504. {
  505. uint8_t status = spi_read_status_register(flash);
  506. spi_prettyprint_status_register_hex(status);
  507. spi_prettyprint_status_register_atmel_at25_srpl(status);
  508. msg_cdbg("Chip status register: Sequential Program Mode Status (SPM) is %sset\n",
  509. (status & (1 << 6)) ? "" : "not ");
  510. spi_prettyprint_status_register_atmel_at25_epewpp(status);
  511. spi_prettyprint_status_register_atmel_at25_swp(status);
  512. spi_prettyprint_status_register_welwip(status);
  513. return 0;
  514. }
  515. /* Some Atmel DataFlash chips support per sector protection bits and the write protection bits in the status
  516. * register do indicate if none, some or all sectors are protected. It is possible to globally (un)lock all
  517. * sectors at once by writing 0 not only the protection bits (2 and 3) but also completely unrelated bits (4 and
  518. * 5) which normally are not touched.
  519. * Affected are all known Atmel chips matched by AT2[56]D[FLQ]..1A? but the AT26DF041. */
  520. int spi_disable_blockprotect_at2x_global_unprotect(struct flashctx *flash)
  521. {
  522. return spi_disable_blockprotect_generic(flash, 0x0C, 1 << 7, 1 << 4, 0x00);
  523. }
  524. int spi_disable_blockprotect_at2x_global_unprotect_sec(struct flashctx *flash)
  525. {
  526. /* FIXME: We should check the security lockdown. */
  527. msg_cinfo("Ignoring security lockdown (if present)\n");
  528. return spi_disable_blockprotect_at2x_global_unprotect(flash);
  529. }
  530. int spi_disable_blockprotect_at25f(struct flashctx *flash)
  531. {
  532. return spi_disable_blockprotect_generic(flash, 0x0C, 1 << 7, 0, 0xFF);
  533. }
  534. int spi_disable_blockprotect_at25f512a(struct flashctx *flash)
  535. {
  536. return spi_disable_blockprotect_generic(flash, 0x04, 1 << 7, 0, 0xFF);
  537. }
  538. int spi_disable_blockprotect_at25f512b(struct flashctx *flash)
  539. {
  540. return spi_disable_blockprotect_generic(flash, 0x04, 1 << 7, 1 << 4, 0xFF);
  541. }
  542. int spi_disable_blockprotect_at25fs010(struct flashctx *flash)
  543. {
  544. return spi_disable_blockprotect_generic(flash, 0x6C, 1 << 7, 0, 0xFF);
  545. }
  546. int spi_disable_blockprotect_at25fs040(struct flashctx *flash)
  547. {
  548. return spi_disable_blockprotect_generic(flash, 0x7C, 1 << 7, 0, 0xFF);
  549. }
  550. /* === Eon === */
  551. int spi_prettyprint_status_register_en25s_wp(struct flashctx *flash)
  552. {
  553. uint8_t status = spi_read_status_register(flash);
  554. spi_prettyprint_status_register_hex(status);
  555. spi_prettyprint_status_register_srwd(status);
  556. msg_cdbg("Chip status register: WP# disable (WPDIS) is %sabled\n", (status & (1 << 6)) ? "en " : "dis");
  557. spi_prettyprint_status_register_bp(status, 3);
  558. spi_prettyprint_status_register_welwip(status);
  559. return 0;
  560. }
  561. /* === Intel/Numonyx/Micron - Spansion === */
  562. int spi_disable_blockprotect_n25q(struct flashctx *flash)
  563. {
  564. return spi_disable_blockprotect_generic(flash, 0x5C, 1 << 7, 0, 0xFF);
  565. }
  566. int spi_prettyprint_status_register_n25q(struct flashctx *flash)
  567. {
  568. uint8_t status = spi_read_status_register(flash);
  569. spi_prettyprint_status_register_hex(status);
  570. spi_prettyprint_status_register_srwd(status);
  571. if (flash->chip->total_size <= 32 / 8 * 1024) /* N25Q16 and N25Q32: reserved */
  572. spi_prettyprint_status_register_bit(status, 6);
  573. else
  574. msg_cdbg("Chip status register: Block Protect 3 (BP3) is %sset\n",
  575. (status & (1 << 6)) ? "" : "not ");
  576. msg_cdbg("Chip status register: Top/Bottom (TB) is %s\n", (status & (1 << 5)) ? "bottom" : "top");
  577. spi_prettyprint_status_register_bp(status, 2);
  578. spi_prettyprint_status_register_welwip(status);
  579. return 0;
  580. }
  581. /* Used by Intel/Numonyx S33 and Spansion S25FL-S chips */
  582. /* TODO: Clear P_FAIL and E_FAIL with Clear SR Fail Flags Command (30h) here? */
  583. int spi_disable_blockprotect_bp2_ep_srwd(struct flashctx *flash)
  584. {
  585. return spi_disable_blockprotect_bp2_srwd(flash);
  586. }
  587. /* Used by Intel/Numonyx S33 and Spansion S25FL-S chips */
  588. int spi_prettyprint_status_register_bp2_ep_srwd(struct flashctx *flash)
  589. {
  590. uint8_t status = spi_read_status_register(flash);
  591. spi_prettyprint_status_register_hex(status);
  592. spi_prettyprint_status_register_srwd(status);
  593. msg_cdbg("Chip status register: Program Fail Flag (P_FAIL) is %sset\n",
  594. (status & (1 << 6)) ? "" : "not ");
  595. msg_cdbg("Chip status register: Erase Fail Flag (E_FAIL) is %sset\n",
  596. (status & (1 << 5)) ? "" : "not ");
  597. spi_prettyprint_status_register_bp(status, 2);
  598. spi_prettyprint_status_register_welwip(status);
  599. return 0;
  600. }
  601. /* === SST === */
  602. static void spi_prettyprint_status_register_sst25_common(uint8_t status)
  603. {
  604. spi_prettyprint_status_register_hex(status);
  605. spi_prettyprint_status_register_bpl(status);
  606. msg_cdbg("Chip status register: Auto Address Increment Programming (AAI) is %sset\n",
  607. (status & (1 << 6)) ? "" : "not ");
  608. spi_prettyprint_status_register_bp(status, 3);
  609. spi_prettyprint_status_register_welwip(status);
  610. }
  611. int spi_prettyprint_status_register_sst25(struct flashctx *flash)
  612. {
  613. uint8_t status = spi_read_status_register(flash);
  614. spi_prettyprint_status_register_sst25_common(status);
  615. return 0;
  616. }
  617. int spi_prettyprint_status_register_sst25vf016(struct flashctx *flash)
  618. {
  619. static const char *const bpt[] = {
  620. "none",
  621. "1F0000H-1FFFFFH",
  622. "1E0000H-1FFFFFH",
  623. "1C0000H-1FFFFFH",
  624. "180000H-1FFFFFH",
  625. "100000H-1FFFFFH",
  626. "all", "all"
  627. };
  628. uint8_t status = spi_read_status_register(flash);
  629. spi_prettyprint_status_register_sst25_common(status);
  630. msg_cdbg("Resulting block protection : %s\n", bpt[(status & 0x1c) >> 2]);
  631. return 0;
  632. }
  633. int spi_prettyprint_status_register_sst25vf040b(struct flashctx *flash)
  634. {
  635. static const char *const bpt[] = {
  636. "none",
  637. "0x70000-0x7ffff",
  638. "0x60000-0x7ffff",
  639. "0x40000-0x7ffff",
  640. "all blocks", "all blocks", "all blocks", "all blocks"
  641. };
  642. uint8_t status = spi_read_status_register(flash);
  643. spi_prettyprint_status_register_sst25_common(status);
  644. msg_cdbg("Resulting block protection : %s\n", bpt[(status & 0x1c) >> 2]);
  645. return 0;
  646. }