1 /***************************************************************************
2 * Copyright (C) 2007 by Dominic Rath <Dominic.Rath@gmx.de> *
3 * Copyright (C) 2002 Thomas Gleixner <tglx@linutronix.de> *
4 * Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net> *
6 * Partially based on drivers/mtd/nand_ids.c from Linux. *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the *
20 * Free Software Foundation, Inc., *
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
22 ***************************************************************************/
32 extern struct nand_device
*nand_devices
;
34 COMMAND_HANDLER(handle_nand_list_command
)
36 struct nand_device
*p
;
41 command_print(CMD_CTX
, "no NAND flash devices configured");
45 for (p
= nand_devices
, i
= 0; p
; p
= p
->next
, i
++)
48 command_print(CMD_CTX
, "#%i: %s (%s) "
49 "pagesize: %i, buswidth: %i,\n\t"
50 "blocksize: %i, blocks: %i",
51 i
, p
->device
->name
, p
->manufacturer
->name
,
52 p
->page_size
, p
->bus_width
,
53 p
->erase_size
, p
->num_blocks
);
55 command_print(CMD_CTX
, "#%i: not probed", i
);
61 COMMAND_HANDLER(handle_nand_info_command
)
70 return ERROR_COMMAND_SYNTAX_ERROR
;
76 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], i
);
81 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], first
);
82 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[2], last
);
86 struct nand_device
*p
;
87 int retval
= CALL_COMMAND_HANDLER(nand_command_get_device
, 0, &p
);
88 if (ERROR_OK
!= retval
)
91 if (NULL
== p
->device
)
93 command_print(CMD_CTX
, "#%s: not probed", CMD_ARGV
[0]);
97 if (first
>= p
->num_blocks
)
98 first
= p
->num_blocks
- 1;
100 if (last
>= p
->num_blocks
)
101 last
= p
->num_blocks
- 1;
103 command_print(CMD_CTX
, "#%i: %s (%s) pagesize: %i, buswidth: %i, erasesize: %i",
104 i
++, p
->device
->name
, p
->manufacturer
->name
, p
->page_size
, p
->bus_width
, p
->erase_size
);
106 for (j
= first
; j
<= last
; j
++)
108 char *erase_state
, *bad_state
;
110 if (p
->blocks
[j
].is_erased
== 0)
111 erase_state
= "not erased";
112 else if (p
->blocks
[j
].is_erased
== 1)
113 erase_state
= "erased";
115 erase_state
= "erase state unknown";
117 if (p
->blocks
[j
].is_bad
== 0)
119 else if (p
->blocks
[j
].is_bad
== 1)
120 bad_state
= " (marked bad)";
122 bad_state
= " (block condition unknown)";
124 command_print(CMD_CTX
,
125 "\t#%i: 0x%8.8" PRIx32
" (%" PRId32
"kB) %s%s",
128 p
->blocks
[j
].size
/ 1024,
136 COMMAND_HANDLER(handle_nand_probe_command
)
140 return ERROR_COMMAND_SYNTAX_ERROR
;
143 struct nand_device
*p
;
144 int retval
= CALL_COMMAND_HANDLER(nand_command_get_device
, 0, &p
);
145 if (ERROR_OK
!= retval
)
148 if ((retval
= nand_probe(p
)) == ERROR_OK
)
150 command_print(CMD_CTX
, "NAND flash device '%s (%s)' found",
151 p
->device
->name
, p
->manufacturer
->name
);
153 else if (retval
== ERROR_NAND_OPERATION_FAILED
)
155 command_print(CMD_CTX
, "probing failed for NAND flash device");
159 command_print(CMD_CTX
, "unknown error when probing NAND flash device");
165 COMMAND_HANDLER(handle_nand_erase_command
)
167 if (CMD_ARGC
!= 1 && CMD_ARGC
!= 3)
169 return ERROR_COMMAND_SYNTAX_ERROR
;
173 struct nand_device
*p
;
174 int retval
= CALL_COMMAND_HANDLER(nand_command_get_device
, 0, &p
);
175 if (ERROR_OK
!= retval
)
178 unsigned long offset
;
179 unsigned long length
;
181 /* erase specified part of the chip; or else everything */
183 unsigned long size
= p
->erase_size
* p
->num_blocks
;
185 COMMAND_PARSE_NUMBER(ulong
, CMD_ARGV
[1], offset
);
186 if ((offset
% p
->erase_size
) != 0 || offset
>= size
)
187 return ERROR_INVALID_ARGUMENTS
;
189 COMMAND_PARSE_NUMBER(ulong
, CMD_ARGV
[2], length
);
190 if ((length
== 0) || (length
% p
->erase_size
) != 0
191 || (length
+ offset
) > size
)
192 return ERROR_INVALID_ARGUMENTS
;
194 offset
/= p
->erase_size
;
195 length
/= p
->erase_size
;
198 length
= p
->num_blocks
;
201 retval
= nand_erase(p
, offset
, offset
+ length
- 1);
202 if (retval
== ERROR_OK
)
204 command_print(CMD_CTX
, "erased blocks %lu to %lu "
205 "on NAND flash device #%s '%s'",
206 offset
, offset
+ length
,
207 CMD_ARGV
[0], p
->device
->name
);
209 else if (retval
== ERROR_NAND_OPERATION_FAILED
)
211 command_print(CMD_CTX
, "erase failed");
215 command_print(CMD_CTX
, "unknown error when erasing NAND flash device");
221 COMMAND_HANDLER(handle_nand_check_bad_blocks_command
)
226 if ((CMD_ARGC
< 1) || (CMD_ARGC
> 3) || (CMD_ARGC
== 2))
228 return ERROR_COMMAND_SYNTAX_ERROR
;
232 struct nand_device
*p
;
233 int retval
= CALL_COMMAND_HANDLER(nand_command_get_device
, 0, &p
);
234 if (ERROR_OK
!= retval
)
239 unsigned long offset
;
240 unsigned long length
;
242 COMMAND_PARSE_NUMBER(ulong
, CMD_ARGV
[1], offset
);
243 if (offset
% p
->erase_size
)
244 return ERROR_INVALID_ARGUMENTS
;
245 offset
/= p
->erase_size
;
247 COMMAND_PARSE_NUMBER(ulong
, CMD_ARGV
[2], length
);
248 if (length
% p
->erase_size
)
249 return ERROR_INVALID_ARGUMENTS
;
252 length
/= p
->erase_size
;
255 last
= offset
+ length
;
258 retval
= nand_build_bbt(p
, first
, last
);
259 if (retval
== ERROR_OK
)
261 command_print(CMD_CTX
, "checked NAND flash device for bad blocks, "
262 "use \"nand info\" command to list blocks");
264 else if (retval
== ERROR_NAND_OPERATION_FAILED
)
266 command_print(CMD_CTX
, "error when checking for bad blocks on "
267 "NAND flash device");
271 command_print(CMD_CTX
, "unknown error when checking for bad "
272 "blocks on NAND flash device");
278 COMMAND_HANDLER(handle_nand_write_command
)
280 struct nand_device
*nand
= NULL
;
281 struct nand_fileio_state s
;
282 int retval
= CALL_COMMAND_HANDLER(nand_fileio_parse_args
,
283 &s
, &nand
, FILEIO_READ
, false, true);
284 if (ERROR_OK
!= retval
)
287 uint32_t total_bytes
= s
.size
;
290 int bytes_read
= nand_fileio_read(nand
, &s
);
293 command_print(CMD_CTX
, "error while reading file");
294 return nand_fileio_cleanup(&s
);
296 s
.size
-= bytes_read
;
298 retval
= nand_write_page(nand
, s
.address
/ nand
->page_size
,
299 s
.page
, s
.page_size
, s
.oob
, s
.oob_size
);
300 if (ERROR_OK
!= retval
)
302 command_print(CMD_CTX
, "failed writing file %s "
303 "to NAND flash %s at offset 0x%8.8" PRIx32
,
304 CMD_ARGV
[1], CMD_ARGV
[0], s
.address
);
305 return nand_fileio_cleanup(&s
);
307 s
.address
+= s
.page_size
;
310 if (nand_fileio_finish(&s
))
312 command_print(CMD_CTX
, "wrote file %s to NAND flash %s up to "
313 "offset 0x%8.8" PRIx32
" in %fs (%0.3f KiB/s)",
314 CMD_ARGV
[1], CMD_ARGV
[0], s
.address
, duration_elapsed(&s
.bench
),
315 duration_kbps(&s
.bench
, total_bytes
));
320 COMMAND_HANDLER(handle_nand_verify_command
)
322 struct nand_device
*nand
= NULL
;
323 struct nand_fileio_state file
;
324 int retval
= CALL_COMMAND_HANDLER(nand_fileio_parse_args
,
325 &file
, &nand
, FILEIO_READ
, false, true);
326 if (ERROR_OK
!= retval
)
329 struct nand_fileio_state dev
;
330 nand_fileio_init(&dev
);
331 dev
.address
= file
.address
;
332 dev
.size
= file
.size
;
333 dev
.oob_format
= file
.oob_format
;
334 retval
= nand_fileio_start(CMD_CTX
, nand
, NULL
, FILEIO_NONE
, &dev
);
335 if (ERROR_OK
!= retval
)
338 while (file
.size
> 0)
340 retval
= nand_read_page(nand
, dev
.address
/ dev
.page_size
,
341 dev
.page
, dev
.page_size
, dev
.oob
, dev
.oob_size
);
342 if (ERROR_OK
!= retval
)
344 command_print(CMD_CTX
, "reading NAND flash page failed");
345 nand_fileio_cleanup(&dev
);
346 nand_fileio_cleanup(&file
);
350 int bytes_read
= nand_fileio_read(nand
, &file
);
353 command_print(CMD_CTX
, "error while reading file");
354 nand_fileio_cleanup(&dev
);
355 nand_fileio_cleanup(&file
);
359 if ((dev
.page
&& memcmp(dev
.page
, file
.page
, dev
.page_size
)) ||
360 (dev
.oob
&& memcmp(dev
.oob
, file
.oob
, dev
.oob_size
)) )
362 command_print(CMD_CTX
, "NAND flash contents differ "
363 "at 0x%8.8" PRIx32
, dev
.address
);
364 nand_fileio_cleanup(&dev
);
365 nand_fileio_cleanup(&file
);
369 file
.size
-= bytes_read
;
370 dev
.address
+= nand
->page_size
;
373 if (nand_fileio_finish(&file
) == ERROR_OK
)
375 command_print(CMD_CTX
, "verified file %s in NAND flash %s "
376 "up to offset 0x%8.8" PRIx32
" in %fs (%0.3f KiB/s)",
377 CMD_ARGV
[1], CMD_ARGV
[0], dev
.address
, duration_elapsed(&file
.bench
),
378 duration_kbps(&file
.bench
, dev
.size
));
381 return nand_fileio_cleanup(&dev
);
384 COMMAND_HANDLER(handle_nand_dump_command
)
386 struct nand_device
*nand
= NULL
;
387 struct nand_fileio_state s
;
388 int retval
= CALL_COMMAND_HANDLER(nand_fileio_parse_args
,
389 &s
, &nand
, FILEIO_WRITE
, true, false);
390 if (ERROR_OK
!= retval
)
396 retval
= nand_read_page(nand
, s
.address
/ nand
->page_size
,
397 s
.page
, s
.page_size
, s
.oob
, s
.oob_size
);
398 if (ERROR_OK
!= retval
)
400 command_print(CMD_CTX
, "reading NAND flash page failed");
401 nand_fileio_cleanup(&s
);
406 fileio_write(&s
.fileio
, s
.page_size
, s
.page
, &size_written
);
409 fileio_write(&s
.fileio
, s
.oob_size
, s
.oob
, &size_written
);
411 s
.size
-= nand
->page_size
;
412 s
.address
+= nand
->page_size
;
415 if (nand_fileio_finish(&s
) == ERROR_OK
)
417 command_print(CMD_CTX
, "dumped %ld bytes in %fs (%0.3f KiB/s)",
418 (long)s
.fileio
.size
, duration_elapsed(&s
.bench
),
419 duration_kbps(&s
.bench
, s
.fileio
.size
));
424 COMMAND_HANDLER(handle_nand_raw_access_command
)
426 if ((CMD_ARGC
< 1) || (CMD_ARGC
> 2))
428 return ERROR_COMMAND_SYNTAX_ERROR
;
431 struct nand_device
*p
;
432 int retval
= CALL_COMMAND_HANDLER(nand_command_get_device
, 0, &p
);
433 if (ERROR_OK
!= retval
)
436 if (NULL
== p
->device
)
438 command_print(CMD_CTX
, "#%s: not probed", CMD_ARGV
[0]);
443 COMMAND_PARSE_ENABLE(CMD_ARGV
[1], p
->use_raw
);
445 const char *msg
= p
->use_raw
? "enabled" : "disabled";
446 command_print(CMD_CTX
, "raw access is %s", msg
);
451 static const struct command_registration nand_exec_command_handlers
[] = {
454 .handler
= handle_nand_list_command
,
455 .mode
= COMMAND_EXEC
,
456 .help
= "list configured NAND flash devices",
460 .handler
= handle_nand_info_command
,
461 .mode
= COMMAND_EXEC
,
462 .usage
= "[banknum | first_bank_num last_bank_num]",
463 .help
= "print info about one or more NAND flash devices",
467 .handler
= handle_nand_probe_command
,
468 .mode
= COMMAND_EXEC
,
470 .help
= "identify NAND flash device",
473 .name
= "check_bad_blocks",
474 .handler
= handle_nand_check_bad_blocks_command
,
475 .mode
= COMMAND_EXEC
,
476 .usage
= "bank_id [offset length]",
477 .help
= "check all or part of NAND flash device for bad blocks",
481 .handler
= handle_nand_erase_command
,
482 .mode
= COMMAND_EXEC
,
483 .usage
= "bank_id [offset length]",
484 .help
= "erase all or subset of blocks on NAND flash device",
488 .handler
= handle_nand_dump_command
,
489 .mode
= COMMAND_EXEC
,
490 .usage
= "bank_id filename offset length "
491 "['oob_raw'|'oob_only']",
492 .help
= "dump from NAND flash device",
496 .handler
= handle_nand_verify_command
,
497 .mode
= COMMAND_EXEC
,
498 .usage
= "bank_id filename offset "
499 "['oob_raw'|'oob_only'|'oob_softecc'|'oob_softecc_kw']",
500 .help
= "verify NAND flash device",
504 .handler
= handle_nand_write_command
,
505 .mode
= COMMAND_EXEC
,
506 .usage
= "bank_id filename offset "
507 "['oob_raw'|'oob_only'|'oob_softecc'|'oob_softecc_kw']",
508 .help
= "write to NAND flash device",
511 .name
= "raw_access",
512 .handler
= handle_nand_raw_access_command
,
513 .mode
= COMMAND_EXEC
,
514 .usage
= "bank_id ['enable'|'disable']",
515 .help
= "raw access to NAND flash device",
517 COMMAND_REGISTRATION_DONE
520 static int nand_init(struct command_context
*cmd_ctx
)
524 struct command
*parent
= command_find_in_context(cmd_ctx
, "nand");
525 return register_commands(cmd_ctx
, parent
, nand_exec_command_handlers
);
528 COMMAND_HANDLER(handle_nand_init_command
)
531 return ERROR_COMMAND_SYNTAX_ERROR
;
533 static bool nand_initialized
= false;
534 if (nand_initialized
)
536 LOG_INFO("'nand init' has already been called");
539 nand_initialized
= true;
541 LOG_DEBUG("Initializing NAND devices...");
542 return nand_init(CMD_CTX
);
545 static int nand_list_walker(struct nand_flash_controller
*c
, void *x
)
547 struct command_context
*cmd_ctx
= (struct command_context
*)x
;
548 command_print(cmd_ctx
, " %s", c
->name
);
552 COMMAND_HANDLER(handle_nand_list_drivers
)
554 command_print(CMD_CTX
, "Available NAND flash controller drivers:");
555 return nand_driver_walk(&nand_list_walker
, CMD_CTX
);
558 static COMMAND_HELPER(create_nand_device
, const char *bank_name
,
559 struct nand_flash_controller
*controller
)
561 if (NULL
!= controller
->commands
)
563 int retval
= register_commands(CMD_CTX
, NULL
,
564 controller
->commands
);
565 if (ERROR_OK
!= retval
)
568 struct nand_device
*c
= malloc(sizeof(struct nand_device
));
570 c
->name
= strdup(bank_name
);
571 c
->controller
= controller
;
572 c
->controller_priv
= NULL
;
573 c
->manufacturer
= NULL
;
576 c
->address_cycles
= 0;
581 int retval
= CALL_COMMAND_HANDLER(controller
->nand_device_command
, c
);
582 if (ERROR_OK
!= retval
)
584 LOG_ERROR("'%s' driver rejected nand flash", controller
->name
);
594 COMMAND_HANDLER(handle_nand_device_command
)
598 LOG_ERROR("incomplete nand device configuration");
599 return ERROR_FLASH_BANK_INVALID
;
602 // save name and increment (for compatibility) with drivers
603 const char *bank_name
= *CMD_ARGV
++;
606 const char *driver_name
= CMD_ARGV
[0];
607 struct nand_flash_controller
*controller
;
608 controller
= nand_driver_find_by_name(CMD_ARGV
[0]);
609 if (NULL
== controller
)
611 LOG_ERROR("No valid NAND flash driver found (%s)", driver_name
);
612 return CALL_COMMAND_HANDLER(handle_nand_list_drivers
);
614 return CALL_COMMAND_HANDLER(create_nand_device
, bank_name
, controller
);
617 static const struct command_registration nand_config_command_handlers
[] = {
620 .handler
= &handle_nand_device_command
,
621 .mode
= COMMAND_CONFIG
,
622 .help
= "defines a new NAND bank",
623 .usage
= "bank_id driver target [driver_options ...]",
627 .handler
= &handle_nand_list_drivers
,
629 .help
= "lists available NAND drivers",
633 .mode
= COMMAND_CONFIG
,
634 .handler
= &handle_nand_init_command
,
635 .help
= "initialize NAND devices",
637 COMMAND_REGISTRATION_DONE
639 static const struct command_registration nand_command_handlers
[] = {
643 .help
= "NAND flash command group",
644 .chain
= nand_config_command_handlers
,
646 COMMAND_REGISTRATION_DONE
649 int nand_register_commands(struct command_context
*cmd_ctx
)
651 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)