Blame view

cmd/nand.c 24.2 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>
8e8ccfe1a   Simon Glass   common: Move the ...
23
  #include <image.h>
cfa460adf   William Juul   Update MTD to tha...
24
  #include <linux/mtd/mtd.h>
addb2e165   Bartlomiej Sieka   Re-factoring the ...
25
  #include <command.h>
24b852a7a   Simon Glass   Move console defi...
26
  #include <console.h>
c7694dd48   Simon Glass   env: Move env_set...
27
  #include <env.h>
addb2e165   Bartlomiej Sieka   Re-factoring the ...
28
29
30
  #include <watchdog.h>
  #include <malloc.h>
  #include <asm/byteorder.h>
addb2e165   Bartlomiej Sieka   Re-factoring the ...
31
32
  #include <jffs2/jffs2.h>
  #include <nand.h>
eb446ef62   Miquel Raynal   cmd: nand/sf: iso...
33
  #include "legacy-mtd-utils.h"
0c8a84916   Ladislav Michl   Separate mtdparts...
34
  #if defined(CONFIG_CMD_MTDPARTS)
856f05441   Stefan Roese   [PATCH] NAND: Par...
35

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

151c06ec6   Scott Wood   mtd: nand: Remove...
54
  	datbuf = memalign(ARCH_DMA_MINALIGN, mtd->writesize);
e40520b5b   Masahiro Yamada   cmd_nand: fix a m...
55
  	if (!datbuf) {
addb2e165   Bartlomiej Sieka   Re-factoring the ...
56
57
58
59
  		puts("No memory for page buffer
  ");
  		return 1;
  	}
e40520b5b   Masahiro Yamada   cmd_nand: fix a m...
60

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

7d25cd34e   Masahiro Yamada   cmd_nand: slight ...
87
  	if (!only_oob) {
151c06ec6   Scott Wood   mtd: nand: Remove...
88
  		i = mtd->writesize >> 4;
7d25cd34e   Masahiro Yamada   cmd_nand: slight ...
89
90
91
  		p = datbuf;
  
  		while (i--) {
9ad754fef   William Juul   make nand dump an...
92
93
94
95
  			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
96
97
  			       p[8], p[9], p[10], p[11], p[12], p[13], p[14],
  			       p[15]);
7d25cd34e   Masahiro Yamada   cmd_nand: slight ...
98
99
  			p += 16;
  		}
addb2e165   Bartlomiej Sieka   Re-factoring the ...
100
  	}
7d25cd34e   Masahiro Yamada   cmd_nand: slight ...
101

addb2e165   Bartlomiej Sieka   Re-factoring the ...
102
103
  	puts("OOB:
  ");
151c06ec6   Scott Wood   mtd: nand: Remove...
104
  	i = mtd->oobsize >> 3;
cfdae12f3   Tom Rini   cmd_nand.c: Fix '...
105
  	p = oobbuf;
addb2e165   Bartlomiej Sieka   Re-factoring the ...
106
  	while (i--) {
cfa460adf   William Juul   Update MTD to tha...
107
108
109
  		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 ...
110
111
  		p += 8;
  	}
e40520b5b   Masahiro Yamada   cmd_nand: fix a m...
112
113
  
  free_all:
9ad754fef   William Juul   make nand dump an...
114
  	free(oobbuf);
e40520b5b   Masahiro Yamada   cmd_nand: fix a m...
115
116
  free_dat:
  	free(datbuf);
addb2e165   Bartlomiej Sieka   Re-factoring the ...
117

e40520b5b   Masahiro Yamada   cmd_nand: fix a m...
118
  	return ret;
addb2e165   Bartlomiej Sieka   Re-factoring the ...
119
120
121
  }
  
  /* ------------------------------------------------------------------------- */
ea533c260   Scott Wood   cmd_nand: some in...
122
123
  static int set_dev(int dev)
  {
ad92dff28   Mugunthan V N   cmd: nand: abstra...
124
125
126
127
  	struct mtd_info *mtd = get_nand_dev_by_index(dev);
  
  	if (!mtd)
  		return -ENODEV;
ea533c260   Scott Wood   cmd_nand: some in...
128
129
130
  
  	if (nand_curr_device == dev)
  		return 0;
ad92dff28   Mugunthan V N   cmd: nand: abstra...
131
  	printf("Device %d: %s", dev, mtd->name);
ea533c260   Scott Wood   cmd_nand: some in...
132
133
134
135
136
  	puts("... is now current device
  ");
  	nand_curr_device = dev;
  
  #ifdef CONFIG_SYS_NAND_SELECT_DEVICE
6308e71be   Grygorii Strashko   cmd: nand: remove...
137
  	board_nand_select_device(mtd_to_nand(mtd), dev);
ea533c260   Scott Wood   cmd_nand: some in...
138
139
140
141
  #endif
  
  	return 0;
  }
50657c273   Nishanth Menon   NAND: Enable nand...
142
143
144
  #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...
145
146
147
148
149
150
  	/*
  	 * 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...
151
152
153
154
155
156
  	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...
157
  		(!(status & NAND_LOCK_STATUS_UNLOCK) ?  "LOCK " : ""),
50657c273   Nishanth Menon   NAND: Enable nand...
158
159
  		((status & NAND_LOCK_STATUS_UNLOCK) ?  "UNLOCK " : ""));
  }
151c06ec6   Scott Wood   mtd: nand: Remove...
160
  static void do_nand_status(struct mtd_info *mtd)
50657c273   Nishanth Menon   NAND: Enable nand...
161
162
163
164
  {
  	ulong block_start = 0;
  	ulong off;
  	int last_status = -1;
17cb4b8f3   Scott Wood   mtd: nand: Add+us...
165
  	struct nand_chip *nand_chip = mtd_to_nand(mtd);
50657c273   Nishanth Menon   NAND: Enable nand...
166
  	/* check the WP bit */
151c06ec6   Scott Wood   mtd: nand: Remove...
167
  	nand_chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
50657c273   Nishanth Menon   NAND: Enable nand...
168
169
  	printf("device is %swrite protected
  ",
151c06ec6   Scott Wood   mtd: nand: Remove...
170
171
  		(nand_chip->read_byte(mtd) & 0x80 ?
  		 "NOT " : ""));
50657c273   Nishanth Menon   NAND: Enable nand...
172

151c06ec6   Scott Wood   mtd: nand: Remove...
173
174
  	for (off = 0; off < mtd->size; off += mtd->erasesize) {
  		int s = nand_get_lock_status(mtd, off);
50657c273   Nishanth Menon   NAND: Enable nand...
175
176
177
  
  		/* print message only if status has changed */
  		if (s != last_status && off != 0) {
151c06ec6   Scott Wood   mtd: nand: Remove...
178
  			print_status(block_start, off, mtd->erasesize,
50657c273   Nishanth Menon   NAND: Enable nand...
179
180
181
182
183
184
  					last_status);
  			block_start = off;
  		}
  		last_status = s;
  	}
  	/* Print the last block info */
151c06ec6   Scott Wood   mtd: nand: Remove...
185
  	print_status(block_start, off, mtd->erasesize, last_status);
50657c273   Nishanth Menon   NAND: Enable nand...
186
187
  }
  #endif
c9f7351b5   Ben Gardiner   NAND: environment...
188
189
  #ifdef CONFIG_ENV_OFFSET_OOB
  unsigned long nand_env_oob_offset;
ea533c260   Scott Wood   cmd_nand: some in...
190
  int do_nand_env_oob(cmd_tbl_t *cmdtp, int argc, char *const argv[])
c9f7351b5   Ben Gardiner   NAND: environment...
191
192
193
  {
  	int ret;
  	uint32_t oob_buf[ENV_OFFSET_SIZE/sizeof(uint32_t)];
ad92dff28   Mugunthan V N   cmd: nand: abstra...
194
  	struct mtd_info *mtd = get_nand_dev_by_index(0);
c9f7351b5   Ben Gardiner   NAND: environment...
195
  	char *cmd = argv[1];
8b7d51249   Scott Wood   nand: Fix some mo...
196
  	if (CONFIG_SYS_MAX_NAND_DEVICE == 0 || !mtd) {
ea533c260   Scott Wood   cmd_nand: some in...
197
198
199
200
201
202
  		puts("no devices available
  ");
  		return 1;
  	}
  
  	set_dev(0);
c9f7351b5   Ben Gardiner   NAND: environment...
203
  	if (!strcmp(cmd, "get")) {
151c06ec6   Scott Wood   mtd: nand: Remove...
204
  		ret = get_nand_env_oob(mtd, &nand_env_oob_offset);
53504a278   Scott Wood   NAND: formatting ...
205
  		if (ret)
c9f7351b5   Ben Gardiner   NAND: environment...
206
  			return 1;
53504a278   Scott Wood   NAND: formatting ...
207
208
209
  
  		printf("0x%08lx
  ", nand_env_oob_offset);
c9f7351b5   Ben Gardiner   NAND: environment...
210
  	} else if (!strcmp(cmd, "set")) {
ea533c260   Scott Wood   cmd_nand: some in...
211
212
  		loff_t addr;
  		loff_t maxsize;
c9f7351b5   Ben Gardiner   NAND: environment...
213
  		struct mtd_oob_ops ops;
ea533c260   Scott Wood   cmd_nand: some in...
214
  		int idx = 0;
c9f7351b5   Ben Gardiner   NAND: environment...
215
216
217
  
  		if (argc < 3)
  			goto usage;
ad92dff28   Mugunthan V N   cmd: nand: abstra...
218
  		mtd = get_nand_dev_by_index(idx);
c39d6a0ea   Tom Rini   nand: Extend nand...
219
  		/* We don't care about size, or maxsize. */
09c328075   Heiko Schocher   mtd, nand: Move c...
220
  		if (mtd_arg_off(argv[2], &idx, &addr, &maxsize, &maxsize,
ad92dff28   Mugunthan V N   cmd: nand: abstra...
221
  				MTD_DEV_TYPE_NAND, mtd->size)) {
09c328075   Heiko Schocher   mtd, nand: Move c...
222
223
224
225
226
  			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
  			return 1;
  		}
151c06ec6   Scott Wood   mtd: nand: Remove...
237
  		if (mtd->oobavail < ENV_OFFSET_SIZE) {
53504a278   Scott Wood   NAND: formatting ...
238
239
240
241
242
  			printf("Insufficient available OOB bytes:
  "
  			       "%d OOB bytes available but %d required for "
  			       "env.oob support
  ",
151c06ec6   Scott Wood   mtd: nand: Remove...
243
  			       mtd->oobavail, ENV_OFFSET_SIZE);
c9f7351b5   Ben Gardiner   NAND: environment...
244
245
  			return 1;
  		}
151c06ec6   Scott Wood   mtd: nand: Remove...
246
  		if ((addr & (mtd->erasesize - 1)) != 0) {
c9f7351b5   Ben Gardiner   NAND: environment...
247
248
249
250
251
252
253
254
255
256
257
258
  			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;
151c06ec6   Scott Wood   mtd: nand: Remove...
259
  		oob_buf[1] = addr / mtd->erasesize;
c9f7351b5   Ben Gardiner   NAND: environment...
260

151c06ec6   Scott Wood   mtd: nand: Remove...
261
  		ret = mtd->write_oob(mtd, ENV_OFFSET_SIZE, &ops);
53504a278   Scott Wood   NAND: formatting ...
262
  		if (ret) {
c9f7351b5   Ben Gardiner   NAND: environment...
263
264
265
266
  			printf("Error writing OOB block 0
  ");
  			return ret;
  		}
53504a278   Scott Wood   NAND: formatting ...
267

151c06ec6   Scott Wood   mtd: nand: Remove...
268
  		ret = get_nand_env_oob(mtd, &nand_env_oob_offset);
53504a278   Scott Wood   NAND: formatting ...
269
270
271
272
273
274
275
276
  		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...
277
278
279
  			       "0x%08llx expected but got 0x%08lx
  ",
  			       (unsigned long long)addr, nand_env_oob_offset);
53504a278   Scott Wood   NAND: formatting ...
280
281
  			return 1;
  		}
c9f7351b5   Ben Gardiner   NAND: environment...
282
283
284
285
286
287
288
  	} else {
  		goto usage;
  	}
  
  	return ret;
  
  usage:
4c12eeb8b   Simon Glass   Convert cmd_usage...
289
  	return CMD_RET_USAGE;
c9f7351b5   Ben Gardiner   NAND: environment...
290
291
292
  }
  
  #endif
ce80ddc18   Marek Vasut   NAND: Make page, ...
293
  static void nand_print_and_set_info(int idx)
672ed2aee   Wolfgang Grandegger   Enable multi chip...
294
  {
ad92dff28   Mugunthan V N   cmd: nand: abstra...
295
296
297
298
299
300
  	struct mtd_info *mtd;
  	struct nand_chip *chip;
  
  	mtd = get_nand_dev_by_index(idx);
  	if (!mtd)
  		return;
ce80ddc18   Marek Vasut   NAND: Make page, ...
301

ad92dff28   Mugunthan V N   cmd: nand: abstra...
302
  	chip = mtd_to_nand(mtd);
672ed2aee   Wolfgang Grandegger   Enable multi chip...
303
304
305
306
307
  	printf("Device %d: ", idx);
  	if (chip->numchips > 1)
  		printf("%dx ", chip->numchips);
  	printf("%s, sector size %u KiB
  ",
151c06ec6   Scott Wood   mtd: nand: Remove...
308
309
310
311
312
313
314
  	       mtd->name, mtd->erasesize >> 10);
  	printf("  Page size   %8d b
  ", mtd->writesize);
  	printf("  OOB size    %8d b
  ", mtd->oobsize);
  	printf("  Erase size  %8d b
  ", mtd->erasesize);
5db73feb1   Heiko Schocher   cmd, nand: add mo...
315
316
  	printf("  subpagesize %8d b
  ", chip->subpagesize);
66dc09c55   Lothar Waßmann   cmd, nand: fix br...
317
318
319
320
  	printf("  options     0x%08x
  ", chip->options);
  	printf("  bbt options 0x%08x
  ", chip->bbt_options);
ce80ddc18   Marek Vasut   NAND: Make page, ...
321
322
  
  	/* Set geometry info */
018f53032   Simon Glass   env: Rename commo...
323
324
325
  	env_set_hex("nand_writesize", mtd->writesize);
  	env_set_hex("nand_oobsize", mtd->oobsize);
  	env_set_hex("nand_erasesize", mtd->erasesize);
672ed2aee   Wolfgang Grandegger   Enable multi chip...
326
  }
151c06ec6   Scott Wood   mtd: nand: Remove...
327
  static int raw_access(struct mtd_info *mtd, ulong addr, loff_t off,
2dc3c483a   Boris Brezillon   cmd, nand: add an...
328
  		      ulong count, int read, int no_verify)
418396e21   Scott Wood   nand: extend .raw...
329
330
  {
  	int ret = 0;
418396e21   Scott Wood   nand: extend .raw...
331
332
333
334
335
  
  	while (count--) {
  		/* Raw access */
  		mtd_oob_ops_t ops = {
  			.datbuf = (u8 *)addr,
151c06ec6   Scott Wood   mtd: nand: Remove...
336
337
338
  			.oobbuf = ((u8 *)addr) + mtd->writesize,
  			.len = mtd->writesize,
  			.ooblen = mtd->oobsize,
dfe64e2c8   Sergey Lapin   mtd: resync with ...
339
  			.mode = MTD_OPS_RAW
418396e21   Scott Wood   nand: extend .raw...
340
  		};
6b94f118a   Peter Tyser   cmd_nand: Verify ...
341
  		if (read) {
151c06ec6   Scott Wood   mtd: nand: Remove...
342
  			ret = mtd_read_oob(mtd, off, &ops);
6b94f118a   Peter Tyser   cmd_nand: Verify ...
343
  		} else {
151c06ec6   Scott Wood   mtd: nand: Remove...
344
  			ret = mtd_write_oob(mtd, off, &ops);
2dc3c483a   Boris Brezillon   cmd, nand: add an...
345
  			if (!ret && !no_verify)
151c06ec6   Scott Wood   mtd: nand: Remove...
346
  				ret = nand_verify_page_oob(mtd, &ops, off);
6b94f118a   Peter Tyser   cmd_nand: Verify ...
347
  		}
418396e21   Scott Wood   nand: extend .raw...
348
349
350
351
352
353
354
  
  		if (ret) {
  			printf("%s: error at offset %llx, ret %d
  ",
  				__func__, (long long)off, ret);
  			break;
  		}
151c06ec6   Scott Wood   mtd: nand: Remove...
355
356
  		addr += mtd->writesize + mtd->oobsize;
  		off += mtd->writesize;
418396e21   Scott Wood   nand: extend .raw...
357
358
359
360
  	}
  
  	return ret;
  }
e834402fa   Harvey Chapman   nand: adjust eras...
361
  /* Adjust a chip/partition size down for bad blocks so we don't
9b80aa8ec   Scott Wood   nand: Don't call ...
362
   * read/write past the end of a chip/partition by accident.
e834402fa   Harvey Chapman   nand: adjust eras...
363
364
365
366
367
368
   */
  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.
  	 */
ad92dff28   Mugunthan V N   cmd: nand: abstra...
369
  	struct mtd_info *mtd = get_nand_dev_by_index(dev);
e834402fa   Harvey Chapman   nand: adjust eras...
370
371
372
373
  	loff_t maxoffset = offset + *size;
  	int badblocks = 0;
  
  	/* count badblocks in NAND from offset to offset + size */
151c06ec6   Scott Wood   mtd: nand: Remove...
374
375
  	for (; offset < maxoffset; offset += mtd->erasesize) {
  		if (nand_block_isbad(mtd, offset))
e834402fa   Harvey Chapman   nand: adjust eras...
376
377
378
379
  			badblocks++;
  	}
  	/* adjust size if any bad blocks found */
  	if (badblocks) {
151c06ec6   Scott Wood   mtd: nand: Remove...
380
  		*size -= badblocks * mtd->erasesize;
e834402fa   Harvey Chapman   nand: adjust eras...
381
382
383
384
385
  		printf("size adjusted to 0x%llx (%d bad blocks)
  ",
  		       (unsigned long long)*size, badblocks);
  	}
  }
088f1b199   Kim Phillips   common/cmd_*.c: s...
386
  static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
addb2e165   Bartlomiej Sieka   Re-factoring the ...
387
  {
ea533c260   Scott Wood   cmd_nand: some in...
388
389
  	int i, ret = 0;
  	ulong addr;
c39d6a0ea   Tom Rini   nand: Extend nand...
390
  	loff_t off, size, maxsize;
addb2e165   Bartlomiej Sieka   Re-factoring the ...
391
  	char *cmd, *s;
151c06ec6   Scott Wood   mtd: nand: Remove...
392
  	struct mtd_info *mtd;
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
393
394
  #ifdef CONFIG_SYS_NAND_QUIET
  	int quiet = CONFIG_SYS_NAND_QUIET;
c750d2e66   Matthias Fuchs   NAND: Add CFG_NAN...
395
  #else
2255b2d20   Stefan Roese   * Several improve...
396
  	int quiet = 0;
c750d2e66   Matthias Fuchs   NAND: Add CFG_NAN...
397
  #endif
00caae6d4   Simon Glass   env: Rename geten...
398
  	const char *quiet_str = env_get("quiet");
ea533c260   Scott Wood   cmd_nand: some in...
399
  	int dev = nand_curr_device;
8c5659a6d   Scott Wood   nand commands: ma...
400
  	int repeat = flag & CMD_FLAG_REPEAT;
addb2e165   Bartlomiej Sieka   Re-factoring the ...
401
402
403
404
  
  	/* at least two arguments please */
  	if (argc < 2)
  		goto usage;
2255b2d20   Stefan Roese   * Several improve...
405
406
  	if (quiet_str)
  		quiet = simple_strtoul(quiet_str, NULL, 0) != 0;
addb2e165   Bartlomiej Sieka   Re-factoring the ...
407
  	cmd = argv[1];
8c5659a6d   Scott Wood   nand commands: ma...
408
409
410
  	/* Only "dump" is repeatable. */
  	if (repeat && strcmp(cmd, "dump"))
  		return 0;
addb2e165   Bartlomiej Sieka   Re-factoring the ...
411
412
413
414
  	if (strcmp(cmd, "info") == 0) {
  
  		putc('
  ');
ad92dff28   Mugunthan V N   cmd: nand: abstra...
415
416
  		for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
  			nand_print_and_set_info(i);
addb2e165   Bartlomiej Sieka   Re-factoring the ...
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
  	/* 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.
  	 */
ad92dff28   Mugunthan V N   cmd: nand: abstra...
448
449
  	mtd = get_nand_dev_by_index(dev);
  	if (!mtd) {
addb2e165   Bartlomiej Sieka   Re-factoring the ...
450
451
452
453
454
  		puts("
  no devices available
  ");
  		return 1;
  	}
addb2e165   Bartlomiej Sieka   Re-factoring the ...
455
456
  
  	if (strcmp(cmd, "bad") == 0) {
ea533c260   Scott Wood   cmd_nand: some in...
457
458
459
  		printf("
  Device %d bad blocks:
  ", dev);
151c06ec6   Scott Wood   mtd: nand: Remove...
460
461
  		for (off = 0; off < mtd->size; off += mtd->erasesize)
  			if (nand_block_isbad(mtd, off))
ea533c260   Scott Wood   cmd_nand: some in...
462
463
  				printf("  %08llx
  ", (unsigned long long)off);
addb2e165   Bartlomiej Sieka   Re-factoring the ...
464
465
  		return 0;
  	}
856f05441   Stefan Roese   [PATCH] NAND: Par...
466
467
468
469
470
  	/*
  	 * Syntax is:
  	 *   0    1     2       3    4
  	 *   nand erase [clean] [off size]
  	 */
304863225   Scott Wood   nand erase: .spre...
471
  	if (strncmp(cmd, "erase", 5) == 0 || strncmp(cmd, "scrub", 5) == 0) {
2255b2d20   Stefan Roese   * Several improve...
472
  		nand_erase_options_t opts;
856f05441   Stefan Roese   [PATCH] NAND: Par...
473
  		/* "clean" at index 2 means request to write cleanmarker */
3043c045d   William Juul   Whitespace cleanu...
474
  		int clean = argc > 2 && !strcmp("clean", argv[2]);
608998166   Marek Vasut   NAND: Add -y opti...
475
476
  		int scrub_yes = argc > 2 && !strcmp("-y", argv[2]);
  		int o = (clean || scrub_yes) ? 3 : 2;
304863225   Scott Wood   nand erase: .spre...
477
  		int scrub = !strncmp(cmd, "scrub", 5);
304863225   Scott Wood   nand erase: .spre...
478
479
  		int spread = 0;
  		int args = 2;
608998166   Marek Vasut   NAND: Add -y opti...
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
  		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...
496
497
498
499
500
  
  		if (cmd[5] != 0) {
  			if (!strcmp(&cmd[5], ".spread")) {
  				spread = 1;
  			} else if (!strcmp(&cmd[5], ".part")) {
304863225   Scott Wood   nand erase: .spre...
501
502
  				args = 1;
  			} else if (!strcmp(&cmd[5], ".chip")) {
304863225   Scott Wood   nand erase: .spre...
503
504
505
506
507
508
509
510
511
512
513
514
515
  				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...
516

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

ad92dff28   Mugunthan V N   cmd: nand: abstra...
528
  		mtd = get_nand_dev_by_index(dev);
ea533c260   Scott Wood   cmd_nand: some in...
529

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
  			}
  		}
151c06ec6   Scott Wood   mtd: nand: Remove...
551
  		ret = nand_erase_opts(mtd, &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);
151c06ec6   Scott Wood   mtd: nand: Remove...
562
  		ret = nand_dump(mtd, 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;
2dc3c483a   Boris Brezillon   cmd, nand: add an...
571
  		int no_verify = 0;
2255b2d20   Stefan Roese   * Several improve...
572

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

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

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

2dc3c483a   Boris Brezillon   cmd, nand: add an...
583
  		if (s && !strncmp(s, ".raw", 4)) {
418396e21   Scott Wood   nand: extend .raw...
584
  			raw = 1;
2dc3c483a   Boris Brezillon   cmd, nand: add an...
585
586
  			if (!strcmp(s, ".raw.noverify"))
  				no_verify = 1;
09c328075   Heiko Schocher   mtd, nand: Move c...
587
588
  			if (mtd_arg_off(argv[3], &dev, &off, &size, &maxsize,
  					MTD_DEV_TYPE_NAND,
ad92dff28   Mugunthan V N   cmd: nand: abstra...
589
  					mtd->size))
09c328075   Heiko Schocher   mtd, nand: Move c...
590
591
592
  				return 1;
  
  			if (set_dev(dev))
418396e21   Scott Wood   nand: extend .raw...
593
  				return 1;
ad92dff28   Mugunthan V N   cmd: nand: abstra...
594
  			mtd = get_nand_dev_by_index(dev);
93d3232d9   Rostislav Lisovy   cmd_nand: Update ...
595

418396e21   Scott Wood   nand: extend .raw...
596
597
598
599
600
  			if (argc > 4 && !str2long(argv[4], &pagecount)) {
  				printf("'%s' is not a number
  ", argv[4]);
  				return 1;
  			}
151c06ec6   Scott Wood   mtd: nand: Remove...
601
  			if (pagecount * mtd->writesize > size) {
418396e21   Scott Wood   nand: extend .raw...
602
603
604
605
  				puts("Size exceeds partition or device limit
  ");
  				return -1;
  			}
151c06ec6   Scott Wood   mtd: nand: Remove...
606
  			rwsize = pagecount * (mtd->writesize + mtd->oobsize);
418396e21   Scott Wood   nand: extend .raw...
607
  		} else {
09c328075   Heiko Schocher   mtd, nand: Move c...
608
609
610
  			if (mtd_arg_off_size(argc - 3, argv + 3, &dev, &off,
  					     &size, &maxsize,
  					     MTD_DEV_TYPE_NAND,
ad92dff28   Mugunthan V N   cmd: nand: abstra...
611
  					     mtd->size) != 0)
09c328075   Heiko Schocher   mtd, nand: Move c...
612
613
614
  				return 1;
  
  			if (set_dev(dev))
418396e21   Scott Wood   nand: extend .raw...
615
  				return 1;
e834402fa   Harvey Chapman   nand: adjust eras...
616
617
618
  			/* size is unspecified */
  			if (argc < 5)
  				adjust_size_for_badblocks(&size, off, dev);
418396e21   Scott Wood   nand: extend .raw...
619
620
  			rwsize = size;
  		}
ad92dff28   Mugunthan V N   cmd: nand: abstra...
621
  		mtd = get_nand_dev_by_index(dev);
93d3232d9   Rostislav Lisovy   cmd_nand: Update ...
622

984e03cdf   Scott Wood   NAND: Always skip...
623
624
  		if (!s || !strcmp(s, ".jffs2") ||
  		    !strcmp(s, ".e") || !strcmp(s, ".i")) {
dfbf617ff   Scott Wood   NAND read/write fix
625
  			if (read)
151c06ec6   Scott Wood   mtd: nand: Remove...
626
  				ret = nand_read_skip_bad(mtd, off, &rwsize,
c39d6a0ea   Tom Rini   nand: Extend nand...
627
  							 NULL, maxsize,
4b0708093   Wolfgang Denk   Coding Style clea...
628
  							 (u_char *)addr);
dfbf617ff   Scott Wood   NAND read/write fix
629
  			else
151c06ec6   Scott Wood   mtd: nand: Remove...
630
  				ret = nand_write_skip_bad(mtd, off, &rwsize,
c39d6a0ea   Tom Rini   nand: Extend nand...
631
  							  NULL, maxsize,
6b94f118a   Peter Tyser   cmd_nand: Verify ...
632
633
  							  (u_char *)addr,
  							  WITH_WR_VERIFY);
c9494866d   Ben Gardiner   cmd_nand: add nan...
634
635
636
637
638
639
640
  #ifdef CONFIG_CMD_NAND_TRIMFFS
  		} else if (!strcmp(s, ".trimffs")) {
  			if (read) {
  				printf("Unknown nand command suffix '%s'
  ", s);
  				return 1;
  			}
151c06ec6   Scott Wood   mtd: nand: Remove...
641
  			ret = nand_write_skip_bad(mtd, off, &rwsize, NULL,
c39d6a0ea   Tom Rini   nand: Extend nand...
642
  						maxsize, (u_char *)addr,
6b94f118a   Peter Tyser   cmd_nand: Verify ...
643
  						WITH_DROP_FFS | WITH_WR_VERIFY);
c9494866d   Ben Gardiner   cmd_nand: add nan...
644
  #endif
dfc99e143   Mike Frysinger   cmd_nand: drop du...
645
  		} else if (!strcmp(s, ".oob")) {
cfa460adf   William Juul   Update MTD to tha...
646
647
648
  			/* out-of-band data */
  			mtd_oob_ops_t ops = {
  				.oobbuf = (u8 *)addr,
ea533c260   Scott Wood   cmd_nand: some in...
649
  				.ooblen = rwsize,
dfe64e2c8   Sergey Lapin   mtd: resync with ...
650
  				.mode = MTD_OPS_RAW
cfa460adf   William Juul   Update MTD to tha...
651
  			};
62d4f4365   Harald Welte   Re-introduce the ...
652
  			if (read)
151c06ec6   Scott Wood   mtd: nand: Remove...
653
  				ret = mtd_read_oob(mtd, off, &ops);
62d4f4365   Harald Welte   Re-introduce the ...
654
  			else
151c06ec6   Scott Wood   mtd: nand: Remove...
655
  				ret = mtd_write_oob(mtd, off, &ops);
418396e21   Scott Wood   nand: extend .raw...
656
  		} else if (raw) {
2dc3c483a   Boris Brezillon   cmd, nand: add an...
657
658
  			ret = raw_access(mtd, addr, off, pagecount, read,
  					 no_verify);
856f05441   Stefan Roese   [PATCH] NAND: Par...
659
  		} else {
984e03cdf   Scott Wood   NAND: Always skip...
660
661
662
  			printf("Unknown nand command suffix '%s'.
  ", s);
  			return 1;
2255b2d20   Stefan Roese   * Several improve...
663
  		}
ea533c260   Scott Wood   cmd_nand: some in...
664
665
  		printf(" %zu bytes %s: %s
  ", rwsize,
2255b2d20   Stefan Roese   * Several improve...
666
  		       read ? "read" : "written", ret ? "ERROR" : "OK");
addb2e165   Bartlomiej Sieka   Re-factoring the ...
667
668
669
  
  		return ret == 0 ? 0 : 1;
  	}
2255b2d20   Stefan Roese   * Several improve...
670

3287f6d38   Benoît Thébaudeau   nand: Add torture...
671
672
  #ifdef CONFIG_CMD_NAND_TORTURE
  	if (strcmp(cmd, "torture") == 0) {
1866be7d2   Max Krummenacher   nand: extend nand...
673
674
  		loff_t endoff;
  		unsigned int failed = 0, passed = 0;
3287f6d38   Benoît Thébaudeau   nand: Add torture...
675
676
677
678
679
680
681
682
  		if (argc < 3)
  			goto usage;
  
  		if (!str2off(argv[2], &off)) {
  			puts("Offset is not a valid number
  ");
  			return 1;
  		}
1866be7d2   Max Krummenacher   nand: extend nand...
683
684
685
686
687
688
689
690
  		size = mtd->erasesize;
  		if (argc > 3) {
  			if (!str2off(argv[3], &size)) {
  				puts("Size is not a valid number
  ");
  				return 1;
  			}
  		}
3287f6d38   Benoît Thébaudeau   nand: Add torture...
691

1866be7d2   Max Krummenacher   nand: extend nand...
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
  		endoff = off + size;
  		if (endoff > mtd->size) {
  			puts("Arguments beyond end of NAND
  ");
  			return 1;
  		}
  
  		off = round_down(off, mtd->erasesize);
  		endoff = round_up(endoff, mtd->erasesize);
  		size = endoff - off;
  		printf("
  NAND torture: device %d offset 0x%llx size 0x%llx (block size 0x%x)
  ",
  		       dev, off, size, mtd->erasesize);
  		while (off < endoff) {
  			ret = nand_torture(mtd, off);
  			if (ret) {
  				failed++;
  				printf("  block at 0x%llx failed
  ", off);
  			} else {
  				passed++;
  			}
  			off += mtd->erasesize;
  		}
  		printf(" Passed: %u, failed: %u
  ", passed, failed);
  		return failed != 0;
3287f6d38   Benoît Thébaudeau   nand: Add torture...
720
721
  	}
  #endif
2255b2d20   Stefan Roese   * Several improve...
722
  	if (strcmp(cmd, "markbad") == 0) {
8360b66ba   Wolfgang Denk   nand/onenand: Fix...
723
724
  		argc -= 2;
  		argv += 2;
2255b2d20   Stefan Roese   * Several improve...
725

8360b66ba   Wolfgang Denk   nand/onenand: Fix...
726
727
728
729
730
  		if (argc <= 0)
  			goto usage;
  
  		while (argc > 0) {
  			addr = simple_strtoul(*argv, NULL, 16);
151c06ec6   Scott Wood   mtd: nand: Remove...
731
  			if (mtd_block_markbad(mtd, addr)) {
8360b66ba   Wolfgang Denk   nand/onenand: Fix...
732
733
734
735
736
737
738
739
740
741
742
743
744
  				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...
745
  		}
8360b66ba   Wolfgang Denk   nand/onenand: Fix...
746
  		return ret;
2255b2d20   Stefan Roese   * Several improve...
747
  	}
dfbf617ff   Scott Wood   NAND read/write fix
748

2255b2d20   Stefan Roese   * Several improve...
749
750
751
752
  	if (strcmp(cmd, "biterr") == 0) {
  		/* todo */
  		return 1;
  	}
50657c273   Nishanth Menon   NAND: Enable nand...
753
  #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
2255b2d20   Stefan Roese   * Several improve...
754
  	if (strcmp(cmd, "lock") == 0) {
50657c273   Nishanth Menon   NAND: Enable nand...
755
  		int tight = 0;
2255b2d20   Stefan Roese   * Several improve...
756
757
758
759
760
761
762
  		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...
763
  		if (status) {
151c06ec6   Scott Wood   mtd: nand: Remove...
764
  			do_nand_status(mtd);
cfa460adf   William Juul   Update MTD to tha...
765
  		} else {
151c06ec6   Scott Wood   mtd: nand: Remove...
766
  			if (!nand_lock(mtd, tight)) {
5e1dae5c3   William Juul   Fixing coding sty...
767
768
769
770
771
772
773
  				puts("NAND flash successfully locked
  ");
  			} else {
  				puts("Error locking NAND flash
  ");
  				return 1;
  			}
2255b2d20   Stefan Roese   * Several improve...
774
775
776
  		}
  		return 0;
  	}
eee623a50   Joe Hershberger   nand: Add support...
777
778
779
780
781
782
783
  	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...
784
785
  		if (mtd_arg_off_size(argc - 2, argv + 2, &dev, &off, &size,
  				     &maxsize, MTD_DEV_TYPE_NAND,
ad92dff28   Mugunthan V N   cmd: nand: abstra...
786
  				     mtd->size) < 0)
09c328075   Heiko Schocher   mtd, nand: Move c...
787
788
789
  			return 1;
  
  		if (set_dev(dev))
856f05441   Stefan Roese   [PATCH] NAND: Par...
790
  			return 1;
2255b2d20   Stefan Roese   * Several improve...
791

ad92dff28   Mugunthan V N   cmd: nand: abstra...
792
793
794
  		mtd = get_nand_dev_by_index(dev);
  
  		if (!nand_unlock(mtd, off, size, allexcept)) {
5e1dae5c3   William Juul   Fixing coding sty...
795
796
797
798
  			puts("NAND flash successfully unlocked
  ");
  		} else {
  			puts("Error unlocking NAND flash, "
3043c045d   William Juul   Whitespace cleanu...
799
800
  			     "write and erase will probably fail
  ");
5e1dae5c3   William Juul   Fixing coding sty...
801
802
  			return 1;
  		}
2255b2d20   Stefan Roese   * Several improve...
803
804
  		return 0;
  	}
50657c273   Nishanth Menon   NAND: Enable nand...
805
  #endif
2255b2d20   Stefan Roese   * Several improve...
806

addb2e165   Bartlomiej Sieka   Re-factoring the ...
807
  usage:
4c12eeb8b   Simon Glass   Convert cmd_usage...
808
  	return CMD_RET_USAGE;
addb2e165   Bartlomiej Sieka   Re-factoring the ...
809
  }
088f1b199   Kim Phillips   common/cmd_*.c: s...
810
811
  #ifdef CONFIG_SYS_LONGHELP
  static char nand_help_text[] =
a89c33db9   Wolfgang Denk   General help mess...
812
813
814
815
816
817
818
819
820
821
822
823
  	"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...
824
825
  	"nand read.raw - addr off|partition [count]
  "
2dc3c483a   Boris Brezillon   cmd, nand: add an...
826
827
  	"nand write.raw[.noverify] - addr off|partition [count]
  "
418396e21   Scott Wood   nand: extend .raw...
828
829
  	"    Use read.raw/write.raw to avoid ECC and access the flash as-is.
  "
c9494866d   Ben Gardiner   cmd_nand: add nan...
830
831
832
833
834
835
836
837
838
839
  #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...
840
  	"nand erase[.spread] [clean] off size - erase 'size' bytes "
304863225   Scott Wood   nand erase: .spre...
841
842
843
844
845
846
847
848
849
850
  	"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...
851
852
853
854
  	"nand bad - show bad blocks
  "
  	"nand dump[.oob] off - dump page
  "
3287f6d38   Benoît Thébaudeau   nand: Add torture...
855
  #ifdef CONFIG_CMD_NAND_TORTURE
1866be7d2   Max Krummenacher   nand: extend nand...
856
857
858
859
  	"nand torture off - torture one block at offset
  "
  	"nand torture off [size] - torture blocks from off to off+size
  "
3287f6d38   Benoît Thébaudeau   nand: Add torture...
860
  #endif
608998166   Marek Vasut   NAND: Add -y opti...
861
862
  	"nand scrub [-y] off size | scrub.part partition | scrub.chip
  "
304863225   Scott Wood   nand erase: .spre...
863
864
  	"    really clean NAND erasing bad blocks (UNSAFE)
  "
a89c33db9   Wolfgang Denk   General help mess...
865
866
867
  	"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...
868
  #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
a89c33db9   Wolfgang Denk   General help mess...
869
870
871
872
873
874
  	"
  "
  	"nand lock [tight] [status]
  "
  	"    bring nand to lock state or display locked pages
  "
eee623a50   Joe Hershberger   nand: Add support...
875
  	"nand unlock[.allexcept] [offset] [size] - unlock section"
50657c273   Nishanth Menon   NAND: Enable nand...
876
  #endif
c9f7351b5   Ben Gardiner   NAND: environment...
877
878
879
880
881
882
883
884
885
886
  #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...
887
888
889
890
891
892
  	"";
  #endif
  
  U_BOOT_CMD(
  	nand, CONFIG_SYS_MAXARGS, 1, do_nand,
  	"NAND sub-system", nand_help_text
50657c273   Nishanth Menon   NAND: Enable nand...
893
  );
addb2e165   Bartlomiej Sieka   Re-factoring the ...
894

151c06ec6   Scott Wood   mtd: nand: Remove...
895
  static int nand_load_image(cmd_tbl_t *cmdtp, struct mtd_info *mtd,
4b0708093   Wolfgang Denk   Coding Style clea...
896
  			   ulong offset, ulong addr, char *cmd)
addb2e165   Bartlomiej Sieka   Re-factoring the ...
897
  {
addb2e165   Bartlomiej Sieka   Re-factoring the ...
898
  	int r;
67d668bf9   Mike Frysinger   autostart: unify ...
899
  	char *s;
4ca79f477   Wolfgang Denk   NAND: fix some st...
900
  	size_t cnt;
c76c93a3d   Tom Rini   configs: Rename C...
901
  #if defined(CONFIG_LEGACY_IMAGE_FORMAT)
addb2e165   Bartlomiej Sieka   Re-factoring the ...
902
  	image_header_t *hdr;
21d29f7f9   Heiko Schocher   bootm: make use o...
903
  #endif
09475f752   Marian Balakowicz   [new uImage] Add ...
904
  #if defined(CONFIG_FIT)
3bab76a26   Marian Balakowicz   Delay FIT format ...
905
  	const void *fit_hdr = NULL;
09475f752   Marian Balakowicz   [new uImage] Add ...
906
  #endif
10e038932   Thomas Knobloch   [NAND] Bad block ...
907
908
909
  
  	s = strchr(cmd, '.');
  	if (s != NULL &&
65d8bc94d   Scott Wood   NAND: Have nboot ...
910
  	    (strcmp(s, ".jffs2") && strcmp(s, ".e") && strcmp(s, ".i"))) {
984e03cdf   Scott Wood   NAND: Always skip...
911
912
  		printf("Unknown nand load suffix '%s'
  ", s);
770605e4f   Simon Glass   bootstage: Replac...
913
  		bootstage_error(BOOTSTAGE_ID_NAND_SUFFIX);
984e03cdf   Scott Wood   NAND: Always skip...
914
915
  		return 1;
  	}
addb2e165   Bartlomiej Sieka   Re-factoring the ...
916

151c06ec6   Scott Wood   mtd: nand: Remove...
917
918
919
  	printf("
  Loading from %s, offset 0x%lx
  ", mtd->name, offset);
addb2e165   Bartlomiej Sieka   Re-factoring the ...
920

151c06ec6   Scott Wood   mtd: nand: Remove...
921
922
923
  	cnt = mtd->writesize;
  	r = nand_read_skip_bad(mtd, offset, &cnt, NULL, mtd->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_HDR_READ);
addb2e165   Bartlomiej Sieka   Re-factoring the ...
928
929
  		return 1;
  	}
770605e4f   Simon Glass   bootstage: Replac...
930
  	bootstage_mark(BOOTSTAGE_ID_NAND_HDR_READ);
addb2e165   Bartlomiej Sieka   Re-factoring the ...
931

9a4daad0a   Marian Balakowicz   [new uImage] Upda...
932
  	switch (genimg_get_format ((void *)addr)) {
c76c93a3d   Tom Rini   configs: Rename C...
933
  #if defined(CONFIG_LEGACY_IMAGE_FORMAT)
d5934ad77   Marian Balakowicz   [new uImage] Add ...
934
935
  	case IMAGE_FORMAT_LEGACY:
  		hdr = (image_header_t *)addr;
770605e4f   Simon Glass   bootstage: Replac...
936
  		bootstage_mark(BOOTSTAGE_ID_NAND_TYPE);
d5934ad77   Marian Balakowicz   [new uImage] Add ...
937
  		image_print_contents (hdr);
addb2e165   Bartlomiej Sieka   Re-factoring the ...
938

d5934ad77   Marian Balakowicz   [new uImage] Add ...
939
940
  		cnt = image_get_image_size (hdr);
  		break;
21d29f7f9   Heiko Schocher   bootm: make use o...
941
  #endif
d5934ad77   Marian Balakowicz   [new uImage] Add ...
942
943
  #if defined(CONFIG_FIT)
  	case IMAGE_FORMAT_FIT:
09475f752   Marian Balakowicz   [new uImage] Add ...
944
  		fit_hdr = (const void *)addr;
09475f752   Marian Balakowicz   [new uImage] Add ...
945
946
947
948
949
  		puts ("Fit image detected...
  ");
  
  		cnt = fit_get_size (fit_hdr);
  		break;
d5934ad77   Marian Balakowicz   [new uImage] Add ...
950
951
  #endif
  	default:
770605e4f   Simon Glass   bootstage: Replac...
952
  		bootstage_error(BOOTSTAGE_ID_NAND_TYPE);
d5934ad77   Marian Balakowicz   [new uImage] Add ...
953
954
  		puts ("** Unknown image type
  ");
addb2e165   Bartlomiej Sieka   Re-factoring the ...
955
956
  		return 1;
  	}
770605e4f   Simon Glass   bootstage: Replac...
957
  	bootstage_mark(BOOTSTAGE_ID_NAND_TYPE);
addb2e165   Bartlomiej Sieka   Re-factoring the ...
958

151c06ec6   Scott Wood   mtd: nand: Remove...
959
960
  	r = nand_read_skip_bad(mtd, offset, &cnt, NULL, mtd->size,
  			       (u_char *)addr);
addb2e165   Bartlomiej Sieka   Re-factoring the ...
961
  	if (r) {
856f05441   Stefan Roese   [PATCH] NAND: Par...
962
963
  		puts("** Read error
  ");
770605e4f   Simon Glass   bootstage: Replac...
964
  		bootstage_error(BOOTSTAGE_ID_NAND_READ);
addb2e165   Bartlomiej Sieka   Re-factoring the ...
965
966
  		return 1;
  	}
770605e4f   Simon Glass   bootstage: Replac...
967
  	bootstage_mark(BOOTSTAGE_ID_NAND_READ);
addb2e165   Bartlomiej Sieka   Re-factoring the ...
968

09475f752   Marian Balakowicz   [new uImage] Add ...
969
970
  #if defined(CONFIG_FIT)
  	/* This cannot be done earlier, we need complete FIT image in RAM first */
3bab76a26   Marian Balakowicz   Delay FIT format ...
971
972
  	if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) {
  		if (!fit_check_format (fit_hdr)) {
770605e4f   Simon Glass   bootstage: Replac...
973
  			bootstage_error(BOOTSTAGE_ID_NAND_FIT_READ);
3bab76a26   Marian Balakowicz   Delay FIT format ...
974
975
976
977
  			puts ("** Bad FIT image format
  ");
  			return 1;
  		}
770605e4f   Simon Glass   bootstage: Replac...
978
  		bootstage_mark(BOOTSTAGE_ID_NAND_FIT_READ_OK);
3bab76a26   Marian Balakowicz   Delay FIT format ...
979
980
  		fit_print_contents (fit_hdr);
  	}
09475f752   Marian Balakowicz   [new uImage] Add ...
981
  #endif
addb2e165   Bartlomiej Sieka   Re-factoring the ...
982
  	/* Loading ok, update default load address */
bb872dd93   Simon Glass   image: Rename loa...
983
  	image_load_addr = addr;
addb2e165   Bartlomiej Sieka   Re-factoring the ...
984

67d668bf9   Mike Frysinger   autostart: unify ...
985
  	return bootm_maybe_autostart(cmdtp, cmd);
addb2e165   Bartlomiej Sieka   Re-factoring the ...
986
  }
088f1b199   Kim Phillips   common/cmd_*.c: s...
987
988
  static int do_nandboot(cmd_tbl_t *cmdtp, int flag, int argc,
  		       char * const argv[])
856f05441   Stefan Roese   [PATCH] NAND: Par...
989
990
991
992
  {
  	char *boot_device = NULL;
  	int idx;
  	ulong addr, offset = 0;
ad92dff28   Mugunthan V N   cmd: nand: abstra...
993
  	struct mtd_info *mtd;
0c8a84916   Ladislav Michl   Separate mtdparts...
994
  #if defined(CONFIG_CMD_MTDPARTS)
856f05441   Stefan Roese   [PATCH] NAND: Par...
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
  	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 ...
1011
  				addr = simple_strtoul(argv[1], NULL, 16);
856f05441   Stefan Roese   [PATCH] NAND: Par...
1012
  			else
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
1013
  				addr = CONFIG_SYS_LOAD_ADDR;
ad92dff28   Mugunthan V N   cmd: nand: abstra...
1014
1015
1016
1017
  
  			mtd = get_nand_dev_by_index(dev->id->num);
  			return nand_load_image(cmdtp, mtd, part->offset,
  					       addr, argv[0]);
856f05441   Stefan Roese   [PATCH] NAND: Par...
1018
1019
1020
  		}
  	}
  #endif
770605e4f   Simon Glass   bootstage: Replac...
1021
  	bootstage_mark(BOOTSTAGE_ID_NAND_PART);
856f05441   Stefan Roese   [PATCH] NAND: Par...
1022
1023
  	switch (argc) {
  	case 1:
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
1024
  		addr = CONFIG_SYS_LOAD_ADDR;
00caae6d4   Simon Glass   env: Rename geten...
1025
  		boot_device = env_get("bootdevice");
856f05441   Stefan Roese   [PATCH] NAND: Par...
1026
1027
1028
  		break;
  	case 2:
  		addr = simple_strtoul(argv[1], NULL, 16);
00caae6d4   Simon Glass   env: Rename geten...
1029
  		boot_device = env_get("bootdevice");
856f05441   Stefan Roese   [PATCH] NAND: Par...
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
  		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...
1041
  #if defined(CONFIG_CMD_MTDPARTS)
856f05441   Stefan Roese   [PATCH] NAND: Par...
1042
1043
  usage:
  #endif
770605e4f   Simon Glass   bootstage: Replac...
1044
  		bootstage_error(BOOTSTAGE_ID_NAND_SUFFIX);
4c12eeb8b   Simon Glass   Convert cmd_usage...
1045
  		return CMD_RET_USAGE;
856f05441   Stefan Roese   [PATCH] NAND: Par...
1046
  	}
770605e4f   Simon Glass   bootstage: Replac...
1047
  	bootstage_mark(BOOTSTAGE_ID_NAND_SUFFIX);
856f05441   Stefan Roese   [PATCH] NAND: Par...
1048
1049
1050
1051
1052
  
  	if (!boot_device) {
  		puts("
  ** No boot device **
  ");
770605e4f   Simon Glass   bootstage: Replac...
1053
  		bootstage_error(BOOTSTAGE_ID_NAND_BOOT_DEVICE);
856f05441   Stefan Roese   [PATCH] NAND: Par...
1054
1055
  		return 1;
  	}
770605e4f   Simon Glass   bootstage: Replac...
1056
  	bootstage_mark(BOOTSTAGE_ID_NAND_BOOT_DEVICE);
addb2e165   Bartlomiej Sieka   Re-factoring the ...
1057

856f05441   Stefan Roese   [PATCH] NAND: Par...
1058
  	idx = simple_strtoul(boot_device, NULL, 16);
ad92dff28   Mugunthan V N   cmd: nand: abstra...
1059
1060
  	mtd = get_nand_dev_by_index(idx);
  	if (!mtd) {
856f05441   Stefan Roese   [PATCH] NAND: Par...
1061
1062
1063
  		printf("
  ** Device %d not available
  ", idx);
770605e4f   Simon Glass   bootstage: Replac...
1064
  		bootstage_error(BOOTSTAGE_ID_NAND_AVAILABLE);
856f05441   Stefan Roese   [PATCH] NAND: Par...
1065
1066
  		return 1;
  	}
770605e4f   Simon Glass   bootstage: Replac...
1067
  	bootstage_mark(BOOTSTAGE_ID_NAND_AVAILABLE);
856f05441   Stefan Roese   [PATCH] NAND: Par...
1068

ad92dff28   Mugunthan V N   cmd: nand: abstra...
1069
  	return nand_load_image(cmdtp, mtd, offset, addr, argv[0]);
856f05441   Stefan Roese   [PATCH] NAND: Par...
1070
1071
1072
  }
  
  U_BOOT_CMD(nboot, 4, 1, do_nandboot,
2fb2604d5   Peter Tyser   Command usage cle...
1073
  	"boot from NAND device",
a89c33db9   Wolfgang Denk   General help mess...
1074
1075
  	"[partition] | [[[loadAddr] dev] offset]"
  );