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, see <http://www.gnu.org/licenses/>. *
20 ***************************************************************************/
29 static struct nand_ecclayout nand_oob_16
= {
31 .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
51 void nand_fileio_init(struct nand_fileio_state
*state
)
53 memset(state
, 0, sizeof(*state
));
54 state
->oob_format
= NAND_OOB_NONE
;
57 int nand_fileio_start(struct command_context
*cmd_ctx
,
58 struct nand_device
*nand
, const char *filename
, int filemode
,
59 struct nand_fileio_state
*state
)
61 if (state
->address
% nand
->page_size
) {
62 command_print(cmd_ctx
, "only page-aligned addresses are supported");
63 return ERROR_COMMAND_SYNTAX_ERROR
;
66 duration_start(&state
->bench
);
68 if (NULL
!= filename
) {
69 int retval
= fileio_open(&state
->fileio
, filename
, filemode
, FILEIO_BINARY
);
70 if (ERROR_OK
!= retval
) {
71 const char *msg
= (FILEIO_READ
== filemode
) ? "read" : "write";
72 command_print(cmd_ctx
, "failed to open '%s' for %s access",
76 state
->file_opened
= true;
79 if (!(state
->oob_format
& NAND_OOB_ONLY
)) {
80 state
->page_size
= nand
->page_size
;
81 state
->page
= malloc(nand
->page_size
);
84 if (state
->oob_format
& (NAND_OOB_RAW
| NAND_OOB_SW_ECC
| NAND_OOB_SW_ECC_KW
)) {
85 if (nand
->page_size
== 512) {
87 state
->eccpos
= nand_oob_16
.eccpos
;
88 } else if (nand
->page_size
== 2048) {
90 state
->eccpos
= nand_oob_64
.eccpos
;
92 state
->oob
= malloc(state
->oob_size
);
97 int nand_fileio_cleanup(struct nand_fileio_state
*state
)
99 if (state
->file_opened
)
100 fileio_close(state
->fileio
);
112 int nand_fileio_finish(struct nand_fileio_state
*state
)
114 nand_fileio_cleanup(state
);
115 return duration_measure(&state
->bench
);
118 COMMAND_HELPER(nand_fileio_parse_args
, struct nand_fileio_state
*state
,
119 struct nand_device
**dev
, enum fileio_access filemode
,
120 bool need_size
, bool sw_ecc
)
122 nand_fileio_init(state
);
124 unsigned minargs
= need_size
? 4 : 3;
125 if (CMD_ARGC
< minargs
)
126 return ERROR_COMMAND_SYNTAX_ERROR
;
128 struct nand_device
*nand
;
129 int retval
= CALL_COMMAND_HANDLER(nand_command_get_device
, 0, &nand
);
130 if (ERROR_OK
!= retval
)
133 if (NULL
== nand
->device
) {
134 command_print(CMD_CTX
, "#%s: not probed", CMD_ARGV
[0]);
135 return ERROR_NAND_DEVICE_NOT_PROBED
;
138 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[2], state
->address
);
140 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[3], state
->size
);
141 if (state
->size
% nand
->page_size
) {
142 command_print(CMD_CTX
, "only page-aligned sizes are supported");
143 return ERROR_COMMAND_SYNTAX_ERROR
;
147 if (CMD_ARGC
> minargs
) {
148 for (unsigned i
= minargs
; i
< CMD_ARGC
; i
++) {
149 if (!strcmp(CMD_ARGV
[i
], "oob_raw"))
150 state
->oob_format
|= NAND_OOB_RAW
;
151 else if (!strcmp(CMD_ARGV
[i
], "oob_only"))
152 state
->oob_format
|= NAND_OOB_RAW
| NAND_OOB_ONLY
;
153 else if (sw_ecc
&& !strcmp(CMD_ARGV
[i
], "oob_softecc"))
154 state
->oob_format
|= NAND_OOB_SW_ECC
;
155 else if (sw_ecc
&& !strcmp(CMD_ARGV
[i
], "oob_softecc_kw"))
156 state
->oob_format
|= NAND_OOB_SW_ECC_KW
;
158 command_print(CMD_CTX
, "unknown option: %s", CMD_ARGV
[i
]);
159 return ERROR_COMMAND_SYNTAX_ERROR
;
164 retval
= nand_fileio_start(CMD_CTX
, nand
, CMD_ARGV
[1], filemode
, state
);
165 if (ERROR_OK
!= retval
)
170 retval
= fileio_size(state
->fileio
, &filesize
);
171 if (retval
!= ERROR_OK
)
173 state
->size
= filesize
;
182 * @returns If no error occurred, returns number of bytes consumed;
183 * otherwise, returns a negative error code.)
185 int nand_fileio_read(struct nand_device
*nand
, struct nand_fileio_state
*s
)
187 size_t total_read
= 0;
190 if (NULL
!= s
->page
) {
191 fileio_read(s
->fileio
, s
->page_size
, s
->page
, &one_read
);
192 if (one_read
< s
->page_size
)
193 memset(s
->page
+ one_read
, 0xff, s
->page_size
- one_read
);
194 total_read
+= one_read
;
197 if (s
->oob_format
& NAND_OOB_SW_ECC
) {
199 memset(s
->oob
, 0xff, s
->oob_size
);
200 for (uint32_t i
= 0, j
= 0; i
< s
->page_size
; i
+= 256) {
201 nand_calculate_ecc(nand
, s
->page
+ i
, ecc
);
202 s
->oob
[s
->eccpos
[j
++]] = ecc
[0];
203 s
->oob
[s
->eccpos
[j
++]] = ecc
[1];
204 s
->oob
[s
->eccpos
[j
++]] = ecc
[2];
206 } else if (s
->oob_format
& NAND_OOB_SW_ECC_KW
) {
208 * In this case eccpos is not used as
209 * the ECC data is always stored contigously
210 * at the end of the OOB area. It consists
211 * of 10 bytes per 512-byte data block.
213 uint8_t *ecc
= s
->oob
+ s
->oob_size
- s
->page_size
/ 512 * 10;
214 memset(s
->oob
, 0xff, s
->oob_size
);
215 for (uint32_t i
= 0; i
< s
->page_size
; i
+= 512) {
216 nand_calculate_ecc_kw(nand
, s
->page
+ i
, ecc
);
219 } else if (NULL
!= s
->oob
) {
220 fileio_read(s
->fileio
, s
->oob_size
, s
->oob
, &one_read
);
221 if (one_read
< s
->oob_size
)
222 memset(s
->oob
+ one_read
, 0xff, s
->oob_size
- one_read
);
223 total_read
+= one_read
;