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 static struct nand_ecclayout nand_oob_16
= {
32 .eccpos
= {0, 1, 2, 3, 6, 7},
38 static struct nand_ecclayout nand_oob_64
= {
41 40, 41, 42, 43, 44, 45, 46, 47,
42 48, 49, 50, 51, 52, 53, 54, 55,
43 56, 57, 58, 59, 60, 61, 62, 63},
49 void nand_fileio_init(struct nand_fileio_state
*state
)
51 memset(state
, 0, sizeof(*state
));
52 state
->oob_format
= NAND_OOB_NONE
;
55 int nand_fileio_start(struct command_context
*cmd_ctx
,
56 struct nand_device
*nand
, const char *filename
, int filemode
,
57 struct nand_fileio_state
*state
)
59 if (state
->address
% nand
->page_size
)
61 command_print(cmd_ctx
, "only page-aligned addresses are supported");
62 return ERROR_COMMAND_SYNTAX_ERROR
;
65 duration_start(&state
->bench
);
69 int retval
= fileio_open(&state
->fileio
, filename
, filemode
, FILEIO_BINARY
);
70 if (ERROR_OK
!= retval
)
72 const char *msg
= (FILEIO_READ
== filemode
) ? "read" : "write";
73 command_print(cmd_ctx
, "failed to open '%s' for %s access",
77 state
->file_opened
= true;
80 if (!(state
->oob_format
& NAND_OOB_ONLY
))
82 state
->page_size
= nand
->page_size
;
83 state
->page
= malloc(nand
->page_size
);
86 if (state
->oob_format
& (NAND_OOB_RAW
| NAND_OOB_SW_ECC
| NAND_OOB_SW_ECC_KW
))
88 if (nand
->page_size
== 512)
91 state
->eccpos
= nand_oob_16
.eccpos
;
93 else if (nand
->page_size
== 2048)
96 state
->eccpos
= nand_oob_64
.eccpos
;
98 state
->oob
= malloc(state
->oob_size
);
103 int nand_fileio_cleanup(struct nand_fileio_state
*state
)
105 if (state
->file_opened
)
106 fileio_close(&state
->fileio
);
120 int nand_fileio_finish(struct nand_fileio_state
*state
)
122 nand_fileio_cleanup(state
);
123 return duration_measure(&state
->bench
);
126 COMMAND_HELPER(nand_fileio_parse_args
, struct nand_fileio_state
*state
,
127 struct nand_device
**dev
, enum fileio_access filemode
,
128 bool need_size
, bool sw_ecc
)
130 nand_fileio_init(state
);
132 unsigned minargs
= need_size
? 4 : 3;
133 if (CMD_ARGC
< minargs
)
134 return ERROR_COMMAND_SYNTAX_ERROR
;
136 struct nand_device
*nand
;
137 int retval
= CALL_COMMAND_HANDLER(nand_command_get_device
, 0, &nand
);
138 if (ERROR_OK
!= retval
)
141 if (NULL
== nand
->device
)
143 command_print(CMD_CTX
, "#%s: not probed", CMD_ARGV
[0]);
147 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[2], state
->address
);
150 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[3], state
->size
);
151 if (state
->size
% nand
->page_size
)
153 command_print(CMD_CTX
, "only page-aligned sizes are supported");
154 return ERROR_COMMAND_SYNTAX_ERROR
;
158 if (CMD_ARGC
> minargs
)
160 for (unsigned i
= minargs
; i
< CMD_ARGC
; i
++)
162 if (!strcmp(CMD_ARGV
[i
], "oob_raw"))
163 state
->oob_format
|= NAND_OOB_RAW
;
164 else if (!strcmp(CMD_ARGV
[i
], "oob_only"))
165 state
->oob_format
|= NAND_OOB_RAW
| NAND_OOB_ONLY
;
166 else if (sw_ecc
&& !strcmp(CMD_ARGV
[i
], "oob_softecc"))
167 state
->oob_format
|= NAND_OOB_SW_ECC
;
168 else if (sw_ecc
&& !strcmp(CMD_ARGV
[i
], "oob_softecc_kw"))
169 state
->oob_format
|= NAND_OOB_SW_ECC_KW
;
172 command_print(CMD_CTX
, "unknown option: %s", CMD_ARGV
[i
]);
173 return ERROR_COMMAND_SYNTAX_ERROR
;
178 retval
= nand_fileio_start(CMD_CTX
, nand
, CMD_ARGV
[1], filemode
, state
);
179 if (ERROR_OK
!= retval
)
185 retval
= fileio_size(&state
->fileio
, &filesize
);
186 if (retval
!= ERROR_OK
)
188 state
->size
= filesize
;
197 * @returns If no error occurred, returns number of bytes consumed;
198 * otherwise, returns a negative error code.)
200 int nand_fileio_read(struct nand_device
*nand
, struct nand_fileio_state
*s
)
202 size_t total_read
= 0;
207 fileio_read(&s
->fileio
, s
->page_size
, s
->page
, &one_read
);
208 if (one_read
< s
->page_size
)
209 memset(s
->page
+ one_read
, 0xff, s
->page_size
- one_read
);
210 total_read
+= one_read
;
213 if (s
->oob_format
& NAND_OOB_SW_ECC
)
216 memset(s
->oob
, 0xff, s
->oob_size
);
217 for (uint32_t i
= 0, j
= 0; i
< s
->page_size
; i
+= 256)
219 nand_calculate_ecc(nand
, s
->page
+ i
, ecc
);
220 s
->oob
[s
->eccpos
[j
++]] = ecc
[0];
221 s
->oob
[s
->eccpos
[j
++]] = ecc
[1];
222 s
->oob
[s
->eccpos
[j
++]] = ecc
[2];
225 else if (s
->oob_format
& NAND_OOB_SW_ECC_KW
)
228 * In this case eccpos is not used as
229 * the ECC data is always stored contigously
230 * at the end of the OOB area. It consists
231 * of 10 bytes per 512-byte data block.
233 uint8_t *ecc
= s
->oob
+ s
->oob_size
- s
->page_size
/ 512 * 10;
234 memset(s
->oob
, 0xff, s
->oob_size
);
235 for (uint32_t i
= 0; i
< s
->page_size
; i
+= 512)
237 nand_calculate_ecc_kw(nand
, s
->page
+ i
, ecc
);
241 else if (NULL
!= s
->oob
)
243 fileio_read(&s
->fileio
, s
->oob_size
, s
->oob
, &one_read
);
244 if (one_read
< s
->oob_size
)
245 memset(s
->oob
+ one_read
, 0xff, s
->oob_size
- one_read
);
246 total_read
+= one_read
;