]>
Commit | Line | Data |
---|---|---|
c74b2108 SK |
1 | /* |
2 | * NAND driver for TI DaVinci based boards. | |
3 | * | |
4 | * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> | |
5 | * | |
6 | * Based on Linux DaVinci NAND driver by TI. Original copyright follows: | |
7 | */ | |
8 | ||
9 | /* | |
10 | * | |
11 | * linux/drivers/mtd/nand/nand_davinci.c | |
12 | * | |
13 | * NAND Flash Driver | |
14 | * | |
15 | * Copyright (C) 2006 Texas Instruments. | |
16 | * | |
17 | * ---------------------------------------------------------------------------- | |
18 | * | |
19 | * This program is free software; you can redistribute it and/or modify | |
20 | * it under the terms of the GNU General Public License as published by | |
21 | * the Free Software Foundation; either version 2 of the License, or | |
22 | * (at your option) any later version. | |
23 | * | |
24 | * This program is distributed in the hope that it will be useful, | |
25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
27 | * GNU General Public License for more details. | |
28 | * | |
29 | * You should have received a copy of the GNU General Public License | |
30 | * along with this program; if not, write to the Free Software | |
31 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
32 | * ---------------------------------------------------------------------------- | |
33 | * | |
34 | * Overview: | |
35 | * This is a device driver for the NAND flash device found on the | |
36 | * DaVinci board which utilizes the Samsung k9k2g08 part. | |
37 | * | |
38 | Modifications: | |
39 | ver. 1.0: Feb 2005, Vinod/Sudhakar | |
40 | - | |
41 | * | |
42 | */ | |
43 | ||
44 | #include <common.h> | |
cfa460ad | 45 | #include <asm/io.h> |
c74b2108 | 46 | |
6d0f6bcf | 47 | #ifdef CONFIG_SYS_USE_NAND |
cc4a0cee | 48 | #if !defined(CONFIG_NAND_LEGACY) |
c74b2108 SK |
49 | |
50 | #include <nand.h> | |
51 | #include <asm/arch/nand_defs.h> | |
52 | #include <asm/arch/emif_defs.h> | |
53 | ||
6d0f6bcf | 54 | extern struct nand_chip nand_dev_desc[CONFIG_SYS_MAX_NAND_DEVICE]; |
c74b2108 | 55 | |
cfa460ad | 56 | static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) |
c74b2108 SK |
57 | { |
58 | struct nand_chip *this = mtd->priv; | |
59 | u_int32_t IO_ADDR_W = (u_int32_t)this->IO_ADDR_W; | |
60 | ||
61 | IO_ADDR_W &= ~(MASK_ALE|MASK_CLE); | |
62 | ||
cfa460ad WJ |
63 | if (ctrl & NAND_CTRL_CHANGE) { |
64 | if ( ctrl & NAND_CLE ) | |
c74b2108 | 65 | IO_ADDR_W |= MASK_CLE; |
cfa460ad | 66 | if ( ctrl & NAND_ALE ) |
c74b2108 | 67 | IO_ADDR_W |= MASK_ALE; |
cfa460ad | 68 | this->IO_ADDR_W = (void __iomem *) IO_ADDR_W; |
c74b2108 SK |
69 | } |
70 | ||
5e1dae5c | 71 | if (cmd != NAND_CMD_NONE) |
cfa460ad | 72 | writeb(cmd, this->IO_ADDR_W); |
c74b2108 SK |
73 | } |
74 | ||
75 | /* Set WP on deselect, write enable on select */ | |
76 | static void nand_davinci_select_chip(struct mtd_info *mtd, int chip) | |
77 | { | |
78 | #define GPIO_SET_DATA01 0x01c67018 | |
79 | #define GPIO_CLR_DATA01 0x01c6701c | |
80 | #define GPIO_NAND_WP (1 << 4) | |
81 | #ifdef SONATA_BOARD_GPIOWP | |
82 | if (chip < 0) { | |
83 | REG(GPIO_CLR_DATA01) |= GPIO_NAND_WP; | |
84 | } else { | |
85 | REG(GPIO_SET_DATA01) |= GPIO_NAND_WP; | |
86 | } | |
87 | #endif | |
88 | } | |
89 | ||
6d0f6bcf JCPV |
90 | #ifdef CONFIG_SYS_NAND_HW_ECC |
91 | #ifdef CONFIG_SYS_DAVINCI_BROKEN_ECC | |
9b05aa78 HV |
92 | /* Linux-compatible ECC uses MTD defaults. */ |
93 | /* These layouts are not compatible with Linux or RBL/UBL. */ | |
6d0f6bcf | 94 | #ifdef CONFIG_SYS_NAND_LARGEPAGE |
fe56a277 | 95 | static struct nand_ecclayout davinci_nand_ecclayout = { |
c74b2108 SK |
96 | .eccbytes = 12, |
97 | .eccpos = {8, 9, 10, 24, 25, 26, 40, 41, 42, 56, 57, 58}, | |
fe56a277 SK |
98 | .oobfree = { |
99 | {.offset = 2, .length = 6}, | |
100 | {.offset = 12, .length = 12}, | |
101 | {.offset = 28, .length = 12}, | |
102 | {.offset = 44, .length = 12}, | |
103 | {.offset = 60, .length = 4} | |
104 | } | |
c74b2108 | 105 | }; |
6d0f6bcf | 106 | #elif defined(CONFIG_SYS_NAND_SMALLPAGE) |
fe56a277 | 107 | static struct nand_ecclayout davinci_nand_ecclayout = { |
c74b2108 SK |
108 | .eccbytes = 3, |
109 | .eccpos = {0, 1, 2}, | |
fe56a277 SK |
110 | .oobfree = { |
111 | {.offset = 6, .length = 2}, | |
112 | {.offset = 8, .length = 8} | |
113 | } | |
c74b2108 SK |
114 | }; |
115 | #else | |
6d0f6bcf | 116 | #error "Either CONFIG_SYS_NAND_LARGEPAGE or CONFIG_SYS_NAND_SMALLPAGE must be defined!" |
c74b2108 | 117 | #endif |
6d0f6bcf | 118 | #endif /* CONFIG_SYS_DAVINCI_BROKEN_ECC */ |
c74b2108 SK |
119 | |
120 | static void nand_davinci_enable_hwecc(struct mtd_info *mtd, int mode) | |
121 | { | |
122 | emifregs emif_addr; | |
123 | int dummy; | |
124 | ||
125 | emif_addr = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE; | |
126 | ||
127 | dummy = emif_addr->NANDF1ECC; | |
128 | dummy = emif_addr->NANDF2ECC; | |
129 | dummy = emif_addr->NANDF3ECC; | |
130 | dummy = emif_addr->NANDF4ECC; | |
131 | ||
950a3924 | 132 | emif_addr->NANDFCR |= (1 << 8); |
c74b2108 SK |
133 | } |
134 | ||
135 | static u_int32_t nand_davinci_readecc(struct mtd_info *mtd, u_int32_t region) | |
136 | { | |
137 | u_int32_t ecc = 0; | |
138 | emifregs emif_base_addr; | |
139 | ||
140 | emif_base_addr = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE; | |
141 | ||
142 | if (region == 1) | |
143 | ecc = emif_base_addr->NANDF1ECC; | |
144 | else if (region == 2) | |
145 | ecc = emif_base_addr->NANDF2ECC; | |
146 | else if (region == 3) | |
147 | ecc = emif_base_addr->NANDF3ECC; | |
148 | else if (region == 4) | |
149 | ecc = emif_base_addr->NANDF4ECC; | |
150 | ||
151 | return(ecc); | |
152 | } | |
153 | ||
154 | static int nand_davinci_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code) | |
155 | { | |
156 | u_int32_t tmp; | |
6d0f6bcf | 157 | #ifdef CONFIG_SYS_DAVINCI_BROKEN_ECC |
9b05aa78 HV |
158 | /* |
159 | * This is not how you should read ECCs on large page Davinci devices. | |
160 | * The region parameter gets you ECCs for flash chips on different chip | |
161 | * selects, not the 4x512 byte pages in a 2048 byte page. | |
162 | * | |
163 | * Preserved for backwards compatibility though. | |
164 | */ | |
165 | ||
c74b2108 SK |
166 | int region, n; |
167 | struct nand_chip *this = mtd->priv; | |
168 | ||
cfa460ad | 169 | n = (this->ecc.size/512); |
c74b2108 | 170 | |
950a3924 | 171 | region = 1; |
c74b2108 SK |
172 | while (n--) { |
173 | tmp = nand_davinci_readecc(mtd, region); | |
174 | *ecc_code++ = tmp; | |
175 | *ecc_code++ = tmp >> 16; | |
176 | *ecc_code++ = ((tmp >> 8) & 0x0f) | ((tmp >> 20) & 0xf0); | |
177 | region++; | |
178 | } | |
9b05aa78 HV |
179 | #else |
180 | const int region = 1; | |
181 | ||
182 | tmp = nand_davinci_readecc(mtd, region); | |
183 | ||
184 | /* Squeeze 4 bytes ECC into 3 bytes by removing RESERVED bits | |
185 | * and shifting. RESERVED bits are 31 to 28 and 15 to 12. */ | |
186 | tmp = (tmp & 0x00000fff) | ((tmp & 0x0fff0000) >> 4); | |
187 | ||
188 | /* Invert so that erased block ECC is correct */ | |
189 | tmp = ~tmp; | |
190 | ||
191 | *ecc_code++ = tmp; | |
192 | *ecc_code++ = tmp >> 8; | |
193 | *ecc_code++ = tmp >> 16; | |
6d0f6bcf | 194 | #endif /* CONFIG_SYS_DAVINCI_BROKEN_ECC */ |
c74b2108 SK |
195 | return(0); |
196 | } | |
197 | ||
6d0f6bcf | 198 | #ifdef CONFIG_SYS_DAVINCI_BROKEN_ECC |
c74b2108 SK |
199 | static void nand_davinci_gen_true_ecc(u_int8_t *ecc_buf) |
200 | { | |
201 | u_int32_t tmp = ecc_buf[0] | (ecc_buf[1] << 16) | ((ecc_buf[2] & 0xf0) << 20) | ((ecc_buf[2] & 0x0f) << 8); | |
202 | ||
203 | ecc_buf[0] = ~(P64o(tmp) | P64e(tmp) | P32o(tmp) | P32e(tmp) | P16o(tmp) | P16e(tmp) | P8o(tmp) | P8e(tmp)); | |
204 | ecc_buf[1] = ~(P1024o(tmp) | P1024e(tmp) | P512o(tmp) | P512e(tmp) | P256o(tmp) | P256e(tmp) | P128o(tmp) | P128e(tmp)); | |
205 | ecc_buf[2] = ~( P4o(tmp) | P4e(tmp) | P2o(tmp) | P2e(tmp) | P1o(tmp) | P1e(tmp) | P2048o(tmp) | P2048e(tmp)); | |
206 | } | |
207 | ||
208 | static int nand_davinci_compare_ecc(u_int8_t *ecc_nand, u_int8_t *ecc_calc, u_int8_t *page_data) | |
209 | { | |
210 | u_int32_t i; | |
211 | u_int8_t tmp0_bit[8], tmp1_bit[8], tmp2_bit[8]; | |
212 | u_int8_t comp0_bit[8], comp1_bit[8], comp2_bit[8]; | |
213 | u_int8_t ecc_bit[24]; | |
214 | u_int8_t ecc_sum = 0; | |
215 | u_int8_t find_bit = 0; | |
216 | u_int32_t find_byte = 0; | |
217 | int is_ecc_ff; | |
218 | ||
219 | is_ecc_ff = ((*ecc_nand == 0xff) && (*(ecc_nand + 1) == 0xff) && (*(ecc_nand + 2) == 0xff)); | |
220 | ||
221 | nand_davinci_gen_true_ecc(ecc_nand); | |
222 | nand_davinci_gen_true_ecc(ecc_calc); | |
223 | ||
224 | for (i = 0; i <= 2; i++) { | |
225 | *(ecc_nand + i) = ~(*(ecc_nand + i)); | |
226 | *(ecc_calc + i) = ~(*(ecc_calc + i)); | |
227 | } | |
228 | ||
229 | for (i = 0; i < 8; i++) { | |
230 | tmp0_bit[i] = *ecc_nand % 2; | |
231 | *ecc_nand = *ecc_nand / 2; | |
232 | } | |
233 | ||
234 | for (i = 0; i < 8; i++) { | |
235 | tmp1_bit[i] = *(ecc_nand + 1) % 2; | |
236 | *(ecc_nand + 1) = *(ecc_nand + 1) / 2; | |
237 | } | |
238 | ||
239 | for (i = 0; i < 8; i++) { | |
240 | tmp2_bit[i] = *(ecc_nand + 2) % 2; | |
241 | *(ecc_nand + 2) = *(ecc_nand + 2) / 2; | |
242 | } | |
243 | ||
244 | for (i = 0; i < 8; i++) { | |
245 | comp0_bit[i] = *ecc_calc % 2; | |
246 | *ecc_calc = *ecc_calc / 2; | |
247 | } | |
248 | ||
249 | for (i = 0; i < 8; i++) { | |
250 | comp1_bit[i] = *(ecc_calc + 1) % 2; | |
251 | *(ecc_calc + 1) = *(ecc_calc + 1) / 2; | |
252 | } | |
253 | ||
254 | for (i = 0; i < 8; i++) { | |
255 | comp2_bit[i] = *(ecc_calc + 2) % 2; | |
256 | *(ecc_calc + 2) = *(ecc_calc + 2) / 2; | |
257 | } | |
258 | ||
259 | for (i = 0; i< 6; i++) | |
260 | ecc_bit[i] = tmp2_bit[i + 2] ^ comp2_bit[i + 2]; | |
261 | ||
262 | for (i = 0; i < 8; i++) | |
263 | ecc_bit[i + 6] = tmp0_bit[i] ^ comp0_bit[i]; | |
264 | ||
265 | for (i = 0; i < 8; i++) | |
266 | ecc_bit[i + 14] = tmp1_bit[i] ^ comp1_bit[i]; | |
267 | ||
268 | ecc_bit[22] = tmp2_bit[0] ^ comp2_bit[0]; | |
269 | ecc_bit[23] = tmp2_bit[1] ^ comp2_bit[1]; | |
270 | ||
271 | for (i = 0; i < 24; i++) | |
272 | ecc_sum += ecc_bit[i]; | |
273 | ||
274 | switch (ecc_sum) { | |
275 | case 0: | |
276 | /* Not reached because this function is not called if | |
277 | ECC values are equal */ | |
278 | return 0; | |
279 | case 1: | |
280 | /* Uncorrectable error */ | |
3167c538 SW |
281 | MTDDEBUG (MTD_DEBUG_LEVEL0, |
282 | "ECC UNCORRECTED_ERROR 1\n"); | |
c74b2108 SK |
283 | return(-1); |
284 | case 12: | |
285 | /* Correctable error */ | |
286 | find_byte = (ecc_bit[23] << 8) + | |
287 | (ecc_bit[21] << 7) + | |
288 | (ecc_bit[19] << 6) + | |
289 | (ecc_bit[17] << 5) + | |
290 | (ecc_bit[15] << 4) + | |
291 | (ecc_bit[13] << 3) + | |
292 | (ecc_bit[11] << 2) + | |
293 | (ecc_bit[9] << 1) + | |
294 | ecc_bit[7]; | |
295 | ||
296 | find_bit = (ecc_bit[5] << 2) + (ecc_bit[3] << 1) + ecc_bit[1]; | |
297 | ||
3167c538 SW |
298 | MTDDEBUG (MTD_DEBUG_LEVEL0, "Correcting single bit ECC " |
299 | "error at offset: %d, bit: %d\n", | |
300 | find_byte, find_bit); | |
c74b2108 SK |
301 | |
302 | page_data[find_byte] ^= (1 << find_bit); | |
303 | ||
304 | return(0); | |
305 | default: | |
306 | if (is_ecc_ff) { | |
307 | if (ecc_calc[0] == 0 && ecc_calc[1] == 0 && ecc_calc[2] == 0) | |
308 | return(0); | |
309 | } | |
3167c538 SW |
310 | MTDDEBUG (MTD_DEBUG_LEVEL0, |
311 | "UNCORRECTED_ERROR default\n"); | |
c74b2108 SK |
312 | return(-1); |
313 | } | |
314 | } | |
6d0f6bcf | 315 | #endif /* CONFIG_SYS_DAVINCI_BROKEN_ECC */ |
c74b2108 SK |
316 | |
317 | static int nand_davinci_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc) | |
318 | { | |
9b05aa78 | 319 | struct nand_chip *this = mtd->priv; |
6d0f6bcf | 320 | #ifdef CONFIG_SYS_DAVINCI_BROKEN_ECC |
c74b2108 SK |
321 | int block_count = 0, i, rc; |
322 | ||
cfa460ad | 323 | block_count = (this->ecc.size/512); |
c74b2108 SK |
324 | for (i = 0; i < block_count; i++) { |
325 | if (memcmp(read_ecc, calc_ecc, 3) != 0) { | |
326 | rc = nand_davinci_compare_ecc(read_ecc, calc_ecc, dat); | |
327 | if (rc < 0) { | |
328 | return(rc); | |
329 | } | |
330 | } | |
331 | read_ecc += 3; | |
332 | calc_ecc += 3; | |
333 | dat += 512; | |
334 | } | |
9b05aa78 HV |
335 | #else |
336 | u_int32_t ecc_nand = read_ecc[0] | (read_ecc[1] << 8) | | |
337 | (read_ecc[2] << 16); | |
338 | u_int32_t ecc_calc = calc_ecc[0] | (calc_ecc[1] << 8) | | |
339 | (calc_ecc[2] << 16); | |
340 | u_int32_t diff = ecc_calc ^ ecc_nand; | |
341 | ||
342 | if (diff) { | |
343 | if ((((diff >> 12) ^ diff) & 0xfff) == 0xfff) { | |
344 | /* Correctable error */ | |
345 | if ((diff >> (12 + 3)) < this->ecc.size) { | |
346 | uint8_t find_bit = 1 << ((diff >> 12) & 7); | |
347 | uint32_t find_byte = diff >> (12 + 3); | |
348 | ||
349 | dat[find_byte] ^= find_bit; | |
350 | MTDDEBUG(MTD_DEBUG_LEVEL0, "Correcting single " | |
351 | "bit ECC error at offset: %d, bit: " | |
352 | "%d\n", find_byte, find_bit); | |
353 | return 1; | |
354 | } else { | |
355 | return -1; | |
356 | } | |
357 | } else if (!(diff & (diff - 1))) { | |
358 | /* Single bit ECC error in the ECC itself, | |
359 | nothing to fix */ | |
360 | MTDDEBUG(MTD_DEBUG_LEVEL0, "Single bit ECC error in " | |
361 | "ECC.\n"); | |
362 | return 1; | |
363 | } else { | |
364 | /* Uncorrectable error */ | |
365 | MTDDEBUG(MTD_DEBUG_LEVEL0, "ECC UNCORRECTED_ERROR 1\n"); | |
366 | return -1; | |
367 | } | |
368 | } | |
6d0f6bcf | 369 | #endif /* CONFIG_SYS_DAVINCI_BROKEN_ECC */ |
c74b2108 SK |
370 | return(0); |
371 | } | |
6d0f6bcf | 372 | #endif /* CONFIG_SYS_NAND_HW_ECC */ |
c74b2108 SK |
373 | |
374 | static int nand_davinci_dev_ready(struct mtd_info *mtd) | |
375 | { | |
376 | emifregs emif_addr; | |
377 | ||
378 | emif_addr = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE; | |
379 | ||
380 | return(emif_addr->NANDFSR & 0x1); | |
381 | } | |
382 | ||
cfa460ad | 383 | static int nand_davinci_waitfunc(struct mtd_info *mtd, struct nand_chip *this) |
c74b2108 SK |
384 | { |
385 | while(!nand_davinci_dev_ready(mtd)) {;} | |
386 | *NAND_CE0CLE = NAND_STATUS; | |
387 | return(*NAND_CE0DATA); | |
388 | } | |
389 | ||
390 | static void nand_flash_init(void) | |
391 | { | |
950a3924 WD |
392 | u_int32_t acfg1 = 0x3ffffffc; |
393 | u_int32_t acfg2 = 0x3ffffffc; | |
394 | u_int32_t acfg3 = 0x3ffffffc; | |
395 | u_int32_t acfg4 = 0x3ffffffc; | |
396 | emifregs emif_regs; | |
397 | ||
398 | /*------------------------------------------------------------------* | |
399 | * NAND FLASH CHIP TIMEOUT @ 459 MHz * | |
400 | * * | |
401 | * AEMIF.CLK freq = PLL1/6 = 459/6 = 76.5 MHz * | |
402 | * AEMIF.CLK period = 1/76.5 MHz = 13.1 ns * | |
403 | * * | |
404 | *------------------------------------------------------------------*/ | |
405 | acfg1 = 0 | |
53677ef1 WD |
406 | | (0 << 31 ) /* selectStrobe */ |
407 | | (0 << 30 ) /* extWait */ | |
408 | | (1 << 26 ) /* writeSetup 10 ns */ | |
409 | | (3 << 20 ) /* writeStrobe 40 ns */ | |
410 | | (1 << 17 ) /* writeHold 10 ns */ | |
411 | | (1 << 13 ) /* readSetup 10 ns */ | |
412 | | (5 << 7 ) /* readStrobe 60 ns */ | |
413 | | (1 << 4 ) /* readHold 10 ns */ | |
414 | | (3 << 2 ) /* turnAround ?? ns */ | |
415 | | (0 << 0 ) /* asyncSize 8-bit bus */ | |
416 | ; | |
950a3924 WD |
417 | |
418 | emif_regs = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE; | |
419 | ||
420 | emif_regs->AWCCR |= 0x10000000; | |
421 | emif_regs->AB1CR = acfg1; /* 0x08244128 */; | |
422 | emif_regs->AB2CR = acfg2; | |
423 | emif_regs->AB3CR = acfg3; | |
424 | emif_regs->AB4CR = acfg4; | |
425 | emif_regs->NANDFCR = 0x00000101; | |
c74b2108 SK |
426 | } |
427 | ||
428 | int board_nand_init(struct nand_chip *nand) | |
429 | { | |
430 | nand->IO_ADDR_R = (void __iomem *)NAND_CE0DATA; | |
431 | nand->IO_ADDR_W = (void __iomem *)NAND_CE0DATA; | |
432 | nand->chip_delay = 0; | |
433 | nand->select_chip = nand_davinci_select_chip; | |
6d0f6bcf | 434 | #ifdef CONFIG_SYS_NAND_USE_FLASH_BBT |
c74b2108 SK |
435 | nand->options = NAND_USE_FLASH_BBT; |
436 | #endif | |
6d0f6bcf | 437 | #ifdef CONFIG_SYS_NAND_HW_ECC |
5e1dae5c | 438 | nand->ecc.mode = NAND_ECC_HW; |
6d0f6bcf | 439 | #ifdef CONFIG_SYS_DAVINCI_BROKEN_ECC |
9b05aa78 | 440 | nand->ecc.layout = &davinci_nand_ecclayout; |
6d0f6bcf | 441 | #ifdef CONFIG_SYS_NAND_LARGEPAGE |
5e1dae5c WJ |
442 | nand->ecc.size = 2048; |
443 | nand->ecc.bytes = 12; | |
6d0f6bcf | 444 | #elif defined(CONFIG_SYS_NAND_SMALLPAGE) |
5e1dae5c WJ |
445 | nand->ecc.size = 512; |
446 | nand->ecc.bytes = 3; | |
c74b2108 | 447 | #else |
6d0f6bcf | 448 | #error "Either CONFIG_SYS_NAND_LARGEPAGE or CONFIG_SYS_NAND_SMALLPAGE must be defined!" |
c74b2108 | 449 | #endif |
9b05aa78 HV |
450 | #else |
451 | nand->ecc.size = 512; | |
452 | nand->ecc.bytes = 3; | |
6d0f6bcf | 453 | #endif /* CONFIG_SYS_DAVINCI_BROKEN_ECC */ |
cfa460ad WJ |
454 | nand->ecc.calculate = nand_davinci_calculate_ecc; |
455 | nand->ecc.correct = nand_davinci_correct_data; | |
4cbb651b | 456 | nand->ecc.hwctl = nand_davinci_enable_hwecc; |
c74b2108 | 457 | #else |
5e1dae5c | 458 | nand->ecc.mode = NAND_ECC_SOFT; |
6d0f6bcf | 459 | #endif /* CONFIG_SYS_NAND_HW_ECC */ |
c74b2108 SK |
460 | |
461 | /* Set address of hardware control function */ | |
cfa460ad | 462 | nand->cmd_ctrl = nand_davinci_hwcontrol; |
c74b2108 SK |
463 | |
464 | nand->dev_ready = nand_davinci_dev_ready; | |
465 | nand->waitfunc = nand_davinci_waitfunc; | |
466 | ||
467 | nand_flash_init(); | |
468 | ||
469 | return(0); | |
470 | } | |
471 | ||
472 | #else | |
473 | #error "U-Boot legacy NAND support not available for DaVinci chips" | |
474 | #endif | |
6d0f6bcf | 475 | #endif /* CONFIG_SYS_USE_NAND */ |