blob: 1da5b03a31ba52790dfbf8aac6326e1c2fed94f5 [file] [log] [blame]
wdenkdc7c9a12003-03-26 06:55:25 +00001/*
2 * Driver for NAND support, Rick Bronson
3 * borrowed heavily from:
4 * (c) 1999 Machine Vision Holdings, Inc.
5 * (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org>
6 *
7 */
8
9#include <common.h>
wdenkdc7c9a12003-03-26 06:55:25 +000010#include <command.h>
11#include <malloc.h>
12#include <asm/io.h>
13
14#ifdef CONFIG_SHOW_BOOT_PROGRESS
15# include <status_led.h>
16# define SHOW_BOOT_PROGRESS(arg) show_boot_progress(arg)
17#else
18# define SHOW_BOOT_PROGRESS(arg)
19#endif
20
21#if (CONFIG_COMMANDS & CFG_CMD_NAND)
22
wdenkdc7c9a12003-03-26 06:55:25 +000023#include <linux/mtd/nand.h>
24#include <linux/mtd/nand_ids.h>
wdenk7a8e9bed2003-05-31 18:35:21 +000025#include <jffs2/jffs2.h>
wdenkdc7c9a12003-03-26 06:55:25 +000026
27/*
28 * Definition of the out of band configuration structure
29 */
30struct nand_oob_config {
31 int ecc_pos[6]; /* position of ECC bytes inside oob */
32 int badblock_pos; /* position of bad block flag inside oob -1 = inactive */
33 int eccvalid_pos; /* position of ECC valid flag inside oob -1 = inactive */
34} oob_config = { {0}, 0, 0};
35
wdenk7a8e9bed2003-05-31 18:35:21 +000036#undef NAND_DEBUG
wdenkdc7c9a12003-03-26 06:55:25 +000037#undef PSYCHO_DEBUG
wdenk7a8e9bed2003-05-31 18:35:21 +000038
39/* ****************** WARNING *********************
40 * When ALLOW_ERASE_BAD_DEBUG is non-zero the erase command will
41 * erase (or at least attempt to erase) blocks that are marked
42 * bad. This can be very handy if you are _sure_ that the block
43 * is OK, say because you marked a good block bad to test bad
44 * block handling and you are done testing, or if you have
45 * accidentally marked blocks bad.
46 *
47 * Erasing factory marked bad blocks is a _bad_ idea. If the
48 * erase succeeds there is no reliable way to find them again,
49 * and attempting to program or erase bad blocks can affect
50 * the data in _other_ (good) blocks.
51 */
52#define ALLOW_ERASE_BAD_DEBUG 0
wdenkdc7c9a12003-03-26 06:55:25 +000053
54#define CONFIG_MTD_NAND_ECC /* enable ECC */
55/* #define CONFIG_MTD_NAND_ECC_JFFS2 */
56
wdenk7a8e9bed2003-05-31 18:35:21 +000057/* bits for nand_rw() `cmd'; or together as needed */
58#define NANDRW_READ 0x01
59#define NANDRW_WRITE 0x00
60#define NANDRW_JFFS2 0x02
61
wdenkdc7c9a12003-03-26 06:55:25 +000062/*
63 * Function Prototypes
64 */
65static void nand_print(struct nand_chip *nand);
66static int nand_rw (struct nand_chip* nand, int cmd,
67 size_t start, size_t len,
68 size_t * retlen, u_char * buf);
wdenk7a8e9bed2003-05-31 18:35:21 +000069static int nand_erase(struct nand_chip* nand, size_t ofs, size_t len, int clean);
wdenkdc7c9a12003-03-26 06:55:25 +000070static int nand_read_ecc(struct nand_chip *nand, size_t start, size_t len,
71 size_t * retlen, u_char *buf, u_char *ecc_code);
72static int nand_write_ecc (struct nand_chip* nand, size_t to, size_t len,
73 size_t * retlen, const u_char * buf, u_char * ecc_code);
wdenk7a8e9bed2003-05-31 18:35:21 +000074static void nand_print_bad(struct nand_chip *nand);
75static int nand_read_oob(struct nand_chip* nand, size_t ofs, size_t len,
76 size_t * retlen, u_char * buf);
77static int nand_write_oob(struct nand_chip* nand, size_t ofs, size_t len,
78 size_t * retlen, const u_char * buf);
wdenkdc7c9a12003-03-26 06:55:25 +000079#ifdef CONFIG_MTD_NAND_ECC
80static int nand_correct_data (u_char *dat, u_char *read_ecc, u_char *calc_ecc);
81static void nand_calculate_ecc (const u_char *dat, u_char *ecc_code);
82#endif
83
wdenk7a8e9bed2003-05-31 18:35:21 +000084struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE] = {{0}};
wdenkdc7c9a12003-03-26 06:55:25 +000085
86/* Current NAND Device */
87static int curr_device = -1;
88
89/* ------------------------------------------------------------------------- */
90
91int do_nand (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
92{
93 int rcode = 0;
94
95 switch (argc) {
96 case 0:
97 case 1:
98 printf ("Usage:\n%s\n", cmdtp->usage);
99 return 1;
100 case 2:
wdenk8bde7f72003-06-27 21:31:46 +0000101 if (strcmp(argv[1],"info") == 0) {
wdenkdc7c9a12003-03-26 06:55:25 +0000102 int i;
103
104 putc ('\n');
105
106 for (i=0; i<CFG_MAX_NAND_DEVICE; ++i) {
107 if(nand_dev_desc[i].ChipID == NAND_ChipID_UNKNOWN)
108 continue; /* list only known devices */
109 printf ("Device %d: ", i);
110 nand_print(&nand_dev_desc[i]);
111 }
112 return 0;
113
114 } else if (strcmp(argv[1],"device") == 0) {
115 if ((curr_device < 0) || (curr_device >= CFG_MAX_NAND_DEVICE)) {
116 puts ("\nno devices available\n");
117 return 1;
118 }
119 printf ("\nDevice %d: ", curr_device);
120 nand_print(&nand_dev_desc[curr_device]);
121 return 0;
wdenk7a8e9bed2003-05-31 18:35:21 +0000122
123 } else if (strcmp(argv[1],"bad") == 0) {
124 if ((curr_device < 0) || (curr_device >= CFG_MAX_NAND_DEVICE)) {
125 puts ("\nno devices available\n");
126 return 1;
127 }
128 printf ("\nDevice %d bad blocks:\n", curr_device);
129 nand_print_bad(&nand_dev_desc[curr_device]);
130 return 0;
131
wdenkdc7c9a12003-03-26 06:55:25 +0000132 }
133 printf ("Usage:\n%s\n", cmdtp->usage);
134 return 1;
135 case 3:
136 if (strcmp(argv[1],"device") == 0) {
137 int dev = (int)simple_strtoul(argv[2], NULL, 10);
138
139 printf ("\nDevice %d: ", dev);
140 if (dev >= CFG_MAX_NAND_DEVICE) {
141 puts ("unknown device\n");
142 return 1;
143 }
144 nand_print(&nand_dev_desc[dev]);
145 /*nand_print (dev);*/
146
147 if (nand_dev_desc[dev].ChipID == NAND_ChipID_UNKNOWN) {
148 return 1;
149 }
150
151 curr_device = dev;
152
153 puts ("... is now current device\n");
154
155 return 0;
156 }
wdenk7a8e9bed2003-05-31 18:35:21 +0000157 else if (strcmp(argv[1],"erase") == 0 && strcmp(argv[2], "clean") == 0) {
158 struct nand_chip* nand = &nand_dev_desc[curr_device];
159 ulong off = 0;
160 ulong size = nand->totlen;
161 int ret;
162
163 printf ("\nNAND erase: device %d offset %ld, size %ld ... ",
164 curr_device, off, size);
165
166 ret = nand_erase (nand, off, size, 1);
167
168 printf("%s\n", ret ? "ERROR" : "OK");
169
170 return ret;
171 }
wdenkdc7c9a12003-03-26 06:55:25 +0000172
173 printf ("Usage:\n%s\n", cmdtp->usage);
174 return 1;
175 default:
176 /* at least 4 args */
177
wdenk7a8e9bed2003-05-31 18:35:21 +0000178 if (strncmp(argv[1], "read", 4) == 0 ||
179 strncmp(argv[1], "write", 5) == 0) {
wdenkdc7c9a12003-03-26 06:55:25 +0000180 ulong addr = simple_strtoul(argv[2], NULL, 16);
181 ulong off = simple_strtoul(argv[3], NULL, 16);
182 ulong size = simple_strtoul(argv[4], NULL, 16);
wdenk7a8e9bed2003-05-31 18:35:21 +0000183 int cmd = (strncmp(argv[1], "read", 4) == 0) ?
184 NANDRW_READ : NANDRW_WRITE;
wdenkdc7c9a12003-03-26 06:55:25 +0000185 int ret, total;
wdenk7a8e9bed2003-05-31 18:35:21 +0000186 char* cmdtail = strchr(argv[1], '.');
187
188 if (cmdtail && !strncmp(cmdtail, ".oob", 2)) {
189 /* read out-of-band data */
190 if (cmd & NANDRW_READ) {
191 ret = nand_read_oob(nand_dev_desc + curr_device,
192 off, size, &total,
193 (u_char*)addr);
194 }
195 else {
196 ret = nand_write_oob(nand_dev_desc + curr_device,
197 off, size, &total,
198 (u_char*)addr);
199 }
200 return ret;
201 }
202 else if (cmdtail && !strncmp(cmdtail, ".jffs2", 2))
203 cmd |= NANDRW_JFFS2; /* skip bad blocks */
204#ifdef SXNI855T
205 /* need ".e" same as ".j" for compatibility with older units */
206 else if (cmdtail && !strcmp(cmdtail, ".e"))
207 cmd |= NANDRW_JFFS2; /* skip bad blocks */
208#endif
209 else if (cmdtail) {
210 printf ("Usage:\n%s\n", cmdtp->usage);
211 return 1;
212 }
wdenkdc7c9a12003-03-26 06:55:25 +0000213
214 printf ("\nNAND %s: device %d offset %ld, size %ld ... ",
wdenk7a8e9bed2003-05-31 18:35:21 +0000215 (cmd & NANDRW_READ) ? "read" : "write",
216 curr_device, off, size);
wdenkdc7c9a12003-03-26 06:55:25 +0000217
218 ret = nand_rw(nand_dev_desc + curr_device, cmd, off, size,
219 &total, (u_char*)addr);
220
wdenk7a8e9bed2003-05-31 18:35:21 +0000221 printf ("%d bytes %s: %s\n", total,
222 (cmd & NANDRW_READ) ? "read" : "write",
wdenkdc7c9a12003-03-26 06:55:25 +0000223 ret ? "ERROR" : "OK");
224
225 return ret;
wdenk7a8e9bed2003-05-31 18:35:21 +0000226 } else if (strcmp(argv[1],"erase") == 0 &&
227 (argc == 4 || strcmp("clean", argv[2]) == 0)) {
228 int clean = argc == 5;
229 ulong off = simple_strtoul(argv[2 + clean], NULL, 16);
230 ulong size = simple_strtoul(argv[3 + clean], NULL, 16);
wdenkdc7c9a12003-03-26 06:55:25 +0000231 int ret;
232
233 printf ("\nNAND erase: device %d offset %ld, size %ld ... ",
234 curr_device, off, size);
235
wdenk7a8e9bed2003-05-31 18:35:21 +0000236 ret = nand_erase (nand_dev_desc + curr_device, off, size, clean);
wdenkdc7c9a12003-03-26 06:55:25 +0000237
238 printf("%s\n", ret ? "ERROR" : "OK");
239
240 return ret;
241 } else {
242 printf ("Usage:\n%s\n", cmdtp->usage);
243 rcode = 1;
244 }
245
246 return rcode;
247 }
248}
249
wdenkb0fce992003-06-29 21:03:46 +0000250cmd_tbl_t U_BOOT_CMD(NAND) = MK_CMD_ENTRY(
251 "nand", 5, 1, do_nand,
252 "nand - NAND sub-system\n",
253 "info - show available NAND devices\n"
254 "nand device [dev] - show or set current device\n"
255 "nand read[.jffs2] addr off size\n"
256 "nand write[.jffs2] addr off size - read/write `size' bytes starting\n"
257 " at offset `off' to/from memory address `addr'\n"
258 "nand erase [clean] [off size] - erase `size' bytes from\n"
259 " offset `off' (entire device if not specified)\n"
260 "nand bad - show bad blocks\n"
261 "nand read.oob addr off size - read out-of-band data\n"
262 "nand write.oob addr off size - read out-of-band data\n"
263);
264
wdenkdc7c9a12003-03-26 06:55:25 +0000265int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
266{
267 char *boot_device = NULL;
268 char *ep;
269 int dev;
270 ulong cnt;
271 ulong addr;
272 ulong offset = 0;
273 image_header_t *hdr;
274 int rcode = 0;
275 switch (argc) {
276 case 1:
277 addr = CFG_LOAD_ADDR;
278 boot_device = getenv ("bootdevice");
279 break;
280 case 2:
281 addr = simple_strtoul(argv[1], NULL, 16);
282 boot_device = getenv ("bootdevice");
283 break;
284 case 3:
285 addr = simple_strtoul(argv[1], NULL, 16);
286 boot_device = argv[2];
287 break;
288 case 4:
289 addr = simple_strtoul(argv[1], NULL, 16);
290 boot_device = argv[2];
291 offset = simple_strtoul(argv[3], NULL, 16);
292 break;
293 default:
294 printf ("Usage:\n%s\n", cmdtp->usage);
295 SHOW_BOOT_PROGRESS (-1);
296 return 1;
297 }
298
299 if (!boot_device) {
300 puts ("\n** No boot device **\n");
301 SHOW_BOOT_PROGRESS (-1);
302 return 1;
303 }
304
305 dev = simple_strtoul(boot_device, &ep, 16);
306
307 if ((dev >= CFG_MAX_NAND_DEVICE) ||
308 (nand_dev_desc[dev].ChipID == NAND_ChipID_UNKNOWN)) {
309 printf ("\n** Device %d not available\n", dev);
310 SHOW_BOOT_PROGRESS (-1);
311 return 1;
312 }
313
wdenk7a8e9bed2003-05-31 18:35:21 +0000314 printf ("\nLoading from device %d: %s at 0x%lx (offset 0x%lx)\n",
wdenkdc7c9a12003-03-26 06:55:25 +0000315 dev, nand_dev_desc[dev].name, nand_dev_desc[dev].IO_ADDR,
316 offset);
317
wdenk7a8e9bed2003-05-31 18:35:21 +0000318 if (nand_rw (nand_dev_desc + dev, NANDRW_READ, offset,
wdenkdc7c9a12003-03-26 06:55:25 +0000319 SECTORSIZE, NULL, (u_char *)addr)) {
320 printf ("** Read error on %d\n", dev);
321 SHOW_BOOT_PROGRESS (-1);
322 return 1;
323 }
324
325 hdr = (image_header_t *)addr;
326
327 if (ntohl(hdr->ih_magic) == IH_MAGIC) {
328
329 print_image_hdr (hdr);
330
331 cnt = (ntohl(hdr->ih_size) + sizeof(image_header_t));
332 cnt -= SECTORSIZE;
333 } else {
334 printf ("\n** Bad Magic Number 0x%x **\n", hdr->ih_magic);
335 SHOW_BOOT_PROGRESS (-1);
336 return 1;
337 }
338
wdenk7a8e9bed2003-05-31 18:35:21 +0000339 if (nand_rw (nand_dev_desc + dev, NANDRW_READ, offset + SECTORSIZE, cnt,
wdenkdc7c9a12003-03-26 06:55:25 +0000340 NULL, (u_char *)(addr+SECTORSIZE))) {
341 printf ("** Read error on %d\n", dev);
342 SHOW_BOOT_PROGRESS (-1);
343 return 1;
344 }
345
346 /* Loading ok, update default load address */
347
348 load_addr = addr;
349
350 /* Check if we should attempt an auto-start */
351 if (((ep = getenv("autostart")) != NULL) && (strcmp(ep,"yes") == 0)) {
352 char *local_args[2];
353 extern int do_bootm (cmd_tbl_t *, int, int, char *[]);
354
355 local_args[0] = argv[0];
356 local_args[1] = NULL;
357
wdenk7a8e9bed2003-05-31 18:35:21 +0000358 printf ("Automatic boot of image at addr 0x%08lx ...\n", addr);
wdenkdc7c9a12003-03-26 06:55:25 +0000359
360 do_bootm (cmdtp, 0, 1, local_args);
361 rcode = 1;
362 }
363 return rcode;
364}
365
wdenkb0fce992003-06-29 21:03:46 +0000366cmd_tbl_t U_BOOT_CMD(NBOOT) = MK_CMD_ENTRY(
367 "nboot", 4, 1, do_nandboot,
368 "nboot - boot from NAND device\n",
369 "loadAddr dev\n"
370);
371
wdenk7a8e9bed2003-05-31 18:35:21 +0000372/* returns 0 if block containing pos is OK:
373 * valid erase block and
374 * not marked bad, or no bad mark position is specified
375 * returns 1 if marked bad or otherwise invalid
376 */
377int check_block(struct nand_chip* nand, unsigned long pos)
378{
379 int retlen;
380 uint8_t oob_data;
381 int page0 = pos & (-nand->erasesize);
382 int page1 = page0 + nand->oobblock;
383 int badpos = oob_config.badblock_pos;
384
385 if (pos >= nand->totlen)
386 return 1;
387
388 if (badpos < 0)
389 return 0; /* no way to check, assume OK */
390
391 /* Note - bad block marker can be on first or second page */
392 if (nand_read_oob(nand, page0 + badpos, 1, &retlen, &oob_data) ||
393 oob_data != 0xff ||
394 nand_read_oob(nand, page1 + badpos, 1, &retlen, &oob_data) ||
395 oob_data != 0xff)
396 return 1;
397
398 return 0;
399}
wdenk8bde7f72003-06-27 21:31:46 +0000400
wdenk7a8e9bed2003-05-31 18:35:21 +0000401/* print bad blocks in NAND flash */
402static void nand_print_bad(struct nand_chip* nand)
403{
404 unsigned long pos;
405
406 for (pos = 0; pos < nand->totlen; pos += nand->erasesize) {
407 if (check_block(nand, pos))
408 printf(" 0x%8.8lx\n", pos);
409 }
410 puts("\n");
411}
412
413/* cmd: 0: NANDRW_WRITE write, fail on bad block
414 * 1: NANDRW_READ read, fail on bad block
415 * 2: NANDRW_WRITE | NANDRW_JFFS2 write, skip bad blocks
416 * 3: NANDRW_READ | NANDRW_JFFS2 read, data all 0xff for bad blocks
417 */
wdenkdc7c9a12003-03-26 06:55:25 +0000418static int nand_rw (struct nand_chip* nand, int cmd,
419 size_t start, size_t len,
420 size_t * retlen, u_char * buf)
421{
422 int noecc, ret = 0, n, total = 0;
423 char eccbuf[6];
wdenk7a8e9bed2003-05-31 18:35:21 +0000424 /* eblk (once set) is the start of the erase block containing the
425 * data being processed.
426 */
427 unsigned long eblk = ~0; /* force mismatch on first pass */
428 unsigned long erasesize = nand->erasesize;
wdenkdc7c9a12003-03-26 06:55:25 +0000429
wdenk7a8e9bed2003-05-31 18:35:21 +0000430 while (len) {
431 if ((start & (-erasesize)) != eblk) {
432 /* have crossed into new erase block, deal with
433 * it if it is sure marked bad.
434 */
435 eblk = start & (-erasesize); /* start of block */
436 if (check_block(nand, eblk)) {
437 if (cmd == (NANDRW_READ | NANDRW_JFFS2)) {
438 while (len > 0 &&
439 start - eblk < erasesize) {
440 *(buf++) = 0xff;
441 ++start;
442 ++total;
443 --len;
444 }
445 continue;
446 }
447 else if (cmd == (NANDRW_WRITE | NANDRW_JFFS2)) {
448 /* skip bad block */
449 start += erasesize;
450 continue;
451 }
452 else {
453 ret = 1;
454 break;
455 }
456 }
457 }
wdenkdc7c9a12003-03-26 06:55:25 +0000458 /* The ECC will not be calculated correctly if
459 less than 512 is written or read */
460 noecc = (start != (start | 0x1ff) + 1) || (len < 0x200);
wdenk7a8e9bed2003-05-31 18:35:21 +0000461 if (cmd & NANDRW_READ)
462 ret = nand_read_ecc(nand, start,
463 min(len, eblk + erasesize - start),
wdenkdc7c9a12003-03-26 06:55:25 +0000464 &n, (u_char*)buf,
465 noecc ? NULL : eccbuf);
466 else
wdenk7a8e9bed2003-05-31 18:35:21 +0000467 ret = nand_write_ecc(nand, start,
468 min(len, eblk + erasesize - start),
wdenkdc7c9a12003-03-26 06:55:25 +0000469 &n, (u_char*)buf,
470 noecc ? NULL : eccbuf);
471
472 if (ret)
473 break;
474
475 start += n;
476 buf += n;
477 total += n;
478 len -= n;
479 }
480 if (retlen)
481 *retlen = total;
482
483 return ret;
484}
485
486static void nand_print(struct nand_chip *nand)
wdenk0db5bca2003-03-31 17:27:09 +0000487{
wdenk7a8e9bed2003-05-31 18:35:21 +0000488 if (nand->numchips > 1) {
489 printf("%s at 0x%lx,\n"
490 "\t %d chips %s, size %d MB, \n"
491 "\t total size %ld MB, sector size %ld kB\n",
492 nand->name, nand->IO_ADDR, nand->numchips,
493 nand->chips_name, 1 << (nand->chipshift - 20),
494 nand->totlen >> 20, nand->erasesize >> 10);
495 }
496 else {
wdenk8bde7f72003-06-27 21:31:46 +0000497 printf("%s at 0x%lx (", nand->chips_name, nand->IO_ADDR);
wdenk7a8e9bed2003-05-31 18:35:21 +0000498 print_size(nand->totlen, ", ");
499 print_size(nand->erasesize, " sector)\n");
wdenkdc7c9a12003-03-26 06:55:25 +0000500 }
501}
502
503/* ------------------------------------------------------------------------- */
504
505/* This function is needed to avoid calls of the __ashrdi3 function. */
wdenk0db5bca2003-03-31 17:27:09 +0000506#if 0
wdenkdc7c9a12003-03-26 06:55:25 +0000507static int shr(int val, int shift)
wdenk0db5bca2003-03-31 17:27:09 +0000508{
wdenkdc7c9a12003-03-26 06:55:25 +0000509 return val >> shift;
510}
wdenk0db5bca2003-03-31 17:27:09 +0000511#endif
wdenkdc7c9a12003-03-26 06:55:25 +0000512static int NanD_WaitReady(struct nand_chip *nand)
513{
514 /* This is inline, to optimise the common case, where it's ready instantly */
515 int ret = 0;
wdenk0db5bca2003-03-31 17:27:09 +0000516 NAND_WAIT_READY(nand);
wdenkdc7c9a12003-03-26 06:55:25 +0000517
518 return ret;
519}
520
521/* NanD_Command: Send a flash command to the flash chip */
522
523static inline int NanD_Command(struct nand_chip *nand, unsigned char command)
524{
525 unsigned long nandptr = nand->IO_ADDR;
526
527 /* Assert the CLE (Command Latch Enable) line to the flash chip */
528 NAND_CTL_SETCLE(nandptr);
529
530 /* Send the command */
531 WRITE_NAND_COMMAND(command, nandptr);
532
533 /* Lower the CLE line */
534 NAND_CTL_CLRCLE(nandptr);
535
536 return NanD_WaitReady(nand);
537}
538
539/* NanD_Address: Set the current address for the flash chip */
540
541static int NanD_Address(struct nand_chip *nand, int numbytes, unsigned long ofs)
wdenk0db5bca2003-03-31 17:27:09 +0000542{
543 unsigned long nandptr;
544 int i;
wdenkdc7c9a12003-03-26 06:55:25 +0000545
wdenk0db5bca2003-03-31 17:27:09 +0000546 nandptr = nand->IO_ADDR;
wdenkdc7c9a12003-03-26 06:55:25 +0000547
548 /* Assert the ALE (Address Latch Enable) line to the flash chip */
wdenk0db5bca2003-03-31 17:27:09 +0000549 NAND_CTL_SETALE(nandptr);
wdenkdc7c9a12003-03-26 06:55:25 +0000550
wdenk0db5bca2003-03-31 17:27:09 +0000551 /* Send the address */
552 /* Devices with 256-byte page are addressed as:
553 * Column (bits 0-7), Page (bits 8-15, 16-23, 24-31)
554 * there is no device on the market with page256
555 * and more than 24 bits.
556 * Devices with 512-byte page are addressed as:
557 * Column (bits 0-7), Page (bits 9-16, 17-24, 25-31)
558 * 25-31 is sent only if the chip support it.
559 * bit 8 changes the read command to be sent
560 * (NAND_CMD_READ0 or NAND_CMD_READ1).
wdenkdc7c9a12003-03-26 06:55:25 +0000561 */
562
wdenk0db5bca2003-03-31 17:27:09 +0000563 if (numbytes == ADDR_COLUMN || numbytes == ADDR_COLUMN_PAGE)
564 WRITE_NAND_ADDRESS(ofs, nandptr);
wdenkdc7c9a12003-03-26 06:55:25 +0000565
wdenk0db5bca2003-03-31 17:27:09 +0000566 ofs = ofs >> nand->page_shift;
wdenkdc7c9a12003-03-26 06:55:25 +0000567
wdenk0db5bca2003-03-31 17:27:09 +0000568 if (numbytes == ADDR_PAGE || numbytes == ADDR_COLUMN_PAGE)
569 for (i = 0; i < nand->pageadrlen; i++, ofs = ofs >> 8)
570 WRITE_NAND_ADDRESS(ofs, nandptr);
wdenkdc7c9a12003-03-26 06:55:25 +0000571
wdenk0db5bca2003-03-31 17:27:09 +0000572 /* Lower the ALE line */
573 NAND_CTL_CLRALE(nandptr);
wdenkdc7c9a12003-03-26 06:55:25 +0000574
wdenk0db5bca2003-03-31 17:27:09 +0000575 /* Wait for the chip to respond */
576 return NanD_WaitReady(nand);
577}
wdenkdc7c9a12003-03-26 06:55:25 +0000578
579/* NanD_SelectChip: Select a given flash chip within the current floor */
580
581static inline int NanD_SelectChip(struct nand_chip *nand, int chip)
582{
583 /* Wait for it to be ready */
584 return NanD_WaitReady(nand);
585}
586
587/* NanD_IdentChip: Identify a given NAND chip given {floor,chip} */
588
589static int NanD_IdentChip(struct nand_chip *nand, int floor, int chip)
590{
591 int mfr, id, i;
592
wdenk0db5bca2003-03-31 17:27:09 +0000593 NAND_ENABLE_CE(nand); /* set pin low */
wdenkdc7c9a12003-03-26 06:55:25 +0000594 /* Reset the chip */
595 if (NanD_Command(nand, NAND_CMD_RESET)) {
596#ifdef NAND_DEBUG
597 printf("NanD_Command (reset) for %d,%d returned true\n",
598 floor, chip);
599#endif
wdenk0db5bca2003-03-31 17:27:09 +0000600 NAND_DISABLE_CE(nand); /* set pin high */
wdenkdc7c9a12003-03-26 06:55:25 +0000601 return 0;
602 }
603
604 /* Read the NAND chip ID: 1. Send ReadID command */
605 if (NanD_Command(nand, NAND_CMD_READID)) {
606#ifdef NAND_DEBUG
607 printf("NanD_Command (ReadID) for %d,%d returned true\n",
608 floor, chip);
609#endif
wdenk0db5bca2003-03-31 17:27:09 +0000610 NAND_DISABLE_CE(nand); /* set pin high */
wdenkdc7c9a12003-03-26 06:55:25 +0000611 return 0;
612 }
613
614 /* Read the NAND chip ID: 2. Send address byte zero */
615 NanD_Address(nand, ADDR_COLUMN, 0);
616
617 /* Read the manufacturer and device id codes from the device */
618
619 mfr = READ_NAND(nand->IO_ADDR);
620
621 id = READ_NAND(nand->IO_ADDR);
622
wdenk8bde7f72003-06-27 21:31:46 +0000623 NAND_DISABLE_CE(nand); /* set pin high */
wdenkdc7c9a12003-03-26 06:55:25 +0000624 /* No response - return failure */
wdenk0db5bca2003-03-31 17:27:09 +0000625 if (mfr == 0xff || mfr == 0) {
626 printf("NanD_Command (ReadID) got %d %d\n", mfr, id);
627 return 0;
628 }
wdenkdc7c9a12003-03-26 06:55:25 +0000629
630 /* Check it's the same as the first chip we identified.
631 * M-Systems say that any given nand_chip device should only
632 * contain _one_ type of flash part, although that's not a
633 * hardware restriction. */
634 if (nand->mfr) {
635 if (nand->mfr == mfr && nand->id == id)
636 return 1; /* This is another the same the first */
637 else
638 printf("Flash chip at floor %d, chip %d is different:\n",
639 floor, chip);
640 }
641
642 /* Print and store the manufacturer and ID codes. */
643 for (i = 0; nand_flash_ids[i].name != NULL; i++) {
644 if (mfr == nand_flash_ids[i].manufacture_id &&
645 id == nand_flash_ids[i].model_id) {
646#ifdef NAND_DEBUG
647 printf("Flash chip found:\n\t Manufacturer ID: 0x%2.2X, "
648 "Chip ID: 0x%2.2X (%s)\n", mfr, id,
649 nand_flash_ids[i].name);
650#endif
651 if (!nand->mfr) {
652 nand->mfr = mfr;
653 nand->id = id;
654 nand->chipshift =
655 nand_flash_ids[i].chipshift;
656 nand->page256 = nand_flash_ids[i].page256;
wdenk7a8e9bed2003-05-31 18:35:21 +0000657 nand->eccsize = 256;
wdenkdc7c9a12003-03-26 06:55:25 +0000658 if (nand->page256) {
659 nand->oobblock = 256;
660 nand->oobsize = 8;
661 nand->page_shift = 8;
662 } else {
663 nand->oobblock = 512;
664 nand->oobsize = 16;
665 nand->page_shift = 9;
666 }
667 nand->pageadrlen =
668 nand_flash_ids[i].pageadrlen;
669 nand->erasesize =
670 nand_flash_ids[i].erasesize;
671 nand->chips_name =
672 nand_flash_ids[i].name;
673 return 1;
674 }
675 return 0;
676 }
677 }
678
679
680#ifdef NAND_DEBUG
681 /* We haven't fully identified the chip. Print as much as we know. */
682 printf("Unknown flash chip found: %2.2X %2.2X\n",
683 id, mfr);
684#endif
685
686 return 0;
687}
688
689/* NanD_ScanChips: Find all NAND chips present in a nand_chip, and identify them */
690
691static void NanD_ScanChips(struct nand_chip *nand)
692{
693 int floor, chip;
694 int numchips[NAND_MAX_FLOORS];
695 int maxchips = NAND_MAX_CHIPS;
696 int ret = 1;
697
698 nand->numchips = 0;
699 nand->mfr = 0;
700 nand->id = 0;
701
702
703 /* For each floor, find the number of valid chips it contains */
704 for (floor = 0; floor < NAND_MAX_FLOORS; floor++) {
705 ret = 1;
706 numchips[floor] = 0;
707 for (chip = 0; chip < maxchips && ret != 0; chip++) {
708
709 ret = NanD_IdentChip(nand, floor, chip);
710 if (ret) {
711 numchips[floor]++;
712 nand->numchips++;
713 }
714 }
715 }
716
717 /* If there are none at all that we recognise, bail */
718 if (!nand->numchips) {
719 puts ("No flash chips recognised.\n");
720 return;
721 }
722
723 /* Allocate an array to hold the information for each chip */
724 nand->chips = malloc(sizeof(struct Nand) * nand->numchips);
725 if (!nand->chips) {
726 puts ("No memory for allocating chip info structures\n");
727 return;
728 }
729
730 ret = 0;
731
732 /* Fill out the chip array with {floor, chipno} for each
733 * detected chip in the device. */
734 for (floor = 0; floor < NAND_MAX_FLOORS; floor++) {
735 for (chip = 0; chip < numchips[floor]; chip++) {
736 nand->chips[ret].floor = floor;
737 nand->chips[ret].chip = chip;
738 nand->chips[ret].curadr = 0;
739 nand->chips[ret].curmode = 0x50;
740 ret++;
741 }
742 }
743
744 /* Calculate and print the total size of the device */
745 nand->totlen = nand->numchips * (1 << nand->chipshift);
746
747#ifdef NAND_DEBUG
748 printf("%d flash chips found. Total nand_chip size: %ld MB\n",
749 nand->numchips, nand->totlen >> 20);
750#endif
751}
wdenk0db5bca2003-03-31 17:27:09 +0000752
wdenkdc7c9a12003-03-26 06:55:25 +0000753/* we need to be fast here, 1 us per read translates to 1 second per meg */
wdenk7a8e9bed2003-05-31 18:35:21 +0000754static void NanD_ReadBuf(struct nand_chip *nand, u_char *data_buf, int cntr)
wdenk0db5bca2003-03-31 17:27:09 +0000755{
wdenk7a8e9bed2003-05-31 18:35:21 +0000756 unsigned long nandptr = nand->IO_ADDR;
wdenk0db5bca2003-03-31 17:27:09 +0000757
wdenk7a8e9bed2003-05-31 18:35:21 +0000758 while (cntr >= 16) {
wdenk0db5bca2003-03-31 17:27:09 +0000759 *data_buf++ = READ_NAND(nandptr);
760 *data_buf++ = READ_NAND(nandptr);
761 *data_buf++ = READ_NAND(nandptr);
762 *data_buf++ = READ_NAND(nandptr);
763 *data_buf++ = READ_NAND(nandptr);
764 *data_buf++ = READ_NAND(nandptr);
765 *data_buf++ = READ_NAND(nandptr);
766 *data_buf++ = READ_NAND(nandptr);
767 *data_buf++ = READ_NAND(nandptr);
768 *data_buf++ = READ_NAND(nandptr);
769 *data_buf++ = READ_NAND(nandptr);
770 *data_buf++ = READ_NAND(nandptr);
771 *data_buf++ = READ_NAND(nandptr);
772 *data_buf++ = READ_NAND(nandptr);
773 *data_buf++ = READ_NAND(nandptr);
774 *data_buf++ = READ_NAND(nandptr);
775 cntr -= 16;
776 }
777
778 while (cntr > 0) {
779 *data_buf++ = READ_NAND(nandptr);
780 cntr--;
781 }
782}
wdenkdc7c9a12003-03-26 06:55:25 +0000783
wdenkdc7c9a12003-03-26 06:55:25 +0000784/*
785 * NAND read with ECC
786 */
787static int nand_read_ecc(struct nand_chip *nand, size_t start, size_t len,
788 size_t * retlen, u_char *buf, u_char *ecc_code)
789{
790 int col, page;
791 int ecc_status = 0;
792#ifdef CONFIG_MTD_NAND_ECC
793 int j;
794 int ecc_failed = 0;
795 u_char *data_poi;
796 u_char ecc_calc[6];
797#endif
wdenkdc7c9a12003-03-26 06:55:25 +0000798
799 /* Do not allow reads past end of device */
800 if ((start + len) > nand->totlen) {
wdenk0db5bca2003-03-31 17:27:09 +0000801 printf ("%s: Attempt read beyond end of device %x %x %x\n", __FUNCTION__, (uint) start, (uint) len, (uint) nand->totlen);
wdenkdc7c9a12003-03-26 06:55:25 +0000802 *retlen = 0;
803 return -1;
804 }
805
806 /* First we calculate the starting page */
wdenk0db5bca2003-03-31 17:27:09 +0000807 /*page = shr(start, nand->page_shift);*/
808 page = start >> nand->page_shift;
wdenkdc7c9a12003-03-26 06:55:25 +0000809
810 /* Get raw starting column */
811 col = start & (nand->oobblock - 1);
812
813 /* Initialize return value */
814 *retlen = 0;
815
816 /* Select the NAND device */
817 NAND_ENABLE_CE(nand); /* set pin low */
818
819 /* Loop until all data read */
820 while (*retlen < len) {
821
822
823#ifdef CONFIG_MTD_NAND_ECC
824
825 /* Do we have this page in cache ? */
826 if (nand->cache_page == page)
827 goto readdata;
828 /* Send the read command */
829 NanD_Command(nand, NAND_CMD_READ0);
wdenk8bde7f72003-06-27 21:31:46 +0000830 NanD_Address(nand, ADDR_COLUMN_PAGE, (page << nand->page_shift) + col);
wdenkdc7c9a12003-03-26 06:55:25 +0000831 /* Read in a page + oob data */
wdenk7a8e9bed2003-05-31 18:35:21 +0000832 NanD_ReadBuf(nand, nand->data_buf, nand->oobblock + nand->oobsize);
wdenkdc7c9a12003-03-26 06:55:25 +0000833
834 /* copy data into cache, for read out of cache and if ecc fails */
835 if (nand->data_cache)
836 memcpy (nand->data_cache, nand->data_buf, nand->oobblock + nand->oobsize);
837
838 /* Pick the ECC bytes out of the oob data */
839 for (j = 0; j < 6; j++)
840 ecc_code[j] = nand->data_buf[(nand->oobblock + oob_config.ecc_pos[j])];
841
842 /* Calculate the ECC and verify it */
843 /* If block was not written with ECC, skip ECC */
844 if (oob_config.eccvalid_pos != -1 &&
845 (nand->data_buf[nand->oobblock + oob_config.eccvalid_pos] & 0x0f) != 0x0f) {
846
847 nand_calculate_ecc (&nand->data_buf[0], &ecc_calc[0]);
848 switch (nand_correct_data (&nand->data_buf[0], &ecc_code[0], &ecc_calc[0])) {
849 case -1:
wdenk0db5bca2003-03-31 17:27:09 +0000850 printf ("%s: Failed ECC read, page 0x%08x\n", __FUNCTION__, page);
wdenkdc7c9a12003-03-26 06:55:25 +0000851 ecc_failed++;
852 break;
853 case 1:
854 case 2: /* transfer ECC corrected data to cache */
wdenk7a8e9bed2003-05-31 18:35:21 +0000855 if (nand->data_cache)
856 memcpy (nand->data_cache, nand->data_buf, 256);
wdenkdc7c9a12003-03-26 06:55:25 +0000857 break;
858 }
859 }
860
861 if (oob_config.eccvalid_pos != -1 &&
862 nand->oobblock == 512 && (nand->data_buf[nand->oobblock + oob_config.eccvalid_pos] & 0xf0) != 0xf0) {
863
864 nand_calculate_ecc (&nand->data_buf[256], &ecc_calc[3]);
865 switch (nand_correct_data (&nand->data_buf[256], &ecc_code[3], &ecc_calc[3])) {
866 case -1:
wdenk0db5bca2003-03-31 17:27:09 +0000867 printf ("%s: Failed ECC read, page 0x%08x\n", __FUNCTION__, page);
wdenkdc7c9a12003-03-26 06:55:25 +0000868 ecc_failed++;
869 break;
870 case 1:
871 case 2: /* transfer ECC corrected data to cache */
872 if (nand->data_cache)
873 memcpy (&nand->data_cache[256], &nand->data_buf[256], 256);
874 break;
875 }
876 }
877readdata:
878 /* Read the data from ECC data buffer into return buffer */
879 data_poi = (nand->data_cache) ? nand->data_cache : nand->data_buf;
880 data_poi += col;
881 if ((*retlen + (nand->oobblock - col)) >= len) {
wdenk7a8e9bed2003-05-31 18:35:21 +0000882 memcpy (buf + *retlen, data_poi, len - *retlen);
wdenkdc7c9a12003-03-26 06:55:25 +0000883 *retlen = len;
884 } else {
wdenk7a8e9bed2003-05-31 18:35:21 +0000885 memcpy (buf + *retlen, data_poi, nand->oobblock - col);
wdenkdc7c9a12003-03-26 06:55:25 +0000886 *retlen += nand->oobblock - col;
887 }
888 /* Set cache page address, invalidate, if ecc_failed */
889 nand->cache_page = (nand->data_cache && !ecc_failed) ? page : -1;
890
891 ecc_status += ecc_failed;
892 ecc_failed = 0;
893
894#else
895 /* Send the read command */
896 NanD_Command(nand, NAND_CMD_READ0);
wdenk8bde7f72003-06-27 21:31:46 +0000897 NanD_Address(nand, ADDR_COLUMN_PAGE, (page << nand->page_shift) + col);
wdenkdc7c9a12003-03-26 06:55:25 +0000898 /* Read the data directly into the return buffer */
899 if ((*retlen + (nand->oobblock - col)) >= len) {
wdenk7a8e9bed2003-05-31 18:35:21 +0000900 NanD_ReadBuf(nand, buf + *retlen, len - *retlen);
wdenkdc7c9a12003-03-26 06:55:25 +0000901 *retlen = len;
902 /* We're done */
903 continue;
904 } else {
wdenk7a8e9bed2003-05-31 18:35:21 +0000905 NanD_ReadBuf(nand, buf + *retlen, nand->oobblock - col);
wdenkdc7c9a12003-03-26 06:55:25 +0000906 *retlen += nand->oobblock - col;
907 }
908#endif
909 /* For subsequent reads align to page boundary. */
910 col = 0;
911 /* Increment page address */
912 page++;
913 }
914
915 /* De-select the NAND device */
wdenk0db5bca2003-03-31 17:27:09 +0000916 NAND_DISABLE_CE(nand); /* set pin high */
wdenkdc7c9a12003-03-26 06:55:25 +0000917
918 /*
919 * Return success, if no ECC failures, else -EIO
920 * fs driver will take care of that, because
921 * retlen == desired len and result == -EIO
922 */
923 return ecc_status ? -1 : 0;
924}
925
wdenkdc7c9a12003-03-26 06:55:25 +0000926/*
927 * Nand_page_program function is used for write and writev !
928 */
929static int nand_write_page (struct nand_chip *nand,
930 int page, int col, int last, u_char * ecc_code)
931{
932
933 int i;
934#ifdef CONFIG_MTD_NAND_ECC
935 unsigned long nandptr = nand->IO_ADDR;
936#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
937 int ecc_bytes = (nand->oobblock == 512) ? 6 : 3;
938#endif
939#endif
940 /* pad oob area */
941 for (i = nand->oobblock; i < nand->oobblock + nand->oobsize; i++)
942 nand->data_buf[i] = 0xff;
943
944#ifdef CONFIG_MTD_NAND_ECC
945 /* Zero out the ECC array */
946 for (i = 0; i < 6; i++)
947 ecc_code[i] = 0x00;
948
949 /* Read back previous written data, if col > 0 */
950 if (col) {
951 NanD_Command(nand, NAND_CMD_READ0);
wdenk0db5bca2003-03-31 17:27:09 +0000952 NanD_Address(nand, ADDR_COLUMN_PAGE, (page << nand->page_shift) + col);
wdenkdc7c9a12003-03-26 06:55:25 +0000953 for (i = 0; i < col; i++)
954 nand->data_buf[i] = READ_NAND (nandptr);
955 }
956
957 /* Calculate and write the ECC if we have enough data */
958 if ((col < nand->eccsize) && (last >= nand->eccsize)) {
959 nand_calculate_ecc (&nand->data_buf[0], &(ecc_code[0]));
960 for (i = 0; i < 3; i++)
961 nand->data_buf[(nand->oobblock + oob_config.ecc_pos[i])] = ecc_code[i];
962 if (oob_config.eccvalid_pos != -1)
963 nand->data_buf[nand->oobblock + oob_config.eccvalid_pos] = 0xf0;
964 }
965
966 /* Calculate and write the second ECC if we have enough data */
967 if ((nand->oobblock == 512) && (last == nand->oobblock)) {
968 nand_calculate_ecc (&nand->data_buf[256], &(ecc_code[3]));
969 for (i = 3; i < 6; i++)
970 nand->data_buf[(nand->oobblock + oob_config.ecc_pos[i])] = ecc_code[i];
971 if (oob_config.eccvalid_pos != -1)
972 nand->data_buf[nand->oobblock + oob_config.eccvalid_pos] &= 0x0f;
973 }
974#endif
975 /* Prepad for partial page programming !!! */
976 for (i = 0; i < col; i++)
977 nand->data_buf[i] = 0xff;
978
979 /* Postpad for partial page programming !!! oob is already padded */
980 for (i = last; i < nand->oobblock; i++)
981 nand->data_buf[i] = 0xff;
982
983 /* Send command to begin auto page programming */
wdenk7a8e9bed2003-05-31 18:35:21 +0000984 NanD_Command(nand, NAND_CMD_READ0);
wdenkdc7c9a12003-03-26 06:55:25 +0000985 NanD_Command(nand, NAND_CMD_SEQIN);
986 NanD_Address(nand, ADDR_COLUMN_PAGE, (page << nand->page_shift) + col);
987
988 /* Write out complete page of data */
989 for (i = 0; i < (nand->oobblock + nand->oobsize); i++)
wdenk0db5bca2003-03-31 17:27:09 +0000990 WRITE_NAND(nand->data_buf[i], nand->IO_ADDR);
wdenkdc7c9a12003-03-26 06:55:25 +0000991
992 /* Send command to actually program the data */
wdenk0db5bca2003-03-31 17:27:09 +0000993 NanD_Command(nand, NAND_CMD_PAGEPROG);
994 NanD_Command(nand, NAND_CMD_STATUS);
wdenkdc7c9a12003-03-26 06:55:25 +0000995
996 /* See if device thinks it succeeded */
997 if (READ_NAND(nand->IO_ADDR) & 0x01) {
wdenk0db5bca2003-03-31 17:27:09 +0000998 printf ("%s: Failed write, page 0x%08x, ", __FUNCTION__, page);
wdenkdc7c9a12003-03-26 06:55:25 +0000999 return -1;
1000 }
1001#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
1002 /*
1003 * The NAND device assumes that it is always writing to
1004 * a cleanly erased page. Hence, it performs its internal
1005 * write verification only on bits that transitioned from
1006 * 1 to 0. The device does NOT verify the whole page on a
1007 * byte by byte basis. It is possible that the page was
1008 * not completely erased or the page is becoming unusable
1009 * due to wear. The read with ECC would catch the error
1010 * later when the ECC page check fails, but we would rather
1011 * catch it early in the page write stage. Better to write
1012 * no data than invalid data.
1013 */
1014
1015 /* Send command to read back the page */
1016 if (col < nand->eccsize)
wdenk0db5bca2003-03-31 17:27:09 +00001017 NanD_Command(nand, NAND_CMD_READ0);
wdenkdc7c9a12003-03-26 06:55:25 +00001018 else
wdenk0db5bca2003-03-31 17:27:09 +00001019 NanD_Command(nand, NAND_CMD_READ1);
1020 NanD_Address(nand, ADDR_COLUMN_PAGE, (page << nand->page_shift) + col);
wdenkdc7c9a12003-03-26 06:55:25 +00001021
1022 /* Loop through and verify the data */
1023 for (i = col; i < last; i++) {
1024 if (nand->data_buf[i] != readb (nand->IO_ADDR)) {
wdenk0db5bca2003-03-31 17:27:09 +00001025 printf ("%s: Failed write verify, page 0x%08x ", __FUNCTION__, page);
wdenkdc7c9a12003-03-26 06:55:25 +00001026 return -1;
1027 }
1028 }
1029
1030#ifdef CONFIG_MTD_NAND_ECC
1031 /*
1032 * We also want to check that the ECC bytes wrote
1033 * correctly for the same reasons stated above.
1034 */
1035 NanD_Command(nand, NAND_CMD_READOOB);
1036 NanD_Address(nand, ADDR_COLUMN_PAGE, (page << nand->page_shift) + col);
1037 for (i = 0; i < nand->oobsize; i++)
1038 nand->data_buf[i] = readb (nand->IO_ADDR);
1039 for (i = 0; i < ecc_bytes; i++) {
1040 if ((nand->data_buf[(oob_config.ecc_pos[i])] != ecc_code[i]) && ecc_code[i]) {
wdenk0db5bca2003-03-31 17:27:09 +00001041 printf ("%s: Failed ECC write "
1042 "verify, page 0x%08x, " "%6i bytes were succesful\n", __FUNCTION__, page, i);
wdenkdc7c9a12003-03-26 06:55:25 +00001043 return -1;
1044 }
1045 }
1046#endif
1047#endif
1048 return 0;
1049}
wdenk0db5bca2003-03-31 17:27:09 +00001050
wdenkdc7c9a12003-03-26 06:55:25 +00001051static int nand_write_ecc (struct nand_chip* nand, size_t to, size_t len,
1052 size_t * retlen, const u_char * buf, u_char * ecc_code)
1053{
1054 int i, page, col, cnt, ret = 0;
1055
1056 /* Do not allow write past end of device */
1057 if ((to + len) > nand->totlen) {
wdenk0db5bca2003-03-31 17:27:09 +00001058 printf ("%s: Attempt to write past end of page\n", __FUNCTION__);
wdenkdc7c9a12003-03-26 06:55:25 +00001059 return -1;
1060 }
1061
1062 /* Shift to get page */
1063 page = ((int) to) >> nand->page_shift;
1064
1065 /* Get the starting column */
1066 col = to & (nand->oobblock - 1);
1067
1068 /* Initialize return length value */
1069 *retlen = 0;
1070
1071 /* Select the NAND device */
wdenk0db5bca2003-03-31 17:27:09 +00001072 NAND_ENABLE_CE(nand); /* set pin low */
wdenkdc7c9a12003-03-26 06:55:25 +00001073
1074 /* Check the WP bit */
wdenk0db5bca2003-03-31 17:27:09 +00001075 NanD_Command(nand, NAND_CMD_STATUS);
wdenkdc7c9a12003-03-26 06:55:25 +00001076 if (!(READ_NAND(nand->IO_ADDR) & 0x80)) {
wdenk0db5bca2003-03-31 17:27:09 +00001077 printf ("%s: Device is write protected!!!\n", __FUNCTION__);
wdenkdc7c9a12003-03-26 06:55:25 +00001078 ret = -1;
1079 goto out;
1080 }
1081
1082 /* Loop until all data is written */
1083 while (*retlen < len) {
1084 /* Invalidate cache, if we write to this page */
1085 if (nand->cache_page == page)
1086 nand->cache_page = -1;
1087
1088 /* Write data into buffer */
1089 if ((col + len) >= nand->oobblock)
1090 for (i = col, cnt = 0; i < nand->oobblock; i++, cnt++)
1091 nand->data_buf[i] = buf[(*retlen + cnt)];
1092 else
1093 for (i = col, cnt = 0; cnt < (len - *retlen); i++, cnt++)
1094 nand->data_buf[i] = buf[(*retlen + cnt)];
1095 /* We use the same function for write and writev !) */
1096 ret = nand_write_page (nand, page, col, i, ecc_code);
1097 if (ret)
1098 goto out;
1099
1100 /* Next data start at page boundary */
1101 col = 0;
1102
1103 /* Update written bytes count */
1104 *retlen += cnt;
1105
1106 /* Increment page address */
1107 page++;
1108 }
1109
1110 /* Return happy */
1111 *retlen = len;
1112
1113out:
1114 /* De-select the NAND device */
wdenk0db5bca2003-03-31 17:27:09 +00001115 NAND_DISABLE_CE(nand); /* set pin high */
wdenkdc7c9a12003-03-26 06:55:25 +00001116
1117 return ret;
1118}
1119
wdenk7a8e9bed2003-05-31 18:35:21 +00001120/* read from the 16 bytes of oob data that correspond to a 512 byte
1121 * page or 2 256-byte pages.
wdenkdc7c9a12003-03-26 06:55:25 +00001122 */
wdenkdc7c9a12003-03-26 06:55:25 +00001123static int nand_read_oob(struct nand_chip* nand, size_t ofs, size_t len,
wdenk7a8e9bed2003-05-31 18:35:21 +00001124 size_t * retlen, u_char * buf)
wdenkdc7c9a12003-03-26 06:55:25 +00001125{
wdenk7a8e9bed2003-05-31 18:35:21 +00001126 int len256 = 0;
wdenkdc7c9a12003-03-26 06:55:25 +00001127 struct Nand *mychip;
wdenk0db5bca2003-03-31 17:27:09 +00001128 int ret = 0;
wdenkdc7c9a12003-03-26 06:55:25 +00001129
wdenk7a8e9bed2003-05-31 18:35:21 +00001130 mychip = &nand->chips[ofs >> nand->chipshift];
wdenkdc7c9a12003-03-26 06:55:25 +00001131
1132 /* update address for 2M x 8bit devices. OOB starts on the second */
1133 /* page to maintain compatibility with nand_read_ecc. */
1134 if (nand->page256) {
1135 if (!(ofs & 0x8))
1136 ofs += 0x100;
1137 else
1138 ofs -= 0x8;
1139 }
1140
wdenk7a8e9bed2003-05-31 18:35:21 +00001141 NAND_ENABLE_CE(nand); /* set pin low */
wdenkdc7c9a12003-03-26 06:55:25 +00001142 NanD_Command(nand, NAND_CMD_READOOB);
1143 NanD_Address(nand, ADDR_COLUMN_PAGE, ofs);
1144
1145 /* treat crossing 8-byte OOB data for 2M x 8bit devices */
1146 /* Note: datasheet says it should automaticaly wrap to the */
1147 /* next OOB block, but it didn't work here. mf. */
1148 if (nand->page256 && ofs + len > (ofs | 0x7) + 1) {
1149 len256 = (ofs | 0x7) + 1 - ofs;
1150 NanD_ReadBuf(nand, buf, len256);
1151
1152 NanD_Command(nand, NAND_CMD_READOOB);
1153 NanD_Address(nand, ADDR_COLUMN_PAGE, ofs & (~0x1ff));
1154 }
1155
1156 NanD_ReadBuf(nand, &buf[len256], len - len256);
1157
1158 *retlen = len;
1159 /* Reading the full OOB data drops us off of the end of the page,
wdenk8bde7f72003-06-27 21:31:46 +00001160 * causing the flash device to go into busy mode, so we need
1161 * to wait until ready 11.4.1 and Toshiba TC58256FT nands */
wdenkdc7c9a12003-03-26 06:55:25 +00001162
1163 ret = NanD_WaitReady(nand);
wdenk8bde7f72003-06-27 21:31:46 +00001164 NAND_DISABLE_CE(nand); /* set pin high */
wdenkdc7c9a12003-03-26 06:55:25 +00001165
1166 return ret;
1167
1168}
wdenk7a8e9bed2003-05-31 18:35:21 +00001169
1170/* write to the 16 bytes of oob data that correspond to a 512 byte
1171 * page or 2 256-byte pages.
1172 */
wdenkdc7c9a12003-03-26 06:55:25 +00001173static int nand_write_oob(struct nand_chip* nand, size_t ofs, size_t len,
1174 size_t * retlen, const u_char * buf)
1175{
1176 int len256 = 0;
wdenk7a8e9bed2003-05-31 18:35:21 +00001177 int i;
wdenkdc7c9a12003-03-26 06:55:25 +00001178 unsigned long nandptr = nand->IO_ADDR;
1179
1180#ifdef PSYCHO_DEBUG
1181 printf("nand_write_oob(%lx, %d): %2.2X %2.2X %2.2X %2.2X ... %2.2X %2.2X .. %2.2X %2.2X\n",
1182 (long)ofs, len, buf[0], buf[1], buf[2], buf[3],
1183 buf[8], buf[9], buf[14],buf[15]);
1184#endif
1185
wdenk7a8e9bed2003-05-31 18:35:21 +00001186 NAND_ENABLE_CE(nand); /* set pin low to enable chip */
1187
wdenkdc7c9a12003-03-26 06:55:25 +00001188 /* Reset the chip */
1189 NanD_Command(nand, NAND_CMD_RESET);
1190
1191 /* issue the Read2 command to set the pointer to the Spare Data Area. */
1192 NanD_Command(nand, NAND_CMD_READOOB);
1193 NanD_Address(nand, ADDR_COLUMN_PAGE, ofs);
1194
1195 /* update address for 2M x 8bit devices. OOB starts on the second */
1196 /* page to maintain compatibility with nand_read_ecc. */
1197 if (nand->page256) {
1198 if (!(ofs & 0x8))
1199 ofs += 0x100;
1200 else
1201 ofs -= 0x8;
1202 }
1203
1204 /* issue the Serial Data In command to initial the Page Program process */
1205 NanD_Command(nand, NAND_CMD_SEQIN);
1206 NanD_Address(nand, ADDR_COLUMN_PAGE, ofs);
1207
1208 /* treat crossing 8-byte OOB data for 2M x 8bit devices */
1209 /* Note: datasheet says it should automaticaly wrap to the */
1210 /* next OOB block, but it didn't work here. mf. */
1211 if (nand->page256 && ofs + len > (ofs | 0x7) + 1) {
1212 len256 = (ofs | 0x7) + 1 - ofs;
wdenk7a8e9bed2003-05-31 18:35:21 +00001213 for (i = 0; i < len256; i++)
1214 WRITE_NAND(buf[i], nandptr);
wdenkdc7c9a12003-03-26 06:55:25 +00001215
1216 NanD_Command(nand, NAND_CMD_PAGEPROG);
1217 NanD_Command(nand, NAND_CMD_STATUS);
1218 /* NanD_WaitReady() is implicit in NanD_Command */
1219
1220 if (READ_NAND(nandptr) & 1) {
1221 puts ("Error programming oob data\n");
1222 /* There was an error */
wdenk7a8e9bed2003-05-31 18:35:21 +00001223 NAND_DISABLE_CE(nand); /* set pin high */
wdenkdc7c9a12003-03-26 06:55:25 +00001224 *retlen = 0;
1225 return -1;
1226 }
1227 NanD_Command(nand, NAND_CMD_SEQIN);
1228 NanD_Address(nand, ADDR_COLUMN_PAGE, ofs & (~0x1ff));
1229 }
1230
wdenk7a8e9bed2003-05-31 18:35:21 +00001231 for (i = len256; i < len; i++)
1232 WRITE_NAND(buf[i], nandptr);
wdenkdc7c9a12003-03-26 06:55:25 +00001233
1234 NanD_Command(nand, NAND_CMD_PAGEPROG);
1235 NanD_Command(nand, NAND_CMD_STATUS);
1236 /* NanD_WaitReady() is implicit in NanD_Command */
1237
1238 if (READ_NAND(nandptr) & 1) {
1239 puts ("Error programming oob data\n");
1240 /* There was an error */
wdenk7a8e9bed2003-05-31 18:35:21 +00001241 NAND_DISABLE_CE(nand); /* set pin high */
wdenkdc7c9a12003-03-26 06:55:25 +00001242 *retlen = 0;
1243 return -1;
1244 }
1245
wdenk7a8e9bed2003-05-31 18:35:21 +00001246 NAND_DISABLE_CE(nand); /* set pin high */
wdenkdc7c9a12003-03-26 06:55:25 +00001247 *retlen = len;
1248 return 0;
1249
1250}
wdenkdc7c9a12003-03-26 06:55:25 +00001251
wdenk7a8e9bed2003-05-31 18:35:21 +00001252static int nand_erase(struct nand_chip* nand, size_t ofs, size_t len, int clean)
wdenkdc7c9a12003-03-26 06:55:25 +00001253{
wdenk7a8e9bed2003-05-31 18:35:21 +00001254 /* This is defined as a structure so it will work on any system
1255 * using native endian jffs2 (the default).
1256 */
1257 static struct jffs2_unknown_node clean_marker = {
1258 JFFS2_MAGIC_BITMASK,
1259 JFFS2_NODETYPE_CLEANMARKER,
1260 8 /* 8 bytes in this node */
1261 };
wdenkdc7c9a12003-03-26 06:55:25 +00001262 unsigned long nandptr;
1263 struct Nand *mychip;
wdenk85ec0bc2003-03-31 16:34:49 +00001264 int ret = 0;
wdenkdc7c9a12003-03-26 06:55:25 +00001265
1266 if (ofs & (nand->erasesize-1) || len & (nand->erasesize-1)) {
1267 printf ("Offset and size must be sector aligned, erasesize = %d\n",
wdenk8bde7f72003-06-27 21:31:46 +00001268 (int) nand->erasesize);
wdenkdc7c9a12003-03-26 06:55:25 +00001269 return -1;
1270 }
1271
1272 nandptr = nand->IO_ADDR;
1273
wdenk85ec0bc2003-03-31 16:34:49 +00001274 /* Select the NAND device */
1275 NAND_ENABLE_CE(nand); /* set pin low */
1276
1277 /* Check the WP bit */
1278 NanD_Command(nand, NAND_CMD_STATUS);
1279 if (!(READ_NAND(nand->IO_ADDR) & 0x80)) {
1280 printf ("nand_write_ecc: Device is write protected!!!\n");
1281 ret = -1;
1282 goto out;
1283 }
1284
wdenk0db5bca2003-03-31 17:27:09 +00001285 /* Check the WP bit */
1286 NanD_Command(nand, NAND_CMD_STATUS);
1287 if (!(READ_NAND(nand->IO_ADDR) & 0x80)) {
1288 printf ("%s: Device is write protected!!!\n", __FUNCTION__);
1289 ret = -1;
1290 goto out;
1291 }
1292
wdenkdc7c9a12003-03-26 06:55:25 +00001293 /* FIXME: Do nand in the background. Use timers or schedule_task() */
1294 while(len) {
wdenk0db5bca2003-03-31 17:27:09 +00001295 /*mychip = &nand->chips[shr(ofs, nand->chipshift)];*/
1296 mychip = &nand->chips[ofs >> nand->chipshift];
wdenkdc7c9a12003-03-26 06:55:25 +00001297
wdenk7a8e9bed2003-05-31 18:35:21 +00001298 /* always check for bad block first, genuine bad blocks
1299 * should _never_ be erased.
1300 */
1301 if (ALLOW_ERASE_BAD_DEBUG || !check_block(nand, ofs)) {
1302 /* Select the NAND device */
1303 NAND_ENABLE_CE(nand); /* set pin low */
wdenkdc7c9a12003-03-26 06:55:25 +00001304
wdenk7a8e9bed2003-05-31 18:35:21 +00001305 NanD_Command(nand, NAND_CMD_ERASE1);
1306 NanD_Address(nand, ADDR_PAGE, ofs);
1307 NanD_Command(nand, NAND_CMD_ERASE2);
wdenkdc7c9a12003-03-26 06:55:25 +00001308
wdenk7a8e9bed2003-05-31 18:35:21 +00001309 NanD_Command(nand, NAND_CMD_STATUS);
1310
1311 if (READ_NAND(nandptr) & 1) {
1312 printf ("%s: Error erasing at 0x%lx\n",
1313 __FUNCTION__, (long)ofs);
1314 /* There was an error */
1315 ret = -1;
1316 goto out;
1317 }
1318 if (clean) {
1319 int n; /* return value not used */
1320 int p, l;
1321
1322 /* clean marker position and size depend
1323 * on the page size, since 256 byte pages
1324 * only have 8 bytes of oob data
1325 */
1326 if (nand->page256) {
1327 p = NAND_JFFS2_OOB8_FSDAPOS;
1328 l = NAND_JFFS2_OOB8_FSDALEN;
1329 }
1330 else {
1331 p = NAND_JFFS2_OOB16_FSDAPOS;
1332 l = NAND_JFFS2_OOB16_FSDALEN;
1333 }
1334
1335 ret = nand_write_oob(nand, ofs + p, l, &n,
1336 (u_char *)&clean_marker);
1337 /* quit here if write failed */
1338 if (ret)
1339 goto out;
1340 }
wdenkdc7c9a12003-03-26 06:55:25 +00001341 }
1342 ofs += nand->erasesize;
1343 len -= nand->erasesize;
1344 }
1345
wdenk85ec0bc2003-03-31 16:34:49 +00001346out:
1347 /* De-select the NAND device */
1348 NAND_DISABLE_CE(nand); /* set pin high */
1349
1350 return ret;
wdenkdc7c9a12003-03-26 06:55:25 +00001351}
1352
1353static inline int nandcheck(unsigned long potential, unsigned long physadr)
1354{
wdenkdc7c9a12003-03-26 06:55:25 +00001355 return 0;
1356}
1357
1358void nand_probe(unsigned long physadr)
1359{
1360 struct nand_chip *nand = NULL;
1361 int i = 0, ChipID = 1;
1362
1363#ifdef CONFIG_MTD_NAND_ECC_JFFS2
1364 oob_config.ecc_pos[0] = NAND_JFFS2_OOB_ECCPOS0;
1365 oob_config.ecc_pos[1] = NAND_JFFS2_OOB_ECCPOS1;
1366 oob_config.ecc_pos[2] = NAND_JFFS2_OOB_ECCPOS2;
1367 oob_config.ecc_pos[3] = NAND_JFFS2_OOB_ECCPOS3;
1368 oob_config.ecc_pos[4] = NAND_JFFS2_OOB_ECCPOS4;
1369 oob_config.ecc_pos[5] = NAND_JFFS2_OOB_ECCPOS5;
wdenkdc7c9a12003-03-26 06:55:25 +00001370 oob_config.eccvalid_pos = 4;
1371#else
1372 oob_config.ecc_pos[0] = NAND_NOOB_ECCPOS0;
1373 oob_config.ecc_pos[1] = NAND_NOOB_ECCPOS1;
1374 oob_config.ecc_pos[2] = NAND_NOOB_ECCPOS2;
1375 oob_config.ecc_pos[3] = NAND_NOOB_ECCPOS3;
1376 oob_config.ecc_pos[4] = NAND_NOOB_ECCPOS4;
1377 oob_config.ecc_pos[5] = NAND_NOOB_ECCPOS5;
wdenkdc7c9a12003-03-26 06:55:25 +00001378 oob_config.eccvalid_pos = NAND_NOOB_ECCVPOS;
1379#endif
wdenk7a8e9bed2003-05-31 18:35:21 +00001380 oob_config.badblock_pos = 5;
wdenkdc7c9a12003-03-26 06:55:25 +00001381
1382 for (i=0; i<CFG_MAX_NAND_DEVICE; i++) {
1383 if (nand_dev_desc[i].ChipID == NAND_ChipID_UNKNOWN) {
1384 nand = nand_dev_desc + i;
1385 break;
1386 }
1387 }
1388
wdenk7a8e9bed2003-05-31 18:35:21 +00001389 memset((char *)nand, 0, sizeof(struct nand_chip));
1390
1391 nand->IO_ADDR = physadr;
1392 nand->cache_page = -1; /* init the cache page */
1393 NanD_ScanChips(nand);
1394
1395 if (nand->totlen == 0) {
1396 /* no chips found, clean up and quit */
1397 memset((char *)nand, 0, sizeof(struct nand_chip));
1398 nand->ChipID = NAND_ChipID_UNKNOWN;
1399 return;
1400 }
1401
1402 nand->ChipID = ChipID;
wdenk0db5bca2003-03-31 17:27:09 +00001403 if (curr_device == -1)
1404 curr_device = i;
wdenkdc7c9a12003-03-26 06:55:25 +00001405
wdenk0db5bca2003-03-31 17:27:09 +00001406 nand->data_buf = malloc (nand->oobblock + nand->oobsize);
1407 if (!nand->data_buf) {
1408 puts ("Cannot allocate memory for data structures.\n");
1409 return;
1410 }
wdenkdc7c9a12003-03-26 06:55:25 +00001411}
1412
1413#ifdef CONFIG_MTD_NAND_ECC
1414/*
1415 * Pre-calculated 256-way 1 byte column parity
1416 */
1417static const u_char nand_ecc_precalc_table[] = {
1418 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
1419 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
1420 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
1421 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
1422 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
1423 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
1424 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
1425 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
1426 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
1427 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
1428 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
1429 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
1430 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
1431 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
1432 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
1433 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00
1434};
1435
1436
1437/*
1438 * Creates non-inverted ECC code from line parity
1439 */
1440static void nand_trans_result(u_char reg2, u_char reg3,
1441 u_char *ecc_code)
1442{
1443 u_char a, b, i, tmp1, tmp2;
1444
1445 /* Initialize variables */
1446 a = b = 0x80;
1447 tmp1 = tmp2 = 0;
1448
1449 /* Calculate first ECC byte */
1450 for (i = 0; i < 4; i++) {
1451 if (reg3 & a) /* LP15,13,11,9 --> ecc_code[0] */
1452 tmp1 |= b;
1453 b >>= 1;
1454 if (reg2 & a) /* LP14,12,10,8 --> ecc_code[0] */
1455 tmp1 |= b;
1456 b >>= 1;
1457 a >>= 1;
1458 }
1459
1460 /* Calculate second ECC byte */
1461 b = 0x80;
1462 for (i = 0; i < 4; i++) {
1463 if (reg3 & a) /* LP7,5,3,1 --> ecc_code[1] */
1464 tmp2 |= b;
1465 b >>= 1;
1466 if (reg2 & a) /* LP6,4,2,0 --> ecc_code[1] */
1467 tmp2 |= b;
1468 b >>= 1;
1469 a >>= 1;
1470 }
1471
1472 /* Store two of the ECC bytes */
1473 ecc_code[0] = tmp1;
1474 ecc_code[1] = tmp2;
1475}
1476
1477/*
1478 * Calculate 3 byte ECC code for 256 byte block
1479 */
1480static void nand_calculate_ecc (const u_char *dat, u_char *ecc_code)
1481{
wdenk7a8e9bed2003-05-31 18:35:21 +00001482 u_char idx, reg1, reg3;
wdenkdc7c9a12003-03-26 06:55:25 +00001483 int j;
1484
1485 /* Initialize variables */
wdenk7a8e9bed2003-05-31 18:35:21 +00001486 reg1 = reg3 = 0;
wdenkdc7c9a12003-03-26 06:55:25 +00001487 ecc_code[0] = ecc_code[1] = ecc_code[2] = 0;
1488
1489 /* Build up column parity */
1490 for(j = 0; j < 256; j++) {
1491
1492 /* Get CP0 - CP5 from table */
1493 idx = nand_ecc_precalc_table[dat[j]];
wdenk7a8e9bed2003-05-31 18:35:21 +00001494 reg1 ^= idx;
wdenkdc7c9a12003-03-26 06:55:25 +00001495
1496 /* All bit XOR = 1 ? */
1497 if (idx & 0x40) {
1498 reg3 ^= (u_char) j;
wdenkdc7c9a12003-03-26 06:55:25 +00001499 }
1500 }
1501
1502 /* Create non-inverted ECC code from line parity */
wdenk7a8e9bed2003-05-31 18:35:21 +00001503 nand_trans_result((reg1 & 0x40) ? ~reg3 : reg3, reg3, ecc_code);
wdenkdc7c9a12003-03-26 06:55:25 +00001504
1505 /* Calculate final ECC code */
1506 ecc_code[0] = ~ecc_code[0];
1507 ecc_code[1] = ~ecc_code[1];
1508 ecc_code[2] = ((~reg1) << 2) | 0x03;
1509}
1510
1511/*
1512 * Detect and correct a 1 bit error for 256 byte block
1513 */
1514static int nand_correct_data (u_char *dat, u_char *read_ecc, u_char *calc_ecc)
1515{
1516 u_char a, b, c, d1, d2, d3, add, bit, i;
1517
1518 /* Do error detection */
1519 d1 = calc_ecc[0] ^ read_ecc[0];
1520 d2 = calc_ecc[1] ^ read_ecc[1];
1521 d3 = calc_ecc[2] ^ read_ecc[2];
1522
1523 if ((d1 | d2 | d3) == 0) {
1524 /* No errors */
1525 return 0;
1526 }
1527 else {
1528 a = (d1 ^ (d1 >> 1)) & 0x55;
1529 b = (d2 ^ (d2 >> 1)) & 0x55;
1530 c = (d3 ^ (d3 >> 1)) & 0x54;
1531
1532 /* Found and will correct single bit error in the data */
1533 if ((a == 0x55) && (b == 0x55) && (c == 0x54)) {
1534 c = 0x80;
1535 add = 0;
1536 a = 0x80;
1537 for (i=0; i<4; i++) {
1538 if (d1 & c)
1539 add |= a;
1540 c >>= 2;
1541 a >>= 1;
1542 }
1543 c = 0x80;
1544 for (i=0; i<4; i++) {
1545 if (d2 & c)
1546 add |= a;
1547 c >>= 2;
1548 a >>= 1;
1549 }
1550 bit = 0;
1551 b = 0x04;
1552 c = 0x80;
1553 for (i=0; i<3; i++) {
1554 if (d3 & c)
1555 bit |= b;
1556 c >>= 2;
1557 b >>= 1;
1558 }
1559 b = 0x01;
1560 a = dat[add];
1561 a ^= (b << bit);
1562 dat[add] = a;
1563 return 1;
1564 }
1565 else {
1566 i = 0;
1567 while (d1) {
1568 if (d1 & 0x01)
1569 ++i;
1570 d1 >>= 1;
1571 }
1572 while (d2) {
1573 if (d2 & 0x01)
1574 ++i;
1575 d2 >>= 1;
1576 }
1577 while (d3) {
1578 if (d3 & 0x01)
1579 ++i;
1580 d3 >>= 1;
1581 }
1582 if (i == 1) {
1583 /* ECC Code Error Correction */
1584 read_ecc[0] = calc_ecc[0];
1585 read_ecc[1] = calc_ecc[1];
1586 read_ecc[2] = calc_ecc[2];
1587 return 2;
1588 }
1589 else {
1590 /* Uncorrectable Error */
1591 return -1;
1592 }
1593 }
1594 }
1595
1596 /* Should never happen */
1597 return -1;
1598}
1599#endif
1600#endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) */