Blame view

common/cmd_nand.c 23.4 KB
dc7c9a1a5   wdenk   * Patch by Rick B...
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>
384cc6874   wdenk   Patches by Josef ...
6
   *
c9f7351b5   Ben Gardiner   NAND: environment...
7
8
9
10
   * Ported 'dynenv' to 'nand env.oob' command
   * (C) 2010 Nanometrics, Inc.
   * 'dynenv' -- Dynamic environment offset in NAND OOB
   * (C) Copyright 2006-2007 OpenMoko, Inc.
384cc6874   wdenk   Patches by Josef ...
11
12
   * Added 16-bit nand support
   * (C) 2004 Texas Instruments
ea533c260   Scott Wood   cmd_nand: some in...
13
   *
418396e21   Scott Wood   nand: extend .raw...
14
   * Copyright 2010, 2012 Freescale Semiconductor
ea533c260   Scott Wood   cmd_nand: some in...
15
16
17
18
19
   * The portions of this file whose copyright is held by Freescale and which
   * are not considered a derived work of GPL v2-only code may be distributed
   * and/or modified under the terms of the GNU General Public License as
   * published by the Free Software Foundation; either version 2 of the
   * License, or (at your option) any later version.
dc7c9a1a5   wdenk   * Patch by Rick B...
20
21
22
   */
  
  #include <common.h>
cfa460adf   William Juul   Update MTD to tha...
23
  #include <linux/mtd/mtd.h>
addb2e165   Bartlomiej Sieka   Re-factoring the ...
24
25
26
27
  #include <command.h>
  #include <watchdog.h>
  #include <malloc.h>
  #include <asm/byteorder.h>
addb2e165   Bartlomiej Sieka   Re-factoring the ...
28
29
  #include <jffs2/jffs2.h>
  #include <nand.h>
0c8a84916   Ladislav Michl   Separate mtdparts...
30
  #if defined(CONFIG_CMD_MTDPARTS)
856f05441   Stefan Roese   [PATCH] NAND: Par...
31

445093d17   Wolfgang Denk   Fix "par[t]ition"...
32
  /* partition handling routines */
856f05441   Stefan Roese   [PATCH] NAND: Par...
33
34
35
  int mtdparts_init(void);
  int id_parse(const char *id, const char **ret_id, u8 *dev_type, u8 *dev_num);
  int find_dev_and_part(const char *id, struct mtd_device **dev,
4b0708093   Wolfgang Denk   Coding Style clea...
36
  		      u8 *part_num, struct part_info **part);
856f05441   Stefan Roese   [PATCH] NAND: Par...
37
  #endif
8c5659a6d   Scott Wood   nand commands: ma...
38
  static int nand_dump(nand_info_t *nand, ulong off, int only_oob, int repeat)
addb2e165   Bartlomiej Sieka   Re-factoring the ...
39
40
  {
  	int i;
9ad754fef   William Juul   make nand dump an...
41
  	u_char *datbuf, *oobbuf, *p;
8c5659a6d   Scott Wood   nand commands: ma...
42
  	static loff_t last;
e40520b5b   Masahiro Yamada   cmd_nand: fix a m...
43
  	int ret = 0;
8c5659a6d   Scott Wood   nand commands: ma...
44
45
46
47
48
  
  	if (repeat)
  		off = last + nand->writesize;
  
  	last = off;
addb2e165   Bartlomiej Sieka   Re-factoring the ...
49

62fd66f3d   Thierry Reding   cmd_nand: dump: A...
50
  	datbuf = memalign(ARCH_DMA_MINALIGN, nand->writesize);
e40520b5b   Masahiro Yamada   cmd_nand: fix a m...
51
  	if (!datbuf) {
addb2e165   Bartlomiej Sieka   Re-factoring the ...
52
53
54
55
  		puts("No memory for page buffer
  ");
  		return 1;
  	}
e40520b5b   Masahiro Yamada   cmd_nand: fix a m...
56
57
58
59
60
61
62
63
  
  	oobbuf = memalign(ARCH_DMA_MINALIGN, nand->oobsize);
  	if (!oobbuf) {
  		puts("No memory for page buffer
  ");
  		ret = 1;
  		goto free_dat;
  	}
cfa460adf   William Juul   Update MTD to tha...
64
  	off &= ~(nand->writesize - 1);
cfa460adf   William Juul   Update MTD to tha...
65
  	loff_t addr = (loff_t) off;
9ad754fef   William Juul   make nand dump an...
66
67
68
  	struct mtd_oob_ops ops;
  	memset(&ops, 0, sizeof(ops));
  	ops.datbuf = datbuf;
cfdae12f3   Tom Rini   cmd_nand.c: Fix '...
69
  	ops.oobbuf = oobbuf;
9ad754fef   William Juul   make nand dump an...
70
71
  	ops.len = nand->writesize;
  	ops.ooblen = nand->oobsize;
dfe64e2c8   Sergey Lapin   mtd: resync with ...
72
73
  	ops.mode = MTD_OPS_RAW;
  	i = mtd_read_oob(nand, addr, &ops);
addb2e165   Bartlomiej Sieka   Re-factoring the ...
74
  	if (i < 0) {
e870690bd   Stefan Roese   MTD/NAND: Fix pri...
75
76
  		printf("Error (%d) reading page %08lx
  ", i, off);
e40520b5b   Masahiro Yamada   cmd_nand: fix a m...
77
78
  		ret = 1;
  		goto free_all;
addb2e165   Bartlomiej Sieka   Re-factoring the ...
79
  	}
e870690bd   Stefan Roese   MTD/NAND: Fix pri...
80
81
  	printf("Page %08lx dump:
  ", off);
4b0708093   Wolfgang Denk   Coding Style clea...
82

7d25cd34e   Masahiro Yamada   cmd_nand: slight ...
83
84
85
86
87
  	if (!only_oob) {
  		i = nand->writesize >> 4;
  		p = datbuf;
  
  		while (i--) {
9ad754fef   William Juul   make nand dump an...
88
89
90
91
  			printf("\t%02x %02x %02x %02x %02x %02x %02x %02x"
  			       "  %02x %02x %02x %02x %02x %02x %02x %02x
  ",
  			       p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
dfbf617ff   Scott Wood   NAND read/write fix
92
93
  			       p[8], p[9], p[10], p[11], p[12], p[13], p[14],
  			       p[15]);
7d25cd34e   Masahiro Yamada   cmd_nand: slight ...
94
95
  			p += 16;
  		}
addb2e165   Bartlomiej Sieka   Re-factoring the ...
96
  	}
7d25cd34e   Masahiro Yamada   cmd_nand: slight ...
97

addb2e165   Bartlomiej Sieka   Re-factoring the ...
98
99
100
  	puts("OOB:
  ");
  	i = nand->oobsize >> 3;
cfdae12f3   Tom Rini   cmd_nand.c: Fix '...
101
  	p = oobbuf;
addb2e165   Bartlomiej Sieka   Re-factoring the ...
102
  	while (i--) {
cfa460adf   William Juul   Update MTD to tha...
103
104
105
  		printf("\t%02x %02x %02x %02x %02x %02x %02x %02x
  ",
  		       p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
addb2e165   Bartlomiej Sieka   Re-factoring the ...
106
107
  		p += 8;
  	}
e40520b5b   Masahiro Yamada   cmd_nand: fix a m...
108
109
  
  free_all:
9ad754fef   William Juul   make nand dump an...
110
  	free(oobbuf);
e40520b5b   Masahiro Yamada   cmd_nand: fix a m...
111
112
  free_dat:
  	free(datbuf);
addb2e165   Bartlomiej Sieka   Re-factoring the ...
113

e40520b5b   Masahiro Yamada   cmd_nand: fix a m...
114
  	return ret;
addb2e165   Bartlomiej Sieka   Re-factoring the ...
115
116
117
  }
  
  /* ------------------------------------------------------------------------- */
ea533c260   Scott Wood   cmd_nand: some in...
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
  static int set_dev(int dev)
  {
  	if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE ||
  	    !nand_info[dev].name) {
  		puts("No such device
  ");
  		return -1;
  	}
  
  	if (nand_curr_device == dev)
  		return 0;
  
  	printf("Device %d: %s", dev, nand_info[dev].name);
  	puts("... is now current device
  ");
  	nand_curr_device = dev;
  
  #ifdef CONFIG_SYS_NAND_SELECT_DEVICE
  	board_nand_select_device(nand_info[dev].priv, dev);
  #endif
  
  	return 0;
  }
50657c273   Nishanth Menon   NAND: Enable nand...
141
142
143
  #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
  static void print_status(ulong start, ulong end, ulong erasesize, int status)
  {
e70bfa298   Joe Hershberger   nand: Make NAND l...
144
145
146
147
148
149
  	/*
  	 * Micron NAND flash (e.g. MT29F4G08ABADAH4) BLOCK LOCK READ STATUS is
  	 * not the same as others.  Instead of bit 1 being lock, it is
  	 * #lock_tight. To make the driver support either format, ignore bit 1
  	 * and use only bit 0 and bit 2.
  	 */
50657c273   Nishanth Menon   NAND: Enable nand...
150
151
152
153
154
155
  	printf("%08lx - %08lx: %08lx blocks %s%s%s
  ",
  		start,
  		end - 1,
  		(end - start) / erasesize,
  		((status & NAND_LOCK_STATUS_TIGHT) ?  "TIGHT " : ""),
e70bfa298   Joe Hershberger   nand: Make NAND l...
156
  		(!(status & NAND_LOCK_STATUS_UNLOCK) ?  "LOCK " : ""),
50657c273   Nishanth Menon   NAND: Enable nand...
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
  		((status & NAND_LOCK_STATUS_UNLOCK) ?  "UNLOCK " : ""));
  }
  
  static void do_nand_status(nand_info_t *nand)
  {
  	ulong block_start = 0;
  	ulong off;
  	int last_status = -1;
  
  	struct nand_chip *nand_chip = nand->priv;
  	/* check the WP bit */
  	nand_chip->cmdfunc(nand, NAND_CMD_STATUS, -1, -1);
  	printf("device is %swrite protected
  ",
  		(nand_chip->read_byte(nand) & 0x80 ?
  		"NOT " : ""));
  
  	for (off = 0; off < nand->size; off += nand->erasesize) {
  		int s = nand_get_lock_status(nand, off);
  
  		/* print message only if status has changed */
  		if (s != last_status && off != 0) {
  			print_status(block_start, off, nand->erasesize,
  					last_status);
  			block_start = off;
  		}
  		last_status = s;
  	}
  	/* Print the last block info */
  	print_status(block_start, off, nand->erasesize, last_status);
  }
  #endif
c9f7351b5   Ben Gardiner   NAND: environment...
189
190
  #ifdef CONFIG_ENV_OFFSET_OOB
  unsigned long nand_env_oob_offset;
ea533c260   Scott Wood   cmd_nand: some in...
191
  int do_nand_env_oob(cmd_tbl_t *cmdtp, int argc, char *const argv[])
c9f7351b5   Ben Gardiner   NAND: environment...
192
193
194
  {
  	int ret;
  	uint32_t oob_buf[ENV_OFFSET_SIZE/sizeof(uint32_t)];
ea533c260   Scott Wood   cmd_nand: some in...
195
  	nand_info_t *nand = &nand_info[0];
c9f7351b5   Ben Gardiner   NAND: environment...
196
  	char *cmd = argv[1];
ea533c260   Scott Wood   cmd_nand: some in...
197
198
199
200
201
202
203
  	if (CONFIG_SYS_MAX_NAND_DEVICE == 0 || !nand->name) {
  		puts("no devices available
  ");
  		return 1;
  	}
  
  	set_dev(0);
c9f7351b5   Ben Gardiner   NAND: environment...
204
205
  	if (!strcmp(cmd, "get")) {
  		ret = get_nand_env_oob(nand, &nand_env_oob_offset);
53504a278   Scott Wood   NAND: formatting ...
206
  		if (ret)
c9f7351b5   Ben Gardiner   NAND: environment...
207
  			return 1;
53504a278   Scott Wood   NAND: formatting ...
208
209
210
  
  		printf("0x%08lx
  ", nand_env_oob_offset);
c9f7351b5   Ben Gardiner   NAND: environment...
211
  	} else if (!strcmp(cmd, "set")) {
ea533c260   Scott Wood   cmd_nand: some in...
212
213
  		loff_t addr;
  		loff_t maxsize;
c9f7351b5   Ben Gardiner   NAND: environment...
214
  		struct mtd_oob_ops ops;
ea533c260   Scott Wood   cmd_nand: some in...
215
  		int idx = 0;
c9f7351b5   Ben Gardiner   NAND: environment...
216
217
218
  
  		if (argc < 3)
  			goto usage;
c39d6a0ea   Tom Rini   nand: Extend nand...
219
  		/* We don't care about size, or maxsize. */
09c328075   Heiko Schocher   mtd, nand: Move c...
220
221
222
223
224
225
226
  		if (mtd_arg_off(argv[2], &idx, &addr, &maxsize, &maxsize,
  				MTD_DEV_TYPE_NAND, nand_info[idx].size)) {
  			puts("Offset or partition name expected
  ");
  			return 1;
  		}
  		if (set_dev(idx)) {
ea533c260   Scott Wood   cmd_nand: some in...
227
228
229
230
231
232
233
234
  			puts("Offset or partition name expected
  ");
  			return 1;
  		}
  
  		if (idx != 0) {
  			puts("Partition not on first NAND device
  ");
c9f7351b5   Ben Gardiner   NAND: environment...
235
236
237
238
  			return 1;
  		}
  
  		if (nand->oobavail < ENV_OFFSET_SIZE) {
53504a278   Scott Wood   NAND: formatting ...
239
240
241
242
243
244
  			printf("Insufficient available OOB bytes:
  "
  			       "%d OOB bytes available but %d required for "
  			       "env.oob support
  ",
  			       nand->oobavail, ENV_OFFSET_SIZE);
c9f7351b5   Ben Gardiner   NAND: environment...
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
  			return 1;
  		}
  
  		if ((addr & (nand->erasesize - 1)) != 0) {
  			printf("Environment offset must be block-aligned
  ");
  			return 1;
  		}
  
  		ops.datbuf = NULL;
  		ops.mode = MTD_OOB_AUTO;
  		ops.ooboffs = 0;
  		ops.ooblen = ENV_OFFSET_SIZE;
  		ops.oobbuf = (void *) oob_buf;
  
  		oob_buf[0] = ENV_OOB_MARKER;
  		oob_buf[1] = addr / nand->erasesize;
  
  		ret = nand->write_oob(nand, ENV_OFFSET_SIZE, &ops);
53504a278   Scott Wood   NAND: formatting ...
264
  		if (ret) {
c9f7351b5   Ben Gardiner   NAND: environment...
265
266
267
268
  			printf("Error writing OOB block 0
  ");
  			return ret;
  		}
53504a278   Scott Wood   NAND: formatting ...
269
270
271
272
273
274
275
276
277
278
  
  		ret = get_nand_env_oob(nand, &nand_env_oob_offset);
  		if (ret) {
  			printf("Error reading env offset in OOB
  ");
  			return ret;
  		}
  
  		if (addr != nand_env_oob_offset) {
  			printf("Verification of env offset in OOB failed: "
ea533c260   Scott Wood   cmd_nand: some in...
279
280
281
  			       "0x%08llx expected but got 0x%08lx
  ",
  			       (unsigned long long)addr, nand_env_oob_offset);
53504a278   Scott Wood   NAND: formatting ...
282
283
  			return 1;
  		}
c9f7351b5   Ben Gardiner   NAND: environment...
284
285
286
287
288
289
290
  	} else {
  		goto usage;
  	}
  
  	return ret;
  
  usage:
4c12eeb8b   Simon Glass   Convert cmd_usage...
291
  	return CMD_RET_USAGE;
c9f7351b5   Ben Gardiner   NAND: environment...
292
293
294
  }
  
  #endif
ce80ddc18   Marek Vasut   NAND: Make page, ...
295
  static void nand_print_and_set_info(int idx)
672ed2aee   Wolfgang Grandegger   Enable multi chip...
296
297
298
  {
  	nand_info_t *nand = &nand_info[idx];
  	struct nand_chip *chip = nand->priv;
ce80ddc18   Marek Vasut   NAND: Make page, ...
299

672ed2aee   Wolfgang Grandegger   Enable multi chip...
300
301
302
303
304
305
  	printf("Device %d: ", idx);
  	if (chip->numchips > 1)
  		printf("%dx ", chip->numchips);
  	printf("%s, sector size %u KiB
  ",
  	       nand->name, nand->erasesize >> 10);
5db73feb1   Heiko Schocher   cmd, nand: add mo...
306
307
308
309
310
311
312
313
314
315
316
317
  	printf("  Page size   %8d b
  ", nand->writesize);
  	printf("  OOB size    %8d b
  ", nand->oobsize);
  	printf("  Erase size  %8d b
  ", nand->erasesize);
  	printf("  subpagesize %8d b
  ", chip->subpagesize);
  	printf("  options     0x%8x
  ", chip->options);
  	printf("  bbt options 0x%8x
  ", chip->bbt_options);
ce80ddc18   Marek Vasut   NAND: Make page, ...
318
319
  
  	/* Set geometry info */
41ef372c1   Simon Glass   common: Use new n...
320
321
322
  	setenv_hex("nand_writesize", nand->writesize);
  	setenv_hex("nand_oobsize", nand->oobsize);
  	setenv_hex("nand_erasesize", nand->erasesize);
672ed2aee   Wolfgang Grandegger   Enable multi chip...
323
  }
418396e21   Scott Wood   nand: extend .raw...
324
325
326
327
  static int raw_access(nand_info_t *nand, ulong addr, loff_t off, ulong count,
  			int read)
  {
  	int ret = 0;
418396e21   Scott Wood   nand: extend .raw...
328
329
330
331
332
333
334
335
  
  	while (count--) {
  		/* Raw access */
  		mtd_oob_ops_t ops = {
  			.datbuf = (u8 *)addr,
  			.oobbuf = ((u8 *)addr) + nand->writesize,
  			.len = nand->writesize,
  			.ooblen = nand->oobsize,
dfe64e2c8   Sergey Lapin   mtd: resync with ...
336
  			.mode = MTD_OPS_RAW
418396e21   Scott Wood   nand: extend .raw...
337
  		};
6b94f118a   Peter Tyser   cmd_nand: Verify ...
338
  		if (read) {
dfe64e2c8   Sergey Lapin   mtd: resync with ...
339
  			ret = mtd_read_oob(nand, off, &ops);
6b94f118a   Peter Tyser   cmd_nand: Verify ...
340
  		} else {
dfe64e2c8   Sergey Lapin   mtd: resync with ...
341
  			ret = mtd_write_oob(nand, off, &ops);
6b94f118a   Peter Tyser   cmd_nand: Verify ...
342
343
344
  			if (!ret)
  				ret = nand_verify_page_oob(nand, &ops, off);
  		}
418396e21   Scott Wood   nand: extend .raw...
345
346
347
348
349
350
351
352
353
354
355
356
357
358
  
  		if (ret) {
  			printf("%s: error at offset %llx, ret %d
  ",
  				__func__, (long long)off, ret);
  			break;
  		}
  
  		addr += nand->writesize + nand->oobsize;
  		off += nand->writesize;
  	}
  
  	return ret;
  }
e834402fa   Harvey Chapman   nand: adjust eras...
359
  /* Adjust a chip/partition size down for bad blocks so we don't
9b80aa8ec   Scott Wood   nand: Don't call ...
360
   * read/write past the end of a chip/partition by accident.
e834402fa   Harvey Chapman   nand: adjust eras...
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
   */
  static void adjust_size_for_badblocks(loff_t *size, loff_t offset, int dev)
  {
  	/* We grab the nand info object here fresh because this is usually
  	 * called after arg_off_size() which can change the value of dev.
  	 */
  	nand_info_t *nand = &nand_info[dev];
  	loff_t maxoffset = offset + *size;
  	int badblocks = 0;
  
  	/* count badblocks in NAND from offset to offset + size */
  	for (; offset < maxoffset; offset += nand->erasesize) {
  		if (nand_block_isbad(nand, offset))
  			badblocks++;
  	}
  	/* adjust size if any bad blocks found */
  	if (badblocks) {
  		*size -= badblocks * nand->erasesize;
  		printf("size adjusted to 0x%llx (%d bad blocks)
  ",
  		       (unsigned long long)*size, badblocks);
  	}
  }
088f1b199   Kim Phillips   common/cmd_*.c: s...
384
  static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
addb2e165   Bartlomiej Sieka   Re-factoring the ...
385
  {
ea533c260   Scott Wood   cmd_nand: some in...
386
387
  	int i, ret = 0;
  	ulong addr;
c39d6a0ea   Tom Rini   nand: Extend nand...
388
  	loff_t off, size, maxsize;
addb2e165   Bartlomiej Sieka   Re-factoring the ...
389
390
  	char *cmd, *s;
  	nand_info_t *nand;
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
391
392
  #ifdef CONFIG_SYS_NAND_QUIET
  	int quiet = CONFIG_SYS_NAND_QUIET;
c750d2e66   Matthias Fuchs   NAND: Add CFG_NAN...
393
  #else
2255b2d20   Stefan Roese   * Several improve...
394
  	int quiet = 0;
c750d2e66   Matthias Fuchs   NAND: Add CFG_NAN...
395
  #endif
2255b2d20   Stefan Roese   * Several improve...
396
  	const char *quiet_str = getenv("quiet");
ea533c260   Scott Wood   cmd_nand: some in...
397
  	int dev = nand_curr_device;
8c5659a6d   Scott Wood   nand commands: ma...
398
  	int repeat = flag & CMD_FLAG_REPEAT;
addb2e165   Bartlomiej Sieka   Re-factoring the ...
399
400
401
402
  
  	/* at least two arguments please */
  	if (argc < 2)
  		goto usage;
2255b2d20   Stefan Roese   * Several improve...
403
404
  	if (quiet_str)
  		quiet = simple_strtoul(quiet_str, NULL, 0) != 0;
addb2e165   Bartlomiej Sieka   Re-factoring the ...
405
  	cmd = argv[1];
8c5659a6d   Scott Wood   nand commands: ma...
406
407
408
  	/* Only "dump" is repeatable. */
  	if (repeat && strcmp(cmd, "dump"))
  		return 0;
addb2e165   Bartlomiej Sieka   Re-factoring the ...
409
410
411
412
  	if (strcmp(cmd, "info") == 0) {
  
  		putc('
  ');
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
413
  		for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) {
addb2e165   Bartlomiej Sieka   Re-factoring the ...
414
  			if (nand_info[i].name)
ce80ddc18   Marek Vasut   NAND: Make page, ...
415
  				nand_print_and_set_info(i);
addb2e165   Bartlomiej Sieka   Re-factoring the ...
416
417
418
419
420
  		}
  		return 0;
  	}
  
  	if (strcmp(cmd, "device") == 0) {
addb2e165   Bartlomiej Sieka   Re-factoring the ...
421
  		if (argc < 3) {
672ed2aee   Wolfgang Grandegger   Enable multi chip...
422
423
  			putc('
  ');
ea533c260   Scott Wood   cmd_nand: some in...
424
  			if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE)
672ed2aee   Wolfgang Grandegger   Enable multi chip...
425
426
  				puts("no devices available
  ");
addb2e165   Bartlomiej Sieka   Re-factoring the ...
427
  			else
ce80ddc18   Marek Vasut   NAND: Make page, ...
428
  				nand_print_and_set_info(dev);
addb2e165   Bartlomiej Sieka   Re-factoring the ...
429
430
  			return 0;
  		}
43a2b0e76   Stefan Roese   Add board/cpu spe...
431

ea533c260   Scott Wood   cmd_nand: some in...
432
433
  		dev = (int)simple_strtoul(argv[2], NULL, 10);
  		set_dev(dev);
43a2b0e76   Stefan Roese   Add board/cpu spe...
434

addb2e165   Bartlomiej Sieka   Re-factoring the ...
435
436
  		return 0;
  	}
c9f7351b5   Ben Gardiner   NAND: environment...
437
438
  #ifdef CONFIG_ENV_OFFSET_OOB
  	/* this command operates only on the first nand device */
ea533c260   Scott Wood   cmd_nand: some in...
439
440
  	if (strcmp(cmd, "env.oob") == 0)
  		return do_nand_env_oob(cmdtp, argc - 1, argv + 1);
c9f7351b5   Ben Gardiner   NAND: environment...
441
  #endif
ea533c260   Scott Wood   cmd_nand: some in...
442
443
444
445
446
447
448
449
  	/* The following commands operate on the current device, unless
  	 * overridden by a partition specifier.  Note that if somehow the
  	 * current device is invalid, it will have to be changed to a valid
  	 * one before these commands can run, even if a partition specifier
  	 * for another device is to be used.
  	 */
  	if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE ||
  	    !nand_info[dev].name) {
addb2e165   Bartlomiej Sieka   Re-factoring the ...
450
451
452
453
454
  		puts("
  no devices available
  ");
  		return 1;
  	}
ea533c260   Scott Wood   cmd_nand: some in...
455
  	nand = &nand_info[dev];
addb2e165   Bartlomiej Sieka   Re-factoring the ...
456
457
  
  	if (strcmp(cmd, "bad") == 0) {
ea533c260   Scott Wood   cmd_nand: some in...
458
459
460
  		printf("
  Device %d bad blocks:
  ", dev);
addb2e165   Bartlomiej Sieka   Re-factoring the ...
461
462
  		for (off = 0; off < nand->size; off += nand->erasesize)
  			if (nand_block_isbad(nand, off))
ea533c260   Scott Wood   cmd_nand: some in...
463
464
  				printf("  %08llx
  ", (unsigned long long)off);
addb2e165   Bartlomiej Sieka   Re-factoring the ...
465
466
  		return 0;
  	}
856f05441   Stefan Roese   [PATCH] NAND: Par...
467
468
469
470
471
  	/*
  	 * Syntax is:
  	 *   0    1     2       3    4
  	 *   nand erase [clean] [off size]
  	 */
304863225   Scott Wood   nand erase: .spre...
472
  	if (strncmp(cmd, "erase", 5) == 0 || strncmp(cmd, "scrub", 5) == 0) {
2255b2d20   Stefan Roese   * Several improve...
473
  		nand_erase_options_t opts;
856f05441   Stefan Roese   [PATCH] NAND: Par...
474
  		/* "clean" at index 2 means request to write cleanmarker */
3043c045d   William Juul   Whitespace cleanu...
475
  		int clean = argc > 2 && !strcmp("clean", argv[2]);
608998166   Marek Vasut   NAND: Add -y opti...
476
477
  		int scrub_yes = argc > 2 && !strcmp("-y", argv[2]);
  		int o = (clean || scrub_yes) ? 3 : 2;
304863225   Scott Wood   nand erase: .spre...
478
  		int scrub = !strncmp(cmd, "scrub", 5);
304863225   Scott Wood   nand erase: .spre...
479
480
  		int spread = 0;
  		int args = 2;
608998166   Marek Vasut   NAND: Add -y opti...
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
  		const char *scrub_warn =
  			"Warning: "
  			"scrub option will erase all factory set bad blocks!
  "
  			"         "
  			"There is no reliable way to recover them.
  "
  			"         "
  			"Use this command only for testing purposes if you
  "
  			"         "
  			"are sure of what you are doing!
  "
  			"
  Really scrub this NAND flash? <y/N>
  ";
304863225   Scott Wood   nand erase: .spre...
497
498
499
500
501
  
  		if (cmd[5] != 0) {
  			if (!strcmp(&cmd[5], ".spread")) {
  				spread = 1;
  			} else if (!strcmp(&cmd[5], ".part")) {
304863225   Scott Wood   nand erase: .spre...
502
503
  				args = 1;
  			} else if (!strcmp(&cmd[5], ".chip")) {
304863225   Scott Wood   nand erase: .spre...
504
505
506
507
508
509
510
511
512
513
514
515
516
  				args = 0;
  			} else {
  				goto usage;
  			}
  		}
  
  		/*
  		 * Don't allow missing arguments to cause full chip/partition
  		 * erases -- easy to do accidentally, e.g. with a misspelled
  		 * variable name.
  		 */
  		if (argc != o + args)
  			goto usage;
2255b2d20   Stefan Roese   * Several improve...
517

304863225   Scott Wood   nand erase: .spre...
518
519
  		printf("
  NAND %s: ", cmd);
856f05441   Stefan Roese   [PATCH] NAND: Par...
520
  		/* skip first two or three arguments, look for offset and size */
09c328075   Heiko Schocher   mtd, nand: Move c...
521
522
523
524
525
526
  		if (mtd_arg_off_size(argc - o, argv + o, &dev, &off, &size,
  				     &maxsize, MTD_DEV_TYPE_NAND,
  				     nand_info[dev].size) != 0)
  			return 1;
  
  		if (set_dev(dev))
856f05441   Stefan Roese   [PATCH] NAND: Par...
527
  			return 1;
2255b2d20   Stefan Roese   * Several improve...
528

ea533c260   Scott Wood   cmd_nand: some in...
529
  		nand = &nand_info[dev];
2255b2d20   Stefan Roese   * Several improve...
530
531
532
533
534
  		memset(&opts, 0, sizeof(opts));
  		opts.offset = off;
  		opts.length = size;
  		opts.jffs2  = clean;
  		opts.quiet  = quiet;
304863225   Scott Wood   nand erase: .spre...
535
  		opts.spread = spread;
2255b2d20   Stefan Roese   * Several improve...
536
537
  
  		if (scrub) {
a5dffa4b6   Pierre Aubert   Add the function ...
538
  			if (scrub_yes) {
608998166   Marek Vasut   NAND: Add -y opti...
539
  				opts.scrub = 1;
a5dffa4b6   Pierre Aubert   Add the function ...
540
541
542
  			} else {
  				puts(scrub_warn);
  				if (confirm_yesno()) {
6b94b4962   Florian Fainelli   cmd_nand: show na...
543
  					opts.scrub = 1;
a5dffa4b6   Pierre Aubert   Add the function ...
544
  				} else {
6b94b4962   Florian Fainelli   cmd_nand: show na...
545
546
  					puts("scrub aborted
  ");
46aabcc44   Masahiro Yamada   cmd_nand: Do not ...
547
  					return 1;
6b94b4962   Florian Fainelli   cmd_nand: show na...
548
  				}
2255b2d20   Stefan Roese   * Several improve...
549
550
551
  			}
  		}
  		ret = nand_erase_opts(nand, &opts);
addb2e165   Bartlomiej Sieka   Re-factoring the ...
552
553
554
555
556
557
558
559
560
  		printf("%s
  ", ret ? "ERROR" : "OK");
  
  		return ret == 0 ? 0 : 1;
  	}
  
  	if (strncmp(cmd, "dump", 4) == 0) {
  		if (argc < 3)
  			goto usage;
addb2e165   Bartlomiej Sieka   Re-factoring the ...
561
  		off = (int)simple_strtoul(argv[2], NULL, 16);
8c5659a6d   Scott Wood   nand commands: ma...
562
  		ret = nand_dump(nand, off, !strcmp(&cmd[4], ".oob"), repeat);
addb2e165   Bartlomiej Sieka   Re-factoring the ...
563
564
  
  		return ret == 0 ? 1 : 0;
addb2e165   Bartlomiej Sieka   Re-factoring the ...
565
  	}
addb2e165   Bartlomiej Sieka   Re-factoring the ...
566
  	if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {
ea533c260   Scott Wood   cmd_nand: some in...
567
  		size_t rwsize;
418396e21   Scott Wood   nand: extend .raw...
568
  		ulong pagecount = 1;
2255b2d20   Stefan Roese   * Several improve...
569
  		int read;
ced199dc8   Harvey Chapman   nand: fix nand re...
570
  		int raw = 0;
2255b2d20   Stefan Roese   * Several improve...
571

addb2e165   Bartlomiej Sieka   Re-factoring the ...
572
573
  		if (argc < 4)
  			goto usage;
2255b2d20   Stefan Roese   * Several improve...
574

addb2e165   Bartlomiej Sieka   Re-factoring the ...
575
  		addr = (ulong)simple_strtoul(argv[2], NULL, 16);
2255b2d20   Stefan Roese   * Several improve...
576
  		read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */
856f05441   Stefan Roese   [PATCH] NAND: Par...
577
578
  		printf("
  NAND %s: ", read ? "read" : "write");
4cbb651b2   William Juul   Remove white spac...
579

2255b2d20   Stefan Roese   * Several improve...
580
  		s = strchr(cmd, '.');
418396e21   Scott Wood   nand: extend .raw...
581

8d75c8964   Steve Sakoman   cmd_nand: fix cra...
582
  		if (s && !strcmp(s, ".raw")) {
418396e21   Scott Wood   nand: extend .raw...
583
  			raw = 1;
09c328075   Heiko Schocher   mtd, nand: Move c...
584
585
586
587
588
589
  			if (mtd_arg_off(argv[3], &dev, &off, &size, &maxsize,
  					MTD_DEV_TYPE_NAND,
  					nand_info[dev].size))
  				return 1;
  
  			if (set_dev(dev))
418396e21   Scott Wood   nand: extend .raw...
590
  				return 1;
93d3232d9   Rostislav Lisovy   cmd_nand: Update ...
591
  			nand = &nand_info[dev];
418396e21   Scott Wood   nand: extend .raw...
592
593
594
595
596
597
598
599
600
601
602
603
604
605
  			if (argc > 4 && !str2long(argv[4], &pagecount)) {
  				printf("'%s' is not a number
  ", argv[4]);
  				return 1;
  			}
  
  			if (pagecount * nand->writesize > size) {
  				puts("Size exceeds partition or device limit
  ");
  				return -1;
  			}
  
  			rwsize = pagecount * (nand->writesize + nand->oobsize);
  		} else {
09c328075   Heiko Schocher   mtd, nand: Move c...
606
607
608
609
610
611
612
  			if (mtd_arg_off_size(argc - 3, argv + 3, &dev, &off,
  					     &size, &maxsize,
  					     MTD_DEV_TYPE_NAND,
  					     nand_info[dev].size) != 0)
  				return 1;
  
  			if (set_dev(dev))
418396e21   Scott Wood   nand: extend .raw...
613
  				return 1;
e834402fa   Harvey Chapman   nand: adjust eras...
614
615
616
  			/* size is unspecified */
  			if (argc < 5)
  				adjust_size_for_badblocks(&size, off, dev);
418396e21   Scott Wood   nand: extend .raw...
617
618
  			rwsize = size;
  		}
93d3232d9   Rostislav Lisovy   cmd_nand: Update ...
619
  		nand = &nand_info[dev];
984e03cdf   Scott Wood   NAND: Always skip...
620
621
  		if (!s || !strcmp(s, ".jffs2") ||
  		    !strcmp(s, ".e") || !strcmp(s, ".i")) {
dfbf617ff   Scott Wood   NAND read/write fix
622
  			if (read)
ea533c260   Scott Wood   cmd_nand: some in...
623
  				ret = nand_read_skip_bad(nand, off, &rwsize,
c39d6a0ea   Tom Rini   nand: Extend nand...
624
  							 NULL, maxsize,
4b0708093   Wolfgang Denk   Coding Style clea...
625
  							 (u_char *)addr);
dfbf617ff   Scott Wood   NAND read/write fix
626
  			else
ea533c260   Scott Wood   cmd_nand: some in...
627
  				ret = nand_write_skip_bad(nand, off, &rwsize,
c39d6a0ea   Tom Rini   nand: Extend nand...
628
  							  NULL, maxsize,
6b94f118a   Peter Tyser   cmd_nand: Verify ...
629
630
  							  (u_char *)addr,
  							  WITH_WR_VERIFY);
c9494866d   Ben Gardiner   cmd_nand: add nan...
631
632
633
634
635
636
637
  #ifdef CONFIG_CMD_NAND_TRIMFFS
  		} else if (!strcmp(s, ".trimffs")) {
  			if (read) {
  				printf("Unknown nand command suffix '%s'
  ", s);
  				return 1;
  			}
c39d6a0ea   Tom Rini   nand: Extend nand...
638
639
  			ret = nand_write_skip_bad(nand, off, &rwsize, NULL,
  						maxsize, (u_char *)addr,
6b94f118a   Peter Tyser   cmd_nand: Verify ...
640
  						WITH_DROP_FFS | WITH_WR_VERIFY);
c9494866d   Ben Gardiner   cmd_nand: add nan...
641
  #endif
dfc99e143   Mike Frysinger   cmd_nand: drop du...
642
  		} else if (!strcmp(s, ".oob")) {
cfa460adf   William Juul   Update MTD to tha...
643
644
645
  			/* out-of-band data */
  			mtd_oob_ops_t ops = {
  				.oobbuf = (u8 *)addr,
ea533c260   Scott Wood   cmd_nand: some in...
646
  				.ooblen = rwsize,
dfe64e2c8   Sergey Lapin   mtd: resync with ...
647
  				.mode = MTD_OPS_RAW
cfa460adf   William Juul   Update MTD to tha...
648
  			};
62d4f4365   Harald Welte   Re-introduce the ...
649
  			if (read)
dfe64e2c8   Sergey Lapin   mtd: resync with ...
650
  				ret = mtd_read_oob(nand, off, &ops);
62d4f4365   Harald Welte   Re-introduce the ...
651
  			else
dfe64e2c8   Sergey Lapin   mtd: resync with ...
652
  				ret = mtd_write_oob(nand, off, &ops);
418396e21   Scott Wood   nand: extend .raw...
653
654
  		} else if (raw) {
  			ret = raw_access(nand, addr, off, pagecount, read);
856f05441   Stefan Roese   [PATCH] NAND: Par...
655
  		} else {
984e03cdf   Scott Wood   NAND: Always skip...
656
657
658
  			printf("Unknown nand command suffix '%s'.
  ", s);
  			return 1;
2255b2d20   Stefan Roese   * Several improve...
659
  		}
ea533c260   Scott Wood   cmd_nand: some in...
660
661
  		printf(" %zu bytes %s: %s
  ", rwsize,
2255b2d20   Stefan Roese   * Several improve...
662
  		       read ? "read" : "written", ret ? "ERROR" : "OK");
addb2e165   Bartlomiej Sieka   Re-factoring the ...
663
664
665
  
  		return ret == 0 ? 0 : 1;
  	}
2255b2d20   Stefan Roese   * Several improve...
666

3287f6d38   Benoît Thébaudeau   nand: Add torture...
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
  #ifdef CONFIG_CMD_NAND_TORTURE
  	if (strcmp(cmd, "torture") == 0) {
  		if (argc < 3)
  			goto usage;
  
  		if (!str2off(argv[2], &off)) {
  			puts("Offset is not a valid number
  ");
  			return 1;
  		}
  
  		printf("
  NAND torture: device %d offset 0x%llx size 0x%x
  ",
  			dev, off, nand->erasesize);
  		ret = nand_torture(nand, off);
  		printf(" %s
  ", ret ? "Failed" : "Passed");
  
  		return ret == 0 ? 0 : 1;
  	}
  #endif
2255b2d20   Stefan Roese   * Several improve...
689
  	if (strcmp(cmd, "markbad") == 0) {
8360b66ba   Wolfgang Denk   nand/onenand: Fix...
690
691
  		argc -= 2;
  		argv += 2;
2255b2d20   Stefan Roese   * Several improve...
692

8360b66ba   Wolfgang Denk   nand/onenand: Fix...
693
694
695
696
697
  		if (argc <= 0)
  			goto usage;
  
  		while (argc > 0) {
  			addr = simple_strtoul(*argv, NULL, 16);
dfe64e2c8   Sergey Lapin   mtd: resync with ...
698
  			if (mtd_block_markbad(nand, addr)) {
8360b66ba   Wolfgang Denk   nand/onenand: Fix...
699
700
701
702
703
704
705
706
707
708
709
710
711
  				printf("block 0x%08lx NOT marked "
  					"as bad! ERROR %d
  ",
  					addr, ret);
  				ret = 1;
  			} else {
  				printf("block 0x%08lx successfully "
  					"marked as bad
  ",
  					addr);
  			}
  			--argc;
  			++argv;
2255b2d20   Stefan Roese   * Several improve...
712
  		}
8360b66ba   Wolfgang Denk   nand/onenand: Fix...
713
  		return ret;
2255b2d20   Stefan Roese   * Several improve...
714
  	}
dfbf617ff   Scott Wood   NAND read/write fix
715

2255b2d20   Stefan Roese   * Several improve...
716
717
718
719
  	if (strcmp(cmd, "biterr") == 0) {
  		/* todo */
  		return 1;
  	}
50657c273   Nishanth Menon   NAND: Enable nand...
720
  #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
2255b2d20   Stefan Roese   * Several improve...
721
  	if (strcmp(cmd, "lock") == 0) {
50657c273   Nishanth Menon   NAND: Enable nand...
722
  		int tight = 0;
2255b2d20   Stefan Roese   * Several improve...
723
724
725
726
727
728
729
  		int status = 0;
  		if (argc == 3) {
  			if (!strcmp("tight", argv[2]))
  				tight = 1;
  			if (!strcmp("status", argv[2]))
  				status = 1;
  		}
2255b2d20   Stefan Roese   * Several improve...
730
  		if (status) {
50657c273   Nishanth Menon   NAND: Enable nand...
731
  			do_nand_status(nand);
cfa460adf   William Juul   Update MTD to tha...
732
  		} else {
5e1dae5c3   William Juul   Fixing coding sty...
733
734
735
736
737
738
739
740
  			if (!nand_lock(nand, tight)) {
  				puts("NAND flash successfully locked
  ");
  			} else {
  				puts("Error locking NAND flash
  ");
  				return 1;
  			}
2255b2d20   Stefan Roese   * Several improve...
741
742
743
  		}
  		return 0;
  	}
eee623a50   Joe Hershberger   nand: Add support...
744
745
746
747
748
749
750
  	if (strncmp(cmd, "unlock", 5) == 0) {
  		int allexcept = 0;
  
  		s = strchr(cmd, '.');
  
  		if (s && !strcmp(s, ".allexcept"))
  			allexcept = 1;
09c328075   Heiko Schocher   mtd, nand: Move c...
751
752
753
754
755
756
  		if (mtd_arg_off_size(argc - 2, argv + 2, &dev, &off, &size,
  				     &maxsize, MTD_DEV_TYPE_NAND,
  				     nand_info[dev].size) < 0)
  			return 1;
  
  		if (set_dev(dev))
856f05441   Stefan Roese   [PATCH] NAND: Par...
757
  			return 1;
2255b2d20   Stefan Roese   * Several improve...
758

eee623a50   Joe Hershberger   nand: Add support...
759
  		if (!nand_unlock(&nand_info[dev], off, size, allexcept)) {
5e1dae5c3   William Juul   Fixing coding sty...
760
761
762
763
  			puts("NAND flash successfully unlocked
  ");
  		} else {
  			puts("Error unlocking NAND flash, "
3043c045d   William Juul   Whitespace cleanu...
764
765
  			     "write and erase will probably fail
  ");
5e1dae5c3   William Juul   Fixing coding sty...
766
767
  			return 1;
  		}
2255b2d20   Stefan Roese   * Several improve...
768
769
  		return 0;
  	}
50657c273   Nishanth Menon   NAND: Enable nand...
770
  #endif
2255b2d20   Stefan Roese   * Several improve...
771

addb2e165   Bartlomiej Sieka   Re-factoring the ...
772
  usage:
4c12eeb8b   Simon Glass   Convert cmd_usage...
773
  	return CMD_RET_USAGE;
addb2e165   Bartlomiej Sieka   Re-factoring the ...
774
  }
088f1b199   Kim Phillips   common/cmd_*.c: s...
775
776
  #ifdef CONFIG_SYS_LONGHELP
  static char nand_help_text[] =
a89c33db9   Wolfgang Denk   General help mess...
777
778
779
780
781
782
783
784
785
786
787
788
  	"info - show available NAND devices
  "
  	"nand device [dev] - show or set current device
  "
  	"nand read - addr off|partition size
  "
  	"nand write - addr off|partition size
  "
  	"    read/write 'size' bytes starting at offset 'off'
  "
  	"    to/from memory address 'addr', skipping bad blocks.
  "
418396e21   Scott Wood   nand: extend .raw...
789
790
791
792
793
794
  	"nand read.raw - addr off|partition [count]
  "
  	"nand write.raw - addr off|partition [count]
  "
  	"    Use read.raw/write.raw to avoid ECC and access the flash as-is.
  "
c9494866d   Ben Gardiner   cmd_nand: add nan...
795
796
797
798
799
800
801
802
803
804
  #ifdef CONFIG_CMD_NAND_TRIMFFS
  	"nand write.trimffs - addr off|partition size
  "
  	"    write 'size' bytes starting at offset 'off' from memory address
  "
  	"    'addr', skipping bad blocks and dropping any pages at the end
  "
  	"    of eraseblocks that contain only 0xFF
  "
  #endif
eb3abce89   Daniel Hobi   cmd_nand: fix hel...
805
  	"nand erase[.spread] [clean] off size - erase 'size' bytes "
304863225   Scott Wood   nand erase: .spre...
806
807
808
809
810
811
812
813
814
815
  	"from offset 'off'
  "
  	"    With '.spread', erase enough for given file size, otherwise,
  "
  	"    'size' includes skipped bad blocks.
  "
  	"nand erase.part [clean] partition - erase entire mtd partition'
  "
  	"nand erase.chip [clean] - erase entire chip'
  "
a89c33db9   Wolfgang Denk   General help mess...
816
817
818
819
  	"nand bad - show bad blocks
  "
  	"nand dump[.oob] off - dump page
  "
3287f6d38   Benoît Thébaudeau   nand: Add torture...
820
821
822
823
  #ifdef CONFIG_CMD_NAND_TORTURE
  	"nand torture off - torture block at offset
  "
  #endif
608998166   Marek Vasut   NAND: Add -y opti...
824
825
  	"nand scrub [-y] off size | scrub.part partition | scrub.chip
  "
304863225   Scott Wood   nand erase: .spre...
826
827
  	"    really clean NAND erasing bad blocks (UNSAFE)
  "
a89c33db9   Wolfgang Denk   General help mess...
828
829
830
  	"nand markbad off [...] - mark bad block(s) at offset (UNSAFE)
  "
  	"nand biterr off - make a bit error at offset (UNSAFE)"
50657c273   Nishanth Menon   NAND: Enable nand...
831
  #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
a89c33db9   Wolfgang Denk   General help mess...
832
833
834
835
836
837
  	"
  "
  	"nand lock [tight] [status]
  "
  	"    bring nand to lock state or display locked pages
  "
eee623a50   Joe Hershberger   nand: Add support...
838
  	"nand unlock[.allexcept] [offset] [size] - unlock section"
50657c273   Nishanth Menon   NAND: Enable nand...
839
  #endif
c9f7351b5   Ben Gardiner   NAND: environment...
840
841
842
843
844
845
846
847
848
849
  #ifdef CONFIG_ENV_OFFSET_OOB
  	"
  "
  	"nand env.oob - environment offset in OOB of block 0 of"
  	"    first device.
  "
  	"nand env.oob set off|partition - set enviromnent offset
  "
  	"nand env.oob get - get environment offset"
  #endif
088f1b199   Kim Phillips   common/cmd_*.c: s...
850
851
852
853
854
855
  	"";
  #endif
  
  U_BOOT_CMD(
  	nand, CONFIG_SYS_MAXARGS, 1, do_nand,
  	"NAND sub-system", nand_help_text
50657c273   Nishanth Menon   NAND: Enable nand...
856
  );
addb2e165   Bartlomiej Sieka   Re-factoring the ...
857

856f05441   Stefan Roese   [PATCH] NAND: Par...
858
  static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand,
4b0708093   Wolfgang Denk   Coding Style clea...
859
  			   ulong offset, ulong addr, char *cmd)
addb2e165   Bartlomiej Sieka   Re-factoring the ...
860
  {
addb2e165   Bartlomiej Sieka   Re-factoring the ...
861
  	int r;
67d668bf9   Mike Frysinger   autostart: unify ...
862
  	char *s;
4ca79f477   Wolfgang Denk   NAND: fix some st...
863
  	size_t cnt;
21d29f7f9   Heiko Schocher   bootm: make use o...
864
  #if defined(CONFIG_IMAGE_FORMAT_LEGACY)
addb2e165   Bartlomiej Sieka   Re-factoring the ...
865
  	image_header_t *hdr;
21d29f7f9   Heiko Schocher   bootm: make use o...
866
  #endif
09475f752   Marian Balakowicz   [new uImage] Add ...
867
  #if defined(CONFIG_FIT)
3bab76a26   Marian Balakowicz   Delay FIT format ...
868
  	const void *fit_hdr = NULL;
09475f752   Marian Balakowicz   [new uImage] Add ...
869
  #endif
10e038932   Thomas Knobloch   [NAND] Bad block ...
870
871
872
  
  	s = strchr(cmd, '.');
  	if (s != NULL &&
65d8bc94d   Scott Wood   NAND: Have nboot ...
873
  	    (strcmp(s, ".jffs2") && strcmp(s, ".e") && strcmp(s, ".i"))) {
984e03cdf   Scott Wood   NAND: Always skip...
874
875
  		printf("Unknown nand load suffix '%s'
  ", s);
770605e4f   Simon Glass   bootstage: Replac...
876
  		bootstage_error(BOOTSTAGE_ID_NAND_SUFFIX);
984e03cdf   Scott Wood   NAND: Always skip...
877
878
  		return 1;
  	}
addb2e165   Bartlomiej Sieka   Re-factoring the ...
879

856f05441   Stefan Roese   [PATCH] NAND: Par...
880
881
882
  	printf("
  Loading from %s, offset 0x%lx
  ", nand->name, offset);
addb2e165   Bartlomiej Sieka   Re-factoring the ...
883

cfa460adf   William Juul   Update MTD to tha...
884
  	cnt = nand->writesize;
c39d6a0ea   Tom Rini   nand: Extend nand...
885
886
  	r = nand_read_skip_bad(nand, offset, &cnt, NULL, nand->size,
  			(u_char *)addr);
addb2e165   Bartlomiej Sieka   Re-factoring the ...
887
  	if (r) {
856f05441   Stefan Roese   [PATCH] NAND: Par...
888
889
  		puts("** Read error
  ");
770605e4f   Simon Glass   bootstage: Replac...
890
  		bootstage_error(BOOTSTAGE_ID_NAND_HDR_READ);
addb2e165   Bartlomiej Sieka   Re-factoring the ...
891
892
  		return 1;
  	}
770605e4f   Simon Glass   bootstage: Replac...
893
  	bootstage_mark(BOOTSTAGE_ID_NAND_HDR_READ);
addb2e165   Bartlomiej Sieka   Re-factoring the ...
894

9a4daad0a   Marian Balakowicz   [new uImage] Upda...
895
  	switch (genimg_get_format ((void *)addr)) {
21d29f7f9   Heiko Schocher   bootm: make use o...
896
  #if defined(CONFIG_IMAGE_FORMAT_LEGACY)
d5934ad77   Marian Balakowicz   [new uImage] Add ...
897
898
  	case IMAGE_FORMAT_LEGACY:
  		hdr = (image_header_t *)addr;
770605e4f   Simon Glass   bootstage: Replac...
899
  		bootstage_mark(BOOTSTAGE_ID_NAND_TYPE);
d5934ad77   Marian Balakowicz   [new uImage] Add ...
900
  		image_print_contents (hdr);
addb2e165   Bartlomiej Sieka   Re-factoring the ...
901

d5934ad77   Marian Balakowicz   [new uImage] Add ...
902
903
  		cnt = image_get_image_size (hdr);
  		break;
21d29f7f9   Heiko Schocher   bootm: make use o...
904
  #endif
d5934ad77   Marian Balakowicz   [new uImage] Add ...
905
906
  #if defined(CONFIG_FIT)
  	case IMAGE_FORMAT_FIT:
09475f752   Marian Balakowicz   [new uImage] Add ...
907
  		fit_hdr = (const void *)addr;
09475f752   Marian Balakowicz   [new uImage] Add ...
908
909
910
911
912
  		puts ("Fit image detected...
  ");
  
  		cnt = fit_get_size (fit_hdr);
  		break;
d5934ad77   Marian Balakowicz   [new uImage] Add ...
913
914
  #endif
  	default:
770605e4f   Simon Glass   bootstage: Replac...
915
  		bootstage_error(BOOTSTAGE_ID_NAND_TYPE);
d5934ad77   Marian Balakowicz   [new uImage] Add ...
916
917
  		puts ("** Unknown image type
  ");
addb2e165   Bartlomiej Sieka   Re-factoring the ...
918
919
  		return 1;
  	}
770605e4f   Simon Glass   bootstage: Replac...
920
  	bootstage_mark(BOOTSTAGE_ID_NAND_TYPE);
addb2e165   Bartlomiej Sieka   Re-factoring the ...
921

c39d6a0ea   Tom Rini   nand: Extend nand...
922
923
  	r = nand_read_skip_bad(nand, offset, &cnt, NULL, nand->size,
  			(u_char *)addr);
addb2e165   Bartlomiej Sieka   Re-factoring the ...
924
  	if (r) {
856f05441   Stefan Roese   [PATCH] NAND: Par...
925
926
  		puts("** Read error
  ");
770605e4f   Simon Glass   bootstage: Replac...
927
  		bootstage_error(BOOTSTAGE_ID_NAND_READ);
addb2e165   Bartlomiej Sieka   Re-factoring the ...
928
929
  		return 1;
  	}
770605e4f   Simon Glass   bootstage: Replac...
930
  	bootstage_mark(BOOTSTAGE_ID_NAND_READ);
addb2e165   Bartlomiej Sieka   Re-factoring the ...
931

09475f752   Marian Balakowicz   [new uImage] Add ...
932
933
  #if defined(CONFIG_FIT)
  	/* This cannot be done earlier, we need complete FIT image in RAM first */
3bab76a26   Marian Balakowicz   Delay FIT format ...
934
935
  	if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) {
  		if (!fit_check_format (fit_hdr)) {
770605e4f   Simon Glass   bootstage: Replac...
936
  			bootstage_error(BOOTSTAGE_ID_NAND_FIT_READ);
3bab76a26   Marian Balakowicz   Delay FIT format ...
937
938
939
940
  			puts ("** Bad FIT image format
  ");
  			return 1;
  		}
770605e4f   Simon Glass   bootstage: Replac...
941
  		bootstage_mark(BOOTSTAGE_ID_NAND_FIT_READ_OK);
3bab76a26   Marian Balakowicz   Delay FIT format ...
942
943
  		fit_print_contents (fit_hdr);
  	}
09475f752   Marian Balakowicz   [new uImage] Add ...
944
  #endif
addb2e165   Bartlomiej Sieka   Re-factoring the ...
945
946
947
  	/* Loading ok, update default load address */
  
  	load_addr = addr;
67d668bf9   Mike Frysinger   autostart: unify ...
948
  	return bootm_maybe_autostart(cmdtp, cmd);
addb2e165   Bartlomiej Sieka   Re-factoring the ...
949
  }
088f1b199   Kim Phillips   common/cmd_*.c: s...
950
951
  static int do_nandboot(cmd_tbl_t *cmdtp, int flag, int argc,
  		       char * const argv[])
856f05441   Stefan Roese   [PATCH] NAND: Par...
952
953
954
955
  {
  	char *boot_device = NULL;
  	int idx;
  	ulong addr, offset = 0;
0c8a84916   Ladislav Michl   Separate mtdparts...
956
  #if defined(CONFIG_CMD_MTDPARTS)
856f05441   Stefan Roese   [PATCH] NAND: Par...
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
  	struct mtd_device *dev;
  	struct part_info *part;
  	u8 pnum;
  
  	if (argc >= 2) {
  		char *p = (argc == 2) ? argv[1] : argv[2];
  		if (!(str2long(p, &addr)) && (mtdparts_init() == 0) &&
  		    (find_dev_and_part(p, &dev, &pnum, &part) == 0)) {
  			if (dev->id->type != MTD_DEV_TYPE_NAND) {
  				puts("Not a NAND device
  ");
  				return 1;
  			}
  			if (argc > 3)
  				goto usage;
  			if (argc == 3)
10e038932   Thomas Knobloch   [NAND] Bad block ...
973
  				addr = simple_strtoul(argv[1], NULL, 16);
856f05441   Stefan Roese   [PATCH] NAND: Par...
974
  			else
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
975
  				addr = CONFIG_SYS_LOAD_ADDR;
856f05441   Stefan Roese   [PATCH] NAND: Par...
976
  			return nand_load_image(cmdtp, &nand_info[dev->id->num],
4b0708093   Wolfgang Denk   Coding Style clea...
977
  					       part->offset, addr, argv[0]);
856f05441   Stefan Roese   [PATCH] NAND: Par...
978
979
980
  		}
  	}
  #endif
770605e4f   Simon Glass   bootstage: Replac...
981
  	bootstage_mark(BOOTSTAGE_ID_NAND_PART);
856f05441   Stefan Roese   [PATCH] NAND: Par...
982
983
  	switch (argc) {
  	case 1:
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
984
  		addr = CONFIG_SYS_LOAD_ADDR;
856f05441   Stefan Roese   [PATCH] NAND: Par...
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
  		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:
0c8a84916   Ladislav Michl   Separate mtdparts...
1001
  #if defined(CONFIG_CMD_MTDPARTS)
856f05441   Stefan Roese   [PATCH] NAND: Par...
1002
1003
  usage:
  #endif
770605e4f   Simon Glass   bootstage: Replac...
1004
  		bootstage_error(BOOTSTAGE_ID_NAND_SUFFIX);
4c12eeb8b   Simon Glass   Convert cmd_usage...
1005
  		return CMD_RET_USAGE;
856f05441   Stefan Roese   [PATCH] NAND: Par...
1006
  	}
770605e4f   Simon Glass   bootstage: Replac...
1007
  	bootstage_mark(BOOTSTAGE_ID_NAND_SUFFIX);
856f05441   Stefan Roese   [PATCH] NAND: Par...
1008
1009
1010
1011
1012
  
  	if (!boot_device) {
  		puts("
  ** No boot device **
  ");
770605e4f   Simon Glass   bootstage: Replac...
1013
  		bootstage_error(BOOTSTAGE_ID_NAND_BOOT_DEVICE);
856f05441   Stefan Roese   [PATCH] NAND: Par...
1014
1015
  		return 1;
  	}
770605e4f   Simon Glass   bootstage: Replac...
1016
  	bootstage_mark(BOOTSTAGE_ID_NAND_BOOT_DEVICE);
addb2e165   Bartlomiej Sieka   Re-factoring the ...
1017

856f05441   Stefan Roese   [PATCH] NAND: Par...
1018
  	idx = simple_strtoul(boot_device, NULL, 16);
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
1019
  	if (idx < 0 || idx >= CONFIG_SYS_MAX_NAND_DEVICE || !nand_info[idx].name) {
856f05441   Stefan Roese   [PATCH] NAND: Par...
1020
1021
1022
  		printf("
  ** Device %d not available
  ", idx);
770605e4f   Simon Glass   bootstage: Replac...
1023
  		bootstage_error(BOOTSTAGE_ID_NAND_AVAILABLE);
856f05441   Stefan Roese   [PATCH] NAND: Par...
1024
1025
  		return 1;
  	}
770605e4f   Simon Glass   bootstage: Replac...
1026
  	bootstage_mark(BOOTSTAGE_ID_NAND_AVAILABLE);
856f05441   Stefan Roese   [PATCH] NAND: Par...
1027
1028
1029
1030
1031
  
  	return nand_load_image(cmdtp, &nand_info[idx], offset, addr, argv[0]);
  }
  
  U_BOOT_CMD(nboot, 4, 1, do_nandboot,
2fb2604d5   Peter Tyser   Command usage cle...
1032
  	"boot from NAND device",
a89c33db9   Wolfgang Denk   General help mess...
1033
1034
  	"[partition] | [[[loadAddr] dev] offset]"
  );