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 ***************************************************************************/
30 #include <target/target.h>
33 extern struct nand_device
*nand_devices
;
35 COMMAND_HANDLER(handle_nand_list_command
)
37 struct nand_device
*p
;
42 command_print(CMD_CTX
, "no NAND flash devices configured");
46 for (p
= nand_devices
, i
= 0; p
; p
= p
->next
, i
++)
49 command_print(CMD_CTX
, "#%i: %s (%s) "
50 "pagesize: %i, buswidth: %i,\n\t"
51 "blocksize: %i, blocks: %i",
52 i
, p
->device
->name
, p
->manufacturer
->name
,
53 p
->page_size
, p
->bus_width
,
54 p
->erase_size
, p
->num_blocks
);
56 command_print(CMD_CTX
, "#%i: not probed", i
);
62 COMMAND_HANDLER(handle_nand_info_command
)
71 return ERROR_COMMAND_SYNTAX_ERROR
;
77 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], i
);
82 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], first
);
83 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[2], last
);
87 struct nand_device
*p
;
88 int retval
= CALL_COMMAND_HANDLER(nand_command_get_device
, 0, &p
);
89 if (ERROR_OK
!= retval
)
92 if (NULL
== p
->device
)
94 command_print(CMD_CTX
, "#%s: not probed", CMD_ARGV
[0]);
98 if (first
>= p
->num_blocks
)
99 first
= p
->num_blocks
- 1;
101 if (last
>= p
->num_blocks
)
102 last
= p
->num_blocks
- 1;
104 command_print(CMD_CTX
, "#%i: %s (%s) pagesize: %i, buswidth: %i, erasesize: %i",
105 i
++, p
->device
->name
, p
->manufacturer
->name
, p
->page_size
, p
->bus_width
, p
->erase_size
);
107 for (j
= first
; j
<= last
; j
++)
109 char *erase_state
, *bad_state
;
111 if (p
->blocks
[j
].is_erased
== 0)
112 erase_state
= "not erased";
113 else if (p
->blocks
[j
].is_erased
== 1)
114 erase_state
= "erased";
116 erase_state
= "erase state unknown";
118 if (p
->blocks
[j
].is_bad
== 0)
120 else if (p
->blocks
[j
].is_bad
== 1)
121 bad_state
= " (marked bad)";
123 bad_state
= " (block condition unknown)";
125 command_print(CMD_CTX
,
126 "\t#%i: 0x%8.8" PRIx32
" (%" PRId32
"kB) %s%s",
129 p
->blocks
[j
].size
/ 1024,
137 COMMAND_HANDLER(handle_nand_probe_command
)
141 return ERROR_COMMAND_SYNTAX_ERROR
;
144 struct nand_device
*p
;
145 int retval
= CALL_COMMAND_HANDLER(nand_command_get_device
, 0, &p
);
146 if (ERROR_OK
!= retval
)
149 if ((retval
= nand_probe(p
)) == ERROR_OK
)
151 command_print(CMD_CTX
, "NAND flash device '%s (%s)' found",
152 p
->device
->name
, p
->manufacturer
->name
);
158 COMMAND_HANDLER(handle_nand_erase_command
)
160 if (CMD_ARGC
!= 1 && CMD_ARGC
!= 3)
162 return ERROR_COMMAND_SYNTAX_ERROR
;
166 struct nand_device
*p
;
167 int retval
= CALL_COMMAND_HANDLER(nand_command_get_device
, 0, &p
);
168 if (ERROR_OK
!= retval
)
171 unsigned long offset
;
172 unsigned long length
;
174 /* erase specified part of the chip; or else everything */
176 unsigned long size
= p
->erase_size
* p
->num_blocks
;
178 COMMAND_PARSE_NUMBER(ulong
, CMD_ARGV
[1], offset
);
179 if ((offset
% p
->erase_size
) != 0 || offset
>= size
)
180 return ERROR_COMMAND_SYNTAX_ERROR
;
182 COMMAND_PARSE_NUMBER(ulong
, CMD_ARGV
[2], length
);
183 if ((length
== 0) || (length
% p
->erase_size
) != 0
184 || (length
+ offset
) > size
)
185 return ERROR_COMMAND_SYNTAX_ERROR
;
187 offset
/= p
->erase_size
;
188 length
/= p
->erase_size
;
191 length
= p
->num_blocks
;
194 retval
= nand_erase(p
, offset
, offset
+ length
- 1);
195 if (retval
== ERROR_OK
)
197 command_print(CMD_CTX
, "erased blocks %lu to %lu "
198 "on NAND flash device #%s '%s'",
199 offset
, offset
+ length
,
200 CMD_ARGV
[0], p
->device
->name
);
206 COMMAND_HANDLER(handle_nand_check_bad_blocks_command
)
211 if ((CMD_ARGC
< 1) || (CMD_ARGC
> 3) || (CMD_ARGC
== 2))
213 return ERROR_COMMAND_SYNTAX_ERROR
;
217 struct nand_device
*p
;
218 int retval
= CALL_COMMAND_HANDLER(nand_command_get_device
, 0, &p
);
219 if (ERROR_OK
!= retval
)
224 unsigned long offset
;
225 unsigned long length
;
227 COMMAND_PARSE_NUMBER(ulong
, CMD_ARGV
[1], offset
);
228 if (offset
% p
->erase_size
)
229 return ERROR_COMMAND_SYNTAX_ERROR
;
230 offset
/= p
->erase_size
;
232 COMMAND_PARSE_NUMBER(ulong
, CMD_ARGV
[2], length
);
233 if (length
% p
->erase_size
)
234 return ERROR_COMMAND_SYNTAX_ERROR
;
237 length
/= p
->erase_size
;
240 last
= offset
+ length
;
243 retval
= nand_build_bbt(p
, first
, last
);
244 if (retval
== ERROR_OK
)
246 command_print(CMD_CTX
, "checked NAND flash device for bad blocks, "
247 "use \"nand info\" command to list blocks");
253 COMMAND_HANDLER(handle_nand_write_command
)
255 struct nand_device
*nand
= NULL
;
256 struct nand_fileio_state s
;
257 int retval
= CALL_COMMAND_HANDLER(nand_fileio_parse_args
,
258 &s
, &nand
, FILEIO_READ
, false, true);
259 if (ERROR_OK
!= retval
)
262 uint32_t total_bytes
= s
.size
;
265 int bytes_read
= nand_fileio_read(nand
, &s
);
268 command_print(CMD_CTX
, "error while reading file");
269 return nand_fileio_cleanup(&s
);
271 s
.size
-= bytes_read
;
273 retval
= nand_write_page(nand
, s
.address
/ nand
->page_size
,
274 s
.page
, s
.page_size
, s
.oob
, s
.oob_size
);
275 if (ERROR_OK
!= retval
)
277 command_print(CMD_CTX
, "failed writing file %s "
278 "to NAND flash %s at offset 0x%8.8" PRIx32
,
279 CMD_ARGV
[1], CMD_ARGV
[0], s
.address
);
280 return nand_fileio_cleanup(&s
);
282 s
.address
+= s
.page_size
;
285 if (nand_fileio_finish(&s
))
287 command_print(CMD_CTX
, "wrote file %s to NAND flash %s up to "
288 "offset 0x%8.8" PRIx32
" in %fs (%0.3f KiB/s)",
289 CMD_ARGV
[1], CMD_ARGV
[0], s
.address
, duration_elapsed(&s
.bench
),
290 duration_kbps(&s
.bench
, total_bytes
));
295 COMMAND_HANDLER(handle_nand_verify_command
)
297 struct nand_device
*nand
= NULL
;
298 struct nand_fileio_state file
;
299 int retval
= CALL_COMMAND_HANDLER(nand_fileio_parse_args
,
300 &file
, &nand
, FILEIO_READ
, false, true);
301 if (ERROR_OK
!= retval
)
304 struct nand_fileio_state dev
;
305 nand_fileio_init(&dev
);
306 dev
.address
= file
.address
;
307 dev
.size
= file
.size
;
308 dev
.oob_format
= file
.oob_format
;
309 retval
= nand_fileio_start(CMD_CTX
, nand
, NULL
, FILEIO_NONE
, &dev
);
310 if (ERROR_OK
!= retval
)
313 while (file
.size
> 0)
315 retval
= nand_read_page(nand
, dev
.address
/ dev
.page_size
,
316 dev
.page
, dev
.page_size
, dev
.oob
, dev
.oob_size
);
317 if (ERROR_OK
!= retval
)
319 command_print(CMD_CTX
, "reading NAND flash page failed");
320 nand_fileio_cleanup(&dev
);
321 nand_fileio_cleanup(&file
);
325 int bytes_read
= nand_fileio_read(nand
, &file
);
328 command_print(CMD_CTX
, "error while reading file");
329 nand_fileio_cleanup(&dev
);
330 nand_fileio_cleanup(&file
);
334 if ((dev
.page
&& memcmp(dev
.page
, file
.page
, dev
.page_size
)) ||
335 (dev
.oob
&& memcmp(dev
.oob
, file
.oob
, dev
.oob_size
)) )
337 command_print(CMD_CTX
, "NAND flash contents differ "
338 "at 0x%8.8" PRIx32
, dev
.address
);
339 nand_fileio_cleanup(&dev
);
340 nand_fileio_cleanup(&file
);
344 file
.size
-= bytes_read
;
345 dev
.address
+= nand
->page_size
;
348 if (nand_fileio_finish(&file
) == ERROR_OK
)
350 command_print(CMD_CTX
, "verified file %s in NAND flash %s "
351 "up to offset 0x%8.8" PRIx32
" in %fs (%0.3f KiB/s)",
352 CMD_ARGV
[1], CMD_ARGV
[0], dev
.address
, duration_elapsed(&file
.bench
),
353 duration_kbps(&file
.bench
, dev
.size
));
356 return nand_fileio_cleanup(&dev
);
359 COMMAND_HANDLER(handle_nand_dump_command
)
362 struct nand_device
*nand
= NULL
;
363 struct nand_fileio_state s
;
364 int retval
= CALL_COMMAND_HANDLER(nand_fileio_parse_args
,
365 &s
, &nand
, FILEIO_WRITE
, true, false);
366 if (ERROR_OK
!= retval
)
372 retval
= nand_read_page(nand
, s
.address
/ nand
->page_size
,
373 s
.page
, s
.page_size
, s
.oob
, s
.oob_size
);
374 if (ERROR_OK
!= retval
)
376 command_print(CMD_CTX
, "reading NAND flash page failed");
377 nand_fileio_cleanup(&s
);
382 fileio_write(&s
.fileio
, s
.page_size
, s
.page
, &size_written
);
385 fileio_write(&s
.fileio
, s
.oob_size
, s
.oob
, &size_written
);
387 s
.size
-= nand
->page_size
;
388 s
.address
+= nand
->page_size
;
391 retval
= fileio_size(&s
.fileio
, &filesize
);
392 if (retval
!= ERROR_OK
)
395 if (nand_fileio_finish(&s
) == ERROR_OK
)
397 command_print(CMD_CTX
, "dumped %ld bytes in %fs (%0.3f KiB/s)",
398 (long)filesize
, duration_elapsed(&s
.bench
),
399 duration_kbps(&s
.bench
, filesize
));
404 COMMAND_HANDLER(handle_nand_raw_access_command
)
406 if ((CMD_ARGC
< 1) || (CMD_ARGC
> 2))
408 return ERROR_COMMAND_SYNTAX_ERROR
;
411 struct nand_device
*p
;
412 int retval
= CALL_COMMAND_HANDLER(nand_command_get_device
, 0, &p
);
413 if (ERROR_OK
!= retval
)
416 if (NULL
== p
->device
)
418 command_print(CMD_CTX
, "#%s: not probed", CMD_ARGV
[0]);
423 COMMAND_PARSE_ENABLE(CMD_ARGV
[1], p
->use_raw
);
425 const char *msg
= p
->use_raw
? "enabled" : "disabled";
426 command_print(CMD_CTX
, "raw access is %s", msg
);
431 static const struct command_registration nand_exec_command_handlers
[] = {
434 .handler
= handle_nand_list_command
,
435 .mode
= COMMAND_EXEC
,
436 .help
= "list configured NAND flash devices",
440 .handler
= handle_nand_info_command
,
441 .mode
= COMMAND_EXEC
,
442 .usage
= "[banknum | first_bank_num last_bank_num]",
443 .help
= "print info about one or more NAND flash devices",
447 .handler
= handle_nand_probe_command
,
448 .mode
= COMMAND_EXEC
,
450 .help
= "identify NAND flash device",
453 .name
= "check_bad_blocks",
454 .handler
= handle_nand_check_bad_blocks_command
,
455 .mode
= COMMAND_EXEC
,
456 .usage
= "bank_id [offset length]",
457 .help
= "check all or part of NAND flash device for bad blocks",
461 .handler
= handle_nand_erase_command
,
462 .mode
= COMMAND_EXEC
,
463 .usage
= "bank_id [offset length]",
464 .help
= "erase all or subset of blocks on NAND flash device",
468 .handler
= handle_nand_dump_command
,
469 .mode
= COMMAND_EXEC
,
470 .usage
= "bank_id filename offset length "
471 "['oob_raw'|'oob_only']",
472 .help
= "dump from NAND flash device",
476 .handler
= handle_nand_verify_command
,
477 .mode
= COMMAND_EXEC
,
478 .usage
= "bank_id filename offset "
479 "['oob_raw'|'oob_only'|'oob_softecc'|'oob_softecc_kw']",
480 .help
= "verify NAND flash device",
484 .handler
= handle_nand_write_command
,
485 .mode
= COMMAND_EXEC
,
486 .usage
= "bank_id filename offset "
487 "['oob_raw'|'oob_only'|'oob_softecc'|'oob_softecc_kw']",
488 .help
= "write to NAND flash device",
491 .name
= "raw_access",
492 .handler
= handle_nand_raw_access_command
,
493 .mode
= COMMAND_EXEC
,
494 .usage
= "bank_id ['enable'|'disable']",
495 .help
= "raw access to NAND flash device",
497 COMMAND_REGISTRATION_DONE
500 static int nand_init(struct command_context
*cmd_ctx
)
504 struct command
*parent
= command_find_in_context(cmd_ctx
, "nand");
505 return register_commands(cmd_ctx
, parent
, nand_exec_command_handlers
);
508 COMMAND_HANDLER(handle_nand_init_command
)
511 return ERROR_COMMAND_SYNTAX_ERROR
;
513 static bool nand_initialized
= false;
514 if (nand_initialized
)
516 LOG_INFO("'nand init' has already been called");
519 nand_initialized
= true;
521 LOG_DEBUG("Initializing NAND devices...");
522 return nand_init(CMD_CTX
);
525 static int nand_list_walker(struct nand_flash_controller
*c
, void *x
)
527 struct command_context
*cmd_ctx
= (struct command_context
*)x
;
528 command_print(cmd_ctx
, " %s", c
->name
);
532 COMMAND_HANDLER(handle_nand_list_drivers
)
534 command_print(CMD_CTX
, "Available NAND flash controller drivers:");
535 return nand_driver_walk(&nand_list_walker
, CMD_CTX
);
538 static COMMAND_HELPER(create_nand_device
, const char *bank_name
,
539 struct nand_flash_controller
*controller
)
541 struct nand_device
*c
;
542 struct target
*target
;
547 LOG_ERROR("missing target");
548 return ERROR_COMMAND_ARGUMENT_INVALID
;
550 target
= get_target(CMD_ARGV
[1]);
552 LOG_ERROR("invalid target %s", CMD_ARGV
[1]);
553 return ERROR_COMMAND_ARGUMENT_INVALID
;
556 if (NULL
!= controller
->commands
)
558 retval
= register_commands(CMD_CTX
, NULL
,
559 controller
->commands
);
560 if (ERROR_OK
!= retval
)
563 c
= malloc(sizeof(struct nand_device
));
566 LOG_ERROR("End of memory");
570 c
->name
= strdup(bank_name
);
572 c
->controller
= controller
;
573 c
->controller_priv
= NULL
;
574 c
->manufacturer
= NULL
;
577 c
->address_cycles
= 0;
582 retval
= CALL_COMMAND_HANDLER(controller
->nand_device_command
, c
);
583 if (ERROR_OK
!= retval
)
585 LOG_ERROR("'%s' driver rejected nand flash", controller
->name
);
595 COMMAND_HANDLER(handle_nand_device_command
)
599 LOG_ERROR("incomplete nand device configuration");
600 return ERROR_FLASH_BANK_INVALID
;
603 // save name and increment (for compatibility) with drivers
604 const char *bank_name
= *CMD_ARGV
++;
607 const char *driver_name
= CMD_ARGV
[0];
608 struct nand_flash_controller
*controller
;
609 controller
= nand_driver_find_by_name(CMD_ARGV
[0]);
610 if (NULL
== controller
)
612 LOG_ERROR("No valid NAND flash driver found (%s)", driver_name
);
613 return CALL_COMMAND_HANDLER(handle_nand_list_drivers
);
615 return CALL_COMMAND_HANDLER(create_nand_device
, bank_name
, controller
);
618 static const struct command_registration nand_config_command_handlers
[] = {
621 .handler
= &handle_nand_device_command
,
622 .mode
= COMMAND_CONFIG
,
623 .help
= "defines a new NAND bank",
624 .usage
= "bank_id driver target [driver_options ...]",
628 .handler
= &handle_nand_list_drivers
,
630 .help
= "lists available NAND drivers",
634 .mode
= COMMAND_CONFIG
,
635 .handler
= &handle_nand_init_command
,
636 .help
= "initialize NAND devices",
638 COMMAND_REGISTRATION_DONE
640 static const struct command_registration nand_command_handlers
[] = {
644 .help
= "NAND flash command group",
645 .chain
= nand_config_command_handlers
,
647 COMMAND_REGISTRATION_DONE
650 int nand_register_commands(struct command_context
*cmd_ctx
)
652 return register_commands(cmd_ctx
, NULL
, nand_command_handlers
);