Blame view

nand_spl/nand_boot.c 7.4 KB
887e2ec9e   Stefan Roese   Add support for A...
1
  /*
46f373838   Stefan Roese   nand_spl: Update ...
2
   * (C) Copyright 2006-2008
887e2ec9e   Stefan Roese   Add support for A...
3
4
   * Stefan Roese, DENX Software Engineering, sr@denx.de.
   *
1a4596601   Wolfgang Denk   Add GPL-2.0+ SPDX...
5
   * SPDX-License-Identifier:	GPL-2.0+
887e2ec9e   Stefan Roese   Add support for A...
6
7
8
9
   */
  
  #include <common.h>
  #include <nand.h>
c568f77ac   Stefan Roese   NAND: Update nand...
10
  #include <asm/io.h>
887e2ec9e   Stefan Roese   Add support for A...
11

6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
12
  static int nand_ecc_pos[] = CONFIG_SYS_NAND_ECCPOS;
42be56f53   Stefan Roese   NAND: Add ECC sup...
13

25efd99db   Scott Wood   nand_spl: store e...
14
15
16
  #define ECCSTEPS	(CONFIG_SYS_NAND_PAGE_SIZE / \
  					CONFIG_SYS_NAND_ECCSIZE)
  #define ECCTOTAL	(ECCSTEPS * CONFIG_SYS_NAND_ECCBYTES)
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
17
  #if (CONFIG_SYS_NAND_PAGE_SIZE <= 512)
46f373838   Stefan Roese   nand_spl: Update ...
18
19
20
  /*
   * NAND command for small page NAND devices (512)
   */
42be56f53   Stefan Roese   NAND: Add ECC sup...
21
  static int nand_command(struct mtd_info *mtd, int block, int page, int offs, u8 cmd)
887e2ec9e   Stefan Roese   Add support for A...
22
  {
511d0c72b   Wolfgang Denk   Coding style cleanup
23
  	struct nand_chip *this = mtd->priv;
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
24
  	int page_addr = page + block * CONFIG_SYS_NAND_PAGE_COUNT;
42be56f53   Stefan Roese   NAND: Add ECC sup...
25

e29816f33   Stefan Roese   nand_spl: nand_bo...
26
27
  	while (!this->dev_ready(mtd))
  		;
887e2ec9e   Stefan Roese   Add support for A...
28
29
  
  	/* Begin command latch cycle */
4f32d7760   Scott Wood   NAND boot: Update...
30
  	this->cmd_ctrl(mtd, cmd, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
887e2ec9e   Stefan Roese   Add support for A...
31
  	/* Set ALE and clear CLE to start address cycle */
887e2ec9e   Stefan Roese   Add support for A...
32
  	/* Column address */
4f32d7760   Scott Wood   NAND boot: Update...
33
  	this->cmd_ctrl(mtd, offs, NAND_CTRL_ALE | NAND_CTRL_CHANGE);
1dac3a518   Scott Wood   nand_spl: Fix cmd...
34
35
36
  	this->cmd_ctrl(mtd, page_addr & 0xff, NAND_CTRL_ALE); /* A[16:9] */
  	this->cmd_ctrl(mtd, (page_addr >> 8) & 0xff,
  		       NAND_CTRL_ALE); /* A[24:17] */
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
37
  #ifdef CONFIG_SYS_NAND_4_ADDR_CYCLE
887e2ec9e   Stefan Roese   Add support for A...
38
  	/* One more address cycle for devices > 32MiB */
1dac3a518   Scott Wood   nand_spl: Fix cmd...
39
40
  	this->cmd_ctrl(mtd, (page_addr >> 16) & 0x0f,
  		       NAND_CTRL_ALE); /* A[28:25] */
887e2ec9e   Stefan Roese   Add support for A...
41
42
  #endif
  	/* Latch in address */
c568f77ac   Stefan Roese   NAND: Update nand...
43
  	this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
887e2ec9e   Stefan Roese   Add support for A...
44
45
46
47
  
  	/*
  	 * Wait a while for the data to be ready
  	 */
a9c847cb3   Stefan Roese   nand_spl: nand_bo...
48
49
  	while (!this->dev_ready(mtd))
  		;
887e2ec9e   Stefan Roese   Add support for A...
50

42be56f53   Stefan Roese   NAND: Add ECC sup...
51
52
  	return 0;
  }
46f373838   Stefan Roese   nand_spl: Update ...
53
54
55
56
57
58
59
  #else
  /*
   * NAND command for large page NAND devices (2k)
   */
  static int nand_command(struct mtd_info *mtd, int block, int page, int offs, u8 cmd)
  {
  	struct nand_chip *this = mtd->priv;
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
60
  	int page_addr = page + block * CONFIG_SYS_NAND_PAGE_COUNT;
837097831   Alex Waterman   Decreases code si...
61
62
  	void (*hwctrl)(struct mtd_info *mtd, int cmd,
  			unsigned int ctrl) = this->cmd_ctrl;
46f373838   Stefan Roese   nand_spl: Update ...
63

a9c847cb3   Stefan Roese   nand_spl: nand_bo...
64
65
  	while (!this->dev_ready(mtd))
  		;
46f373838   Stefan Roese   nand_spl: Update ...
66
67
68
  
  	/* Emulate NAND_CMD_READOOB */
  	if (cmd == NAND_CMD_READOOB) {
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
69
  		offs += CONFIG_SYS_NAND_PAGE_SIZE;
46f373838   Stefan Roese   nand_spl: Update ...
70
71
  		cmd = NAND_CMD_READ0;
  	}
65a9db7be   Alex Waterman   nand_spl: Fix lar...
72
73
74
  	/* Shift the offset from byte addressing to word addressing. */
  	if (this->options & NAND_BUSWIDTH_16)
  		offs >>= 1;
46f373838   Stefan Roese   nand_spl: Update ...
75
  	/* Begin command latch cycle */
837097831   Alex Waterman   Decreases code si...
76
  	hwctrl(mtd, cmd, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
46f373838   Stefan Roese   nand_spl: Update ...
77
  	/* Set ALE and clear CLE to start address cycle */
46f373838   Stefan Roese   nand_spl: Update ...
78
  	/* Column address */
837097831   Alex Waterman   Decreases code si...
79
  	hwctrl(mtd, offs & 0xff,
4b0708093   Wolfgang Denk   Coding Style clea...
80
  		       NAND_CTRL_ALE | NAND_CTRL_CHANGE); /* A[7:0] */
837097831   Alex Waterman   Decreases code si...
81
  	hwctrl(mtd, (offs >> 8) & 0xff, NAND_CTRL_ALE); /* A[11:9] */
46f373838   Stefan Roese   nand_spl: Update ...
82
  	/* Row address */
837097831   Alex Waterman   Decreases code si...
83
84
  	hwctrl(mtd, (page_addr & 0xff), NAND_CTRL_ALE); /* A[19:12] */
  	hwctrl(mtd, ((page_addr >> 8) & 0xff),
1dac3a518   Scott Wood   nand_spl: Fix cmd...
85
  		       NAND_CTRL_ALE); /* A[27:20] */
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
86
  #ifdef CONFIG_SYS_NAND_5_ADDR_CYCLE
46f373838   Stefan Roese   nand_spl: Update ...
87
  	/* One more address cycle for devices > 128MiB */
837097831   Alex Waterman   Decreases code si...
88
  	hwctrl(mtd, (page_addr >> 16) & 0x0f,
1dac3a518   Scott Wood   nand_spl: Fix cmd...
89
  		       NAND_CTRL_ALE); /* A[31:28] */
46f373838   Stefan Roese   nand_spl: Update ...
90
91
  #endif
  	/* Latch in address */
837097831   Alex Waterman   Decreases code si...
92
  	hwctrl(mtd, NAND_CMD_READSTART,
4b0708093   Wolfgang Denk   Coding Style clea...
93
  		       NAND_CTRL_CLE | NAND_CTRL_CHANGE);
837097831   Alex Waterman   Decreases code si...
94
  	hwctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
46f373838   Stefan Roese   nand_spl: Update ...
95
96
97
98
  
  	/*
  	 * Wait a while for the data to be ready
  	 */
a9c847cb3   Stefan Roese   nand_spl: nand_bo...
99
100
  	while (!this->dev_ready(mtd))
  		;
46f373838   Stefan Roese   nand_spl: Update ...
101
102
103
104
  
  	return 0;
  }
  #endif
42be56f53   Stefan Roese   NAND: Add ECC sup...
105
106
107
108
  
  static int nand_is_bad_block(struct mtd_info *mtd, int block)
  {
  	struct nand_chip *this = mtd->priv;
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
109
  	nand_command(mtd, block, 0, CONFIG_SYS_NAND_BAD_BLOCK_POS, NAND_CMD_READOOB);
42be56f53   Stefan Roese   NAND: Add ECC sup...
110

887e2ec9e   Stefan Roese   Add support for A...
111
  	/*
eced4626e   Alex Waterman   NAND: Add 16bit N...
112
  	 * Read one byte (or two if it's a 16 bit chip).
887e2ec9e   Stefan Roese   Add support for A...
113
  	 */
eced4626e   Alex Waterman   NAND: Add 16bit N...
114
115
116
117
118
119
120
  	if (this->options & NAND_BUSWIDTH_16) {
  		if (readw(this->IO_ADDR_R) != 0xffff)
  			return 1;
  	} else {
  		if (readb(this->IO_ADDR_R) != 0xff)
  			return 1;
  	}
887e2ec9e   Stefan Roese   Add support for A...
121
122
123
  
  	return 0;
  }
dc7cd8e59   Heiko Schocher   spl, nand: add 4b...
124
125
126
127
  #if defined(CONFIG_SYS_NAND_4BIT_HW_ECC_OOBFIRST)
  static int nand_read_page(struct mtd_info *mtd, int block, int page, uchar *dst)
  {
  	struct nand_chip *this = mtd->priv;
25efd99db   Scott Wood   nand_spl: store e...
128
129
130
  	u_char ecc_calc[ECCTOTAL];
  	u_char ecc_code[ECCTOTAL];
  	u_char oob_data[CONFIG_SYS_NAND_OOBSIZE];
dc7cd8e59   Heiko Schocher   spl, nand: add 4b...
131
132
133
  	int i;
  	int eccsize = CONFIG_SYS_NAND_ECCSIZE;
  	int eccbytes = CONFIG_SYS_NAND_ECCBYTES;
25efd99db   Scott Wood   nand_spl: store e...
134
  	int eccsteps = ECCSTEPS;
dc7cd8e59   Heiko Schocher   spl, nand: add 4b...
135
  	uint8_t *p = dst;
dc7cd8e59   Heiko Schocher   spl, nand: add 4b...
136

dc7cd8e59   Heiko Schocher   spl, nand: add 4b...
137
138
139
140
141
  	nand_command(mtd, block, page, 0, NAND_CMD_READOOB);
  	this->read_buf(mtd, oob_data, CONFIG_SYS_NAND_OOBSIZE);
  	nand_command(mtd, block, page, 0, NAND_CMD_READ0);
  
  	/* Pick the ECC bytes out of the oob data */
25efd99db   Scott Wood   nand_spl: store e...
142
  	for (i = 0; i < ECCTOTAL; i++)
dc7cd8e59   Heiko Schocher   spl, nand: add 4b...
143
144
145
146
147
148
149
  		ecc_code[i] = oob_data[nand_ecc_pos[i]];
  
  
  	for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
  		this->ecc.hwctl(mtd, NAND_ECC_READ);
  		this->read_buf(mtd, p, eccsize);
  		this->ecc.calculate(mtd, p, &ecc_calc[i]);
40a0682d4   Anatolij Gustschin   nand_spl/nand_boo...
150
  		this->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
dc7cd8e59   Heiko Schocher   spl, nand: add 4b...
151
152
153
154
155
  	}
  
  	return 0;
  }
  #else
887e2ec9e   Stefan Roese   Add support for A...
156
157
  static int nand_read_page(struct mtd_info *mtd, int block, int page, uchar *dst)
  {
511d0c72b   Wolfgang Denk   Coding style cleanup
158
  	struct nand_chip *this = mtd->priv;
25efd99db   Scott Wood   nand_spl: store e...
159
160
161
  	u_char ecc_calc[ECCTOTAL];
  	u_char ecc_code[ECCTOTAL];
  	u_char oob_data[CONFIG_SYS_NAND_OOBSIZE];
887e2ec9e   Stefan Roese   Add support for A...
162
  	int i;
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
163
164
  	int eccsize = CONFIG_SYS_NAND_ECCSIZE;
  	int eccbytes = CONFIG_SYS_NAND_ECCBYTES;
25efd99db   Scott Wood   nand_spl: store e...
165
  	int eccsteps = ECCSTEPS;
42be56f53   Stefan Roese   NAND: Add ECC sup...
166
  	uint8_t *p = dst;
887e2ec9e   Stefan Roese   Add support for A...
167

42be56f53   Stefan Roese   NAND: Add ECC sup...
168
  	nand_command(mtd, block, page, 0, NAND_CMD_READ0);
887e2ec9e   Stefan Roese   Add support for A...
169

42be56f53   Stefan Roese   NAND: Add ECC sup...
170
  	for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
c568f77ac   Stefan Roese   NAND: Update nand...
171
  		this->ecc.hwctl(mtd, NAND_ECC_READ);
42be56f53   Stefan Roese   NAND: Add ECC sup...
172
  		this->read_buf(mtd, p, eccsize);
c568f77ac   Stefan Roese   NAND: Update nand...
173
  		this->ecc.calculate(mtd, p, &ecc_calc[i]);
42be56f53   Stefan Roese   NAND: Add ECC sup...
174
  	}
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
175
  	this->read_buf(mtd, oob_data, CONFIG_SYS_NAND_OOBSIZE);
42be56f53   Stefan Roese   NAND: Add ECC sup...
176
177
  
  	/* Pick the ECC bytes out of the oob data */
25efd99db   Scott Wood   nand_spl: store e...
178
  	for (i = 0; i < ECCTOTAL; i++)
42be56f53   Stefan Roese   NAND: Add ECC sup...
179
  		ecc_code[i] = oob_data[nand_ecc_pos[i]];
25efd99db   Scott Wood   nand_spl: store e...
180
  	eccsteps = ECCSTEPS;
42be56f53   Stefan Roese   NAND: Add ECC sup...
181
182
183
184
185
186
187
  	p = dst;
  
  	for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
  		/* No chance to do something with the possible error message
  		 * from correct_data(). We just hope that all possible errors
  		 * are corrected by this routine.
  		 */
6d68621ce   Stefan Roese   nand_boot.c: Fix ...
188
  		this->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
42be56f53   Stefan Roese   NAND: Add ECC sup...
189
  	}
887e2ec9e   Stefan Roese   Add support for A...
190
191
192
  
  	return 0;
  }
dc7cd8e59   Heiko Schocher   spl, nand: add 4b...
193
  #endif /* #if defined(CONFIG_SYS_NAND_4BIT_HW_ECC_OOBFIRST) */
887e2ec9e   Stefan Roese   Add support for A...
194

aa646643b   Guennadi Liakhovetski   nand_spl: Support...
195
  static int nand_load(struct mtd_info *mtd, unsigned int offs,
4b0708093   Wolfgang Denk   Coding Style clea...
196
  		     unsigned int uboot_size, uchar *dst)
887e2ec9e   Stefan Roese   Add support for A...
197
  {
aa646643b   Guennadi Liakhovetski   nand_spl: Support...
198
199
  	unsigned int block, lastblock;
  	unsigned int page;
887e2ec9e   Stefan Roese   Add support for A...
200
201
  
  	/*
aa646643b   Guennadi Liakhovetski   nand_spl: Support...
202
  	 * offs has to be aligned to a page address!
887e2ec9e   Stefan Roese   Add support for A...
203
  	 */
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
204
205
206
  	block = offs / CONFIG_SYS_NAND_BLOCK_SIZE;
  	lastblock = (offs + uboot_size - 1) / CONFIG_SYS_NAND_BLOCK_SIZE;
  	page = (offs % CONFIG_SYS_NAND_BLOCK_SIZE) / CONFIG_SYS_NAND_PAGE_SIZE;
887e2ec9e   Stefan Roese   Add support for A...
207

aa646643b   Guennadi Liakhovetski   nand_spl: Support...
208
  	while (block <= lastblock) {
887e2ec9e   Stefan Roese   Add support for A...
209
210
211
212
  		if (!nand_is_bad_block(mtd, block)) {
  			/*
  			 * Skip bad blocks
  			 */
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
213
  			while (page < CONFIG_SYS_NAND_PAGE_COUNT) {
887e2ec9e   Stefan Roese   Add support for A...
214
  				nand_read_page(mtd, block, page, dst);
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
215
  				dst += CONFIG_SYS_NAND_PAGE_SIZE;
aa646643b   Guennadi Liakhovetski   nand_spl: Support...
216
  				page++;
887e2ec9e   Stefan Roese   Add support for A...
217
  			}
aa646643b   Guennadi Liakhovetski   nand_spl: Support...
218
219
220
  			page = 0;
  		} else {
  			lastblock++;
887e2ec9e   Stefan Roese   Add support for A...
221
222
223
224
225
226
227
  		}
  
  		block++;
  	}
  
  	return 0;
  }
64852d09e   Stefan Roese   ppc4xx/NAND_SPL: ...
228
229
230
231
232
  /*
   * The main entry for NAND booting. It's necessary that SDRAM is already
   * configured and available since this code loads the main U-Boot image
   * from NAND into SDRAM and starts it from there.
   */
887e2ec9e   Stefan Roese   Add support for A...
233
234
  void nand_boot(void)
  {
887e2ec9e   Stefan Roese   Add support for A...
235
236
  	struct nand_chip nand_chip;
  	nand_info_t nand_info;
e4c095085   Scott Wood   NAND boot: MPC831...
237
  	__attribute__((noreturn)) void (*uboot)(void);
887e2ec9e   Stefan Roese   Add support for A...
238
239
  
  	/*
887e2ec9e   Stefan Roese   Add support for A...
240
241
  	 * Init board specific nand support
  	 */
48571ff00   Sughosh Ganu   Add board support...
242
  	nand_chip.select_chip = NULL;
887e2ec9e   Stefan Roese   Add support for A...
243
  	nand_info.priv = &nand_chip;
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
244
  	nand_chip.IO_ADDR_R = nand_chip.IO_ADDR_W = (void  __iomem *)CONFIG_SYS_NAND_BASE;
887e2ec9e   Stefan Roese   Add support for A...
245
  	nand_chip.dev_ready = NULL;	/* preset to NULL */
a89a99015   Stefan Roese   nand_spl: nand_bo...
246
  	nand_chip.options = 0;
887e2ec9e   Stefan Roese   Add support for A...
247
  	board_nand_init(&nand_chip);
aa646643b   Guennadi Liakhovetski   nand_spl: Support...
248
249
  	if (nand_chip.select_chip)
  		nand_chip.select_chip(&nand_info, 0);
887e2ec9e   Stefan Roese   Add support for A...
250
251
252
  	/*
  	 * Load U-Boot image from NAND into RAM
  	 */
6d68621ce   Stefan Roese   nand_boot.c: Fix ...
253
254
  	nand_load(&nand_info, CONFIG_SYS_NAND_U_BOOT_OFFS, CONFIG_SYS_NAND_U_BOOT_SIZE,
  		  (uchar *)CONFIG_SYS_NAND_U_BOOT_DST);
887e2ec9e   Stefan Roese   Add support for A...
255

b74ab7373   Guennadi Liakhovetski   nand_spl: read en...
256
257
258
259
260
261
262
263
264
  #ifdef CONFIG_NAND_ENV_DST
  	nand_load(&nand_info, CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE,
  		  (uchar *)CONFIG_NAND_ENV_DST);
  
  #ifdef CONFIG_ENV_OFFSET_REDUND
  	nand_load(&nand_info, CONFIG_ENV_OFFSET_REDUND, CONFIG_ENV_SIZE,
  		  (uchar *)CONFIG_NAND_ENV_DST + CONFIG_ENV_SIZE);
  #endif
  #endif
aa646643b   Guennadi Liakhovetski   nand_spl: Support...
265
266
  	if (nand_chip.select_chip)
  		nand_chip.select_chip(&nand_info, -1);
887e2ec9e   Stefan Roese   Add support for A...
267
268
269
  	/*
  	 * Jump to U-Boot image
  	 */
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
270
  	uboot = (void *)CONFIG_SYS_NAND_U_BOOT_START;
887e2ec9e   Stefan Roese   Add support for A...
271
272
  	(*uboot)();
  }