blob: 8d5e5255bb144ff793bb00f56183b43935f8a884 [file] [log] [blame]
Stefan Tauner6ee37e22012-12-29 15:03:51 +00001/*
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.
Stefan Tauner6ee37e22012-12-29 15:03:51 +000018 */
19
20#include "flash.h"
21#include "chipdrivers.h"
Nico Huberd5185632024-01-05 18:44:41 +010022#include "spi_command.h"
Stefan Tauner6ee37e22012-12-29 15:03:51 +000023#include "spi.h"
24
25/* === Generic functions === */
Nico Huber3f3c1f32022-05-28 16:48:26 +020026
27/*
28 * Writing SR2 or higher with an extended WRSR command requires
29 * writing all lower SRx along with it, so just read the lower
30 * SRx and write them back.
31 */
32static int spi_prepare_wrsr_ext(
33 uint8_t write_cmd[4], size_t *const write_cmd_len,
34 const struct flashctx *const flash,
35 const enum flash_reg reg, const uint8_t value)
36{
37 enum flash_reg reg_it;
38 size_t i = 0;
39
40 write_cmd[i++] = JEDEC_WRSR;
41
42 for (reg_it = STATUS1; reg_it < reg; ++reg_it) {
43 uint8_t sr;
44
45 if (spi_read_register(flash, reg_it, &sr)) {
46 msg_cerr("Writing SR%d failed: failed to read SR%d for writeback.\n",
47 reg - STATUS1 + 1, reg_it - STATUS1 + 1);
48 return 1;
49 }
50 write_cmd[i++] = sr;
51 }
52
53 write_cmd[i++] = value;
54 *write_cmd_len = i;
55
56 return 0;
57}
58
Nico Huber4ac536b2024-07-21 00:22:29 +020059int spi_write_register(const struct flashctx *flash, enum flash_reg reg,
60 uint8_t value, enum wrsr_target target)
Stefan Tauner6ee37e22012-12-29 15:03:51 +000061{
62 int feature_bits = flash->chip->feature_bits;
Nikolai Artemiev01675222021-10-20 22:30:41 +110063
Nico Huber3f3c1f32022-05-28 16:48:26 +020064 uint8_t write_cmd[4];
Nikolai Artemiev01675222021-10-20 22:30:41 +110065 size_t write_cmd_len = 0;
66
67 /*
68 * Create SPI write command sequence based on the destination register
69 * and the chip's supported command set.
70 */
71 switch (reg) {
72 case STATUS1:
73 write_cmd[0] = JEDEC_WRSR;
74 write_cmd[1] = value;
75 write_cmd_len = JEDEC_WRSR_OUTSIZE;
76 break;
Nikolai Artemiev9de3f872021-10-20 22:32:25 +110077 case STATUS2:
78 if (feature_bits & FEATURE_WRSR2) {
79 write_cmd[0] = JEDEC_WRSR2;
80 write_cmd[1] = value;
81 write_cmd_len = JEDEC_WRSR2_OUTSIZE;
82 break;
83 }
Nico Huber3f3c1f32022-05-28 16:48:26 +020084 if (feature_bits & FEATURE_WRSR_EXT2) {
85 if (spi_prepare_wrsr_ext(write_cmd, &write_cmd_len, flash, reg, value))
Nikolai Artemiev9de3f872021-10-20 22:32:25 +110086 return 1;
Nikolai Artemiev9de3f872021-10-20 22:32:25 +110087 break;
88 }
89 msg_cerr("Cannot write SR2: unsupported by chip\n");
90 return 1;
Sergii Dmytruk0b2e7dd2021-12-19 18:37:51 +020091 case STATUS3:
Nico Huber3f3c1f32022-05-28 16:48:26 +020092 if (feature_bits & FEATURE_WRSR3) {
93 write_cmd[0] = JEDEC_WRSR3;
94 write_cmd[1] = value;
95 write_cmd_len = JEDEC_WRSR3_OUTSIZE;
96 break;
97 }
98 if ((feature_bits & FEATURE_WRSR_EXT3) == FEATURE_WRSR_EXT3) {
99 if (spi_prepare_wrsr_ext(write_cmd, &write_cmd_len, flash, reg, value))
100 return 1;
101 break;
102 }
103 msg_cerr("Cannot write SR3: unsupported by chip\n");
104 return 1;
Sergii Dmytruk3d728e72021-11-27 15:14:27 +0200105 case SECURITY:
106 /*
107 * Security register doesn't have a normal write operation. Instead,
108 * there are separate commands that set individual OTP bits.
109 */
110 msg_cerr("Cannot write SECURITY: unsupported by design\n");
111 return 1;
Sergii Dmytrukbd72a472022-07-24 17:11:05 +0300112 case CONFIG:
113 /*
114 * This one is read via a separate command, but written as if it's SR2
115 * in FEATURE_WRSR_EXT2 case of WRSR command.
116 */
117 write_cmd[0] = JEDEC_WRSR;
118 if (spi_read_register(flash, STATUS1, &write_cmd[1])) {
119 msg_cerr("Writing CONFIG failed: failed to read SR1 for writeback.\n");
120 return 1;
121 }
122 write_cmd[2] = value;
123 write_cmd_len = 3;
124 break;
Nikolai Artemiev01675222021-10-20 22:30:41 +1100125 default:
126 msg_cerr("Cannot write register: unknown register\n");
127 return 1;
128 }
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000129
Nikolai Artemieva1d68652021-11-22 13:18:49 +1100130 uint8_t enable_cmd;
Nico Huber4ac536b2024-07-21 00:22:29 +0200131 if (((feature_bits & FEATURE_WRSR_EITHER) == 0) && (target & WRSR_VOLATILE_BITS)) {
132 /* TODO: check database and remove this case! */
133 msg_cwarn("Missing status register write definition, assuming EWSR is needed\n");
134 enable_cmd = JEDEC_EWSR;
135 } else if ((feature_bits & FEATURE_WRSR_WREN) && (target & WRSR_NON_VOLATILE_BITS)) {
Nikolai Artemieva1d68652021-11-22 13:18:49 +1100136 enable_cmd = JEDEC_WREN;
Nico Huber4ac536b2024-07-21 00:22:29 +0200137 } else if ((feature_bits & FEATURE_WRSR_EWSR) && (target & WRSR_VOLATILE_BITS)) {
Nikolai Artemieva1d68652021-11-22 13:18:49 +1100138 enable_cmd = JEDEC_EWSR;
139 } else {
Nico Huber4ac536b2024-07-21 00:22:29 +0200140 msg_cerr("Chip doesn't support %svolatile status register writes.\n",
141 target & WRSR_NON_VOLATILE_BITS ? "non-" : "");
142 return 1;
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000143 }
Nikolai Artemiev01675222021-10-20 22:30:41 +1100144
Nikolai Artemieva1d68652021-11-22 13:18:49 +1100145 struct spi_command cmds[] = {
146 {
Nico Huber1b1deda2024-04-18 00:35:48 +0200147 .io_mode = spi_current_io_mode(flash),
Nico Huberd5185632024-01-05 18:44:41 +0100148 .opcode_len = JEDEC_WREN_OUTSIZE,
Nikolai Artemieva1d68652021-11-22 13:18:49 +1100149 .writearr = &enable_cmd,
Nikolai Artemieva1d68652021-11-22 13:18:49 +1100150 }, {
Nico Huber1b1deda2024-04-18 00:35:48 +0200151 .io_mode = spi_current_io_mode(flash),
Nico Huberd5185632024-01-05 18:44:41 +0100152 .opcode_len = 1,
153 .write_len = write_cmd_len - 1,
Nikolai Artemieva1d68652021-11-22 13:18:49 +1100154 .writearr = write_cmd,
Nico Huberd5185632024-01-05 18:44:41 +0100155 },
156 NULL_SPI_CMD
157 };
Nikolai Artemieva1d68652021-11-22 13:18:49 +1100158
159 int result = spi_send_multicommand(flash, cmds);
160 if (result) {
161 msg_cerr("%s failed during command execution\n", __func__);
162 return result;
163 }
164
165 /*
166 * WRSR performs a self-timed erase before the changes take effect.
167 * This may take 50-85 ms in most cases, and some chips apparently
168 * allow running RDSR only once. Therefore pick an initial delay of
169 * 100 ms, then wait in 10 ms steps until a total of 5 s have elapsed.
170 *
171 * Newer chips with multiple status registers (SR2 etc.) are unlikely
172 * to have problems with multiple RDSR commands, so only wait for the
173 * initial 100 ms if the register we wrote to was SR1.
174 */
175 int delay_ms = 5000;
176 if (reg == STATUS1) {
177 programmer_delay(100 * 1000);
178 delay_ms -= 100;
179 }
180
181 for (; delay_ms > 0; delay_ms -= 10) {
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100182 uint8_t status;
183 result = spi_read_register(flash, STATUS1, &status);
184 if (result)
185 return result;
186 if ((status & SPI_SR_WIP) == 0)
Nikolai Artemieva1d68652021-11-22 13:18:49 +1100187 return 0;
188 programmer_delay(10 * 1000);
189 }
190
191
192 msg_cerr("Error: WIP bit after WRSR never cleared\n");
193 return TIMEOUT_ERROR;
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000194}
195
Nikolai Artemiev01675222021-10-20 22:30:41 +1100196int spi_read_register(const struct flashctx *flash, enum flash_reg reg, uint8_t *value)
197{
Nikolai Artemiev9de3f872021-10-20 22:32:25 +1100198 int feature_bits = flash->chip->feature_bits;
Nikolai Artemiev01675222021-10-20 22:30:41 +1100199 uint8_t read_cmd;
200
201 switch (reg) {
202 case STATUS1:
203 read_cmd = JEDEC_RDSR;
204 break;
Nikolai Artemiev9de3f872021-10-20 22:32:25 +1100205 case STATUS2:
Nico Huber3f3c1f32022-05-28 16:48:26 +0200206 if (feature_bits & (FEATURE_WRSR_EXT2 | FEATURE_WRSR2)) {
Nikolai Artemiev9de3f872021-10-20 22:32:25 +1100207 read_cmd = JEDEC_RDSR2;
208 break;
209 }
210 msg_cerr("Cannot read SR2: unsupported by chip\n");
211 return 1;
Sergii Dmytruk0b2e7dd2021-12-19 18:37:51 +0200212 case STATUS3:
Nico Huber3f3c1f32022-05-28 16:48:26 +0200213 if ((feature_bits & FEATURE_WRSR_EXT3) == FEATURE_WRSR_EXT3
214 || (feature_bits & FEATURE_WRSR3)) {
215 read_cmd = JEDEC_RDSR3;
216 break;
217 }
218 msg_cerr("Cannot read SR3: unsupported by chip\n");
219 return 1;
Sergii Dmytruk3d728e72021-11-27 15:14:27 +0200220 case SECURITY:
221 read_cmd = JEDEC_RDSCUR;
222 break;
Sergii Dmytrukbd72a472022-07-24 17:11:05 +0300223 case CONFIG:
224 read_cmd = JEDEC_RDCR;
225 break;
Nikolai Artemiev01675222021-10-20 22:30:41 +1100226 default:
227 msg_cerr("Cannot read register: unknown register\n");
228 return 1;
229 }
230
231 /* FIXME: No workarounds for driver/hardware bugs in generic code. */
232 /* JEDEC_RDSR_INSIZE=1 but wbsio needs 2 */
233 uint8_t readarr[2];
234
235 int ret = spi_send_command(flash, sizeof(read_cmd), sizeof(readarr), &read_cmd, readarr);
236 if (ret) {
237 msg_cerr("Register read failed!\n");
238 return ret;
239 }
240
241 *value = readarr[0];
242 return 0;
243}
244
Nikolai Artemiev721a4f32020-12-14 07:39:02 +1100245static int spi_restore_status(struct flashctx *flash, uint8_t status)
246{
247 msg_cdbg("restoring chip status (0x%02x)\n", status);
Nico Huber4ac536b2024-07-21 00:22:29 +0200248 return spi_write_register(flash, STATUS1, status, WRSR_EITHER);
Nikolai Artemiev721a4f32020-12-14 07:39:02 +1100249}
250
Stefan Tauner9530a022012-12-29 15:04:05 +0000251/* A generic block protection disable.
252 * Tests if a protection is enabled with the block protection mask (bp_mask) and returns success otherwise.
253 * Tests if the register bits are locked with the lock_mask (lock_mask).
Stefan Taunercecb2c52013-06-20 22:55:41 +0000254 * Tests if a hardware protection is active (i.e. low pin/high bit value) with the write protection mask
255 * (wp_mask) and bails out in that case.
256 * If there are register lock bits set we try to disable them by unsetting those bits of the previous register
257 * contents that are set in the lock_mask. We then check if removing the lock bits has worked and continue as if
258 * they never had been engaged:
259 * If the lock bits are out of the way try to disable engaged protections.
260 * To support uncommon global unprotects (e.g. on most AT2[56]xx1(A)) unprotect_mask can be used to force
261 * bits to 0 additionally to those set in bp_mask and lock_mask. Only bits set in unprotect_mask are potentially
262 * preserved when doing the final unprotect.
263 *
264 * To sum up:
265 * bp_mask: set those bits that correspond to the bits in the status register that indicate an active protection
266 * (which should be unset after this function returns).
267 * lock_mask: set the bits that correspond to the bits that lock changing the bits above.
268 * wp_mask: set the bits that correspond to bits indicating non-software revocable protections.
269 * unprotect_mask: set the bits that should be preserved if possible when unprotecting.
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000270 */
Stefan Taunercecb2c52013-06-20 22:55:41 +0000271static int spi_disable_blockprotect_generic(struct flashctx *flash, uint8_t bp_mask, uint8_t lock_mask, uint8_t wp_mask, uint8_t unprotect_mask)
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000272{
273 uint8_t status;
274 int result;
275
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100276 int ret = spi_read_register(flash, STATUS1, &status);
277 if (ret)
278 return ret;
279
Stefan Tauner9530a022012-12-29 15:04:05 +0000280 if ((status & bp_mask) == 0) {
281 msg_cdbg2("Block protection is disabled.\n");
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000282 return 0;
Stefan Tauner9530a022012-12-29 15:04:05 +0000283 }
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000284
Nikolai Artemiev721a4f32020-12-14 07:39:02 +1100285 /* Restore status register content upon exit in finalize_flash_access(). */
286 register_chip_restore(spi_restore_status, flash, status);
287
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000288 msg_cdbg("Some block protection in effect, disabling... ");
Stefan Tauner9530a022012-12-29 15:04:05 +0000289 if ((status & lock_mask) != 0) {
290 msg_cdbg("\n\tNeed to disable the register lock first... ");
291 if (wp_mask != 0 && (status & wp_mask) == 0) {
292 msg_cerr("Hardware protection is active, disabling write protection is impossible.\n");
293 return 1;
294 }
295 /* All bits except the register lock bit (often called SPRL, SRWD, WPEN) are readonly. */
Nico Huber4ac536b2024-07-21 00:22:29 +0200296 result = spi_write_register(flash, STATUS1, status & ~lock_mask, WRSR_EITHER);
Stefan Tauner9530a022012-12-29 15:04:05 +0000297 if (result) {
Nikolai Artemiev01675222021-10-20 22:30:41 +1100298 msg_cerr("Could not write status register 1.\n");
Stefan Tauner9530a022012-12-29 15:04:05 +0000299 return result;
300 }
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100301
302 ret = spi_read_register(flash, STATUS1, &status);
303 if (ret)
304 return ret;
305
Stefan Taunercecb2c52013-06-20 22:55:41 +0000306 if ((status & lock_mask) != 0) {
307 msg_cerr("Unsetting lock bit(s) failed.\n");
308 return 1;
309 }
Stefan Tauner9530a022012-12-29 15:04:05 +0000310 msg_cdbg("done.\n");
311 }
312 /* Global unprotect. Make sure to mask the register lock bit as well. */
Nico Huber4ac536b2024-07-21 00:22:29 +0200313 result = spi_write_register(flash, STATUS1,
314 status & ~(bp_mask | lock_mask) & unprotect_mask, WRSR_EITHER);
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000315 if (result) {
Nikolai Artemiev01675222021-10-20 22:30:41 +1100316 msg_cerr("Could not write status register 1.\n");
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000317 return result;
318 }
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100319
320 ret = spi_read_register(flash, STATUS1, &status);
321 if (ret)
322 return ret;
323
Stefan Tauner9530a022012-12-29 15:04:05 +0000324 if ((status & bp_mask) != 0) {
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000325 msg_cerr("Block protection could not be disabled!\n");
Yuji Sasaki4af36092019-03-22 10:59:50 -0700326 if (flash->chip->printlock)
327 flash->chip->printlock(flash);
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000328 return 1;
329 }
Stefan Tauner9530a022012-12-29 15:04:05 +0000330 msg_cdbg("disabled.\n");
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000331 return 0;
332}
333
Stefan Tauner9530a022012-12-29 15:04:05 +0000334/* A common block protection disable that tries to unset the status register bits masked by 0x3C. */
335int spi_disable_blockprotect(struct flashctx *flash)
336{
Stefan Taunercecb2c52013-06-20 22:55:41 +0000337 return spi_disable_blockprotect_generic(flash, 0x3C, 0, 0, 0xFF);
Stefan Tauner9530a022012-12-29 15:04:05 +0000338}
339
Wei Hu25584de2018-04-30 14:02:08 -0700340int spi_disable_blockprotect_sst26_global_unprotect(struct flashctx *flash)
341{
342 int result = spi_write_enable(flash);
343 if (result)
344 return result;
345
346 static const unsigned char cmd[] = { 0x98 }; /* ULBPR */
347 result = spi_send_command(flash, sizeof(cmd), 0, cmd, NULL);
348 if (result)
349 msg_cerr("ULBPR failed\n");
350 return result;
351}
352
Stefan Taunera60d4082014-06-04 16:17:03 +0000353/* A common block protection disable that tries to unset the status register bits masked by 0x0C (BP0-1) and
354 * protected/locked by bit #7. Useful when bits 4-5 may be non-0). */
355int spi_disable_blockprotect_bp1_srwd(struct flashctx *flash)
356{
357 return spi_disable_blockprotect_generic(flash, 0x0C, 1 << 7, 0, 0xFF);
358}
359
Stefan Tauner278ba6e2013-06-28 21:28:27 +0000360/* A common block protection disable that tries to unset the status register bits masked by 0x1C (BP0-2) and
361 * protected/locked by bit #7. Useful when bit #5 is neither a protection bit nor reserved (and hence possibly
362 * non-0). */
363int spi_disable_blockprotect_bp2_srwd(struct flashctx *flash)
364{
365 return spi_disable_blockprotect_generic(flash, 0x1C, 1 << 7, 0, 0xFF);
366}
367
368/* A common block protection disable that tries to unset the status register bits masked by 0x3C (BP0-3) and
369 * protected/locked by bit #7. */
370int spi_disable_blockprotect_bp3_srwd(struct flashctx *flash)
371{
372 return spi_disable_blockprotect_generic(flash, 0x3C, 1 << 7, 0, 0xFF);
373}
374
375/* A common block protection disable that tries to unset the status register bits masked by 0x7C (BP0-4) and
376 * protected/locked by bit #7. */
377int spi_disable_blockprotect_bp4_srwd(struct flashctx *flash)
378{
379 return spi_disable_blockprotect_generic(flash, 0x7C, 1 << 7, 0, 0xFF);
380}
Stefan Tauner9530a022012-12-29 15:04:05 +0000381
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000382static void spi_prettyprint_status_register_hex(uint8_t status)
383{
384 msg_cdbg("Chip status register is 0x%02x.\n", status);
385}
386
Stefan Taunerb6b00e92013-06-28 21:28:43 +0000387/* Common highest bit: Status Register Write Disable (SRWD) or Status Register Protect (SRP). */
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000388static void spi_prettyprint_status_register_srwd(uint8_t status)
389{
Stefan Taunerb6b00e92013-06-28 21:28:43 +0000390 msg_cdbg("Chip status register: Status Register Write Disable (SRWD, SRP, ...) is %sset\n",
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000391 (status & (1 << 7)) ? "" : "not ");
392}
393
394/* Common highest bit: Block Protect Write Disable (BPL). */
395static void spi_prettyprint_status_register_bpl(uint8_t status)
396{
397 msg_cdbg("Chip status register: Block Protect Write Disable (BPL) is %sset\n",
398 (status & (1 << 7)) ? "" : "not ");
399}
400
401/* Common lowest 2 bits: WEL and WIP. */
402static void spi_prettyprint_status_register_welwip(uint8_t status)
403{
404 msg_cdbg("Chip status register: Write Enable Latch (WEL) is %sset\n",
405 (status & (1 << 1)) ? "" : "not ");
406 msg_cdbg("Chip status register: Write In Progress (WIP/BUSY) is %sset\n",
407 (status & (1 << 0)) ? "" : "not ");
408}
409
410/* Common block protection (BP) bits. */
411static void spi_prettyprint_status_register_bp(uint8_t status, int bp)
412{
413 switch (bp) {
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000414 case 4:
415 msg_cdbg("Chip status register: Block Protect 4 (BP4) is %sset\n",
Stefan Tauner5c316f92015-02-08 21:57:52 +0000416 (status & (1 << 6)) ? "" : "not ");
Richard Hughesdb7482b2018-12-19 12:04:30 +0000417 /* Fall through. */
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000418 case 3:
419 msg_cdbg("Chip status register: Block Protect 3 (BP3) is %sset\n",
420 (status & (1 << 5)) ? "" : "not ");
Richard Hughesdb7482b2018-12-19 12:04:30 +0000421 /* Fall through. */
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000422 case 2:
423 msg_cdbg("Chip status register: Block Protect 2 (BP2) is %sset\n",
424 (status & (1 << 4)) ? "" : "not ");
Richard Hughesdb7482b2018-12-19 12:04:30 +0000425 /* Fall through. */
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000426 case 1:
427 msg_cdbg("Chip status register: Block Protect 1 (BP1) is %sset\n",
428 (status & (1 << 3)) ? "" : "not ");
Richard Hughesdb7482b2018-12-19 12:04:30 +0000429 /* Fall through. */
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000430 case 0:
431 msg_cdbg("Chip status register: Block Protect 0 (BP0) is %sset\n",
432 (status & (1 << 2)) ? "" : "not ");
433 }
434}
435
436/* Unnamed bits. */
Aidan Thorntondb4e87d2013-08-27 18:01:53 +0000437void spi_prettyprint_status_register_bit(uint8_t status, int bit)
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000438{
439 msg_cdbg("Chip status register: Bit %i is %sset\n", bit, (status & (1 << bit)) ? "" : "not ");
440}
441
442int spi_prettyprint_status_register_plain(struct flashctx *flash)
443{
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100444 uint8_t status;
445 int ret = spi_read_register(flash, STATUS1, &status);
446 if (ret)
447 return ret;
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000448 spi_prettyprint_status_register_hex(status);
449 return 0;
450}
451
Stefan Tauner278ba6e2013-06-28 21:28:27 +0000452/* Print the plain hex value and the welwip bits only. */
453int spi_prettyprint_status_register_default_welwip(struct flashctx *flash)
454{
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100455 uint8_t status;
456 int ret = spi_read_register(flash, STATUS1, &status);
457 if (ret)
458 return ret;
Stefan Tauner278ba6e2013-06-28 21:28:27 +0000459 spi_prettyprint_status_register_hex(status);
460
461 spi_prettyprint_status_register_welwip(status);
462 return 0;
463}
464
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000465/* Works for many chips of the
466 * AMIC A25L series
467 * and MX MX25L512
468 */
Stefan Tauner12f3d512014-05-27 21:27:27 +0000469int spi_prettyprint_status_register_bp1_srwd(struct flashctx *flash)
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000470{
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100471 uint8_t status;
472 int ret = spi_read_register(flash, STATUS1, &status);
473 if (ret)
474 return ret;
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000475 spi_prettyprint_status_register_hex(status);
476
477 spi_prettyprint_status_register_srwd(status);
478 spi_prettyprint_status_register_bit(status, 6);
479 spi_prettyprint_status_register_bit(status, 5);
480 spi_prettyprint_status_register_bit(status, 4);
481 spi_prettyprint_status_register_bp(status, 1);
482 spi_prettyprint_status_register_welwip(status);
483 return 0;
484}
485
486/* Works for many chips of the
487 * AMIC A25L series
Stefan Taunerf4451612013-04-19 01:59:15 +0000488 * PMC Pm25LD series
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000489 */
Stefan Tauner12f3d512014-05-27 21:27:27 +0000490int spi_prettyprint_status_register_bp2_srwd(struct flashctx *flash)
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000491{
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100492 uint8_t status;
493 int ret = spi_read_register(flash, STATUS1, &status);
494 if (ret)
495 return ret;
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000496 spi_prettyprint_status_register_hex(status);
497
498 spi_prettyprint_status_register_srwd(status);
499 spi_prettyprint_status_register_bit(status, 6);
500 spi_prettyprint_status_register_bit(status, 5);
501 spi_prettyprint_status_register_bp(status, 2);
502 spi_prettyprint_status_register_welwip(status);
503 return 0;
504}
505
506/* Works for many chips of the
507 * ST M25P series
508 * MX MX25L series
509 */
Stefan Tauner12f3d512014-05-27 21:27:27 +0000510int spi_prettyprint_status_register_bp3_srwd(struct flashctx *flash)
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000511{
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100512 uint8_t status;
513 int ret = spi_read_register(flash, STATUS1, &status);
514 if (ret)
515 return ret;
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000516 spi_prettyprint_status_register_hex(status);
517
518 spi_prettyprint_status_register_srwd(status);
519 spi_prettyprint_status_register_bit(status, 6);
520 spi_prettyprint_status_register_bp(status, 3);
521 spi_prettyprint_status_register_welwip(status);
522 return 0;
523}
524
Stefan Tauner12f3d512014-05-27 21:27:27 +0000525int spi_prettyprint_status_register_bp4_srwd(struct flashctx *flash)
Stefan Tauner278ba6e2013-06-28 21:28:27 +0000526{
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100527 uint8_t status;
528 int ret = spi_read_register(flash, STATUS1, &status);
529 if (ret)
530 return ret;
Stefan Tauner278ba6e2013-06-28 21:28:27 +0000531 spi_prettyprint_status_register_hex(status);
532
533 spi_prettyprint_status_register_srwd(status);
534 spi_prettyprint_status_register_bp(status, 4);
535 spi_prettyprint_status_register_welwip(status);
536 return 0;
537}
538
Stefan Tauner85f09f72014-05-27 21:27:14 +0000539int spi_prettyprint_status_register_bp2_bpl(struct flashctx *flash)
540{
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100541 uint8_t status;
542 int ret = spi_read_register(flash, STATUS1, &status);
543 if (ret)
544 return ret;
Stefan Tauner85f09f72014-05-27 21:27:14 +0000545 spi_prettyprint_status_register_hex(status);
546
547 spi_prettyprint_status_register_bpl(status);
548 spi_prettyprint_status_register_bit(status, 6);
549 spi_prettyprint_status_register_bit(status, 5);
550 spi_prettyprint_status_register_bp(status, 2);
551 spi_prettyprint_status_register_welwip(status);
552 return 0;
553}
554
Ben Gardnerbcf61092015-11-22 02:23:31 +0000555int spi_prettyprint_status_register_bp2_tb_bpl(struct flashctx *flash)
556{
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100557 uint8_t status;
558 int ret = spi_read_register(flash, STATUS1, &status);
559 if (ret)
560 return ret;
Ben Gardnerbcf61092015-11-22 02:23:31 +0000561 spi_prettyprint_status_register_hex(status);
562
563 spi_prettyprint_status_register_bpl(status);
564 spi_prettyprint_status_register_bit(status, 6);
565 msg_cdbg("Chip status register: Top/Bottom (TB) is %s\n", (status & (1 << 5)) ? "bottom" : "top");
566 spi_prettyprint_status_register_bp(status, 2);
567 spi_prettyprint_status_register_welwip(status);
568 return 0;
569}
570
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000571/* === Amic ===
572 * FIXME: spi_disable_blockprotect is incorrect but works fine for chips using
Stefan Tauner12f3d512014-05-27 21:27:27 +0000573 * spi_prettyprint_status_register_bp1_srwd or
574 * spi_prettyprint_status_register_bp2_srwd.
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000575 * FIXME: spi_disable_blockprotect is incorrect and will fail for chips using
576 * spi_prettyprint_status_register_amic_a25l032 if those have locks controlled
577 * by the second status register.
578 */
579
580int spi_prettyprint_status_register_amic_a25l032(struct flashctx *flash)
581{
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100582 uint8_t status;
583 int ret = spi_read_register(flash, STATUS1, &status);
584 if (ret)
585 return ret;
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000586 spi_prettyprint_status_register_hex(status);
587
588 spi_prettyprint_status_register_srwd(status);
589 msg_cdbg("Chip status register: Sector Protect Size (SEC) is %i KB\n", (status & (1 << 6)) ? 4 : 64);
590 msg_cdbg("Chip status register: Top/Bottom (TB) is %s\n", (status & (1 << 5)) ? "bottom" : "top");
591 spi_prettyprint_status_register_bp(status, 2);
592 spi_prettyprint_status_register_welwip(status);
593 msg_cdbg("Chip status register 2 is NOT decoded!\n");
594 return 0;
595}
596
597/* === Atmel === */
598
599static void spi_prettyprint_status_register_atmel_at25_wpen(uint8_t status)
600{
601 msg_cdbg("Chip status register: Write Protect Enable (WPEN) is %sset\n",
602 (status & (1 << 7)) ? "" : "not ");
603}
604
605static void spi_prettyprint_status_register_atmel_at25_srpl(uint8_t status)
606{
607 msg_cdbg("Chip status register: Sector Protection Register Lock (SRPL) is %sset\n",
608 (status & (1 << 7)) ? "" : "not ");
609}
610
611static void spi_prettyprint_status_register_atmel_at25_epewpp(uint8_t status)
612{
613 msg_cdbg("Chip status register: Erase/Program Error (EPE) is %sset\n",
614 (status & (1 << 5)) ? "" : "not ");
615 msg_cdbg("Chip status register: WP# pin (WPP) is %sasserted\n",
616 (status & (1 << 4)) ? "not " : "");
617}
618
619static void spi_prettyprint_status_register_atmel_at25_swp(uint8_t status)
620{
621 msg_cdbg("Chip status register: Software Protection Status (SWP): ");
622 switch (status & (3 << 2)) {
623 case 0x0 << 2:
624 msg_cdbg("no sectors are protected\n");
625 break;
626 case 0x1 << 2:
627 msg_cdbg("some sectors are protected\n");
628 /* FIXME: Read individual Sector Protection Registers. */
629 break;
630 case 0x3 << 2:
631 msg_cdbg("all sectors are protected\n");
632 break;
633 default:
634 msg_cdbg("reserved for future use\n");
635 break;
636 }
637}
638
639int spi_prettyprint_status_register_at25df(struct flashctx *flash)
640{
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100641 uint8_t status;
642 int ret = spi_read_register(flash, STATUS1, &status);
643 if (ret)
644 return ret;
645
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000646 spi_prettyprint_status_register_hex(status);
647
648 spi_prettyprint_status_register_atmel_at25_srpl(status);
649 spi_prettyprint_status_register_bit(status, 6);
650 spi_prettyprint_status_register_atmel_at25_epewpp(status);
651 spi_prettyprint_status_register_atmel_at25_swp(status);
652 spi_prettyprint_status_register_welwip(status);
653 return 0;
654}
655
656int spi_prettyprint_status_register_at25df_sec(struct flashctx *flash)
657{
658 /* FIXME: We should check the security lockdown. */
659 msg_cdbg("Ignoring security lockdown (if present)\n");
660 msg_cdbg("Ignoring status register byte 2\n");
661 return spi_prettyprint_status_register_at25df(flash);
662}
663
Stefan Tauner57794ac2012-12-29 15:04:20 +0000664/* used for AT25F512, AT25F1024(A), AT25F2048 */
665int spi_prettyprint_status_register_at25f(struct flashctx *flash)
666{
667 uint8_t status;
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100668 int ret = spi_read_register(flash, STATUS1, &status);
669 if (ret)
670 return ret;
Stefan Tauner57794ac2012-12-29 15:04:20 +0000671
Stefan Tauner57794ac2012-12-29 15:04:20 +0000672 spi_prettyprint_status_register_hex(status);
673
674 spi_prettyprint_status_register_atmel_at25_wpen(status);
675 spi_prettyprint_status_register_bit(status, 6);
676 spi_prettyprint_status_register_bit(status, 5);
677 spi_prettyprint_status_register_bit(status, 4);
678 spi_prettyprint_status_register_bp(status, 1);
679 spi_prettyprint_status_register_welwip(status);
680 return 0;
681}
682
683int spi_prettyprint_status_register_at25f512a(struct flashctx *flash)
684{
685 uint8_t status;
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100686 int ret = spi_read_register(flash, STATUS1, &status);
687 if (ret)
688 return ret;
Stefan Tauner57794ac2012-12-29 15:04:20 +0000689
Stefan Tauner57794ac2012-12-29 15:04:20 +0000690 spi_prettyprint_status_register_hex(status);
691
692 spi_prettyprint_status_register_atmel_at25_wpen(status);
693 spi_prettyprint_status_register_bit(status, 6);
694 spi_prettyprint_status_register_bit(status, 5);
695 spi_prettyprint_status_register_bit(status, 4);
696 spi_prettyprint_status_register_bit(status, 3);
697 spi_prettyprint_status_register_bp(status, 0);
698 spi_prettyprint_status_register_welwip(status);
699 return 0;
700}
701
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000702int spi_prettyprint_status_register_at25f512b(struct flashctx *flash)
703{
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100704 uint8_t status;
705 int ret = spi_read_register(flash, STATUS1, &status);
706 if (ret)
707 return ret;
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000708 spi_prettyprint_status_register_hex(status);
709
710 spi_prettyprint_status_register_atmel_at25_srpl(status);
711 spi_prettyprint_status_register_bit(status, 6);
712 spi_prettyprint_status_register_atmel_at25_epewpp(status);
713 spi_prettyprint_status_register_bit(status, 3);
714 spi_prettyprint_status_register_bp(status, 0);
715 spi_prettyprint_status_register_welwip(status);
716 return 0;
717}
718
Stefan Tauner57794ac2012-12-29 15:04:20 +0000719int spi_prettyprint_status_register_at25f4096(struct flashctx *flash)
720{
721 uint8_t status;
722
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100723 int ret = spi_read_register(flash, STATUS1, &status);
724 if (ret)
725 return ret;
726
Stefan Tauner57794ac2012-12-29 15:04:20 +0000727 spi_prettyprint_status_register_hex(status);
728
729 spi_prettyprint_status_register_atmel_at25_wpen(status);
730 spi_prettyprint_status_register_bit(status, 6);
731 spi_prettyprint_status_register_bit(status, 5);
732 spi_prettyprint_status_register_bp(status, 2);
733 spi_prettyprint_status_register_welwip(status);
734 return 0;
735}
736
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000737int spi_prettyprint_status_register_at25fs010(struct flashctx *flash)
738{
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100739 uint8_t status;
740 int ret = spi_read_register(flash, STATUS1, &status);
741 if (ret)
742 return ret;
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000743 spi_prettyprint_status_register_hex(status);
744
745 spi_prettyprint_status_register_atmel_at25_wpen(status);
746 msg_cdbg("Chip status register: Bit 6 / Block Protect 4 (BP4) is "
747 "%sset\n", (status & (1 << 6)) ? "" : "not ");
748 msg_cdbg("Chip status register: Bit 5 / Block Protect 3 (BP3) is "
749 "%sset\n", (status & (1 << 5)) ? "" : "not ");
750 spi_prettyprint_status_register_bit(status, 4);
751 msg_cdbg("Chip status register: Bit 3 / Block Protect 1 (BP1) is "
752 "%sset\n", (status & (1 << 3)) ? "" : "not ");
753 msg_cdbg("Chip status register: Bit 2 / Block Protect 0 (BP0) is "
754 "%sset\n", (status & (1 << 2)) ? "" : "not ");
755 /* FIXME: Pretty-print detailed sector protection status. */
756 spi_prettyprint_status_register_welwip(status);
757 return 0;
758}
759
760int spi_prettyprint_status_register_at25fs040(struct flashctx *flash)
761{
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100762 uint8_t status;
763 int ret = spi_read_register(flash, STATUS1, &status);
764 if (ret)
765 return ret;
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000766 spi_prettyprint_status_register_hex(status);
767
768 spi_prettyprint_status_register_atmel_at25_wpen(status);
769 spi_prettyprint_status_register_bp(status, 4);
770 /* FIXME: Pretty-print detailed sector protection status. */
771 spi_prettyprint_status_register_welwip(status);
772 return 0;
773}
774
775int spi_prettyprint_status_register_at26df081a(struct flashctx *flash)
776{
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100777 uint8_t status;
778 int ret = spi_read_register(flash, STATUS1, &status);
779 if (ret)
780 return ret;
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000781 spi_prettyprint_status_register_hex(status);
782
783 spi_prettyprint_status_register_atmel_at25_srpl(status);
784 msg_cdbg("Chip status register: Sequential Program Mode Status (SPM) is %sset\n",
785 (status & (1 << 6)) ? "" : "not ");
786 spi_prettyprint_status_register_atmel_at25_epewpp(status);
787 spi_prettyprint_status_register_atmel_at25_swp(status);
788 spi_prettyprint_status_register_welwip(status);
789 return 0;
790}
791
Stefan Taunercecb2c52013-06-20 22:55:41 +0000792/* Some Atmel DataFlash chips support per sector protection bits and the write protection bits in the status
793 * register do indicate if none, some or all sectors are protected. It is possible to globally (un)lock all
794 * sectors at once by writing 0 not only the protection bits (2 and 3) but also completely unrelated bits (4 and
795 * 5) which normally are not touched.
796 * Affected are all known Atmel chips matched by AT2[56]D[FLQ]..1A? but the AT26DF041. */
797int spi_disable_blockprotect_at2x_global_unprotect(struct flashctx *flash)
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000798{
Stefan Taunercecb2c52013-06-20 22:55:41 +0000799 return spi_disable_blockprotect_generic(flash, 0x0C, 1 << 7, 1 << 4, 0x00);
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000800}
801
Stefan Taunercecb2c52013-06-20 22:55:41 +0000802int spi_disable_blockprotect_at2x_global_unprotect_sec(struct flashctx *flash)
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000803{
804 /* FIXME: We should check the security lockdown. */
805 msg_cinfo("Ignoring security lockdown (if present)\n");
Stefan Taunercecb2c52013-06-20 22:55:41 +0000806 return spi_disable_blockprotect_at2x_global_unprotect(flash);
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000807}
808
Stefan Tauner57794ac2012-12-29 15:04:20 +0000809int spi_disable_blockprotect_at25f(struct flashctx *flash)
810{
Stefan Taunercecb2c52013-06-20 22:55:41 +0000811 return spi_disable_blockprotect_generic(flash, 0x0C, 1 << 7, 0, 0xFF);
Stefan Tauner57794ac2012-12-29 15:04:20 +0000812}
813
814int spi_disable_blockprotect_at25f512a(struct flashctx *flash)
815{
Stefan Taunercecb2c52013-06-20 22:55:41 +0000816 return spi_disable_blockprotect_generic(flash, 0x04, 1 << 7, 0, 0xFF);
Stefan Tauner57794ac2012-12-29 15:04:20 +0000817}
818
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000819int spi_disable_blockprotect_at25f512b(struct flashctx *flash)
820{
Stefan Taunercecb2c52013-06-20 22:55:41 +0000821 return spi_disable_blockprotect_generic(flash, 0x04, 1 << 7, 1 << 4, 0xFF);
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000822}
823
824int spi_disable_blockprotect_at25fs010(struct flashctx *flash)
825{
Stefan Taunercecb2c52013-06-20 22:55:41 +0000826 return spi_disable_blockprotect_generic(flash, 0x6C, 1 << 7, 0, 0xFF);
Stefan Tauner9530a022012-12-29 15:04:05 +0000827 }
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000828
829int spi_disable_blockprotect_at25fs040(struct flashctx *flash)
830{
Stefan Taunercecb2c52013-06-20 22:55:41 +0000831 return spi_disable_blockprotect_generic(flash, 0x7C, 1 << 7, 0, 0xFF);
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000832}
833
Nikolay Nikolaevd0e3ea12013-06-28 21:29:08 +0000834/* === Eon === */
835
836int spi_prettyprint_status_register_en25s_wp(struct flashctx *flash)
837{
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100838 uint8_t status;
839 int ret = spi_read_register(flash, STATUS1, &status);
840 if (ret)
841 return ret;
Nikolay Nikolaevd0e3ea12013-06-28 21:29:08 +0000842 spi_prettyprint_status_register_hex(status);
843
844 spi_prettyprint_status_register_srwd(status);
845 msg_cdbg("Chip status register: WP# disable (WPDIS) is %sabled\n", (status & (1 << 6)) ? "en " : "dis");
846 spi_prettyprint_status_register_bp(status, 3);
847 spi_prettyprint_status_register_welwip(status);
848 return 0;
849}
850
Nikolay Nikolaevc80c4a32013-06-28 21:29:44 +0000851/* === Intel/Numonyx/Micron - Spansion === */
Stefan Tauner54aaa4a2012-12-29 15:04:12 +0000852
Nikolay Nikolaev6f59b0b2013-06-28 21:29:51 +0000853int spi_disable_blockprotect_n25q(struct flashctx *flash)
854{
855 return spi_disable_blockprotect_generic(flash, 0x5C, 1 << 7, 0, 0xFF);
856}
857
858int spi_prettyprint_status_register_n25q(struct flashctx *flash)
859{
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100860 uint8_t status;
861 int ret = spi_read_register(flash, STATUS1, &status);
862 if (ret)
863 return ret;
Nikolay Nikolaev6f59b0b2013-06-28 21:29:51 +0000864 spi_prettyprint_status_register_hex(status);
865
866 spi_prettyprint_status_register_srwd(status);
867 if (flash->chip->total_size <= 32 / 8 * 1024) /* N25Q16 and N25Q32: reserved */
868 spi_prettyprint_status_register_bit(status, 6);
869 else
870 msg_cdbg("Chip status register: Block Protect 3 (BP3) is %sset\n",
871 (status & (1 << 6)) ? "" : "not ");
872 msg_cdbg("Chip status register: Top/Bottom (TB) is %s\n", (status & (1 << 5)) ? "bottom" : "top");
873 spi_prettyprint_status_register_bp(status, 2);
874 spi_prettyprint_status_register_welwip(status);
875 return 0;
876}
877
Nikolay Nikolaevc80c4a32013-06-28 21:29:44 +0000878/* Used by Intel/Numonyx S33 and Spansion S25FL-S chips */
Stefan Tauner54aaa4a2012-12-29 15:04:12 +0000879/* TODO: Clear P_FAIL and E_FAIL with Clear SR Fail Flags Command (30h) here? */
Nikolay Nikolaevc80c4a32013-06-28 21:29:44 +0000880int spi_disable_blockprotect_bp2_ep_srwd(struct flashctx *flash)
Stefan Tauner54aaa4a2012-12-29 15:04:12 +0000881{
Stefan Tauner278ba6e2013-06-28 21:28:27 +0000882 return spi_disable_blockprotect_bp2_srwd(flash);
Stefan Tauner54aaa4a2012-12-29 15:04:12 +0000883}
884
Nikolay Nikolaevc80c4a32013-06-28 21:29:44 +0000885/* Used by Intel/Numonyx S33 and Spansion S25FL-S chips */
886int spi_prettyprint_status_register_bp2_ep_srwd(struct flashctx *flash)
Stefan Tauner54aaa4a2012-12-29 15:04:12 +0000887{
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100888 uint8_t status;
889 int ret = spi_read_register(flash, STATUS1, &status);
890 if (ret)
891 return ret;
Stefan Taunerc2eec2c2014-05-03 21:33:01 +0000892 spi_prettyprint_status_register_hex(status);
Stefan Tauner54aaa4a2012-12-29 15:04:12 +0000893
894 spi_prettyprint_status_register_srwd(status);
895 msg_cdbg("Chip status register: Program Fail Flag (P_FAIL) is %sset\n",
896 (status & (1 << 6)) ? "" : "not ");
897 msg_cdbg("Chip status register: Erase Fail Flag (E_FAIL) is %sset\n",
898 (status & (1 << 5)) ? "" : "not ");
899 spi_prettyprint_status_register_bp(status, 2);
900 spi_prettyprint_status_register_welwip(status);
901 return 0;
902}
903
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000904/* === SST === */
905
906static void spi_prettyprint_status_register_sst25_common(uint8_t status)
907{
908 spi_prettyprint_status_register_hex(status);
909
910 spi_prettyprint_status_register_bpl(status);
911 msg_cdbg("Chip status register: Auto Address Increment Programming (AAI) is %sset\n",
912 (status & (1 << 6)) ? "" : "not ");
913 spi_prettyprint_status_register_bp(status, 3);
914 spi_prettyprint_status_register_welwip(status);
915}
916
917int spi_prettyprint_status_register_sst25(struct flashctx *flash)
918{
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100919 uint8_t status;
920 int ret = spi_read_register(flash, STATUS1, &status);
921 if (ret)
922 return ret;
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000923 spi_prettyprint_status_register_sst25_common(status);
924 return 0;
925}
926
927int spi_prettyprint_status_register_sst25vf016(struct flashctx *flash)
928{
929 static const char *const bpt[] = {
930 "none",
931 "1F0000H-1FFFFFH",
932 "1E0000H-1FFFFFH",
933 "1C0000H-1FFFFFH",
934 "180000H-1FFFFFH",
935 "100000H-1FFFFFH",
936 "all", "all"
937 };
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100938 uint8_t status;
939 int ret = spi_read_register(flash, STATUS1, &status);
940 if (ret)
941 return ret;
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000942 spi_prettyprint_status_register_sst25_common(status);
943 msg_cdbg("Resulting block protection : %s\n", bpt[(status & 0x1c) >> 2]);
944 return 0;
945}
946
947int spi_prettyprint_status_register_sst25vf040b(struct flashctx *flash)
948{
949 static const char *const bpt[] = {
950 "none",
951 "0x70000-0x7ffff",
952 "0x60000-0x7ffff",
953 "0x40000-0x7ffff",
954 "all blocks", "all blocks", "all blocks", "all blocks"
955 };
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100956 uint8_t status;
957 int ret = spi_read_register(flash, STATUS1, &status);
958 if (ret)
959 return ret;
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000960 spi_prettyprint_status_register_sst25_common(status);
961 msg_cdbg("Resulting block protection : %s\n", bpt[(status & 0x1c) >> 2]);
962 return 0;
963}