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
);
157 COMMAND_HANDLER(handle_nand_erase_command
)
159 if (CMD_ARGC
!= 1 && CMD_ARGC
!= 3)
161 return ERROR_COMMAND_SYNTAX_ERROR
;
165 struct nand_device
*p
;
166 int retval
= CALL_COMMAND_HANDLER(nand_command_get_device
, 0, &p
);
167 if (ERROR_OK
!= retval
)
170 unsigned long offset
;
171 unsigned long length
;
173 /* erase specified part of the chip; or else everything */
175 unsigned long size
= p
->erase_size
* p
->num_blocks
;
177 COMMAND_PARSE_NUMBER(ulong
, CMD_ARGV
[1], offset
);
178 if ((offset
% p
->erase_size
) != 0 || offset
>= size
)
179 return ERROR_INVALID_ARGUMENTS
;
181 COMMAND_PARSE_NUMBER(ulong
, CMD_ARGV
[2], length
);
182 if ((length
== 0) || (length
% p
->erase_size
) != 0
183 || (length
+ offset
) > size
)
184 return ERROR_INVALID_ARGUMENTS
;
186 offset
/= p
->erase_size
;
187 length
/= p
->erase_size
;
190 length
= p
->num_blocks
;
193 retval
= nand_erase(p
, offset
, offset
+ length
- 1);
194 if (retval
== ERROR_OK
)
196 command_print(CMD_CTX
, "erased blocks %lu to %lu "
197 "on NAND flash device #%s '%s'",
198 offset
, offset
+ length
,
199 CMD_ARGV
[0], p
->device
->name
);
205 COMMAND_HANDLER(handle_nand_check_bad_blocks_command
)
210 if ((CMD_ARGC
< 1) || (CMD_ARGC
> 3) || (CMD_ARGC
== 2))
212 return ERROR_COMMAND_SYNTAX_ERROR
;
216 struct nand_device
*p
;
217 int retval
= CALL_COMMAND_HANDLER(nand_command_get_device
, 0, &p
);
218 if (ERROR_OK
!= retval
)
223 unsigned long offset
;
224 unsigned long length
;
226 COMMAND_PARSE_NUMBER(ulong
, CMD_ARGV
[1], offset
);
227 if (offset
% p
->erase_size
)
228 return ERROR_INVALID_ARGUMENTS
;
229 offset
/= p
->erase_size
;
231 COMMAND_PARSE_NUMBER(ulong
, CMD_ARGV
[2], length
);
232 if (length
% p
->erase_size
)
233 return ERROR_INVALID_ARGUMENTS
;
236 length
/= p
->erase_size
;
239 last
= offset
+ length
;
242 retval
= nand_build_bbt(p
, first
, last
);
243 if (retval
== ERROR_OK
)
245 command_print(CMD_CTX
, "checked NAND flash device for bad blocks, "
246 "use \"nand info\" command to list blocks");
252 COMMAND_HANDLER(handle_nand_write_command
)
254 struct nand_device
*nand
= NULL
;
255 struct nand_fileio_state s
;
256 int retval
= CALL_COMMAND_HANDLER(nand_fileio_parse_args
,
257 &s
, &nand
, FILEIO_READ
, false, true);
258 if (ERROR_OK
!= retval
)
261 uint32_t total_bytes
= s
.size
;
264 int bytes_read
= nand_fileio_read(nand
, &s
);
267 command_print(CMD_CTX
, "error while reading file");
268 return nand_fileio_cleanup(&s
);
270 s
.size
-= bytes_read
;
272 retval
= nand_write_page(nand
, s
.address
/ nand
->page_size
,
273 s
.page
, s
.page_size
, s
.oob
, s
.oob_size
);
274 if (ERROR_OK
!= retval
)
276 command_print(CMD_CTX
, "failed writing file %s "
277 "to NAND flash %s at offset 0x%8.8" PRIx32
,
278 CMD_ARGV
[1], CMD_ARGV
[0], s
.address
);
279 return nand_fileio_cleanup(&s
);
281 s
.address
+= s
.page_size
;
284 if (nand_fileio_finish(&s
))
286 command_print(CMD_CTX
, "wrote file %s to NAND flash %s up to "
287 "offset 0x%8.8" PRIx32
" in %fs (%0.3f KiB/s)",
288 CMD_ARGV
[1], CMD_ARGV
[0], s
.address
, duration_elapsed(&s
.bench
),
289 duration_kbps(&s
.bench
, total_bytes
));
294 COMMAND_HANDLER(handle_nand_verify_command
)
296 struct nand_device
*nand
= NULL
;
297 struct nand_fileio_state file
;
298 int retval
= CALL_COMMAND_HANDLER(nand_fileio_parse_args
,
299 &file
, &nand
, FILEIO_READ
, false, true);
300 if (ERROR_OK
!= retval
)
303 struct nand_fileio_state dev
;
304 nand_fileio_init(&dev
);
305 dev
.address
= file
.address
;
306 dev
.size
= file
.size
;
307 dev
.oob_format
= file
.oob_format
;
308 retval
= nand_fileio_start(CMD_CTX
, nand
, NULL
, FILEIO_NONE
, &dev
);
309 if (ERROR_OK
!= retval
)
312 while (file
.size
> 0)
314 retval
= nand_read_page(nand
, dev
.address
/ dev
.page_size
,
315 dev
.page
, dev
.page_size
, dev
.oob
, dev
.oob_size
);
316 if (ERROR_OK
!= retval
)
318 command_print(CMD_CTX
, "reading NAND flash page failed");
319 nand_fileio_cleanup(&dev
);
320 nand_fileio_cleanup(&file
);
324 int bytes_read
= nand_fileio_read(nand
, &file
);
327 command_print(CMD_CTX
, "error while reading file");
328 nand_fileio_cleanup(&dev
);
329 nand_fileio_cleanup(&file
);
333 if ((dev
.page
&& memcmp(dev
.page
, file
.page
, dev
.page_size
)) ||
334 (dev
.oob
&& memcmp(dev
.oob
, file
.oob
, dev
.oob_size
)) )
336 command_print(CMD_CTX
, "NAND flash contents differ "
337 "at 0x%8.8" PRIx32
, dev
.address
);
338 nand_fileio_cleanup(&dev
);
339 nand_fileio_cleanup(&file
);
343 file
.size
-= bytes_read
;
344 dev
.address
+= nand
->page_size
;
347 if (nand_fileio_finish(&file
) == ERROR_OK
)
349 command_print(CMD_CTX
, "verified file %s in NAND flash %s "
350 "up to offset 0x%8.8" PRIx32
" in %fs (%0.3f KiB/s)",
351 CMD_ARGV
[1], CMD_ARGV
[0], dev
.address
, duration_elapsed(&file
.bench
),
352 duration_kbps(&file
.bench
, dev
.size
));
355 return nand_fileio_cleanup(&dev
);
358 COMMAND_HANDLER(handle_nand_dump_command
)
360 struct nand_device
*nand
= NULL
;
361 struct nand_fileio_state s
;
362 int retval
= CALL_COMMAND_HANDLER(nand_fileio_parse_args
,
363 &s
, &nand
, FILEIO_WRITE
, true, false);
364 if (ERROR_OK
!= retval
)
370 retval
= nand_read_page(nand
, s
.address
/ nand
->page_size
,
371 s
.page
, s
.page_size
, s
.oob
, s
.oob_size
);
372 if (ERROR_OK
!= retval
)
374 command_print(CMD_CTX
, "reading NAND flash page failed");
375 nand_fileio_cleanup(&s
);
380 fileio_write(&s
.fileio
, s
.page_size
, s
.page
, &size_written
);
383 fileio_write(&s
.fileio
, s
.oob_size
, s
.oob
, &size_written
);
385 s
.size
-= nand
->page_size
;
386 s
.address
+= nand
->page_size
;
389 if (nand_fileio_finish(&s
) == ERROR_OK
)
391 command_print(CMD_CTX
, "dumped %ld bytes in %fs (%0.3f KiB/s)",
392 (long)s
.fileio
.size
, duration_elapsed(&s
.bench
),
393 duration_kbps(&s
.bench
, s
.fileio
.size
));
398 COMMAND_HANDLER(handle_nand_raw_access_command
)
400 if ((CMD_ARGC
< 1) || (CMD_ARGC
> 2))
402 return ERROR_COMMAND_SYNTAX_ERROR
;
405 struct nand_device
*p
;
406 int retval
= CALL_COMMAND_HANDLER(nand_command_get_device
, 0, &p
);
407 if (ERROR_OK
!= retval
)
410 if (NULL
== p
->device
)
412 command_print(CMD_CTX
, "#%s: not probed", CMD_ARGV
[0]);
417 COMMAND_PARSE_ENABLE(CMD_ARGV
[1], p
->use_raw
);
419 const char *msg
= p
->use_raw
? "enabled" : "disabled";
420 command_print(CMD_CTX
, "raw access is %s", msg
);
425 static const struct command_registration nand_exec_command_handlers
[] = {
428 .handler
= handle_nand_list_command
,
429 .mode
= COMMAND_EXEC
,
430 .help
= "list configured NAND flash devices",
434 .handler
= handle_nand_info_command
,
435 .mode
= COMMAND_EXEC
,
436 .usage
= "[banknum | first_bank_num last_bank_num]",
437 .help
= "print info about one or more NAND flash devices",
441 .handler
= handle_nand_probe_command
,
442 .mode
= COMMAND_EXEC
,
444 .help
= "identify NAND flash device",
447 .name
= "check_bad_blocks",
448 .handler
= handle_nand_check_bad_blocks_command
,
449 .mode
= COMMAND_EXEC
,
450 .usage
= "bank_id [offset length]",
451 .help
= "check all or part of NAND flash device for bad blocks",
455 .handler
= handle_nand_erase_command
,
456 .mode
= COMMAND_EXEC
,
457 .usage
= "bank_id [offset length]",
458 .help
= "erase all or subset of blocks on NAND flash device",
462 .handler
= handle_nand_dump_command
,
463 .mode
= COMMAND_EXEC
,
464 .usage
= "bank_id filename offset length "
465 "['oob_raw'|'oob_only']",
466 .help
= "dump from NAND flash device",
470 .handler
= handle_nand_verify_command
,
471 .mode
= COMMAND_EXEC
,
472 .usage
= "bank_id filename offset "
473 "['oob_raw'|'oob_only'|'oob_softecc'|'oob_softecc_kw']",
474 .help
= "verify NAND flash device",
478 .handler
= handle_nand_write_command
,
479 .mode
= COMMAND_EXEC
,
480 .usage
= "bank_id filename offset "
481 "['oob_raw'|'oob_only'|'oob_softecc'|'oob_softecc_kw']",
482 .help
= "write to NAND flash device",
485 .name
= "raw_access",
486 .handler
= handle_nand_raw_access_command
,
487 .mode
= COMMAND_EXEC
,
488 .usage
= "bank_id ['enable'|'disable']",
489 .help
= "raw access to NAND flash device",
491 COMMAND_REGISTRATION_DONE
494 static int nand_init(struct command_context
*cmd_ctx
)
498 struct command
*parent
= command_find_in_context(cmd_ctx
, "nand");
499 return register_commands(cmd_ctx
, parent
, nand_exec_command_handlers
);
502 COMMAND_HANDLER(handle_nand_init_command
)
505 return ERROR_COMMAND_SYNTAX_ERROR
;
507 static bool nand_initialized
= false;
508 if (nand_initialized
)
510 LOG_INFO("'nand init' has already been called");
513 nand_initialized
= true;
515 LOG_DEBUG("Initializing NAND devices...");
516 return nand_init(CMD_CTX
);
519 static int nand_list_walker(struct nand_flash_controller
*c
, void *x
)
521 struct command_context
*cmd_ctx
= (struct command_context
*)x
;
522 command_print(cmd_ctx
, " %s", c
->name
);
526 COMMAND_HANDLER(handle_nand_list_drivers
)
528 command_print(CMD_CTX
, "Available NAND flash controller drivers:");
529 return nand_driver_walk(&nand_list_walker
, CMD_CTX
);
532 static COMMAND_HELPER(create_nand_device
, const char *bank_name
,
533 struct nand_flash_controller
*controller
)
535 if (NULL
!= controller
->commands
)
537 int retval
= register_commands(CMD_CTX
, NULL
,
538 controller
->commands
);
539 if (ERROR_OK
!= retval
)
542 struct nand_device
*c
= malloc(sizeof(struct nand_device
));
544 c
->name
= strdup(bank_name
);
545 c
->controller
= controller
;
546 c
->controller_priv
= NULL
;
547 c
->manufacturer
= NULL
;
550 c
->address_cycles
= 0;
555 int retval
= CALL_COMMAND_HANDLER(controller
->nand_device_command
, c
);
556 if (ERROR_OK
!= retval
)
558 LOG_ERROR("'%s' driver rejected nand flash", controller
->name
);
568 COMMAND_HANDLER(handle_nand_device_command
)
572 LOG_ERROR("incomplete nand device configuration");
573 return ERROR_FLASH_BANK_INVALID
;
576 // save name and increment (for compatibility) with drivers
577 const char *bank_name
= *CMD_ARGV
++;
580 const char *driver_name
= CMD_ARGV
[0];
581 struct nand_flash_controller
*controller
;
582 controller
= nand_driver_find_by_name(CMD_ARGV
[0]);
583 if (NULL
== controller
)
585 LOG_ERROR("No valid NAND flash driver found (%s)", driver_name
);
586 return CALL_COMMAND_HANDLER(handle_nand_list_drivers
);
588 return CALL_COMMAND_HANDLER(create_nand_device
, bank_name
, controller
);
591 static const struct command_registration nand_config_command_handlers
[] = {
594 .handler
= &handle_nand_device_command
,
595 .mode
= COMMAND_CONFIG
,
596 .help
= "defines a new NAND bank",
597 .usage
= "bank_id driver target [driver_options ...]",
601 .handler
= &handle_nand_list_drivers
,
603 .help
= "lists available NAND drivers",
607 .mode
= COMMAND_CONFIG
,
608 .handler
= &handle_nand_init_command
,
609 .help
= "initialize NAND devices",
611 COMMAND_REGISTRATION_DONE
613 static const struct command_registration nand_command_handlers
[] = {
617 .help
= "NAND flash command group",
618 .chain
= nand_config_command_handlers
,
620 COMMAND_REGISTRATION_DONE
623 int nand_register_commands(struct command_context
*cmd_ctx
)
625 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)