blob: 24bef6c41b8a2031d68d592c3a8a06c0f138aff5 [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
Nikolai Artemiev01675222021-10-20 22:30:41 +110059int spi_write_register(const struct flashctx *flash, enum flash_reg reg, uint8_t value)
Stefan Tauner6ee37e22012-12-29 15:03:51 +000060{
61 int feature_bits = flash->chip->feature_bits;
Nikolai Artemiev01675222021-10-20 22:30:41 +110062
Nico Huber3f3c1f32022-05-28 16:48:26 +020063 uint8_t write_cmd[4];
Nikolai Artemiev01675222021-10-20 22:30:41 +110064 size_t write_cmd_len = 0;
65
66 /*
67 * Create SPI write command sequence based on the destination register
68 * and the chip's supported command set.
69 */
70 switch (reg) {
71 case STATUS1:
72 write_cmd[0] = JEDEC_WRSR;
73 write_cmd[1] = value;
74 write_cmd_len = JEDEC_WRSR_OUTSIZE;
75 break;
Nikolai Artemiev9de3f872021-10-20 22:32:25 +110076 case STATUS2:
77 if (feature_bits & FEATURE_WRSR2) {
78 write_cmd[0] = JEDEC_WRSR2;
79 write_cmd[1] = value;
80 write_cmd_len = JEDEC_WRSR2_OUTSIZE;
81 break;
82 }
Nico Huber3f3c1f32022-05-28 16:48:26 +020083 if (feature_bits & FEATURE_WRSR_EXT2) {
84 if (spi_prepare_wrsr_ext(write_cmd, &write_cmd_len, flash, reg, value))
Nikolai Artemiev9de3f872021-10-20 22:32:25 +110085 return 1;
Nikolai Artemiev9de3f872021-10-20 22:32:25 +110086 break;
87 }
88 msg_cerr("Cannot write SR2: unsupported by chip\n");
89 return 1;
Sergii Dmytruk0b2e7dd2021-12-19 18:37:51 +020090 case STATUS3:
Nico Huber3f3c1f32022-05-28 16:48:26 +020091 if (feature_bits & FEATURE_WRSR3) {
92 write_cmd[0] = JEDEC_WRSR3;
93 write_cmd[1] = value;
94 write_cmd_len = JEDEC_WRSR3_OUTSIZE;
95 break;
96 }
97 if ((feature_bits & FEATURE_WRSR_EXT3) == FEATURE_WRSR_EXT3) {
98 if (spi_prepare_wrsr_ext(write_cmd, &write_cmd_len, flash, reg, value))
99 return 1;
100 break;
101 }
102 msg_cerr("Cannot write SR3: unsupported by chip\n");
103 return 1;
Sergii Dmytruk3d728e72021-11-27 15:14:27 +0200104 case SECURITY:
105 /*
106 * Security register doesn't have a normal write operation. Instead,
107 * there are separate commands that set individual OTP bits.
108 */
109 msg_cerr("Cannot write SECURITY: unsupported by design\n");
110 return 1;
Sergii Dmytrukbd72a472022-07-24 17:11:05 +0300111 case CONFIG:
112 /*
113 * This one is read via a separate command, but written as if it's SR2
114 * in FEATURE_WRSR_EXT2 case of WRSR command.
115 */
116 write_cmd[0] = JEDEC_WRSR;
117 if (spi_read_register(flash, STATUS1, &write_cmd[1])) {
118 msg_cerr("Writing CONFIG failed: failed to read SR1 for writeback.\n");
119 return 1;
120 }
121 write_cmd[2] = value;
122 write_cmd_len = 3;
123 break;
Nikolai Artemiev01675222021-10-20 22:30:41 +1100124 default:
125 msg_cerr("Cannot write register: unknown register\n");
126 return 1;
127 }
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000128
Nikolai Artemieva1d68652021-11-22 13:18:49 +1100129 uint8_t enable_cmd;
130 if (feature_bits & FEATURE_WRSR_WREN) {
131 enable_cmd = JEDEC_WREN;
132 } else if (feature_bits & FEATURE_WRSR_EWSR) {
133 enable_cmd = JEDEC_EWSR;
134 } else {
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000135 msg_cdbg("Missing status register write definition, assuming "
136 "EWSR is needed\n");
Nikolai Artemieva1d68652021-11-22 13:18:49 +1100137 enable_cmd = JEDEC_EWSR;
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000138 }
Nikolai Artemiev01675222021-10-20 22:30:41 +1100139
Nikolai Artemieva1d68652021-11-22 13:18:49 +1100140 struct spi_command cmds[] = {
141 {
Nico Huber1b1deda2024-04-18 00:35:48 +0200142 .io_mode = spi_current_io_mode(flash),
Nico Huberd5185632024-01-05 18:44:41 +0100143 .opcode_len = JEDEC_WREN_OUTSIZE,
Nikolai Artemieva1d68652021-11-22 13:18:49 +1100144 .writearr = &enable_cmd,
Nikolai Artemieva1d68652021-11-22 13:18:49 +1100145 }, {
Nico Huber1b1deda2024-04-18 00:35:48 +0200146 .io_mode = spi_current_io_mode(flash),
Nico Huberd5185632024-01-05 18:44:41 +0100147 .opcode_len = 1,
148 .write_len = write_cmd_len - 1,
Nikolai Artemieva1d68652021-11-22 13:18:49 +1100149 .writearr = write_cmd,
Nico Huberd5185632024-01-05 18:44:41 +0100150 },
151 NULL_SPI_CMD
152 };
Nikolai Artemieva1d68652021-11-22 13:18:49 +1100153
154 int result = spi_send_multicommand(flash, cmds);
155 if (result) {
156 msg_cerr("%s failed during command execution\n", __func__);
157 return result;
158 }
159
160 /*
161 * WRSR performs a self-timed erase before the changes take effect.
162 * This may take 50-85 ms in most cases, and some chips apparently
163 * allow running RDSR only once. Therefore pick an initial delay of
164 * 100 ms, then wait in 10 ms steps until a total of 5 s have elapsed.
165 *
166 * Newer chips with multiple status registers (SR2 etc.) are unlikely
167 * to have problems with multiple RDSR commands, so only wait for the
168 * initial 100 ms if the register we wrote to was SR1.
169 */
170 int delay_ms = 5000;
171 if (reg == STATUS1) {
172 programmer_delay(100 * 1000);
173 delay_ms -= 100;
174 }
175
176 for (; delay_ms > 0; delay_ms -= 10) {
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100177 uint8_t status;
178 result = spi_read_register(flash, STATUS1, &status);
179 if (result)
180 return result;
181 if ((status & SPI_SR_WIP) == 0)
Nikolai Artemieva1d68652021-11-22 13:18:49 +1100182 return 0;
183 programmer_delay(10 * 1000);
184 }
185
186
187 msg_cerr("Error: WIP bit after WRSR never cleared\n");
188 return TIMEOUT_ERROR;
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000189}
190
Nikolai Artemiev01675222021-10-20 22:30:41 +1100191int spi_read_register(const struct flashctx *flash, enum flash_reg reg, uint8_t *value)
192{
Nikolai Artemiev9de3f872021-10-20 22:32:25 +1100193 int feature_bits = flash->chip->feature_bits;
Nikolai Artemiev01675222021-10-20 22:30:41 +1100194 uint8_t read_cmd;
195
196 switch (reg) {
197 case STATUS1:
198 read_cmd = JEDEC_RDSR;
199 break;
Nikolai Artemiev9de3f872021-10-20 22:32:25 +1100200 case STATUS2:
Nico Huber3f3c1f32022-05-28 16:48:26 +0200201 if (feature_bits & (FEATURE_WRSR_EXT2 | FEATURE_WRSR2)) {
Nikolai Artemiev9de3f872021-10-20 22:32:25 +1100202 read_cmd = JEDEC_RDSR2;
203 break;
204 }
205 msg_cerr("Cannot read SR2: unsupported by chip\n");
206 return 1;
Sergii Dmytruk0b2e7dd2021-12-19 18:37:51 +0200207 case STATUS3:
Nico Huber3f3c1f32022-05-28 16:48:26 +0200208 if ((feature_bits & FEATURE_WRSR_EXT3) == FEATURE_WRSR_EXT3
209 || (feature_bits & FEATURE_WRSR3)) {
210 read_cmd = JEDEC_RDSR3;
211 break;
212 }
213 msg_cerr("Cannot read SR3: unsupported by chip\n");
214 return 1;
Sergii Dmytruk3d728e72021-11-27 15:14:27 +0200215 case SECURITY:
216 read_cmd = JEDEC_RDSCUR;
217 break;
Sergii Dmytrukbd72a472022-07-24 17:11:05 +0300218 case CONFIG:
219 read_cmd = JEDEC_RDCR;
220 break;
Nikolai Artemiev01675222021-10-20 22:30:41 +1100221 default:
222 msg_cerr("Cannot read register: unknown register\n");
223 return 1;
224 }
225
226 /* FIXME: No workarounds for driver/hardware bugs in generic code. */
227 /* JEDEC_RDSR_INSIZE=1 but wbsio needs 2 */
228 uint8_t readarr[2];
229
230 int ret = spi_send_command(flash, sizeof(read_cmd), sizeof(readarr), &read_cmd, readarr);
231 if (ret) {
232 msg_cerr("Register read failed!\n");
233 return ret;
234 }
235
236 *value = readarr[0];
237 return 0;
238}
239
Nikolai Artemiev721a4f32020-12-14 07:39:02 +1100240static int spi_restore_status(struct flashctx *flash, uint8_t status)
241{
242 msg_cdbg("restoring chip status (0x%02x)\n", status);
Nikolai Artemiev01675222021-10-20 22:30:41 +1100243 return spi_write_register(flash, STATUS1, status);
Nikolai Artemiev721a4f32020-12-14 07:39:02 +1100244}
245
Stefan Tauner9530a022012-12-29 15:04:05 +0000246/* A generic block protection disable.
247 * Tests if a protection is enabled with the block protection mask (bp_mask) and returns success otherwise.
248 * Tests if the register bits are locked with the lock_mask (lock_mask).
Stefan Taunercecb2c52013-06-20 22:55:41 +0000249 * Tests if a hardware protection is active (i.e. low pin/high bit value) with the write protection mask
250 * (wp_mask) and bails out in that case.
251 * If there are register lock bits set we try to disable them by unsetting those bits of the previous register
252 * contents that are set in the lock_mask. We then check if removing the lock bits has worked and continue as if
253 * they never had been engaged:
254 * If the lock bits are out of the way try to disable engaged protections.
255 * To support uncommon global unprotects (e.g. on most AT2[56]xx1(A)) unprotect_mask can be used to force
256 * bits to 0 additionally to those set in bp_mask and lock_mask. Only bits set in unprotect_mask are potentially
257 * preserved when doing the final unprotect.
258 *
259 * To sum up:
260 * bp_mask: set those bits that correspond to the bits in the status register that indicate an active protection
261 * (which should be unset after this function returns).
262 * lock_mask: set the bits that correspond to the bits that lock changing the bits above.
263 * wp_mask: set the bits that correspond to bits indicating non-software revocable protections.
264 * unprotect_mask: set the bits that should be preserved if possible when unprotecting.
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000265 */
Stefan Taunercecb2c52013-06-20 22:55:41 +0000266static 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 +0000267{
268 uint8_t status;
269 int result;
270
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100271 int ret = spi_read_register(flash, STATUS1, &status);
272 if (ret)
273 return ret;
274
Stefan Tauner9530a022012-12-29 15:04:05 +0000275 if ((status & bp_mask) == 0) {
276 msg_cdbg2("Block protection is disabled.\n");
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000277 return 0;
Stefan Tauner9530a022012-12-29 15:04:05 +0000278 }
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000279
Nikolai Artemiev721a4f32020-12-14 07:39:02 +1100280 /* Restore status register content upon exit in finalize_flash_access(). */
281 register_chip_restore(spi_restore_status, flash, status);
282
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000283 msg_cdbg("Some block protection in effect, disabling... ");
Stefan Tauner9530a022012-12-29 15:04:05 +0000284 if ((status & lock_mask) != 0) {
285 msg_cdbg("\n\tNeed to disable the register lock first... ");
286 if (wp_mask != 0 && (status & wp_mask) == 0) {
287 msg_cerr("Hardware protection is active, disabling write protection is impossible.\n");
288 return 1;
289 }
290 /* All bits except the register lock bit (often called SPRL, SRWD, WPEN) are readonly. */
Nikolai Artemiev01675222021-10-20 22:30:41 +1100291 result = spi_write_register(flash, STATUS1, status & ~lock_mask);
Stefan Tauner9530a022012-12-29 15:04:05 +0000292 if (result) {
Nikolai Artemiev01675222021-10-20 22:30:41 +1100293 msg_cerr("Could not write status register 1.\n");
Stefan Tauner9530a022012-12-29 15:04:05 +0000294 return result;
295 }
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100296
297 ret = spi_read_register(flash, STATUS1, &status);
298 if (ret)
299 return ret;
300
Stefan Taunercecb2c52013-06-20 22:55:41 +0000301 if ((status & lock_mask) != 0) {
302 msg_cerr("Unsetting lock bit(s) failed.\n");
303 return 1;
304 }
Stefan Tauner9530a022012-12-29 15:04:05 +0000305 msg_cdbg("done.\n");
306 }
307 /* Global unprotect. Make sure to mask the register lock bit as well. */
Nikolai Artemiev01675222021-10-20 22:30:41 +1100308 result = spi_write_register(flash, STATUS1, status & ~(bp_mask | lock_mask) & unprotect_mask);
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000309 if (result) {
Nikolai Artemiev01675222021-10-20 22:30:41 +1100310 msg_cerr("Could not write status register 1.\n");
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000311 return result;
312 }
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100313
314 ret = spi_read_register(flash, STATUS1, &status);
315 if (ret)
316 return ret;
317
Stefan Tauner9530a022012-12-29 15:04:05 +0000318 if ((status & bp_mask) != 0) {
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000319 msg_cerr("Block protection could not be disabled!\n");
Yuji Sasaki4af36092019-03-22 10:59:50 -0700320 if (flash->chip->printlock)
321 flash->chip->printlock(flash);
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000322 return 1;
323 }
Stefan Tauner9530a022012-12-29 15:04:05 +0000324 msg_cdbg("disabled.\n");
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000325 return 0;
326}
327
Stefan Tauner9530a022012-12-29 15:04:05 +0000328/* A common block protection disable that tries to unset the status register bits masked by 0x3C. */
329int spi_disable_blockprotect(struct flashctx *flash)
330{
Stefan Taunercecb2c52013-06-20 22:55:41 +0000331 return spi_disable_blockprotect_generic(flash, 0x3C, 0, 0, 0xFF);
Stefan Tauner9530a022012-12-29 15:04:05 +0000332}
333
Wei Hu25584de2018-04-30 14:02:08 -0700334int spi_disable_blockprotect_sst26_global_unprotect(struct flashctx *flash)
335{
336 int result = spi_write_enable(flash);
337 if (result)
338 return result;
339
340 static const unsigned char cmd[] = { 0x98 }; /* ULBPR */
341 result = spi_send_command(flash, sizeof(cmd), 0, cmd, NULL);
342 if (result)
343 msg_cerr("ULBPR failed\n");
344 return result;
345}
346
Stefan Taunera60d4082014-06-04 16:17:03 +0000347/* A common block protection disable that tries to unset the status register bits masked by 0x0C (BP0-1) and
348 * protected/locked by bit #7. Useful when bits 4-5 may be non-0). */
349int spi_disable_blockprotect_bp1_srwd(struct flashctx *flash)
350{
351 return spi_disable_blockprotect_generic(flash, 0x0C, 1 << 7, 0, 0xFF);
352}
353
Stefan Tauner278ba6e2013-06-28 21:28:27 +0000354/* A common block protection disable that tries to unset the status register bits masked by 0x1C (BP0-2) and
355 * protected/locked by bit #7. Useful when bit #5 is neither a protection bit nor reserved (and hence possibly
356 * non-0). */
357int spi_disable_blockprotect_bp2_srwd(struct flashctx *flash)
358{
359 return spi_disable_blockprotect_generic(flash, 0x1C, 1 << 7, 0, 0xFF);
360}
361
362/* A common block protection disable that tries to unset the status register bits masked by 0x3C (BP0-3) and
363 * protected/locked by bit #7. */
364int spi_disable_blockprotect_bp3_srwd(struct flashctx *flash)
365{
366 return spi_disable_blockprotect_generic(flash, 0x3C, 1 << 7, 0, 0xFF);
367}
368
369/* A common block protection disable that tries to unset the status register bits masked by 0x7C (BP0-4) and
370 * protected/locked by bit #7. */
371int spi_disable_blockprotect_bp4_srwd(struct flashctx *flash)
372{
373 return spi_disable_blockprotect_generic(flash, 0x7C, 1 << 7, 0, 0xFF);
374}
Stefan Tauner9530a022012-12-29 15:04:05 +0000375
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000376static void spi_prettyprint_status_register_hex(uint8_t status)
377{
378 msg_cdbg("Chip status register is 0x%02x.\n", status);
379}
380
Stefan Taunerb6b00e92013-06-28 21:28:43 +0000381/* Common highest bit: Status Register Write Disable (SRWD) or Status Register Protect (SRP). */
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000382static void spi_prettyprint_status_register_srwd(uint8_t status)
383{
Stefan Taunerb6b00e92013-06-28 21:28:43 +0000384 msg_cdbg("Chip status register: Status Register Write Disable (SRWD, SRP, ...) is %sset\n",
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000385 (status & (1 << 7)) ? "" : "not ");
386}
387
388/* Common highest bit: Block Protect Write Disable (BPL). */
389static void spi_prettyprint_status_register_bpl(uint8_t status)
390{
391 msg_cdbg("Chip status register: Block Protect Write Disable (BPL) is %sset\n",
392 (status & (1 << 7)) ? "" : "not ");
393}
394
395/* Common lowest 2 bits: WEL and WIP. */
396static void spi_prettyprint_status_register_welwip(uint8_t status)
397{
398 msg_cdbg("Chip status register: Write Enable Latch (WEL) is %sset\n",
399 (status & (1 << 1)) ? "" : "not ");
400 msg_cdbg("Chip status register: Write In Progress (WIP/BUSY) is %sset\n",
401 (status & (1 << 0)) ? "" : "not ");
402}
403
404/* Common block protection (BP) bits. */
405static void spi_prettyprint_status_register_bp(uint8_t status, int bp)
406{
407 switch (bp) {
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000408 case 4:
409 msg_cdbg("Chip status register: Block Protect 4 (BP4) is %sset\n",
Stefan Tauner5c316f92015-02-08 21:57:52 +0000410 (status & (1 << 6)) ? "" : "not ");
Richard Hughesdb7482b2018-12-19 12:04:30 +0000411 /* Fall through. */
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000412 case 3:
413 msg_cdbg("Chip status register: Block Protect 3 (BP3) is %sset\n",
414 (status & (1 << 5)) ? "" : "not ");
Richard Hughesdb7482b2018-12-19 12:04:30 +0000415 /* Fall through. */
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000416 case 2:
417 msg_cdbg("Chip status register: Block Protect 2 (BP2) is %sset\n",
418 (status & (1 << 4)) ? "" : "not ");
Richard Hughesdb7482b2018-12-19 12:04:30 +0000419 /* Fall through. */
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000420 case 1:
421 msg_cdbg("Chip status register: Block Protect 1 (BP1) is %sset\n",
422 (status & (1 << 3)) ? "" : "not ");
Richard Hughesdb7482b2018-12-19 12:04:30 +0000423 /* Fall through. */
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000424 case 0:
425 msg_cdbg("Chip status register: Block Protect 0 (BP0) is %sset\n",
426 (status & (1 << 2)) ? "" : "not ");
427 }
428}
429
430/* Unnamed bits. */
Aidan Thorntondb4e87d2013-08-27 18:01:53 +0000431void spi_prettyprint_status_register_bit(uint8_t status, int bit)
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000432{
433 msg_cdbg("Chip status register: Bit %i is %sset\n", bit, (status & (1 << bit)) ? "" : "not ");
434}
435
436int spi_prettyprint_status_register_plain(struct flashctx *flash)
437{
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100438 uint8_t status;
439 int ret = spi_read_register(flash, STATUS1, &status);
440 if (ret)
441 return ret;
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000442 spi_prettyprint_status_register_hex(status);
443 return 0;
444}
445
Stefan Tauner278ba6e2013-06-28 21:28:27 +0000446/* Print the plain hex value and the welwip bits only. */
447int spi_prettyprint_status_register_default_welwip(struct flashctx *flash)
448{
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100449 uint8_t status;
450 int ret = spi_read_register(flash, STATUS1, &status);
451 if (ret)
452 return ret;
Stefan Tauner278ba6e2013-06-28 21:28:27 +0000453 spi_prettyprint_status_register_hex(status);
454
455 spi_prettyprint_status_register_welwip(status);
456 return 0;
457}
458
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000459/* Works for many chips of the
460 * AMIC A25L series
461 * and MX MX25L512
462 */
Stefan Tauner12f3d512014-05-27 21:27:27 +0000463int spi_prettyprint_status_register_bp1_srwd(struct flashctx *flash)
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000464{
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100465 uint8_t status;
466 int ret = spi_read_register(flash, STATUS1, &status);
467 if (ret)
468 return ret;
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000469 spi_prettyprint_status_register_hex(status);
470
471 spi_prettyprint_status_register_srwd(status);
472 spi_prettyprint_status_register_bit(status, 6);
473 spi_prettyprint_status_register_bit(status, 5);
474 spi_prettyprint_status_register_bit(status, 4);
475 spi_prettyprint_status_register_bp(status, 1);
476 spi_prettyprint_status_register_welwip(status);
477 return 0;
478}
479
480/* Works for many chips of the
481 * AMIC A25L series
Stefan Taunerf4451612013-04-19 01:59:15 +0000482 * PMC Pm25LD series
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000483 */
Stefan Tauner12f3d512014-05-27 21:27:27 +0000484int spi_prettyprint_status_register_bp2_srwd(struct flashctx *flash)
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000485{
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100486 uint8_t status;
487 int ret = spi_read_register(flash, STATUS1, &status);
488 if (ret)
489 return ret;
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000490 spi_prettyprint_status_register_hex(status);
491
492 spi_prettyprint_status_register_srwd(status);
493 spi_prettyprint_status_register_bit(status, 6);
494 spi_prettyprint_status_register_bit(status, 5);
495 spi_prettyprint_status_register_bp(status, 2);
496 spi_prettyprint_status_register_welwip(status);
497 return 0;
498}
499
500/* Works for many chips of the
501 * ST M25P series
502 * MX MX25L series
503 */
Stefan Tauner12f3d512014-05-27 21:27:27 +0000504int spi_prettyprint_status_register_bp3_srwd(struct flashctx *flash)
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000505{
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100506 uint8_t status;
507 int ret = spi_read_register(flash, STATUS1, &status);
508 if (ret)
509 return ret;
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000510 spi_prettyprint_status_register_hex(status);
511
512 spi_prettyprint_status_register_srwd(status);
513 spi_prettyprint_status_register_bit(status, 6);
514 spi_prettyprint_status_register_bp(status, 3);
515 spi_prettyprint_status_register_welwip(status);
516 return 0;
517}
518
Stefan Tauner12f3d512014-05-27 21:27:27 +0000519int spi_prettyprint_status_register_bp4_srwd(struct flashctx *flash)
Stefan Tauner278ba6e2013-06-28 21:28:27 +0000520{
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100521 uint8_t status;
522 int ret = spi_read_register(flash, STATUS1, &status);
523 if (ret)
524 return ret;
Stefan Tauner278ba6e2013-06-28 21:28:27 +0000525 spi_prettyprint_status_register_hex(status);
526
527 spi_prettyprint_status_register_srwd(status);
528 spi_prettyprint_status_register_bp(status, 4);
529 spi_prettyprint_status_register_welwip(status);
530 return 0;
531}
532
Stefan Tauner85f09f72014-05-27 21:27:14 +0000533int spi_prettyprint_status_register_bp2_bpl(struct flashctx *flash)
534{
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100535 uint8_t status;
536 int ret = spi_read_register(flash, STATUS1, &status);
537 if (ret)
538 return ret;
Stefan Tauner85f09f72014-05-27 21:27:14 +0000539 spi_prettyprint_status_register_hex(status);
540
541 spi_prettyprint_status_register_bpl(status);
542 spi_prettyprint_status_register_bit(status, 6);
543 spi_prettyprint_status_register_bit(status, 5);
544 spi_prettyprint_status_register_bp(status, 2);
545 spi_prettyprint_status_register_welwip(status);
546 return 0;
547}
548
Ben Gardnerbcf61092015-11-22 02:23:31 +0000549int spi_prettyprint_status_register_bp2_tb_bpl(struct flashctx *flash)
550{
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100551 uint8_t status;
552 int ret = spi_read_register(flash, STATUS1, &status);
553 if (ret)
554 return ret;
Ben Gardnerbcf61092015-11-22 02:23:31 +0000555 spi_prettyprint_status_register_hex(status);
556
557 spi_prettyprint_status_register_bpl(status);
558 spi_prettyprint_status_register_bit(status, 6);
559 msg_cdbg("Chip status register: Top/Bottom (TB) is %s\n", (status & (1 << 5)) ? "bottom" : "top");
560 spi_prettyprint_status_register_bp(status, 2);
561 spi_prettyprint_status_register_welwip(status);
562 return 0;
563}
564
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000565/* === Amic ===
566 * FIXME: spi_disable_blockprotect is incorrect but works fine for chips using
Stefan Tauner12f3d512014-05-27 21:27:27 +0000567 * spi_prettyprint_status_register_bp1_srwd or
568 * spi_prettyprint_status_register_bp2_srwd.
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000569 * FIXME: spi_disable_blockprotect is incorrect and will fail for chips using
570 * spi_prettyprint_status_register_amic_a25l032 if those have locks controlled
571 * by the second status register.
572 */
573
574int spi_prettyprint_status_register_amic_a25l032(struct flashctx *flash)
575{
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100576 uint8_t status;
577 int ret = spi_read_register(flash, STATUS1, &status);
578 if (ret)
579 return ret;
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000580 spi_prettyprint_status_register_hex(status);
581
582 spi_prettyprint_status_register_srwd(status);
583 msg_cdbg("Chip status register: Sector Protect Size (SEC) is %i KB\n", (status & (1 << 6)) ? 4 : 64);
584 msg_cdbg("Chip status register: Top/Bottom (TB) is %s\n", (status & (1 << 5)) ? "bottom" : "top");
585 spi_prettyprint_status_register_bp(status, 2);
586 spi_prettyprint_status_register_welwip(status);
587 msg_cdbg("Chip status register 2 is NOT decoded!\n");
588 return 0;
589}
590
591/* === Atmel === */
592
593static void spi_prettyprint_status_register_atmel_at25_wpen(uint8_t status)
594{
595 msg_cdbg("Chip status register: Write Protect Enable (WPEN) is %sset\n",
596 (status & (1 << 7)) ? "" : "not ");
597}
598
599static void spi_prettyprint_status_register_atmel_at25_srpl(uint8_t status)
600{
601 msg_cdbg("Chip status register: Sector Protection Register Lock (SRPL) is %sset\n",
602 (status & (1 << 7)) ? "" : "not ");
603}
604
605static void spi_prettyprint_status_register_atmel_at25_epewpp(uint8_t status)
606{
607 msg_cdbg("Chip status register: Erase/Program Error (EPE) is %sset\n",
608 (status & (1 << 5)) ? "" : "not ");
609 msg_cdbg("Chip status register: WP# pin (WPP) is %sasserted\n",
610 (status & (1 << 4)) ? "not " : "");
611}
612
613static void spi_prettyprint_status_register_atmel_at25_swp(uint8_t status)
614{
615 msg_cdbg("Chip status register: Software Protection Status (SWP): ");
616 switch (status & (3 << 2)) {
617 case 0x0 << 2:
618 msg_cdbg("no sectors are protected\n");
619 break;
620 case 0x1 << 2:
621 msg_cdbg("some sectors are protected\n");
622 /* FIXME: Read individual Sector Protection Registers. */
623 break;
624 case 0x3 << 2:
625 msg_cdbg("all sectors are protected\n");
626 break;
627 default:
628 msg_cdbg("reserved for future use\n");
629 break;
630 }
631}
632
633int spi_prettyprint_status_register_at25df(struct flashctx *flash)
634{
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100635 uint8_t status;
636 int ret = spi_read_register(flash, STATUS1, &status);
637 if (ret)
638 return ret;
639
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000640 spi_prettyprint_status_register_hex(status);
641
642 spi_prettyprint_status_register_atmel_at25_srpl(status);
643 spi_prettyprint_status_register_bit(status, 6);
644 spi_prettyprint_status_register_atmel_at25_epewpp(status);
645 spi_prettyprint_status_register_atmel_at25_swp(status);
646 spi_prettyprint_status_register_welwip(status);
647 return 0;
648}
649
650int spi_prettyprint_status_register_at25df_sec(struct flashctx *flash)
651{
652 /* FIXME: We should check the security lockdown. */
653 msg_cdbg("Ignoring security lockdown (if present)\n");
654 msg_cdbg("Ignoring status register byte 2\n");
655 return spi_prettyprint_status_register_at25df(flash);
656}
657
Stefan Tauner57794ac2012-12-29 15:04:20 +0000658/* used for AT25F512, AT25F1024(A), AT25F2048 */
659int spi_prettyprint_status_register_at25f(struct flashctx *flash)
660{
661 uint8_t status;
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100662 int ret = spi_read_register(flash, STATUS1, &status);
663 if (ret)
664 return ret;
Stefan Tauner57794ac2012-12-29 15:04:20 +0000665
Stefan Tauner57794ac2012-12-29 15:04:20 +0000666 spi_prettyprint_status_register_hex(status);
667
668 spi_prettyprint_status_register_atmel_at25_wpen(status);
669 spi_prettyprint_status_register_bit(status, 6);
670 spi_prettyprint_status_register_bit(status, 5);
671 spi_prettyprint_status_register_bit(status, 4);
672 spi_prettyprint_status_register_bp(status, 1);
673 spi_prettyprint_status_register_welwip(status);
674 return 0;
675}
676
677int spi_prettyprint_status_register_at25f512a(struct flashctx *flash)
678{
679 uint8_t status;
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100680 int ret = spi_read_register(flash, STATUS1, &status);
681 if (ret)
682 return ret;
Stefan Tauner57794ac2012-12-29 15:04:20 +0000683
Stefan Tauner57794ac2012-12-29 15:04:20 +0000684 spi_prettyprint_status_register_hex(status);
685
686 spi_prettyprint_status_register_atmel_at25_wpen(status);
687 spi_prettyprint_status_register_bit(status, 6);
688 spi_prettyprint_status_register_bit(status, 5);
689 spi_prettyprint_status_register_bit(status, 4);
690 spi_prettyprint_status_register_bit(status, 3);
691 spi_prettyprint_status_register_bp(status, 0);
692 spi_prettyprint_status_register_welwip(status);
693 return 0;
694}
695
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000696int spi_prettyprint_status_register_at25f512b(struct flashctx *flash)
697{
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100698 uint8_t status;
699 int ret = spi_read_register(flash, STATUS1, &status);
700 if (ret)
701 return ret;
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000702 spi_prettyprint_status_register_hex(status);
703
704 spi_prettyprint_status_register_atmel_at25_srpl(status);
705 spi_prettyprint_status_register_bit(status, 6);
706 spi_prettyprint_status_register_atmel_at25_epewpp(status);
707 spi_prettyprint_status_register_bit(status, 3);
708 spi_prettyprint_status_register_bp(status, 0);
709 spi_prettyprint_status_register_welwip(status);
710 return 0;
711}
712
Stefan Tauner57794ac2012-12-29 15:04:20 +0000713int spi_prettyprint_status_register_at25f4096(struct flashctx *flash)
714{
715 uint8_t status;
716
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100717 int ret = spi_read_register(flash, STATUS1, &status);
718 if (ret)
719 return ret;
720
Stefan Tauner57794ac2012-12-29 15:04:20 +0000721 spi_prettyprint_status_register_hex(status);
722
723 spi_prettyprint_status_register_atmel_at25_wpen(status);
724 spi_prettyprint_status_register_bit(status, 6);
725 spi_prettyprint_status_register_bit(status, 5);
726 spi_prettyprint_status_register_bp(status, 2);
727 spi_prettyprint_status_register_welwip(status);
728 return 0;
729}
730
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000731int spi_prettyprint_status_register_at25fs010(struct flashctx *flash)
732{
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100733 uint8_t status;
734 int ret = spi_read_register(flash, STATUS1, &status);
735 if (ret)
736 return ret;
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000737 spi_prettyprint_status_register_hex(status);
738
739 spi_prettyprint_status_register_atmel_at25_wpen(status);
740 msg_cdbg("Chip status register: Bit 6 / Block Protect 4 (BP4) is "
741 "%sset\n", (status & (1 << 6)) ? "" : "not ");
742 msg_cdbg("Chip status register: Bit 5 / Block Protect 3 (BP3) is "
743 "%sset\n", (status & (1 << 5)) ? "" : "not ");
744 spi_prettyprint_status_register_bit(status, 4);
745 msg_cdbg("Chip status register: Bit 3 / Block Protect 1 (BP1) is "
746 "%sset\n", (status & (1 << 3)) ? "" : "not ");
747 msg_cdbg("Chip status register: Bit 2 / Block Protect 0 (BP0) is "
748 "%sset\n", (status & (1 << 2)) ? "" : "not ");
749 /* FIXME: Pretty-print detailed sector protection status. */
750 spi_prettyprint_status_register_welwip(status);
751 return 0;
752}
753
754int spi_prettyprint_status_register_at25fs040(struct flashctx *flash)
755{
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100756 uint8_t status;
757 int ret = spi_read_register(flash, STATUS1, &status);
758 if (ret)
759 return ret;
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000760 spi_prettyprint_status_register_hex(status);
761
762 spi_prettyprint_status_register_atmel_at25_wpen(status);
763 spi_prettyprint_status_register_bp(status, 4);
764 /* FIXME: Pretty-print detailed sector protection status. */
765 spi_prettyprint_status_register_welwip(status);
766 return 0;
767}
768
769int spi_prettyprint_status_register_at26df081a(struct flashctx *flash)
770{
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100771 uint8_t status;
772 int ret = spi_read_register(flash, STATUS1, &status);
773 if (ret)
774 return ret;
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000775 spi_prettyprint_status_register_hex(status);
776
777 spi_prettyprint_status_register_atmel_at25_srpl(status);
778 msg_cdbg("Chip status register: Sequential Program Mode Status (SPM) is %sset\n",
779 (status & (1 << 6)) ? "" : "not ");
780 spi_prettyprint_status_register_atmel_at25_epewpp(status);
781 spi_prettyprint_status_register_atmel_at25_swp(status);
782 spi_prettyprint_status_register_welwip(status);
783 return 0;
784}
785
Stefan Taunercecb2c52013-06-20 22:55:41 +0000786/* Some Atmel DataFlash chips support per sector protection bits and the write protection bits in the status
787 * register do indicate if none, some or all sectors are protected. It is possible to globally (un)lock all
788 * sectors at once by writing 0 not only the protection bits (2 and 3) but also completely unrelated bits (4 and
789 * 5) which normally are not touched.
790 * Affected are all known Atmel chips matched by AT2[56]D[FLQ]..1A? but the AT26DF041. */
791int spi_disable_blockprotect_at2x_global_unprotect(struct flashctx *flash)
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000792{
Stefan Taunercecb2c52013-06-20 22:55:41 +0000793 return spi_disable_blockprotect_generic(flash, 0x0C, 1 << 7, 1 << 4, 0x00);
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000794}
795
Stefan Taunercecb2c52013-06-20 22:55:41 +0000796int spi_disable_blockprotect_at2x_global_unprotect_sec(struct flashctx *flash)
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000797{
798 /* FIXME: We should check the security lockdown. */
799 msg_cinfo("Ignoring security lockdown (if present)\n");
Stefan Taunercecb2c52013-06-20 22:55:41 +0000800 return spi_disable_blockprotect_at2x_global_unprotect(flash);
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000801}
802
Stefan Tauner57794ac2012-12-29 15:04:20 +0000803int spi_disable_blockprotect_at25f(struct flashctx *flash)
804{
Stefan Taunercecb2c52013-06-20 22:55:41 +0000805 return spi_disable_blockprotect_generic(flash, 0x0C, 1 << 7, 0, 0xFF);
Stefan Tauner57794ac2012-12-29 15:04:20 +0000806}
807
808int spi_disable_blockprotect_at25f512a(struct flashctx *flash)
809{
Stefan Taunercecb2c52013-06-20 22:55:41 +0000810 return spi_disable_blockprotect_generic(flash, 0x04, 1 << 7, 0, 0xFF);
Stefan Tauner57794ac2012-12-29 15:04:20 +0000811}
812
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000813int spi_disable_blockprotect_at25f512b(struct flashctx *flash)
814{
Stefan Taunercecb2c52013-06-20 22:55:41 +0000815 return spi_disable_blockprotect_generic(flash, 0x04, 1 << 7, 1 << 4, 0xFF);
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000816}
817
818int spi_disable_blockprotect_at25fs010(struct flashctx *flash)
819{
Stefan Taunercecb2c52013-06-20 22:55:41 +0000820 return spi_disable_blockprotect_generic(flash, 0x6C, 1 << 7, 0, 0xFF);
Stefan Tauner9530a022012-12-29 15:04:05 +0000821 }
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000822
823int spi_disable_blockprotect_at25fs040(struct flashctx *flash)
824{
Stefan Taunercecb2c52013-06-20 22:55:41 +0000825 return spi_disable_blockprotect_generic(flash, 0x7C, 1 << 7, 0, 0xFF);
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000826}
827
Nikolay Nikolaevd0e3ea12013-06-28 21:29:08 +0000828/* === Eon === */
829
830int spi_prettyprint_status_register_en25s_wp(struct flashctx *flash)
831{
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100832 uint8_t status;
833 int ret = spi_read_register(flash, STATUS1, &status);
834 if (ret)
835 return ret;
Nikolay Nikolaevd0e3ea12013-06-28 21:29:08 +0000836 spi_prettyprint_status_register_hex(status);
837
838 spi_prettyprint_status_register_srwd(status);
839 msg_cdbg("Chip status register: WP# disable (WPDIS) is %sabled\n", (status & (1 << 6)) ? "en " : "dis");
840 spi_prettyprint_status_register_bp(status, 3);
841 spi_prettyprint_status_register_welwip(status);
842 return 0;
843}
844
Nikolay Nikolaevc80c4a32013-06-28 21:29:44 +0000845/* === Intel/Numonyx/Micron - Spansion === */
Stefan Tauner54aaa4a2012-12-29 15:04:12 +0000846
Nikolay Nikolaev6f59b0b2013-06-28 21:29:51 +0000847int spi_disable_blockprotect_n25q(struct flashctx *flash)
848{
849 return spi_disable_blockprotect_generic(flash, 0x5C, 1 << 7, 0, 0xFF);
850}
851
852int spi_prettyprint_status_register_n25q(struct flashctx *flash)
853{
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100854 uint8_t status;
855 int ret = spi_read_register(flash, STATUS1, &status);
856 if (ret)
857 return ret;
Nikolay Nikolaev6f59b0b2013-06-28 21:29:51 +0000858 spi_prettyprint_status_register_hex(status);
859
860 spi_prettyprint_status_register_srwd(status);
861 if (flash->chip->total_size <= 32 / 8 * 1024) /* N25Q16 and N25Q32: reserved */
862 spi_prettyprint_status_register_bit(status, 6);
863 else
864 msg_cdbg("Chip status register: Block Protect 3 (BP3) is %sset\n",
865 (status & (1 << 6)) ? "" : "not ");
866 msg_cdbg("Chip status register: Top/Bottom (TB) is %s\n", (status & (1 << 5)) ? "bottom" : "top");
867 spi_prettyprint_status_register_bp(status, 2);
868 spi_prettyprint_status_register_welwip(status);
869 return 0;
870}
871
Nikolay Nikolaevc80c4a32013-06-28 21:29:44 +0000872/* Used by Intel/Numonyx S33 and Spansion S25FL-S chips */
Stefan Tauner54aaa4a2012-12-29 15:04:12 +0000873/* TODO: Clear P_FAIL and E_FAIL with Clear SR Fail Flags Command (30h) here? */
Nikolay Nikolaevc80c4a32013-06-28 21:29:44 +0000874int spi_disable_blockprotect_bp2_ep_srwd(struct flashctx *flash)
Stefan Tauner54aaa4a2012-12-29 15:04:12 +0000875{
Stefan Tauner278ba6e2013-06-28 21:28:27 +0000876 return spi_disable_blockprotect_bp2_srwd(flash);
Stefan Tauner54aaa4a2012-12-29 15:04:12 +0000877}
878
Nikolay Nikolaevc80c4a32013-06-28 21:29:44 +0000879/* Used by Intel/Numonyx S33 and Spansion S25FL-S chips */
880int spi_prettyprint_status_register_bp2_ep_srwd(struct flashctx *flash)
Stefan Tauner54aaa4a2012-12-29 15:04:12 +0000881{
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100882 uint8_t status;
883 int ret = spi_read_register(flash, STATUS1, &status);
884 if (ret)
885 return ret;
Stefan Taunerc2eec2c2014-05-03 21:33:01 +0000886 spi_prettyprint_status_register_hex(status);
Stefan Tauner54aaa4a2012-12-29 15:04:12 +0000887
888 spi_prettyprint_status_register_srwd(status);
889 msg_cdbg("Chip status register: Program Fail Flag (P_FAIL) is %sset\n",
890 (status & (1 << 6)) ? "" : "not ");
891 msg_cdbg("Chip status register: Erase Fail Flag (E_FAIL) is %sset\n",
892 (status & (1 << 5)) ? "" : "not ");
893 spi_prettyprint_status_register_bp(status, 2);
894 spi_prettyprint_status_register_welwip(status);
895 return 0;
896}
897
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000898/* === SST === */
899
900static void spi_prettyprint_status_register_sst25_common(uint8_t status)
901{
902 spi_prettyprint_status_register_hex(status);
903
904 spi_prettyprint_status_register_bpl(status);
905 msg_cdbg("Chip status register: Auto Address Increment Programming (AAI) is %sset\n",
906 (status & (1 << 6)) ? "" : "not ");
907 spi_prettyprint_status_register_bp(status, 3);
908 spi_prettyprint_status_register_welwip(status);
909}
910
911int spi_prettyprint_status_register_sst25(struct flashctx *flash)
912{
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100913 uint8_t status;
914 int ret = spi_read_register(flash, STATUS1, &status);
915 if (ret)
916 return ret;
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000917 spi_prettyprint_status_register_sst25_common(status);
918 return 0;
919}
920
921int spi_prettyprint_status_register_sst25vf016(struct flashctx *flash)
922{
923 static const char *const bpt[] = {
924 "none",
925 "1F0000H-1FFFFFH",
926 "1E0000H-1FFFFFH",
927 "1C0000H-1FFFFFH",
928 "180000H-1FFFFFH",
929 "100000H-1FFFFFH",
930 "all", "all"
931 };
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100932 uint8_t status;
933 int ret = spi_read_register(flash, STATUS1, &status);
934 if (ret)
935 return ret;
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000936 spi_prettyprint_status_register_sst25_common(status);
937 msg_cdbg("Resulting block protection : %s\n", bpt[(status & 0x1c) >> 2]);
938 return 0;
939}
940
941int spi_prettyprint_status_register_sst25vf040b(struct flashctx *flash)
942{
943 static const char *const bpt[] = {
944 "none",
945 "0x70000-0x7ffff",
946 "0x60000-0x7ffff",
947 "0x40000-0x7ffff",
948 "all blocks", "all blocks", "all blocks", "all blocks"
949 };
Nikolai Artemievb8a90d02021-10-28 16:18:28 +1100950 uint8_t status;
951 int ret = spi_read_register(flash, STATUS1, &status);
952 if (ret)
953 return ret;
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000954 spi_prettyprint_status_register_sst25_common(status);
955 msg_cdbg("Resulting block protection : %s\n", bpt[(status & 0x1c) >> 2]);
956 return 0;
957}