summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/flash/nand.c61
-rw-r--r--src/flash/nand.h12
2 files changed, 68 insertions, 5 deletions
diff --git a/src/flash/nand.c b/src/flash/nand.c
index 7946e344..6977b68a 100644
--- a/src/flash/nand.c
+++ b/src/flash/nand.c
@@ -186,6 +186,39 @@ nand_manufacturer_t nand_manuf_ids[] =
{0x0, NULL},
};
+/*
+ * Define default oob placement schemes for large and small page devices
+ */
+
+nand_ecclayout_t nand_oob_8 = {
+ .eccbytes = 3,
+ .eccpos = {0, 1, 2},
+ .oobfree = {
+ {.offset = 3,
+ .length = 2},
+ {.offset = 6,
+ .length = 2}}
+};
+
+nand_ecclayout_t nand_oob_16 = {
+ .eccbytes = 6,
+ .eccpos = {0, 1, 2, 3, 6, 7},
+ .oobfree = {
+ {.offset = 8,
+ . length = 8}}
+};
+
+nand_ecclayout_t nand_oob_64 = {
+ .eccbytes = 24,
+ .eccpos = {
+ 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63},
+ .oobfree = {
+ {.offset = 2,
+ .length = 38}}
+};
+
/* nand device <nand_controller> [controller options]
*/
int handle_nand_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
@@ -1291,6 +1324,7 @@ int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char
u32 page_size = 0;
u8 *oob = NULL;
u32 oob_size = 0;
+ const int *eccpos = NULL;
offset = strtoul(args[2], NULL, 0);
@@ -1303,6 +1337,8 @@ int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char
oob_format |= NAND_OOB_RAW;
else if (!strcmp(args[i], "oob_only"))
oob_format |= NAND_OOB_RAW | NAND_OOB_ONLY;
+ else if (!strcmp(args[i], "oob_softecc"))
+ oob_format |= NAND_OOB_SW_ECC;
else
{
command_print(cmd_ctx, "unknown option: %s", args[i]);
@@ -1326,12 +1362,15 @@ int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char
page = malloc(p->page_size);
}
- if (oob_format & NAND_OOB_RAW)
+ if (oob_format & (NAND_OOB_RAW | NAND_OOB_SW_ECC))
{
- if (p->page_size == 512)
+ if (p->page_size == 512) {
oob_size = 16;
- else if (p->page_size == 2048)
+ eccpos = nand_oob_16.eccpos;
+ } else if (p->page_size == 2048) {
oob_size = 64;
+ eccpos = nand_oob_64.eccpos;
+ }
oob = malloc(oob_size);
}
@@ -1357,8 +1396,20 @@ int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char
memset(page + size_read, 0xff, page_size - size_read);
}
}
-
- if (NULL != oob)
+
+ if (oob_format & NAND_OOB_SW_ECC)
+ {
+ int i, j;
+ u8 ecc[3];
+ memset(oob, 0xff, oob_size);
+ for (i = 0, j = 0; i < page_size; i += 256) {
+ nand_calculate_ecc(p, page+i, ecc);
+ oob[eccpos[j++]] = ecc[0];
+ oob[eccpos[j++]] = ecc[1];
+ oob[eccpos[j++]] = ecc[2];
+ }
+ }
+ else if (NULL != oob)
{
fileio_read(&fileio, oob_size, oob, &size_read);
buf_cnt -= size_read;
diff --git a/src/flash/nand.h b/src/flash/nand.h
index 5535221a..bd9554c3 100644
--- a/src/flash/nand.h
+++ b/src/flash/nand.h
@@ -56,6 +56,18 @@ typedef struct nand_block_s
int is_bad;
} nand_block_t;
+struct nand_oobfree {
+ int offset;
+ int length;
+};
+
+typedef struct nand_ecclayout_s {
+ int eccbytes;
+ int eccpos[64];
+ int oobavail;
+ struct nand_oobfree oobfree[2];
+} nand_ecclayout_t;
+
typedef struct nand_device_s
{
nand_flash_controller_t *controller;