1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2007 by Dominic Rath <Dominic.Rath@gmx.de> *
5 * Copyright (C) 2002 Thomas Gleixner <tglx@linutronix.de> *
6 * Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net> *
8 * Partially based on drivers/mtd/nand_ids.c from Linux. *
9 ***************************************************************************/
18 #include <target/target.h>
21 extern struct nand_device
*nand_devices
;
23 COMMAND_HANDLER(handle_nand_list_command
)
25 struct nand_device
*p
;
29 command_print(CMD
, "no NAND flash devices configured");
33 for (p
= nand_devices
, i
= 0; p
; p
= p
->next
, i
++) {
35 command_print(CMD
, "#%i: %s (%s) "
36 "pagesize: %i, buswidth: %i,\n\t"
37 "blocksize: %i, blocks: %i",
38 i
, p
->device
->name
, p
->manufacturer
->name
,
39 p
->page_size
, p
->bus_width
,
40 p
->erase_size
, p
->num_blocks
);
42 command_print(CMD
, "#%i: not probed", i
);
48 COMMAND_HANDLER(handle_nand_info_command
)
57 return ERROR_COMMAND_SYNTAX_ERROR
;
63 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], i
);
68 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], first
);
69 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[2], last
);
73 struct nand_device
*p
;
74 int retval
= CALL_COMMAND_HANDLER(nand_command_get_device
, 0, &p
);
75 if (retval
!= ERROR_OK
)
79 command_print(CMD
, "#%s: not probed", CMD_ARGV
[0]);
83 if (first
>= p
->num_blocks
)
84 first
= p
->num_blocks
- 1;
86 if (last
>= p
->num_blocks
)
87 last
= p
->num_blocks
- 1;
90 "#%i: %s (%s) pagesize: %i, buswidth: %i, erasesize: %i",
93 p
->manufacturer
->name
,
98 for (j
= first
; j
<= last
; j
++) {
99 char *erase_state
, *bad_state
;
101 if (p
->blocks
[j
].is_erased
== 0)
102 erase_state
= "not erased";
103 else if (p
->blocks
[j
].is_erased
== 1)
104 erase_state
= "erased";
106 erase_state
= "erase state unknown";
108 if (p
->blocks
[j
].is_bad
== 0)
110 else if (p
->blocks
[j
].is_bad
== 1)
111 bad_state
= " (marked bad)";
113 bad_state
= " (block condition unknown)";
116 "\t#%i: 0x%8.8" PRIx32
" (%" PRIu32
"kB) %s%s",
119 p
->blocks
[j
].size
/ 1024,
127 COMMAND_HANDLER(handle_nand_probe_command
)
130 return ERROR_COMMAND_SYNTAX_ERROR
;
132 struct nand_device
*p
;
133 int retval
= CALL_COMMAND_HANDLER(nand_command_get_device
, 0, &p
);
134 if (retval
!= ERROR_OK
)
137 retval
= nand_probe(p
);
138 if (retval
== ERROR_OK
) {
139 command_print(CMD
, "NAND flash device '%s (%s)' found",
140 p
->device
->name
, p
->manufacturer
->name
);
146 COMMAND_HANDLER(handle_nand_erase_command
)
148 if (CMD_ARGC
!= 1 && CMD_ARGC
!= 3)
149 return ERROR_COMMAND_SYNTAX_ERROR
;
151 struct nand_device
*p
;
152 int retval
= CALL_COMMAND_HANDLER(nand_command_get_device
, 0, &p
);
153 if (retval
!= ERROR_OK
)
156 unsigned long offset
;
157 unsigned long length
;
159 /* erase specified part of the chip; or else everything */
161 unsigned long size
= p
->erase_size
* p
->num_blocks
;
163 COMMAND_PARSE_NUMBER(ulong
, CMD_ARGV
[1], offset
);
164 if ((offset
% p
->erase_size
) != 0 || offset
>= size
)
165 return ERROR_COMMAND_SYNTAX_ERROR
;
167 COMMAND_PARSE_NUMBER(ulong
, CMD_ARGV
[2], length
);
168 if ((length
== 0) || (length
% p
->erase_size
) != 0
169 || (length
+ offset
) > size
)
170 return ERROR_COMMAND_SYNTAX_ERROR
;
172 offset
/= p
->erase_size
;
173 length
/= p
->erase_size
;
176 length
= p
->num_blocks
;
179 retval
= nand_erase(p
, offset
, offset
+ length
- 1);
180 if (retval
== ERROR_OK
) {
181 command_print(CMD
, "erased blocks %lu to %lu "
182 "on NAND flash device #%s '%s'",
183 offset
, offset
+ length
- 1,
184 CMD_ARGV
[0], p
->device
->name
);
190 COMMAND_HANDLER(handle_nand_check_bad_blocks_command
)
195 if ((CMD_ARGC
< 1) || (CMD_ARGC
> 3) || (CMD_ARGC
== 2))
196 return ERROR_COMMAND_SYNTAX_ERROR
;
198 struct nand_device
*p
;
199 int retval
= CALL_COMMAND_HANDLER(nand_command_get_device
, 0, &p
);
200 if (retval
!= ERROR_OK
)
204 unsigned long offset
;
205 unsigned long length
;
207 COMMAND_PARSE_NUMBER(ulong
, CMD_ARGV
[1], offset
);
208 if (offset
% p
->erase_size
)
209 return ERROR_COMMAND_SYNTAX_ERROR
;
210 offset
/= p
->erase_size
;
212 COMMAND_PARSE_NUMBER(ulong
, CMD_ARGV
[2], length
);
213 if (length
% p
->erase_size
)
214 return ERROR_COMMAND_SYNTAX_ERROR
;
217 length
/= p
->erase_size
;
220 last
= offset
+ length
;
223 retval
= nand_build_bbt(p
, first
, last
);
224 if (retval
== ERROR_OK
) {
225 command_print(CMD
, "checked NAND flash device for bad blocks, "
226 "use \"nand info\" command to list blocks");
232 COMMAND_HANDLER(handle_nand_write_command
)
234 struct nand_device
*nand
= NULL
;
235 struct nand_fileio_state s
;
236 int retval
= CALL_COMMAND_HANDLER(nand_fileio_parse_args
,
237 &s
, &nand
, FILEIO_READ
, false, true);
238 if (retval
!= ERROR_OK
)
241 uint32_t total_bytes
= s
.size
;
243 int bytes_read
= nand_fileio_read(nand
, &s
);
244 if (bytes_read
<= 0) {
245 command_print(CMD
, "error while reading file");
246 nand_fileio_cleanup(&s
);
249 s
.size
-= bytes_read
;
251 retval
= nand_write_page(nand
, s
.address
/ nand
->page_size
,
252 s
.page
, s
.page_size
, s
.oob
, s
.oob_size
);
253 if (retval
!= ERROR_OK
) {
254 command_print(CMD
, "failed writing file %s "
255 "to NAND flash %s at offset 0x%8.8" PRIx32
,
256 CMD_ARGV
[1], CMD_ARGV
[0], s
.address
);
257 nand_fileio_cleanup(&s
);
260 s
.address
+= s
.page_size
;
263 if (nand_fileio_finish(&s
) == ERROR_OK
) {
264 command_print(CMD
, "wrote file %s to NAND flash %s up to "
265 "offset 0x%8.8" PRIx32
" in %fs (%0.3f KiB/s)",
266 CMD_ARGV
[1], CMD_ARGV
[0], s
.address
, duration_elapsed(&s
.bench
),
267 duration_kbps(&s
.bench
, total_bytes
));
272 COMMAND_HANDLER(handle_nand_verify_command
)
274 struct nand_device
*nand
= NULL
;
275 struct nand_fileio_state file
;
276 int retval
= CALL_COMMAND_HANDLER(nand_fileio_parse_args
,
277 &file
, &nand
, FILEIO_READ
, false, true);
278 if (retval
!= ERROR_OK
)
281 struct nand_fileio_state dev
;
282 nand_fileio_init(&dev
);
283 dev
.address
= file
.address
;
284 dev
.size
= file
.size
;
285 dev
.oob_format
= file
.oob_format
;
286 retval
= nand_fileio_start(CMD
, nand
, NULL
, FILEIO_NONE
, &dev
);
287 if (retval
!= ERROR_OK
)
290 while (file
.size
> 0) {
291 retval
= nand_read_page(nand
, dev
.address
/ dev
.page_size
,
292 dev
.page
, dev
.page_size
, dev
.oob
, dev
.oob_size
);
293 if (retval
!= ERROR_OK
) {
294 command_print(CMD
, "reading NAND flash page failed");
295 nand_fileio_cleanup(&dev
);
296 nand_fileio_cleanup(&file
);
300 int bytes_read
= nand_fileio_read(nand
, &file
);
301 if (bytes_read
<= 0) {
302 command_print(CMD
, "error while reading file");
303 nand_fileio_cleanup(&dev
);
304 nand_fileio_cleanup(&file
);
308 if ((dev
.page
&& memcmp(dev
.page
, file
.page
, dev
.page_size
)) ||
309 (dev
.oob
&& memcmp(dev
.oob
, file
.oob
, dev
.oob_size
))) {
310 command_print(CMD
, "NAND flash contents differ "
311 "at 0x%8.8" PRIx32
, dev
.address
);
312 nand_fileio_cleanup(&dev
);
313 nand_fileio_cleanup(&file
);
317 file
.size
-= bytes_read
;
318 dev
.address
+= nand
->page_size
;
321 if (nand_fileio_finish(&file
) == ERROR_OK
) {
322 command_print(CMD
, "verified file %s in NAND flash %s "
323 "up to offset 0x%8.8" PRIx32
" in %fs (%0.3f KiB/s)",
324 CMD_ARGV
[1], CMD_ARGV
[0], dev
.address
, duration_elapsed(&file
.bench
),
325 duration_kbps(&file
.bench
, dev
.size
));
328 return nand_fileio_cleanup(&dev
);
331 COMMAND_HANDLER(handle_nand_dump_command
)
334 struct nand_device
*nand
= NULL
;
335 struct nand_fileio_state s
;
336 int retval
= CALL_COMMAND_HANDLER(nand_fileio_parse_args
,
337 &s
, &nand
, FILEIO_WRITE
, true, false);
338 if (retval
!= ERROR_OK
)
343 retval
= nand_read_page(nand
, s
.address
/ nand
->page_size
,
344 s
.page
, s
.page_size
, s
.oob
, s
.oob_size
);
345 if (retval
!= ERROR_OK
) {
346 command_print(CMD
, "reading NAND flash page failed");
347 nand_fileio_cleanup(&s
);
352 fileio_write(s
.fileio
, s
.page_size
, s
.page
, &size_written
);
355 fileio_write(s
.fileio
, s
.oob_size
, s
.oob
, &size_written
);
357 s
.size
-= nand
->page_size
;
358 s
.address
+= nand
->page_size
;
361 retval
= fileio_size(s
.fileio
, &filesize
);
362 if (retval
!= ERROR_OK
)
365 if (nand_fileio_finish(&s
) == ERROR_OK
) {
366 command_print(CMD
, "dumped %zu bytes in %fs (%0.3f KiB/s)",
367 filesize
, duration_elapsed(&s
.bench
),
368 duration_kbps(&s
.bench
, filesize
));
373 COMMAND_HANDLER(handle_nand_raw_access_command
)
375 if ((CMD_ARGC
< 1) || (CMD_ARGC
> 2))
376 return ERROR_COMMAND_SYNTAX_ERROR
;
378 struct nand_device
*p
;
379 int retval
= CALL_COMMAND_HANDLER(nand_command_get_device
, 0, &p
);
380 if (retval
!= ERROR_OK
)
384 command_print(CMD
, "#%s: not probed", CMD_ARGV
[0]);
389 COMMAND_PARSE_ENABLE(CMD_ARGV
[1], p
->use_raw
);
391 const char *msg
= p
->use_raw
? "enabled" : "disabled";
392 command_print(CMD
, "raw access is %s", msg
);
397 static const struct command_registration nand_exec_command_handlers
[] = {
400 .handler
= handle_nand_list_command
,
401 .mode
= COMMAND_EXEC
,
402 .help
= "list configured NAND flash devices",
407 .handler
= handle_nand_info_command
,
408 .mode
= COMMAND_EXEC
,
409 .usage
= "[banknum | first_bank_num last_bank_num]",
410 .help
= "print info about one or more NAND flash devices",
414 .handler
= handle_nand_probe_command
,
415 .mode
= COMMAND_EXEC
,
417 .help
= "identify NAND flash device",
420 .name
= "check_bad_blocks",
421 .handler
= handle_nand_check_bad_blocks_command
,
422 .mode
= COMMAND_EXEC
,
423 .usage
= "bank_id [offset length]",
424 .help
= "check all or part of NAND flash device for bad blocks",
428 .handler
= handle_nand_erase_command
,
429 .mode
= COMMAND_EXEC
,
430 .usage
= "bank_id [offset length]",
431 .help
= "erase all or subset of blocks on NAND flash device",
435 .handler
= handle_nand_dump_command
,
436 .mode
= COMMAND_EXEC
,
437 .usage
= "bank_id filename offset length "
438 "['oob_raw'|'oob_only']",
439 .help
= "dump from NAND flash device",
443 .handler
= handle_nand_verify_command
,
444 .mode
= COMMAND_EXEC
,
445 .usage
= "bank_id filename offset "
446 "['oob_raw'|'oob_only'|'oob_softecc'|'oob_softecc_kw']",
447 .help
= "verify NAND flash device",
451 .handler
= handle_nand_write_command
,
452 .mode
= COMMAND_EXEC
,
453 .usage
= "bank_id filename offset "
454 "['oob_raw'|'oob_only'|'oob_softecc'|'oob_softecc_kw']",
455 .help
= "write to NAND flash device",
458 .name
= "raw_access",
459 .handler
= handle_nand_raw_access_command
,
460 .mode
= COMMAND_EXEC
,
461 .usage
= "bank_id ['enable'|'disable']",
462 .help
= "raw access to NAND flash device",
464 COMMAND_REGISTRATION_DONE
467 static int nand_init(struct command_context
*cmd_ctx
)
472 return register_commands(cmd_ctx
, "nand", nand_exec_command_handlers
);
475 COMMAND_HANDLER(handle_nand_init_command
)
478 return ERROR_COMMAND_SYNTAX_ERROR
;
480 static bool nand_initialized
;
481 if (nand_initialized
) {
482 LOG_INFO("'nand init' has already been called");
485 nand_initialized
= true;
487 LOG_DEBUG("Initializing NAND devices...");
488 return nand_init(CMD_CTX
);
491 static int nand_list_walker(struct nand_flash_controller
*c
, void *x
)
493 struct command_invocation
*cmd
= x
;
494 command_print(cmd
, " %s", c
->name
);
498 COMMAND_HANDLER(handle_nand_list_drivers
)
500 command_print(CMD
, "Available NAND flash controller drivers:");
501 return nand_driver_walk(&nand_list_walker
, CMD
);
504 static COMMAND_HELPER(create_nand_device
, const char *bank_name
,
505 struct nand_flash_controller
*controller
)
507 struct nand_device
*c
;
508 struct target
*target
;
512 return ERROR_COMMAND_SYNTAX_ERROR
;
513 target
= get_target(CMD_ARGV
[1]);
515 LOG_ERROR("invalid target %s", CMD_ARGV
[1]);
516 return ERROR_COMMAND_ARGUMENT_INVALID
;
519 if (controller
->commands
) {
520 retval
= register_commands(CMD_CTX
, NULL
, controller
->commands
);
521 if (retval
!= ERROR_OK
)
524 c
= malloc(sizeof(struct nand_device
));
526 LOG_ERROR("End of memory");
530 c
->name
= strdup(bank_name
);
532 c
->controller
= controller
;
533 c
->controller_priv
= NULL
;
534 c
->manufacturer
= NULL
;
537 c
->address_cycles
= 0;
542 retval
= CALL_COMMAND_HANDLER(controller
->nand_device_command
, c
);
543 if (retval
!= ERROR_OK
) {
544 LOG_ERROR("'%s' driver rejected nand flash. Usage: %s",
551 if (!controller
->usage
)
552 LOG_DEBUG("'%s' driver usage field missing", controller
->name
);
559 COMMAND_HANDLER(handle_nand_device_command
)
562 return ERROR_COMMAND_SYNTAX_ERROR
;
564 /* save name and increment (for compatibility) with drivers */
565 const char *bank_name
= *CMD_ARGV
++;
568 const char *driver_name
= CMD_ARGV
[0];
569 struct nand_flash_controller
*controller
;
570 controller
= nand_driver_find_by_name(CMD_ARGV
[0]);
572 LOG_ERROR("No valid NAND flash driver found (%s)", driver_name
);
573 return CALL_COMMAND_HANDLER(handle_nand_list_drivers
);
575 return CALL_COMMAND_HANDLER(create_nand_device
, bank_name
, controller
);
578 static const struct command_registration nand_config_command_handlers
[] = {
581 .handler
= &handle_nand_device_command
,
582 .mode
= COMMAND_CONFIG
,
583 .help
= "defines a new NAND bank",
584 .usage
= "bank_id driver target [driver_options ...]",
588 .handler
= &handle_nand_list_drivers
,
590 .help
= "lists available NAND drivers",
595 .mode
= COMMAND_CONFIG
,
596 .handler
= &handle_nand_init_command
,
597 .help
= "initialize NAND devices",
600 COMMAND_REGISTRATION_DONE
603 static const struct command_registration nand_command_handlers
[] = {
607 .help
= "NAND flash command group",
609 .chain
= nand_config_command_handlers
,
611 COMMAND_REGISTRATION_DONE
614 int nand_register_commands(struct command_context
*cmd_ctx
)
616 return register_commands(cmd_ctx
, NULL
, nand_command_handlers
);
Linking to existing account procedure
If you already have an account and want to add another login method
you
MUST first sign in with your existing account and
then change URL to read
https://review.openocd.org/login/?link
to get to this page again but this time it'll work for linking. Thank you.
SSH host keys fingerprints
1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=.. |
|+o.. . |
|*.o . . |
|+B . . . |
|Bo. = o S |
|Oo.+ + = |
|oB=.* = . o |
| =+=.+ + E |
|. .=o . o |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)