The Kirkwood bootrom expects 4-bit ECC from NAND. This adds
4-bit ECC computation to the NAND support and uses it with SheevaPlug.
(patch attached)
Nicolas
diff --git a/src/flash/Makefile.am b/src/flash/Makefile.am
index 7895edc..e5b76cb 100644
--- a/src/flash/Makefile.am
+++ b/src/flash/Makefile.am
@@ -7,7 +7,7 @@ METASOURCES = AUTO
noinst_LTLIBRARIES = libflash.la
libflash_la_SOURCES = \
flash.c lpc2000.c cfi.c non_cfi.c at91sam7.c \
- str7x.c str9x.c aduc702x.c nand.c nand_ecc.c \
+ str7x.c str9x.c aduc702x.c nand.c nand_ecc.c nand_ecc_kw.c \
lpc3180_nand_controller.c stellaris.c str9xpec.c stm32x.c tms470.c \
ecos.c orion_nand.c s3c24xx_nand.c s3c2410_nand.c s3c2412_nand.c \
s3c2440_nand.c s3c2443_nand.c lpc288x.c ocl.c mflash.c pic32mx.c avrf.c
diff --git a/src/flash/nand.c b/src/flash/nand.c
index 8efed03..057feb7 100644
--- a/src/flash/nand.c
+++ b/src/flash/nand.c
@@ -1332,6 +1332,8 @@ static int handle_nand_write_command(struct
command_context_s *cmd_ctx, char *cm
oob_format |= NAND_OOB_RAW |
NAND_OOB_ONLY;
else if (!strcmp(args[i], "oob_softecc"))
oob_format |= NAND_OOB_SW_ECC;
+ else if (!strcmp(args[i], "oob_softecc_kw"))
+ oob_format |= NAND_OOB_SW_ECC_KW;
else
{
command_print(cmd_ctx, "unknown option:
%s", args[i]);
@@ -1355,7 +1357,7 @@ static int handle_nand_write_command(struct
command_context_s *cmd_ctx, char *cm
page = malloc(p->page_size);
}
- if (oob_format & (NAND_OOB_RAW | NAND_OOB_SW_ECC))
+ if (oob_format & (NAND_OOB_RAW | NAND_OOB_SW_ECC |
NAND_OOB_SW_ECC_KW))
{
if (p->page_size == 512) {
oob_size = 16;
@@ -1401,6 +1403,21 @@ static int handle_nand_write_command(struct
command_context_s *cmd_ctx, char *cm
oob[eccpos[j++]] = ecc[1];
oob[eccpos[j++]] = ecc[2];
}
+ } else if (oob_format & NAND_OOB_SW_ECC_KW)
+ {
+ /*
+* In this case eccpos is not used as
+* the ECC data is always stored contigously
+* at the end of the OOB area. It consists
+* of 10 bytes per 512-byte data block.
+*/
+ u32 i;
+ u8 *ecc = oob + oob_size - page_size/512 * 10;
+ memset(oob, 0xff, oob_size);
+ for (i = 0; i < page_size; i += 512) {
+ nand_calculate_ecc_kw(p, page+i, ecc);
+ ecc += 10;
+ }
}
else if (NULL != oob)
{
diff --git a/src/flash/nand.h b/src/flash/nand.h
index bd9554c..b3c6b6b 100644
--- a/src/flash/nand.h
+++ b/src/flash/nand.h
@@ -200,6 +200,7 @@ enum oob_formats
NAND_OOB_ONLY = 0x2,/* only OOB data */
NAND_OOB_SW_ECC = 0x10, /* when writing, use SW ECC (as opposed to no
ECC) */
NAND_OOB_HW_ECC = 0x20, /* when writing, use HW ECC (as opposed to no
ECC) */
+ NAND_OOB_SW_ECC_KW = 0x40, /* when writing, use Marvell's Kirkwood
bootrom format */
NAND_OOB_JFFS2 = 0x100, /* when writing, use JFFS2 OOB layout */
NAND_OOB_YAFFS2 = 0x100,/* when writing, use YAFFS2 OOB layout */
};
@@ -210,6 +211,7 @@ extern int nand_read_page_raw(struct nand_device_s *device,
u32 page, u8 *data,
extern int nand_write_page_raw(struct nand_device_s *device, u32 page, u8
*data, u32 data_size, u8 *oob, u32 oob_size);
extern int nand_read_status(struct nand_device_s *device, u8 *status);
extern int nand_calculate_ecc(struct nand_device_s *device, const u8 *dat, u8
*ecc_code);
+extern int nand_calculate_ecc_kw(struct nand_device_s *device, const u8 *dat,
u8 *ecc_code);
extern int nand_register_commands(struct command_context_s *cmd_ctx);
extern int nand_init(struct command_context_s *cmd_ctx);
diff --git a/src/flash/nand_ecc_kw.c b/src/flash/nand_ecc_kw.c
new file mode 100644
index 000..a7fae62
--- /dev/null
+++ b/src/flash/nand_ecc_kw.c
@@ -0,0 +1,174 @@
+/*
+ * Reed-Solomon ECC handling for the Marvell Kirkwood SOC
+ * Copyright (C) 2009 Marvell Semiconductor, Inc.
+ *
+ * Authors: Lennert Buytenhek
+ * Nicolas Pitre
+ *
+ * This file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public L