David Brownell <david-b@pacbell.net>:
Update two oddball NAND commands to work with {offset, length} instead of block numbers, matching the other commands as well as usage in U-Boot and the Linux-MTD utilities. Document them accordingly. Update the single in-tree use of those commands (sheevaplug). ALSO: (a) Document the current 2 GByte/chip ceiling for NAND chipsize. (32 bit offset/length values can't represent 4 GBytes.) Maybe after the upcoming release, the code can switch to 64-bits. (b) The "nand check_bad_blocks" should report "bad" blocks. They are not "invalid" blocks; they're "bad" ones. (c) Tweak the "nand info" command to handle the "no arguments" case sanely (show everything, instead of showing garbage) and not listing the blocksize in hex kbytes (duh). git-svn-id: svn://svn.berlios.de/openocd/trunk@1904 b42882b7-edfa-0310-969c-e2dbd0fdcd60__archive__
parent
c0fc8f93f1
commit
eb385b2e70
|
@ -2616,6 +2616,15 @@ boot loader, operating system, or other data needed to initialize or
|
|||
de-brick a board.
|
||||
@end enumerate
|
||||
|
||||
@b{NOTE:} At the time this text was written, the largest NAND
|
||||
flash fully supported by OpenOCD is 2 GiBytes (16 GiBits).
|
||||
This is because the variables used to hold offsets and lengths
|
||||
are only 32 bits wide.
|
||||
(Larger chips may work in some cases, unless an offset or length
|
||||
is larger than 0xffffffff, the largest 32-bit unsigned integer.)
|
||||
Some larger devices will work, since they are actually multi-chip
|
||||
modules with two smaller chips and individual chipselect lines.
|
||||
|
||||
@section NAND Configuration Commands
|
||||
@cindex NAND configuration
|
||||
|
||||
|
@ -2702,9 +2711,19 @@ spare areas associated with each data page.
|
|||
@end itemize
|
||||
@end deffn
|
||||
|
||||
@deffn Command {nand erase} num ...
|
||||
@deffn Command {nand erase} num offset length
|
||||
@cindex NAND erasing
|
||||
@b{NOTE:} Syntax is in flux.
|
||||
Erases blocks on the specified NAND device, starting at the
|
||||
specified @var{offset} and continuing for @var{length} bytes.
|
||||
Both of those values must be exact multiples of the device's
|
||||
block size, and the region they specify must fit entirely in the chip.
|
||||
The @var{num} parameter is the value shown by @command{nand list}.
|
||||
|
||||
@b{NOTE:} This command will try to erase bad blocks, when told
|
||||
to do so, which will probably invalidate the manufacturer's bad
|
||||
block marker.
|
||||
For the remainder of the current server session, @command{nand info}
|
||||
will still report that the block ``is'' bad.
|
||||
@end deffn
|
||||
|
||||
@deffn Command {nand write} num filename offset [option...]
|
||||
|
@ -2768,8 +2787,18 @@ the underlying driver from applying hardware ECC.
|
|||
@section Other NAND commands
|
||||
@cindex NAND other commands
|
||||
|
||||
@deffn Command {nand check_bad} num ...
|
||||
@b{NOTE:} Syntax is in flux.
|
||||
@deffn Command {nand check_bad_blocks} [offset length]
|
||||
Checks for manufacturer bad block markers on the specified NAND
|
||||
device. If no parameters are provided, checks the whole
|
||||
device; otherwise, starts at the specified @var{offset} and
|
||||
continues for @var{length} bytes.
|
||||
Both of those values must be exact multiples of the device's
|
||||
block size, and the region they specify must fit entirely in the chip.
|
||||
The @var{num} parameter is the value shown by @command{nand list}.
|
||||
|
||||
@b{NOTE:} Before using this command you should force raw access
|
||||
with @command{nand raw_access enable} to ensure that the underlying
|
||||
driver will not try to apply hardware ECC.
|
||||
@end deffn
|
||||
|
||||
@deffn Command {nand info} num
|
||||
|
|
109
src/flash/nand.c
109
src/flash/nand.c
|
@ -309,12 +309,12 @@ int nand_init(struct command_context_s *cmd_ctx)
|
|||
register_command(cmd_ctx, nand_cmd, "probe", handle_nand_probe_command, COMMAND_EXEC,
|
||||
"identify NAND flash device <num>");
|
||||
register_command(cmd_ctx, nand_cmd, "check_bad_blocks", handle_nand_check_bad_blocks_command, COMMAND_EXEC,
|
||||
"check NAND flash device <num> for bad blocks [<first> <last>]");
|
||||
"check NAND flash device <num> for bad blocks [<offset> <length>]");
|
||||
register_command(cmd_ctx, nand_cmd, "erase", handle_nand_erase_command, COMMAND_EXEC,
|
||||
"erase blocks on NAND flash device <num> <first> <last>");
|
||||
"erase blocks on NAND flash device <num> <offset> <length>");
|
||||
register_command(cmd_ctx, nand_cmd, "dump", handle_nand_dump_command, COMMAND_EXEC,
|
||||
"dump from NAND flash device <num> <filename> "
|
||||
"<offset> <size> [oob_raw|oob_only]");
|
||||
"<offset> <length> [oob_raw|oob_only]");
|
||||
register_command(cmd_ctx, nand_cmd, "write", handle_nand_write_command, COMMAND_EXEC,
|
||||
"write to NAND flash device <num> <filename> <offset> [oob_raw|oob_only|oob_softecc|oob_softecc_kw]");
|
||||
register_command(cmd_ctx, nand_cmd, "raw_access", handle_nand_raw_access_command, COMMAND_EXEC,
|
||||
|
@ -360,7 +360,7 @@ static int nand_build_bbt(struct nand_device_s *device, int first, int last)
|
|||
|| (((device->page_size == 512) && (oob[5] != 0xff)) ||
|
||||
((device->page_size == 2048) && (oob[0] != 0xff))))
|
||||
{
|
||||
LOG_WARNING("invalid block: %i", i);
|
||||
LOG_WARNING("bad block: %i", i);
|
||||
device->blocks[i].is_bad = 1;
|
||||
}
|
||||
else
|
||||
|
@ -1093,20 +1093,20 @@ static int handle_nand_info_command(struct command_context_s *cmd_ctx, char *cmd
|
|||
int first = -1;
|
||||
int last = -1;
|
||||
|
||||
if ((argc < 1) || (argc > 3))
|
||||
{
|
||||
switch (argc) {
|
||||
default:
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
}
|
||||
|
||||
if (argc == 2)
|
||||
{
|
||||
case 1:
|
||||
first = 0;
|
||||
last = INT32_MAX;
|
||||
break;
|
||||
case 2:
|
||||
first = last = strtoul(args[1], NULL, 0);
|
||||
}
|
||||
else if (argc == 3)
|
||||
{
|
||||
break;
|
||||
case 3:
|
||||
first = strtoul(args[1], NULL, 0);
|
||||
last = strtoul(args[2], NULL, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
p = get_nand_device_by_num(strtoul(args[0], NULL, 0));
|
||||
|
@ -1141,7 +1141,7 @@ static int handle_nand_info_command(struct command_context_s *cmd_ctx, char *cmd
|
|||
else
|
||||
bad_state = " (block condition unknown)";
|
||||
|
||||
command_print(cmd_ctx, "\t#%i: 0x%8.8x (0x%xkB) %s%s",
|
||||
command_print(cmd_ctx, "\t#%i: 0x%8.8x (%dkB) %s%s",
|
||||
j, p->blocks[j].offset, p->blocks[j].size / 1024,
|
||||
erase_state, bad_state);
|
||||
}
|
||||
|
@ -1203,12 +1203,31 @@ static int handle_nand_erase_command(struct command_context_s *cmd_ctx, char *cm
|
|||
p = get_nand_device_by_num(strtoul(args[0], NULL, 0));
|
||||
if (p)
|
||||
{
|
||||
int first = strtoul(args[1], NULL, 0);
|
||||
int last = strtoul(args[2], NULL, 0);
|
||||
char *cp;
|
||||
unsigned long offset;
|
||||
unsigned long length;
|
||||
|
||||
if ((retval = nand_erase(p, first, last)) == ERROR_OK)
|
||||
offset = strtoul(args[1], &cp, 0);
|
||||
if (*cp || offset == ULONG_MAX || offset % p->erase_size)
|
||||
{
|
||||
command_print(cmd_ctx, "successfully erased blocks %i to %i on NAND flash device '%s'", first, last, p->device->name);
|
||||
return ERROR_INVALID_ARGUMENTS;
|
||||
}
|
||||
offset /= p->erase_size;
|
||||
|
||||
length = strtoul(args[2], &cp, 0);
|
||||
if (*cp || length == ULONG_MAX || length % p->erase_size)
|
||||
{
|
||||
return ERROR_INVALID_ARGUMENTS;
|
||||
}
|
||||
length -= 1;
|
||||
length /= p->erase_size;
|
||||
|
||||
retval = nand_erase(p, offset, offset + length);
|
||||
if (retval == ERROR_OK)
|
||||
{
|
||||
command_print(cmd_ctx, "successfully erased blocks "
|
||||
"%lu to %lu on NAND flash device '%s'",
|
||||
offset, offset + length, p->device->name);
|
||||
}
|
||||
else if (retval == ERROR_NAND_OPERATION_FAILED)
|
||||
{
|
||||
|
@ -1240,31 +1259,53 @@ int handle_nand_check_bad_blocks_command(struct command_context_s *cmd_ctx, char
|
|||
|
||||
}
|
||||
|
||||
if (argc == 3)
|
||||
{
|
||||
first = strtoul(args[1], NULL, 0);
|
||||
last = strtoul(args[2], NULL, 0);
|
||||
p = get_nand_device_by_num(strtoul(args[0], NULL, 0));
|
||||
if (!p) {
|
||||
command_print(cmd_ctx, "NAND flash device '#%s' is out of bounds",
|
||||
args[0]);
|
||||
return ERROR_INVALID_ARGUMENTS;
|
||||
}
|
||||
|
||||
p = get_nand_device_by_num(strtoul(args[0], NULL, 0));
|
||||
if (p)
|
||||
if (argc == 3)
|
||||
{
|
||||
if ((retval = nand_build_bbt(p, first, last)) == ERROR_OK)
|
||||
char *cp;
|
||||
unsigned long offset;
|
||||
unsigned long length;
|
||||
|
||||
offset = strtoul(args[1], &cp, 0);
|
||||
if (*cp || offset == ULONG_MAX || offset % p->erase_size)
|
||||
{
|
||||
command_print(cmd_ctx, "checked NAND flash device for bad blocks, use \"nand info\" command to list blocks");
|
||||
return ERROR_INVALID_ARGUMENTS;
|
||||
}
|
||||
else if (retval == ERROR_NAND_OPERATION_FAILED)
|
||||
offset /= p->erase_size;
|
||||
|
||||
length = strtoul(args[2], &cp, 0);
|
||||
if (*cp || length == ULONG_MAX || length % p->erase_size)
|
||||
{
|
||||
command_print(cmd_ctx, "error when checking for bad blocks on NAND flash device");
|
||||
}
|
||||
else
|
||||
{
|
||||
command_print(cmd_ctx, "unknown error when checking for bad blocks on NAND flash device");
|
||||
return ERROR_INVALID_ARGUMENTS;
|
||||
}
|
||||
length -= 1;
|
||||
length /= p->erase_size;
|
||||
|
||||
first = offset;
|
||||
last = offset + length;
|
||||
}
|
||||
|
||||
retval = nand_build_bbt(p, first, last);
|
||||
if (retval == ERROR_OK)
|
||||
{
|
||||
command_print(cmd_ctx, "checked NAND flash device for bad blocks, "
|
||||
"use \"nand info\" command to list blocks");
|
||||
}
|
||||
else if (retval == ERROR_NAND_OPERATION_FAILED)
|
||||
{
|
||||
command_print(cmd_ctx, "error when checking for bad blocks on "
|
||||
"NAND flash device");
|
||||
}
|
||||
else
|
||||
{
|
||||
command_print(cmd_ctx, "NAND flash device '#%s' is out of bounds", args[0]);
|
||||
command_print(cmd_ctx, "unknown error when checking for bad "
|
||||
"blocks on NAND flash device");
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
|
|
|
@ -98,7 +98,7 @@ proc sheevaplug_reflash_uboot { } {
|
|||
# reflash the u-Boot binary and reboot into it
|
||||
sheevaplug_init
|
||||
nand probe 0
|
||||
nand erase 0 0 4
|
||||
nand erase 0 0x0 0xa0000
|
||||
nand write 0 uboot.bin 0 oob_softecc_kw
|
||||
resume
|
||||
|
||||
|
|
Loading…
Reference in New Issue