cmd_nand.c 48.9 KB
Newer Older
wdenk's avatar
wdenk committed
1
2
3
4
5
/*
 * Driver for NAND support, Rick Bronson
 * borrowed heavily from:
 * (c) 1999 Machine Vision Holdings, Inc.
 * (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org>
wdenk's avatar
wdenk committed
6
7
8
 *
 * Added 16-bit nand support
 * (C) 2004 Texas Instruments
wdenk's avatar
wdenk committed
9
10
11
12
13
14
 */

#include <common.h>
#include <command.h>
#include <malloc.h>
#include <asm/io.h>
15
#include <watchdog.h>
wdenk's avatar
wdenk committed
16
17
18
19
20
21
22
23
24
25
26
27

#ifdef CONFIG_SHOW_BOOT_PROGRESS
# include <status_led.h>
# define SHOW_BOOT_PROGRESS(arg)	show_boot_progress(arg)
#else
# define SHOW_BOOT_PROGRESS(arg)
#endif

#if (CONFIG_COMMANDS & CFG_CMD_NAND)

#include <linux/mtd/nand.h>
#include <linux/mtd/nand_ids.h>
wdenk's avatar
wdenk committed
28
#include <jffs2/jffs2.h>
wdenk's avatar
wdenk committed
29

wdenk's avatar
wdenk committed
30
31
32
33
34
35
#ifdef CONFIG_OMAP1510
void archflashwp(void *archdata, int wp);
#endif

#define ROUND_DOWN(value,boundary)      ((value) & (~((boundary)-1)))

wdenk's avatar
wdenk committed
36
37
38
39
40
41
42
43
44
/*
 * Definition of the out of band configuration structure
 */
struct nand_oob_config {
	int ecc_pos[6];		/* position of ECC bytes inside oob */
	int badblock_pos;	/* position of bad block flag inside oob -1 = inactive */
	int eccvalid_pos;	/* position of ECC valid flag inside oob -1 = inactive */
} oob_config = { {0}, 0, 0};

45
#undef	NAND_DEBUG
wdenk's avatar
wdenk committed
46
#undef	PSYCHO_DEBUG
wdenk's avatar
wdenk committed
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61

/* ****************** WARNING *********************
 * When ALLOW_ERASE_BAD_DEBUG is non-zero the erase command will
 * erase (or at least attempt to erase) blocks that are marked
 * bad. This can be very handy if you are _sure_ that the block
 * is OK, say because you marked a good block bad to test bad
 * block handling and you are done testing, or if you have
 * accidentally marked blocks bad.
 *
 * Erasing factory marked bad blocks is a _bad_ idea. If the
 * erase succeeds there is no reliable way to find them again,
 * and attempting to program or erase bad blocks can affect
 * the data in _other_ (good) blocks.
 */
#define	 ALLOW_ERASE_BAD_DEBUG 0
wdenk's avatar
wdenk committed
62
63

#define CONFIG_MTD_NAND_ECC  /* enable ECC */
wdenk's avatar
wdenk committed
64
#define CONFIG_MTD_NAND_ECC_JFFS2
wdenk's avatar
wdenk committed
65

wdenk's avatar
wdenk committed
66
67
68
69
/* bits for nand_rw() `cmd'; or together as needed */
#define NANDRW_READ	0x01
#define NANDRW_WRITE	0x00
#define NANDRW_JFFS2	0x02
70
#define NANDRW_JFFS2_SKIP	0x04
wdenk's avatar
wdenk committed
71

wdenk's avatar
wdenk committed
72
73
74
75
/*
 * Function Prototypes
 */
static void nand_print(struct nand_chip *nand);
wdenk's avatar
wdenk committed
76
int nand_rw (struct nand_chip* nand, int cmd,
wdenk's avatar
wdenk committed
77
78
	    size_t start, size_t len,
	    size_t * retlen, u_char * buf);
wdenk's avatar
wdenk committed
79
int nand_erase(struct nand_chip* nand, size_t ofs, size_t len, int clean);
wdenk's avatar
wdenk committed
80
81
82
83
static int nand_read_ecc(struct nand_chip *nand, size_t start, size_t len,
		 size_t * retlen, u_char *buf, u_char *ecc_code);
static int nand_write_ecc (struct nand_chip* nand, size_t to, size_t len,
			   size_t * retlen, const u_char * buf, u_char * ecc_code);
wdenk's avatar
wdenk committed
84
85
86
87
88
static void nand_print_bad(struct nand_chip *nand);
static int nand_read_oob(struct nand_chip* nand, size_t ofs, size_t len,
		 size_t * retlen, u_char * buf);
static int nand_write_oob(struct nand_chip* nand, size_t ofs, size_t len,
		 size_t * retlen, const u_char * buf);
wdenk's avatar
wdenk committed
89
static int NanD_WaitReady(struct nand_chip *nand, int ale_wait);
wdenk's avatar
wdenk committed
90
91
92
93
94
#ifdef CONFIG_MTD_NAND_ECC
static int nand_correct_data (u_char *dat, u_char *read_ecc, u_char *calc_ecc);
static void nand_calculate_ecc (const u_char *dat, u_char *ecc_code);
#endif

wdenk's avatar
wdenk committed
95
struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE] = {{0}};
wdenk's avatar
wdenk committed
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111

/* Current NAND Device	*/
static int curr_device = -1;

/* ------------------------------------------------------------------------- */

int do_nand (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
    int rcode = 0;

    switch (argc) {
    case 0:
    case 1:
	printf ("Usage:\n%s\n", cmdtp->usage);
	return 1;
    case 2:
wdenk's avatar
wdenk committed
112
	if (strcmp(argv[1],"info") == 0) {
wdenk's avatar
wdenk committed
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
		int i;

		putc ('\n');

		for (i=0; i<CFG_MAX_NAND_DEVICE; ++i) {
			if(nand_dev_desc[i].ChipID == NAND_ChipID_UNKNOWN)
				continue; /* list only known devices */
			printf ("Device %d: ", i);
			nand_print(&nand_dev_desc[i]);
		}
		return 0;

	} else if (strcmp(argv[1],"device") == 0) {
		if ((curr_device < 0) || (curr_device >= CFG_MAX_NAND_DEVICE)) {
			puts ("\nno devices available\n");
			return 1;
		}
		printf ("\nDevice %d: ", curr_device);
		nand_print(&nand_dev_desc[curr_device]);
		return 0;
wdenk's avatar
wdenk committed
133
134
135
136
137
138
139
140
141
142

	} else if (strcmp(argv[1],"bad") == 0) {
		if ((curr_device < 0) || (curr_device >= CFG_MAX_NAND_DEVICE)) {
			puts ("\nno devices available\n");
			return 1;
		}
		printf ("\nDevice %d bad blocks:\n", curr_device);
		nand_print_bad(&nand_dev_desc[curr_device]);
		return 0;

wdenk's avatar
wdenk committed
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
	}
	printf ("Usage:\n%s\n", cmdtp->usage);
	return 1;
    case 3:
	if (strcmp(argv[1],"device") == 0) {
		int dev = (int)simple_strtoul(argv[2], NULL, 10);

		printf ("\nDevice %d: ", dev);
		if (dev >= CFG_MAX_NAND_DEVICE) {
			puts ("unknown device\n");
			return 1;
		}
		nand_print(&nand_dev_desc[dev]);
		/*nand_print (dev);*/

		if (nand_dev_desc[dev].ChipID == NAND_ChipID_UNKNOWN) {
			return 1;
		}

		curr_device = dev;

		puts ("... is now current device\n");

		return 0;
	}
wdenk's avatar
wdenk committed
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
	else if (strcmp(argv[1],"erase") == 0 && strcmp(argv[2], "clean") == 0) {
		struct nand_chip* nand = &nand_dev_desc[curr_device];
		ulong off = 0;
		ulong size = nand->totlen;
		int ret;

		printf ("\nNAND erase: device %d offset %ld, size %ld ... ",
			curr_device, off, size);

		ret = nand_erase (nand, off, size, 1);

		printf("%s\n", ret ? "ERROR" : "OK");

		return ret;
	}
wdenk's avatar
wdenk committed
183
184
185
186
187
188

	printf ("Usage:\n%s\n", cmdtp->usage);
	return 1;
    default:
	/* at least 4 args */

wdenk's avatar
wdenk committed
189
190
	if (strncmp(argv[1], "read", 4) == 0 ||
	    strncmp(argv[1], "write", 5) == 0) {
wdenk's avatar
wdenk committed
191
192
193
		ulong addr = simple_strtoul(argv[2], NULL, 16);
		ulong off  = simple_strtoul(argv[3], NULL, 16);
		ulong size = simple_strtoul(argv[4], NULL, 16);
wdenk's avatar
wdenk committed
194
195
		int cmd    = (strncmp(argv[1], "read", 4) == 0) ?
				NANDRW_READ : NANDRW_WRITE;
wdenk's avatar
wdenk committed
196
		int ret, total;
wdenk's avatar
wdenk committed
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
		char* cmdtail = strchr(argv[1], '.');

		if (cmdtail && !strncmp(cmdtail, ".oob", 2)) {
			/* read out-of-band data */
			if (cmd & NANDRW_READ) {
				ret = nand_read_oob(nand_dev_desc + curr_device,
						    off, size, &total,
						    (u_char*)addr);
			}
			else {
				ret = nand_write_oob(nand_dev_desc + curr_device,
						     off, size, &total,
						     (u_char*)addr);
			}
			return ret;
		}
		else if (cmdtail && !strncmp(cmdtail, ".jffs2", 2))
			cmd |= NANDRW_JFFS2;	/* skip bad blocks */
215
216
217
218
219
		else if (cmdtail && !strncmp(cmdtail, ".jffs2s", 2)) {
			cmd |= NANDRW_JFFS2;	/* skip bad blocks (on read too) */
			if (cmd & NANDRW_READ)
				cmd |= NANDRW_JFFS2_SKIP;	/* skip bad blocks (on read too) */
		}
wdenk's avatar
wdenk committed
220
221
222
223
224
#ifdef SXNI855T
		/* need ".e" same as ".j" for compatibility with older units */
		else if (cmdtail && !strcmp(cmdtail, ".e"))
			cmd |= NANDRW_JFFS2;	/* skip bad blocks */
#endif
225
226
227
228
229
230
231
232
#ifdef CFG_NAND_SKIP_BAD_DOT_I
		/* need ".i" same as ".jffs2s" for compatibility with older units (esd) */
		/* ".i" for image -> read skips bad block (no 0xff) */
		else if (cmdtail && !strcmp(cmdtail, ".i"))
			cmd |= NANDRW_JFFS2;	/* skip bad blocks (on read too) */
			if (cmd & NANDRW_READ)
				cmd |= NANDRW_JFFS2_SKIP;	/* skip bad blocks (on read too) */
#endif /* CFG_NAND_SKIP_BAD_DOT_I */
wdenk's avatar
wdenk committed
233
234
235
236
		else if (cmdtail) {
			printf ("Usage:\n%s\n", cmdtp->usage);
			return 1;
		}
wdenk's avatar
wdenk committed
237
238

		printf ("\nNAND %s: device %d offset %ld, size %ld ... ",
wdenk's avatar
wdenk committed
239
240
			(cmd & NANDRW_READ) ? "read" : "write",
			curr_device, off, size);
wdenk's avatar
wdenk committed
241
242
243
244

		ret = nand_rw(nand_dev_desc + curr_device, cmd, off, size,
			     &total, (u_char*)addr);

wdenk's avatar
wdenk committed
245
		printf (" %d bytes %s: %s\n", total,
246
			(cmd & NANDRW_READ) ? "read" : "written",
wdenk's avatar
wdenk committed
247
248
249
			ret ? "ERROR" : "OK");

		return ret;
wdenk's avatar
wdenk committed
250
251
252
253
254
	} else if (strcmp(argv[1],"erase") == 0 &&
		   (argc == 4 || strcmp("clean", argv[2]) == 0)) {
		int clean = argc == 5;
		ulong off = simple_strtoul(argv[2 + clean], NULL, 16);
		ulong size = simple_strtoul(argv[3 + clean], NULL, 16);
wdenk's avatar
wdenk committed
255
256
257
258
259
		int ret;

		printf ("\nNAND erase: device %d offset %ld, size %ld ... ",
			curr_device, off, size);

wdenk's avatar
wdenk committed
260
		ret = nand_erase (nand_dev_desc + curr_device, off, size, clean);
wdenk's avatar
wdenk committed
261
262
263
264
265
266
267
268
269
270
271
272
273

		printf("%s\n", ret ? "ERROR" : "OK");

		return ret;
	} else {
		printf ("Usage:\n%s\n", cmdtp->usage);
		rcode = 1;
	}

	return rcode;
    }
}

274
275
U_BOOT_CMD(
	nand,	5,	1,	do_nand,
276
277
278
	"nand    - NAND sub-system\n",
	"info  - show available NAND devices\n"
	"nand device [dev] - show or set current device\n"
279
	"nand read[.jffs2[s]]  addr off size\n"
280
281
282
283
284
285
286
287
288
	"nand write[.jffs2] addr off size - read/write `size' bytes starting\n"
	"    at offset `off' to/from memory address `addr'\n"
	"nand erase [clean] [off size] - erase `size' bytes from\n"
	"    offset `off' (entire device if not specified)\n"
	"nand bad - show bad blocks\n"
	"nand read.oob addr off size - read out-of-band data\n"
	"nand write.oob addr off size - read out-of-band data\n"
);

wdenk's avatar
wdenk committed
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
	char *boot_device = NULL;
	char *ep;
	int dev;
	ulong cnt;
	ulong addr;
	ulong offset = 0;
	image_header_t *hdr;
	int rcode = 0;
	switch (argc) {
	case 1:
		addr = CFG_LOAD_ADDR;
		boot_device = getenv ("bootdevice");
		break;
	case 2:
		addr = simple_strtoul(argv[1], NULL, 16);
		boot_device = getenv ("bootdevice");
		break;
	case 3:
		addr = simple_strtoul(argv[1], NULL, 16);
		boot_device = argv[2];
		break;
	case 4:
		addr = simple_strtoul(argv[1], NULL, 16);
		boot_device = argv[2];
		offset = simple_strtoul(argv[3], NULL, 16);
		break;
	default:
		printf ("Usage:\n%s\n", cmdtp->usage);
		SHOW_BOOT_PROGRESS (-1);
		return 1;
	}

	if (!boot_device) {
		puts ("\n** No boot device **\n");
		SHOW_BOOT_PROGRESS (-1);
		return 1;
	}

	dev = simple_strtoul(boot_device, &ep, 16);

	if ((dev >= CFG_MAX_NAND_DEVICE) ||
	    (nand_dev_desc[dev].ChipID == NAND_ChipID_UNKNOWN)) {
		printf ("\n** Device %d not available\n", dev);
		SHOW_BOOT_PROGRESS (-1);
		return 1;
	}

wdenk's avatar
wdenk committed
338
	printf ("\nLoading from device %d: %s at 0x%lx (offset 0x%lx)\n",
wdenk's avatar
wdenk committed
339
340
341
		dev, nand_dev_desc[dev].name, nand_dev_desc[dev].IO_ADDR,
		offset);

wdenk's avatar
wdenk committed
342
	if (nand_rw (nand_dev_desc + dev, NANDRW_READ, offset,
wdenk's avatar
wdenk committed
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
		    SECTORSIZE, NULL, (u_char *)addr)) {
		printf ("** Read error on %d\n", dev);
		SHOW_BOOT_PROGRESS (-1);
		return 1;
	}

	hdr = (image_header_t *)addr;

	if (ntohl(hdr->ih_magic) == IH_MAGIC) {

		print_image_hdr (hdr);

		cnt = (ntohl(hdr->ih_size) + sizeof(image_header_t));
		cnt -= SECTORSIZE;
	} else {
		printf ("\n** Bad Magic Number 0x%x **\n", hdr->ih_magic);
		SHOW_BOOT_PROGRESS (-1);
		return 1;
	}

wdenk's avatar
wdenk committed
363
	if (nand_rw (nand_dev_desc + dev, NANDRW_READ, offset + SECTORSIZE, cnt,
wdenk's avatar
wdenk committed
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
		    NULL, (u_char *)(addr+SECTORSIZE))) {
		printf ("** Read error on %d\n", dev);
		SHOW_BOOT_PROGRESS (-1);
		return 1;
	}

	/* Loading ok, update default load address */

	load_addr = addr;

	/* Check if we should attempt an auto-start */
	if (((ep = getenv("autostart")) != NULL) && (strcmp(ep,"yes") == 0)) {
		char *local_args[2];
		extern int do_bootm (cmd_tbl_t *, int, int, char *[]);

		local_args[0] = argv[0];
		local_args[1] = NULL;

wdenk's avatar
wdenk committed
382
		printf ("Automatic boot of image at addr 0x%08lx ...\n", addr);
wdenk's avatar
wdenk committed
383
384
385
386
387
388
389

		do_bootm (cmdtp, 0, 1, local_args);
		rcode = 1;
	}
	return rcode;
}

390
391
U_BOOT_CMD(
	nboot,	4,	1,	do_nandboot,
392
393
394
395
	"nboot   - boot from NAND device\n",
	"loadAddr dev\n"
);

wdenk's avatar
wdenk committed
396
397
398
399
400
/* returns 0 if block containing pos is OK:
 *		valid erase block and
 *		not marked bad, or no bad mark position is specified
 * returns 1 if marked bad or otherwise invalid
 */
wdenk's avatar
wdenk committed
401
int check_block (struct nand_chip *nand, unsigned long pos)
wdenk's avatar
wdenk committed
402
403
404
{
	int retlen;
	uint8_t oob_data;
wdenk's avatar
wdenk committed
405
	uint16_t oob_data16[6];
wdenk's avatar
wdenk committed
406
407
408
409
410
411
412
413
414
415
	int page0 = pos & (-nand->erasesize);
	int page1 = page0 + nand->oobblock;
	int badpos = oob_config.badblock_pos;

	if (pos >= nand->totlen)
		return 1;

	if (badpos < 0)
		return 0;	/* no way to check, assume OK */

wdenk's avatar
wdenk committed
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
	if (nand->bus16) {
		if (nand_read_oob(nand, (page0 + 0), 12, &retlen, (uint8_t *)oob_data16)
		    || (oob_data16[2] & 0xff00) != 0xff00)
			return 1;
		if (nand_read_oob(nand, (page1 + 0), 12, &retlen, (uint8_t *)oob_data16)
		    || (oob_data16[2] & 0xff00) != 0xff00)
			return 1;
	} else {
		/* Note - bad block marker can be on first or second page */
		if (nand_read_oob(nand, page0 + badpos, 1, &retlen, &oob_data)
		    || oob_data != 0xff
		    || nand_read_oob (nand, page1 + badpos, 1, &retlen, &oob_data)
		    || oob_data != 0xff)
			return 1;
	}
wdenk's avatar
wdenk committed
431
432
433

	return 0;
}
wdenk's avatar
wdenk committed
434

wdenk's avatar
wdenk committed
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
/* print bad blocks in NAND flash */
static void nand_print_bad(struct nand_chip* nand)
{
	unsigned long pos;

	for (pos = 0; pos < nand->totlen; pos += nand->erasesize) {
		if (check_block(nand, pos))
			printf(" 0x%8.8lx\n", pos);
	}
	puts("\n");
}

/* cmd: 0: NANDRW_WRITE			write, fail on bad block
 *	1: NANDRW_READ			read, fail on bad block
 *	2: NANDRW_WRITE | NANDRW_JFFS2	write, skip bad blocks
 *	3: NANDRW_READ | NANDRW_JFFS2	read, data all 0xff for bad blocks
451
 *      7: NANDRW_READ | NANDRW_JFFS2 | NANDRW_JFFS2_SKIP read, skip bad blocks
wdenk's avatar
wdenk committed
452
 */
wdenk's avatar
wdenk committed
453
int nand_rw (struct nand_chip* nand, int cmd,
wdenk's avatar
wdenk committed
454
455
456
	    size_t start, size_t len,
	    size_t * retlen, u_char * buf)
{
wdenk's avatar
wdenk committed
457
	int ret = 0, n, total = 0;
wdenk's avatar
wdenk committed
458
	char eccbuf[6];
wdenk's avatar
wdenk committed
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
	/* eblk (once set) is the start of the erase block containing the
	 * data being processed.
	 */
	unsigned long eblk = ~0;	/* force mismatch on first pass */
	unsigned long erasesize = nand->erasesize;

	while (len) {
		if ((start & (-erasesize)) != eblk) {
			/* have crossed into new erase block, deal with
			 * it if it is sure marked bad.
			 */
			eblk = start & (-erasesize); /* start of block */
			if (check_block(nand, eblk)) {
				if (cmd == (NANDRW_READ | NANDRW_JFFS2)) {
					while (len > 0 &&
					       start - eblk < erasesize) {
						*(buf++) = 0xff;
						++start;
						++total;
						--len;
					}
					continue;
wdenk's avatar
wdenk committed
481
				} else if (cmd == (NANDRW_READ | NANDRW_JFFS2 | NANDRW_JFFS2_SKIP)) {
482
483
					start += erasesize;
					continue;
wdenk's avatar
wdenk committed
484
				} else if (cmd == (NANDRW_WRITE | NANDRW_JFFS2)) {
wdenk's avatar
wdenk committed
485
486
487
					/* skip bad block */
					start += erasesize;
					continue;
wdenk's avatar
wdenk committed
488
				} else {
wdenk's avatar
wdenk committed
489
490
491
492
493
					ret = 1;
					break;
				}
			}
		}
wdenk's avatar
wdenk committed
494
495
		/* The ECC will not be calculated correctly if
		   less than 512 is written or read */
wdenk's avatar
wdenk committed
496
497
498
499
		/* Is request at least 512 bytes AND it starts on a proper boundry */
		if((start != ROUND_DOWN(start, 0x200)) || (len < 0x200))
			printf("Warning block writes should be at least 512 bytes and start on a 512 byte boundry\n");

wdenk's avatar
wdenk committed
500
		if (cmd & NANDRW_READ) {
wdenk's avatar
wdenk committed
501
502
			ret = nand_read_ecc(nand, start,
					   min(len, eblk + erasesize - start),
wdenk's avatar
wdenk committed
503
					   &n, (u_char*)buf, eccbuf);
wdenk's avatar
wdenk committed
504
		} else {
wdenk's avatar
wdenk committed
505
506
			ret = nand_write_ecc(nand, start,
					    min(len, eblk + erasesize - start),
wdenk's avatar
wdenk committed
507
					    &n, (u_char*)buf, eccbuf);
wdenk's avatar
wdenk committed
508
		}
wdenk's avatar
wdenk committed
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524

		if (ret)
			break;

		start  += n;
		buf   += n;
		total += n;
		len   -= n;
	}
	if (retlen)
		*retlen = total;

	return ret;
}

static void nand_print(struct nand_chip *nand)
525
{
wdenk's avatar
wdenk committed
526
527
528
529
530
531
532
533
534
	if (nand->numchips > 1) {
		printf("%s at 0x%lx,\n"
		       "\t  %d chips %s, size %d MB, \n"
		       "\t  total size %ld MB, sector size %ld kB\n",
		       nand->name, nand->IO_ADDR, nand->numchips,
		       nand->chips_name, 1 << (nand->chipshift - 20),
		       nand->totlen >> 20, nand->erasesize >> 10);
	}
	else {
wdenk's avatar
wdenk committed
535
		printf("%s at 0x%lx (", nand->chips_name, nand->IO_ADDR);
wdenk's avatar
wdenk committed
536
537
		print_size(nand->totlen, ", ");
		print_size(nand->erasesize, " sector)\n");
wdenk's avatar
wdenk committed
538
539
540
541
542
	}
}

/* ------------------------------------------------------------------------- */

wdenk's avatar
wdenk committed
543
static int NanD_WaitReady(struct nand_chip *nand, int ale_wait)
wdenk's avatar
wdenk committed
544
545
546
547
{
	/* This is inline, to optimise the common case, where it's ready instantly */
	int ret = 0;

wdenk's avatar
wdenk committed
548
549
550
551
552
553
#ifdef NAND_NO_RB	/* in config file, shorter delays currently wrap accesses */
	if(ale_wait)
		NAND_WAIT_READY(nand);	/* do the worst case 25us wait */
	else
		udelay(10);
#else	/* has functional r/b signal */
554
	NAND_WAIT_READY(nand);
wdenk's avatar
wdenk committed
555
#endif
wdenk's avatar
wdenk committed
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
	return ret;
}

/* NanD_Command: Send a flash command to the flash chip */

static inline int NanD_Command(struct nand_chip *nand, unsigned char command)
{
	unsigned long nandptr = nand->IO_ADDR;

	/* Assert the CLE (Command Latch Enable) line to the flash chip */
	NAND_CTL_SETCLE(nandptr);

	/* Send the command */
	WRITE_NAND_COMMAND(command, nandptr);

	/* Lower the CLE line */
	NAND_CTL_CLRCLE(nandptr);

wdenk's avatar
wdenk committed
574
575
576
577
#ifdef NAND_NO_RB
	if(command == NAND_CMD_RESET){
		u_char ret_val;
		NanD_Command(nand, NAND_CMD_STATUS);
wdenk's avatar
wdenk committed
578
		do {
wdenk's avatar
wdenk committed
579
580
581
582
583
			ret_val = READ_NAND(nandptr);/* wait till ready */
		} while((ret_val & 0x40) != 0x40);
	}
#endif
	return NanD_WaitReady(nand, 0);
wdenk's avatar
wdenk committed
584
585
586
587
588
}

/* NanD_Address: Set the current address for the flash chip */

static int NanD_Address(struct nand_chip *nand, int numbytes, unsigned long ofs)
589
590
591
{
	unsigned long nandptr;
	int i;
wdenk's avatar
wdenk committed
592

593
	nandptr = nand->IO_ADDR;
wdenk's avatar
wdenk committed
594
595

	/* Assert the ALE (Address Latch Enable) line to the flash chip */
596
597
598
599
600
601
602
603
604
605
606
607
	NAND_CTL_SETALE(nandptr);

	/* Send the address */
	/* Devices with 256-byte page are addressed as:
	 * Column (bits 0-7), Page (bits 8-15, 16-23, 24-31)
	 * there is no device on the market with page256
	 * and more than 24 bits.
	 * Devices with 512-byte page are addressed as:
	 * Column (bits 0-7), Page (bits 9-16, 17-24, 25-31)
	 * 25-31 is sent only if the chip support it.
	 * bit 8 changes the read command to be sent
	 * (NAND_CMD_READ0 or NAND_CMD_READ1).
wdenk's avatar
wdenk committed
608
609
	 */

610
611
	if (numbytes == ADDR_COLUMN || numbytes == ADDR_COLUMN_PAGE)
		WRITE_NAND_ADDRESS(ofs, nandptr);
wdenk's avatar
wdenk committed
612

613
	ofs = ofs >> nand->page_shift;
wdenk's avatar
wdenk committed
614

wdenk's avatar
wdenk committed
615
616
	if (numbytes == ADDR_PAGE || numbytes == ADDR_COLUMN_PAGE) {
		for (i = 0; i < nand->pageadrlen; i++, ofs = ofs >> 8) {
617
			WRITE_NAND_ADDRESS(ofs, nandptr);
wdenk's avatar
wdenk committed
618
619
		}
	}
wdenk's avatar
wdenk committed
620

621
622
	/* Lower the ALE line */
	NAND_CTL_CLRALE(nandptr);
wdenk's avatar
wdenk committed
623

624
	/* Wait for the chip to respond */
wdenk's avatar
wdenk committed
625
	return NanD_WaitReady(nand, 1);
626
}
wdenk's avatar
wdenk committed
627
628
629
630
631
632

/* NanD_SelectChip: Select a given flash chip within the current floor */

static inline int NanD_SelectChip(struct nand_chip *nand, int chip)
{
	/* Wait for it to be ready */
wdenk's avatar
wdenk committed
633
	return NanD_WaitReady(nand, 0);
wdenk's avatar
wdenk committed
634
635
636
637
638
639
640
641
}

/* NanD_IdentChip: Identify a given NAND chip given {floor,chip} */

static int NanD_IdentChip(struct nand_chip *nand, int floor, int chip)
{
	int mfr, id, i;

642
	NAND_ENABLE_CE(nand);  /* set pin low */
wdenk's avatar
wdenk committed
643
644
645
646
647
648
	/* Reset the chip */
	if (NanD_Command(nand, NAND_CMD_RESET)) {
#ifdef NAND_DEBUG
		printf("NanD_Command (reset) for %d,%d returned true\n",
		       floor, chip);
#endif
649
		NAND_DISABLE_CE(nand);  /* set pin high */
wdenk's avatar
wdenk committed
650
651
652
653
654
655
656
657
658
		return 0;
	}

	/* Read the NAND chip ID: 1. Send ReadID command */
	if (NanD_Command(nand, NAND_CMD_READID)) {
#ifdef NAND_DEBUG
		printf("NanD_Command (ReadID) for %d,%d returned true\n",
		       floor, chip);
#endif
659
		NAND_DISABLE_CE(nand);  /* set pin high */
wdenk's avatar
wdenk committed
660
661
662
663
664
665
666
667
668
669
670
671
		return 0;
	}

	/* Read the NAND chip ID: 2. Send address byte zero */
	NanD_Address(nand, ADDR_COLUMN, 0);

	/* Read the manufacturer and device id codes from the device */

	mfr = READ_NAND(nand->IO_ADDR);

	id = READ_NAND(nand->IO_ADDR);

wdenk's avatar
wdenk committed
672
	NAND_DISABLE_CE(nand);  /* set pin high */
wdenk's avatar
wdenk committed
673
	/* No response - return failure */
674
	if (mfr == 0xff || mfr == 0) {
675
#ifdef NAND_DEBUG
676
		printf("NanD_Command (ReadID) got %d %d\n", mfr, id);
677
#endif
678
679
		return 0;
	}
wdenk's avatar
wdenk committed
680
681
682
683
684
685

	/* Check it's the same as the first chip we identified.
	 * M-Systems say that any given nand_chip device should only
	 * contain _one_ type of flash part, although that's not a
	 * hardware restriction. */
	if (nand->mfr) {
wdenk's avatar
wdenk committed
686
		if (nand->mfr == mfr && nand->id == id) {
wdenk's avatar
wdenk committed
687
			return 1;	/* This is another the same the first */
wdenk's avatar
wdenk committed
688
		} else {
wdenk's avatar
wdenk committed
689
690
			printf("Flash chip at floor %d, chip %d is different:\n",
			       floor, chip);
wdenk's avatar
wdenk committed
691
		}
wdenk's avatar
wdenk committed
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
	}

	/* Print and store the manufacturer and ID codes. */
	for (i = 0; nand_flash_ids[i].name != NULL; i++) {
		if (mfr == nand_flash_ids[i].manufacture_id &&
		    id == nand_flash_ids[i].model_id) {
#ifdef NAND_DEBUG
			printf("Flash chip found:\n\t Manufacturer ID: 0x%2.2X, "
			       "Chip ID: 0x%2.2X (%s)\n", mfr, id,
			       nand_flash_ids[i].name);
#endif
			if (!nand->mfr) {
				nand->mfr = mfr;
				nand->id = id;
				nand->chipshift =
				    nand_flash_ids[i].chipshift;
				nand->page256 = nand_flash_ids[i].page256;
wdenk's avatar
wdenk committed
709
				nand->eccsize = 256;
wdenk's avatar
wdenk committed
710
711
712
713
714
715
716
717
718
				if (nand->page256) {
					nand->oobblock = 256;
					nand->oobsize = 8;
					nand->page_shift = 8;
				} else {
					nand->oobblock = 512;
					nand->oobsize = 16;
					nand->page_shift = 9;
				}
wdenk's avatar
wdenk committed
719
720
721
722
723
				nand->pageadrlen = nand_flash_ids[i].pageadrlen;
				nand->erasesize  = nand_flash_ids[i].erasesize;
				nand->chips_name = nand_flash_ids[i].name;
				nand->bus16	 = nand_flash_ids[i].bus16;
 				return 1;
wdenk's avatar
wdenk committed
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
			}
			return 0;
		}
	}


#ifdef NAND_DEBUG
	/* We haven't fully identified the chip. Print as much as we know. */
	printf("Unknown flash chip found: %2.2X %2.2X\n",
	       id, mfr);
#endif

	return 0;
}

/* NanD_ScanChips: Find all NAND chips present in a nand_chip, and identify them */

static void NanD_ScanChips(struct nand_chip *nand)
{
	int floor, chip;
	int numchips[NAND_MAX_FLOORS];
	int maxchips = NAND_MAX_CHIPS;
	int ret = 1;

	nand->numchips = 0;
	nand->mfr = 0;
	nand->id = 0;


	/* For each floor, find the number of valid chips it contains */
	for (floor = 0; floor < NAND_MAX_FLOORS; floor++) {
		ret = 1;
		numchips[floor] = 0;
		for (chip = 0; chip < maxchips && ret != 0; chip++) {

			ret = NanD_IdentChip(nand, floor, chip);
			if (ret) {
				numchips[floor]++;
				nand->numchips++;
			}
		}
	}

	/* If there are none at all that we recognise, bail */
	if (!nand->numchips) {
769
#ifdef NAND_DEBUG
770
		puts ("No NAND flash chips recognised.\n");
771
#endif
wdenk's avatar
wdenk committed
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
		return;
	}

	/* Allocate an array to hold the information for each chip */
	nand->chips = malloc(sizeof(struct Nand) * nand->numchips);
	if (!nand->chips) {
		puts ("No memory for allocating chip info structures\n");
		return;
	}

	ret = 0;

	/* Fill out the chip array with {floor, chipno} for each
	 * detected chip in the device. */
	for (floor = 0; floor < NAND_MAX_FLOORS; floor++) {
		for (chip = 0; chip < numchips[floor]; chip++) {
			nand->chips[ret].floor = floor;
			nand->chips[ret].chip = chip;
			nand->chips[ret].curadr = 0;
			nand->chips[ret].curmode = 0x50;
			ret++;
		}
	}

	/* Calculate and print the total size of the device */
	nand->totlen = nand->numchips * (1 << nand->chipshift);

#ifdef NAND_DEBUG
	printf("%d flash chips found. Total nand_chip size: %ld MB\n",
	       nand->numchips, nand->totlen >> 20);
#endif
}
804

wdenk's avatar
wdenk committed
805
/* we need to be fast here, 1 us per read translates to 1 second per meg */
wdenk's avatar
wdenk committed
806
static void NanD_ReadBuf (struct nand_chip *nand, u_char * data_buf, int cntr)
807
{
wdenk's avatar
wdenk committed
808
	unsigned long nandptr = nand->IO_ADDR;
809

wdenk's avatar
wdenk committed
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
	NanD_Command (nand, NAND_CMD_READ0);

	if (nand->bus16) {
		u16 val;

		while (cntr >= 16) {
			val = READ_NAND (nandptr);
			*data_buf++ = val & 0xff;
			*data_buf++ = val >> 8;
			val = READ_NAND (nandptr);
			*data_buf++ = val & 0xff;
			*data_buf++ = val >> 8;
			val = READ_NAND (nandptr);
			*data_buf++ = val & 0xff;
			*data_buf++ = val >> 8;
			val = READ_NAND (nandptr);
			*data_buf++ = val & 0xff;
			*data_buf++ = val >> 8;
			val = READ_NAND (nandptr);
			*data_buf++ = val & 0xff;
			*data_buf++ = val >> 8;
			val = READ_NAND (nandptr);
			*data_buf++ = val & 0xff;
			*data_buf++ = val >> 8;
			val = READ_NAND (nandptr);
			*data_buf++ = val & 0xff;
			*data_buf++ = val >> 8;
			val = READ_NAND (nandptr);
			*data_buf++ = val & 0xff;
			*data_buf++ = val >> 8;
			cntr -= 16;
		}

		while (cntr > 0) {
			val = READ_NAND (nandptr);
			*data_buf++ = val & 0xff;
			*data_buf++ = val >> 8;
			cntr -= 2;
		}
	} else {
		while (cntr >= 16) {
			*data_buf++ = READ_NAND (nandptr);
			*data_buf++ = READ_NAND (nandptr);
			*data_buf++ = READ_NAND (nandptr);
			*data_buf++ = READ_NAND (nandptr);
			*data_buf++ = READ_NAND (nandptr);
			*data_buf++ = READ_NAND (nandptr);
			*data_buf++ = READ_NAND (nandptr);
			*data_buf++ = READ_NAND (nandptr);
			*data_buf++ = READ_NAND (nandptr);
			*data_buf++ = READ_NAND (nandptr);
			*data_buf++ = READ_NAND (nandptr);
			*data_buf++ = READ_NAND (nandptr);
			*data_buf++ = READ_NAND (nandptr);
			*data_buf++ = READ_NAND (nandptr);
			*data_buf++ = READ_NAND (nandptr);
			*data_buf++ = READ_NAND (nandptr);
			cntr -= 16;
		}

		while (cntr > 0) {
			*data_buf++ = READ_NAND (nandptr);
			cntr--;
		}
874
875
	}
}
wdenk's avatar
wdenk committed
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893

/*
 * NAND read with ECC
 */
static int nand_read_ecc(struct nand_chip *nand, size_t start, size_t len,
		 size_t * retlen, u_char *buf, u_char *ecc_code)
{
	int col, page;
	int ecc_status = 0;
#ifdef CONFIG_MTD_NAND_ECC
	int j;
	int ecc_failed = 0;
	u_char *data_poi;
	u_char ecc_calc[6];
#endif

	/* Do not allow reads past end of device */
	if ((start + len) > nand->totlen) {
wdenk's avatar
wdenk committed
894
895
		printf ("%s: Attempt read beyond end of device %x %x %x\n",
			__FUNCTION__, (uint) start, (uint) len, (uint) nand->totlen);
wdenk's avatar
wdenk committed
896
897
898
899
900
		*retlen = 0;
		return -1;
	}

	/* First we calculate the starting page */
901
902
	/*page = shr(start, nand->page_shift);*/
	page = start >> nand->page_shift;
wdenk's avatar
wdenk committed
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921

	/* Get raw starting column */
	col = start & (nand->oobblock - 1);

	/* Initialize return value */
	*retlen = 0;

	/* Select the NAND device */
	NAND_ENABLE_CE(nand);  /* set pin low */

	/* Loop until all data read */
	while (*retlen < len) {

#ifdef CONFIG_MTD_NAND_ECC
		/* Do we have this page in cache ? */
		if (nand->cache_page == page)
			goto readdata;
		/* Send the read command */
		NanD_Command(nand, NAND_CMD_READ0);
wdenk's avatar
wdenk committed
922
923
924
925
926
927
928
929
		if (nand->bus16) {
 			NanD_Address(nand, ADDR_COLUMN_PAGE,
				     (page << nand->page_shift) + (col >> 1));
		} else {
 			NanD_Address(nand, ADDR_COLUMN_PAGE,
				     (page << nand->page_shift) + col);
		}

wdenk's avatar
wdenk committed
930
		/* Read in a page + oob data */
wdenk's avatar
wdenk committed
931
		NanD_ReadBuf(nand, nand->data_buf, nand->oobblock + nand->oobsize);
wdenk's avatar
wdenk committed
932
933

		/* copy data into cache, for read out of cache and if ecc fails */
wdenk's avatar
wdenk committed
934
935
936
937
		if (nand->data_cache) {
			memcpy (nand->data_cache, nand->data_buf,
				nand->oobblock + nand->oobsize);
		}
wdenk's avatar
wdenk committed
938
939

		/* Pick the ECC bytes out of the oob data */
wdenk's avatar
wdenk committed
940
		for (j = 0; j < 6; j++) {
wdenk's avatar
wdenk committed
941
			ecc_code[j] = nand->data_buf[(nand->oobblock + oob_config.ecc_pos[j])];
wdenk's avatar
wdenk committed
942
		}
wdenk's avatar
wdenk committed
943
944
945
946
947
948
949
950
951

		/* Calculate the ECC and verify it */
		/* If block was not written with ECC, skip ECC */
		if (oob_config.eccvalid_pos != -1 &&
		    (nand->data_buf[nand->oobblock + oob_config.eccvalid_pos] & 0x0f) != 0x0f) {

			nand_calculate_ecc (&nand->data_buf[0], &ecc_calc[0]);
			switch (nand_correct_data (&nand->data_buf[0], &ecc_code[0], &ecc_calc[0])) {
			case -1:
952
				printf ("%s: Failed ECC read, page 0x%08x\n", __FUNCTION__, page);
wdenk's avatar
wdenk committed
953
954
955
956
				ecc_failed++;
				break;
			case 1:
			case 2:	/* transfer ECC corrected data to cache */
wdenk's avatar
wdenk committed
957
958
				if (nand->data_cache)
					memcpy (nand->data_cache, nand->data_buf, 256);
wdenk's avatar
wdenk committed
959
960
961
962
963
964
965
966
967
968
				break;
			}
		}

		if (oob_config.eccvalid_pos != -1 &&
		    nand->oobblock == 512 && (nand->data_buf[nand->oobblock + oob_config.eccvalid_pos] & 0xf0) != 0xf0) {

			nand_calculate_ecc (&nand->data_buf[256], &ecc_calc[3]);
			switch (nand_correct_data (&nand->data_buf[256], &ecc_code[3], &ecc_calc[3])) {
			case -1:
969
				printf ("%s: Failed ECC read, page 0x%08x\n", __FUNCTION__, page);
wdenk's avatar
wdenk committed
970
971
972
973
974
975
976
977
978
979
980
981
982
983
				ecc_failed++;
				break;
			case 1:
			case 2:	/* transfer ECC corrected data to cache */
				if (nand->data_cache)
					memcpy (&nand->data_cache[256], &nand->data_buf[256], 256);
				break;
			}
		}
readdata:
		/* Read the data from ECC data buffer into return buffer */
		data_poi = (nand->data_cache) ? nand->data_cache : nand->data_buf;
		data_poi += col;
		if ((*retlen + (nand->oobblock - col)) >= len) {
wdenk's avatar
wdenk committed
984
			memcpy (buf + *retlen, data_poi, len - *retlen);
wdenk's avatar
wdenk committed
985
986
			*retlen = len;
		} else {
wdenk's avatar
wdenk committed
987
			memcpy (buf + *retlen, data_poi,  nand->oobblock - col);
wdenk's avatar
wdenk committed
988
989
990
991
992
993
994
995
996
997
998
			*retlen += nand->oobblock - col;
		}
		/* Set cache page address, invalidate, if ecc_failed */
		nand->cache_page = (nand->data_cache && !ecc_failed) ? page : -1;

		ecc_status += ecc_failed;
		ecc_failed = 0;

#else
		/* Send the read command */
		NanD_Command(nand, NAND_CMD_READ0);
wdenk's avatar
wdenk committed
999
1000
		if (nand->bus16) {
			NanD_Address(nand, ADDR_COLUMN_PAGE,