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>
cfa460adf   William Juul   Update MTD to tha...
23
  #include <linux/mtd/mtd.h>
addb2e165   Bartlomiej Sieka   Re-factoring the ...
24
  #include <command.h>
24b852a7a   Simon Glass   Move console defi...
25
  #include <console.h>
addb2e165   Bartlomiej Sieka   Re-factoring the ...
26
27
28
  #include <watchdog.h>
  #include <malloc.h>
  #include <asm/byteorder.h>
addb2e165   Bartlomiej Sieka   Re-factoring the ...
29
30
  #include <jffs2/jffs2.h>
  #include <nand.h>
0c8a84916   Ladislav Michl   Separate mtdparts...
31
  #if defined(CONFIG_CMD_MTDPARTS)
856f05441   Stefan Roese   [PATCH] NAND: Par...
32

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

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

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

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

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

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

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

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

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

ad92dff28   Mugunthan V N   cmd: nand: abstra...
300
  	chip = mtd_to_nand(mtd);
672ed2aee   Wolfgang Grandegger   Enable multi chip...
301
302
303
304
305
  	printf("Device %d: ", idx);
  	if (chip->numchips > 1)
  		printf("%dx ", chip->numchips);
  	printf("%s, sector size %u KiB
  ",
151c06ec6   Scott Wood   mtd: nand: Remove...
306
307
308
309
310
311
312
  	       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...
313
314
  	printf("  subpagesize %8d b
  ", chip->subpagesize);
66dc09c55   Lothar Waßmann   cmd, nand: fix br...
315
316
317
318
  	printf("  options     0x%08x
  ", chip->options);
  	printf("  bbt options 0x%08x
  ", chip->bbt_options);
ce80ddc18   Marek Vasut   NAND: Make page, ...
319
320
  
  	/* Set geometry info */
018f53032   Simon Glass   env: Rename commo...
321
322
323
  	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...
324
  }
151c06ec6   Scott Wood   mtd: nand: Remove...
325
  static int raw_access(struct mtd_info *mtd, ulong addr, loff_t off,
2dc3c483a   Boris Brezillon   cmd, nand: add an...
326
  		      ulong count, int read, int no_verify)
418396e21   Scott Wood   nand: extend .raw...
327
328
  {
  	int ret = 0;
418396e21   Scott Wood   nand: extend .raw...
329
330
331
332
333
  
  	while (count--) {
  		/* Raw access */
  		mtd_oob_ops_t ops = {
  			.datbuf = (u8 *)addr,
151c06ec6   Scott Wood   mtd: nand: Remove...
334
335
336
  			.oobbuf = ((u8 *)addr) + mtd->writesize,
  			.len = mtd->writesize,
  			.ooblen = mtd->oobsize,
dfe64e2c8   Sergey Lapin   mtd: resync with ...
337
  			.mode = MTD_OPS_RAW
418396e21   Scott Wood   nand: extend .raw...
338
  		};
6b94f118a   Peter Tyser   cmd_nand: Verify ...
339
  		if (read) {
151c06ec6   Scott Wood   mtd: nand: Remove...
340
  			ret = mtd_read_oob(mtd, off, &ops);
6b94f118a   Peter Tyser   cmd_nand: Verify ...
341
  		} else {
151c06ec6   Scott Wood   mtd: nand: Remove...
342
  			ret = mtd_write_oob(mtd, off, &ops);
2dc3c483a   Boris Brezillon   cmd, nand: add an...
343
  			if (!ret && !no_verify)
151c06ec6   Scott Wood   mtd: nand: Remove...
344
  				ret = nand_verify_page_oob(mtd, &ops, off);
6b94f118a   Peter Tyser   cmd_nand: Verify ...
345
  		}
418396e21   Scott Wood   nand: extend .raw...
346
347
348
349
350
351
352
  
  		if (ret) {
  			printf("%s: error at offset %llx, ret %d
  ",
  				__func__, (long long)off, ret);
  			break;
  		}
151c06ec6   Scott Wood   mtd: nand: Remove...
353
354
  		addr += mtd->writesize + mtd->oobsize;
  		off += mtd->writesize;
418396e21   Scott Wood   nand: extend .raw...
355
356
357
358
  	}
  
  	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
   */
  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...
367
  	struct mtd_info *mtd = get_nand_dev_by_index(dev);
e834402fa   Harvey Chapman   nand: adjust eras...
368
369
370
371
  	loff_t maxoffset = offset + *size;
  	int badblocks = 0;
  
  	/* count badblocks in NAND from offset to offset + size */
151c06ec6   Scott Wood   mtd: nand: Remove...
372
373
  	for (; offset < maxoffset; offset += mtd->erasesize) {
  		if (nand_block_isbad(mtd, offset))
e834402fa   Harvey Chapman   nand: adjust eras...
374
375
376
377
  			badblocks++;
  	}
  	/* adjust size if any bad blocks found */
  	if (badblocks) {
151c06ec6   Scott Wood   mtd: nand: Remove...
378
  		*size -= badblocks * mtd->erasesize;
e834402fa   Harvey Chapman   nand: adjust eras...
379
380
381
382
383
  		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
  	char *cmd, *s;
151c06ec6   Scott Wood   mtd: nand: Remove...
390
  	struct mtd_info *mtd;
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
00caae6d4   Simon Glass   env: Rename geten...
396
  	const char *quiet_str = env_get("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('
  ');
ad92dff28   Mugunthan V N   cmd: nand: abstra...
413
414
  		for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
  			nand_print_and_set_info(i);
addb2e165   Bartlomiej Sieka   Re-factoring the ...
415
416
417
418
  		return 0;
  	}
  
  	if (strcmp(cmd, "device") == 0) {
addb2e165   Bartlomiej Sieka   Re-factoring the ...
419
  		if (argc < 3) {
672ed2aee   Wolfgang Grandegger   Enable multi chip...
420
421
  			putc('
  ');
ea533c260   Scott Wood   cmd_nand: some in...
422
  			if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE)
672ed2aee   Wolfgang Grandegger   Enable multi chip...
423
424
  				puts("no devices available
  ");
addb2e165   Bartlomiej Sieka   Re-factoring the ...
425
  			else
ce80ddc18   Marek Vasut   NAND: Make page, ...
426
  				nand_print_and_set_info(dev);
addb2e165   Bartlomiej Sieka   Re-factoring the ...
427
428
  			return 0;
  		}
43a2b0e76   Stefan Roese   Add board/cpu spe...
429

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

addb2e165   Bartlomiej Sieka   Re-factoring the ...
433
434
  		return 0;
  	}
c9f7351b5   Ben Gardiner   NAND: environment...
435
436
  #ifdef CONFIG_ENV_OFFSET_OOB
  	/* this command operates only on the first nand device */
ea533c260   Scott Wood   cmd_nand: some in...
437
438
  	if (strcmp(cmd, "env.oob") == 0)
  		return do_nand_env_oob(cmdtp, argc - 1, argv + 1);
c9f7351b5   Ben Gardiner   NAND: environment...
439
  #endif
ea533c260   Scott Wood   cmd_nand: some in...
440
441
442
443
444
445
  	/* 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...
446
447
  	mtd = get_nand_dev_by_index(dev);
  	if (!mtd) {
addb2e165   Bartlomiej Sieka   Re-factoring the ...
448
449
450
451
452
  		puts("
  no devices available
  ");
  		return 1;
  	}
addb2e165   Bartlomiej Sieka   Re-factoring the ...
453
454
  
  	if (strcmp(cmd, "bad") == 0) {
ea533c260   Scott Wood   cmd_nand: some in...
455
456
457
  		printf("
  Device %d bad blocks:
  ", dev);
151c06ec6   Scott Wood   mtd: nand: Remove...
458
459
  		for (off = 0; off < mtd->size; off += mtd->erasesize)
  			if (nand_block_isbad(mtd, off))
ea533c260   Scott Wood   cmd_nand: some in...
460
461
  				printf("  %08llx
  ", (unsigned long long)off);
addb2e165   Bartlomiej Sieka   Re-factoring the ...
462
463
  		return 0;
  	}
856f05441   Stefan Roese   [PATCH] NAND: Par...
464
465
466
467
468
  	/*
  	 * Syntax is:
  	 *   0    1     2       3    4
  	 *   nand erase [clean] [off size]
  	 */
304863225   Scott Wood   nand erase: .spre...
469
  	if (strncmp(cmd, "erase", 5) == 0 || strncmp(cmd, "scrub", 5) == 0) {
2255b2d20   Stefan Roese   * Several improve...
470
  		nand_erase_options_t opts;
856f05441   Stefan Roese   [PATCH] NAND: Par...
471
  		/* "clean" at index 2 means request to write cleanmarker */
3043c045d   William Juul   Whitespace cleanu...
472
  		int clean = argc > 2 && !strcmp("clean", argv[2]);
608998166   Marek Vasut   NAND: Add -y opti...
473
474
  		int scrub_yes = argc > 2 && !strcmp("-y", argv[2]);
  		int o = (clean || scrub_yes) ? 3 : 2;
304863225   Scott Wood   nand erase: .spre...
475
  		int scrub = !strncmp(cmd, "scrub", 5);
304863225   Scott Wood   nand erase: .spre...
476
477
  		int spread = 0;
  		int args = 2;
608998166   Marek Vasut   NAND: Add -y opti...
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
  		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...
494
495
496
497
498
  
  		if (cmd[5] != 0) {
  			if (!strcmp(&cmd[5], ".spread")) {
  				spread = 1;
  			} else if (!strcmp(&cmd[5], ".part")) {
304863225   Scott Wood   nand erase: .spre...
499
500
  				args = 1;
  			} else if (!strcmp(&cmd[5], ".chip")) {
304863225   Scott Wood   nand erase: .spre...
501
502
503
504
505
506
507
508
509
510
511
512
513
  				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...
514

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

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

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

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

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

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

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

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

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

3287f6d38   Benoît Thébaudeau   nand: Add torture...
669
670
  #ifdef CONFIG_CMD_NAND_TORTURE
  	if (strcmp(cmd, "torture") == 0) {
1866be7d2   Max Krummenacher   nand: extend nand...
671
672
  		loff_t endoff;
  		unsigned int failed = 0, passed = 0;
3287f6d38   Benoît Thébaudeau   nand: Add torture...
673
674
675
676
677
678
679
680
  		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...
681
682
683
684
685
686
687
688
  		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...
689

1866be7d2   Max Krummenacher   nand: extend nand...
690
691
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
  		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...
718
719
  	}
  #endif
2255b2d20   Stefan Roese   * Several improve...
720
  	if (strcmp(cmd, "markbad") == 0) {
8360b66ba   Wolfgang Denk   nand/onenand: Fix...
721
722
  		argc -= 2;
  		argv += 2;
2255b2d20   Stefan Roese   * Several improve...
723

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

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

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

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

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

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

151c06ec6   Scott Wood   mtd: nand: Remove...
919
920
921
  	cnt = mtd->writesize;
  	r = nand_read_skip_bad(mtd, offset, &cnt, NULL, mtd->size,
  			       (u_char *)addr);
addb2e165   Bartlomiej Sieka   Re-factoring the ...
922
  	if (r) {
856f05441   Stefan Roese   [PATCH] NAND: Par...
923
924
  		puts("** Read error
  ");
770605e4f   Simon Glass   bootstage: Replac...
925
  		bootstage_error(BOOTSTAGE_ID_NAND_HDR_READ);
addb2e165   Bartlomiej Sieka   Re-factoring the ...
926
927
  		return 1;
  	}
770605e4f   Simon Glass   bootstage: Replac...
928
  	bootstage_mark(BOOTSTAGE_ID_NAND_HDR_READ);
addb2e165   Bartlomiej Sieka   Re-factoring the ...
929

9a4daad0a   Marian Balakowicz   [new uImage] Upda...
930
  	switch (genimg_get_format ((void *)addr)) {
21d29f7f9   Heiko Schocher   bootm: make use o...
931
  #if defined(CONFIG_IMAGE_FORMAT_LEGACY)
d5934ad77   Marian Balakowicz   [new uImage] Add ...
932
933
  	case IMAGE_FORMAT_LEGACY:
  		hdr = (image_header_t *)addr;
770605e4f   Simon Glass   bootstage: Replac...
934
  		bootstage_mark(BOOTSTAGE_ID_NAND_TYPE);
d5934ad77   Marian Balakowicz   [new uImage] Add ...
935
  		image_print_contents (hdr);
addb2e165   Bartlomiej Sieka   Re-factoring the ...
936

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

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

09475f752   Marian Balakowicz   [new uImage] Add ...
967
968
  #if defined(CONFIG_FIT)
  	/* This cannot be done earlier, we need complete FIT image in RAM first */
3bab76a26   Marian Balakowicz   Delay FIT format ...
969
970
  	if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) {
  		if (!fit_check_format (fit_hdr)) {
770605e4f   Simon Glass   bootstage: Replac...
971
  			bootstage_error(BOOTSTAGE_ID_NAND_FIT_READ);
3bab76a26   Marian Balakowicz   Delay FIT format ...
972
973
974
975
  			puts ("** Bad FIT image format
  ");
  			return 1;
  		}
770605e4f   Simon Glass   bootstage: Replac...
976
  		bootstage_mark(BOOTSTAGE_ID_NAND_FIT_READ_OK);
3bab76a26   Marian Balakowicz   Delay FIT format ...
977
978
  		fit_print_contents (fit_hdr);
  	}
09475f752   Marian Balakowicz   [new uImage] Add ...
979
  #endif
addb2e165   Bartlomiej Sieka   Re-factoring the ...
980
981
982
  	/* Loading ok, update default load address */
  
  	load_addr = addr;
67d668bf9   Mike Frysinger   autostart: unify ...
983
  	return bootm_maybe_autostart(cmdtp, cmd);
addb2e165   Bartlomiej Sieka   Re-factoring the ...
984
  }
088f1b199   Kim Phillips   common/cmd_*.c: s...
985
986
  static int do_nandboot(cmd_tbl_t *cmdtp, int flag, int argc,
  		       char * const argv[])
856f05441   Stefan Roese   [PATCH] NAND: Par...
987
988
989
990
  {
  	char *boot_device = NULL;
  	int idx;
  	ulong addr, offset = 0;
ad92dff28   Mugunthan V N   cmd: nand: abstra...
991
  	struct mtd_info *mtd;
0c8a84916   Ladislav Michl   Separate mtdparts...
992
  #if defined(CONFIG_CMD_MTDPARTS)
856f05441   Stefan Roese   [PATCH] NAND: Par...
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
  	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 ...
1009
  				addr = simple_strtoul(argv[1], NULL, 16);
856f05441   Stefan Roese   [PATCH] NAND: Par...
1010
  			else
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
1011
  				addr = CONFIG_SYS_LOAD_ADDR;
ad92dff28   Mugunthan V N   cmd: nand: abstra...
1012
1013
1014
1015
  
  			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...
1016
1017
1018
  		}
  	}
  #endif
770605e4f   Simon Glass   bootstage: Replac...
1019
  	bootstage_mark(BOOTSTAGE_ID_NAND_PART);
856f05441   Stefan Roese   [PATCH] NAND: Par...
1020
1021
  	switch (argc) {
  	case 1:
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
1022
  		addr = CONFIG_SYS_LOAD_ADDR;
00caae6d4   Simon Glass   env: Rename geten...
1023
  		boot_device = env_get("bootdevice");
856f05441   Stefan Roese   [PATCH] NAND: Par...
1024
1025
1026
  		break;
  	case 2:
  		addr = simple_strtoul(argv[1], NULL, 16);
00caae6d4   Simon Glass   env: Rename geten...
1027
  		boot_device = env_get("bootdevice");
856f05441   Stefan Roese   [PATCH] NAND: Par...
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
  		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...
1039
  #if defined(CONFIG_CMD_MTDPARTS)
856f05441   Stefan Roese   [PATCH] NAND: Par...
1040
1041
  usage:
  #endif
770605e4f   Simon Glass   bootstage: Replac...
1042
  		bootstage_error(BOOTSTAGE_ID_NAND_SUFFIX);
4c12eeb8b   Simon Glass   Convert cmd_usage...
1043
  		return CMD_RET_USAGE;
856f05441   Stefan Roese   [PATCH] NAND: Par...
1044
  	}
770605e4f   Simon Glass   bootstage: Replac...
1045
  	bootstage_mark(BOOTSTAGE_ID_NAND_SUFFIX);
856f05441   Stefan Roese   [PATCH] NAND: Par...
1046
1047
1048
1049
1050
  
  	if (!boot_device) {
  		puts("
  ** No boot device **
  ");
770605e4f   Simon Glass   bootstage: Replac...
1051
  		bootstage_error(BOOTSTAGE_ID_NAND_BOOT_DEVICE);
856f05441   Stefan Roese   [PATCH] NAND: Par...
1052
1053
  		return 1;
  	}
770605e4f   Simon Glass   bootstage: Replac...
1054
  	bootstage_mark(BOOTSTAGE_ID_NAND_BOOT_DEVICE);
addb2e165   Bartlomiej Sieka   Re-factoring the ...
1055

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

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