]>
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 SK |
46 | |
47 | #ifdef CFG_USE_NAND | |
48 | #if !defined(CFG_NAND_LEGACY) | |
49 | ||
50 | #include <nand.h> | |
51 | #include <asm/arch/nand_defs.h> | |
52 | #include <asm/arch/emif_defs.h> | |
53 | ||
54 | extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE]; | |
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 | ||
cfa460ad WJ |
71 | if (cmd != NAND_CMD_NONE) |
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 | ||
90 | #ifdef CFG_NAND_HW_ECC | |
91 | #ifdef CFG_NAND_LARGEPAGE | |
92 | static struct nand_oobinfo davinci_nand_oobinfo = { | |
93 | .useecc = MTD_NANDECC_AUTOPLACE, | |
94 | .eccbytes = 12, | |
95 | .eccpos = {8, 9, 10, 24, 25, 26, 40, 41, 42, 56, 57, 58}, | |
96 | .oobfree = { {2, 6}, {12, 12}, {28, 12}, {44, 12}, {60, 4} } | |
97 | }; | |
98 | #elif defined(CFG_NAND_SMALLPAGE) | |
99 | static struct nand_oobinfo davinci_nand_oobinfo = { | |
100 | .useecc = MTD_NANDECC_AUTOPLACE, | |
101 | .eccbytes = 3, | |
102 | .eccpos = {0, 1, 2}, | |
103 | .oobfree = { {6, 2}, {8, 8} } | |
104 | }; | |
105 | #else | |
106 | #error "Either CFG_NAND_LARGEPAGE or CFG_NAND_SMALLPAGE must be defined!" | |
107 | #endif | |
108 | ||
109 | static void nand_davinci_enable_hwecc(struct mtd_info *mtd, int mode) | |
110 | { | |
111 | emifregs emif_addr; | |
112 | int dummy; | |
113 | ||
114 | emif_addr = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE; | |
115 | ||
116 | dummy = emif_addr->NANDF1ECC; | |
117 | dummy = emif_addr->NANDF2ECC; | |
118 | dummy = emif_addr->NANDF3ECC; | |
119 | dummy = emif_addr->NANDF4ECC; | |
120 | ||
950a3924 | 121 | emif_addr->NANDFCR |= (1 << 8); |
c74b2108 SK |
122 | } |
123 | ||
124 | static u_int32_t nand_davinci_readecc(struct mtd_info *mtd, u_int32_t region) | |
125 | { | |
126 | u_int32_t ecc = 0; | |
127 | emifregs emif_base_addr; | |
128 | ||
129 | emif_base_addr = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE; | |
130 | ||
131 | if (region == 1) | |
132 | ecc = emif_base_addr->NANDF1ECC; | |
133 | else if (region == 2) | |
134 | ecc = emif_base_addr->NANDF2ECC; | |
135 | else if (region == 3) | |
136 | ecc = emif_base_addr->NANDF3ECC; | |
137 | else if (region == 4) | |
138 | ecc = emif_base_addr->NANDF4ECC; | |
139 | ||
140 | return(ecc); | |
141 | } | |
142 | ||
143 | static int nand_davinci_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code) | |
144 | { | |
145 | u_int32_t tmp; | |
146 | int region, n; | |
147 | struct nand_chip *this = mtd->priv; | |
148 | ||
cfa460ad | 149 | n = (this->ecc.size/512); |
c74b2108 | 150 | |
950a3924 | 151 | region = 1; |
c74b2108 SK |
152 | while (n--) { |
153 | tmp = nand_davinci_readecc(mtd, region); | |
154 | *ecc_code++ = tmp; | |
155 | *ecc_code++ = tmp >> 16; | |
156 | *ecc_code++ = ((tmp >> 8) & 0x0f) | ((tmp >> 20) & 0xf0); | |
157 | region++; | |
158 | } | |
159 | return(0); | |
160 | } | |
161 | ||
162 | static void nand_davinci_gen_true_ecc(u_int8_t *ecc_buf) | |
163 | { | |
164 | u_int32_t tmp = ecc_buf[0] | (ecc_buf[1] << 16) | ((ecc_buf[2] & 0xf0) << 20) | ((ecc_buf[2] & 0x0f) << 8); | |
165 | ||
166 | ecc_buf[0] = ~(P64o(tmp) | P64e(tmp) | P32o(tmp) | P32e(tmp) | P16o(tmp) | P16e(tmp) | P8o(tmp) | P8e(tmp)); | |
167 | ecc_buf[1] = ~(P1024o(tmp) | P1024e(tmp) | P512o(tmp) | P512e(tmp) | P256o(tmp) | P256e(tmp) | P128o(tmp) | P128e(tmp)); | |
168 | ecc_buf[2] = ~( P4o(tmp) | P4e(tmp) | P2o(tmp) | P2e(tmp) | P1o(tmp) | P1e(tmp) | P2048o(tmp) | P2048e(tmp)); | |
169 | } | |
170 | ||
171 | static int nand_davinci_compare_ecc(u_int8_t *ecc_nand, u_int8_t *ecc_calc, u_int8_t *page_data) | |
172 | { | |
173 | u_int32_t i; | |
174 | u_int8_t tmp0_bit[8], tmp1_bit[8], tmp2_bit[8]; | |
175 | u_int8_t comp0_bit[8], comp1_bit[8], comp2_bit[8]; | |
176 | u_int8_t ecc_bit[24]; | |
177 | u_int8_t ecc_sum = 0; | |
178 | u_int8_t find_bit = 0; | |
179 | u_int32_t find_byte = 0; | |
180 | int is_ecc_ff; | |
181 | ||
182 | is_ecc_ff = ((*ecc_nand == 0xff) && (*(ecc_nand + 1) == 0xff) && (*(ecc_nand + 2) == 0xff)); | |
183 | ||
184 | nand_davinci_gen_true_ecc(ecc_nand); | |
185 | nand_davinci_gen_true_ecc(ecc_calc); | |
186 | ||
187 | for (i = 0; i <= 2; i++) { | |
188 | *(ecc_nand + i) = ~(*(ecc_nand + i)); | |
189 | *(ecc_calc + i) = ~(*(ecc_calc + i)); | |
190 | } | |
191 | ||
192 | for (i = 0; i < 8; i++) { | |
193 | tmp0_bit[i] = *ecc_nand % 2; | |
194 | *ecc_nand = *ecc_nand / 2; | |
195 | } | |
196 | ||
197 | for (i = 0; i < 8; i++) { | |
198 | tmp1_bit[i] = *(ecc_nand + 1) % 2; | |
199 | *(ecc_nand + 1) = *(ecc_nand + 1) / 2; | |
200 | } | |
201 | ||
202 | for (i = 0; i < 8; i++) { | |
203 | tmp2_bit[i] = *(ecc_nand + 2) % 2; | |
204 | *(ecc_nand + 2) = *(ecc_nand + 2) / 2; | |
205 | } | |
206 | ||
207 | for (i = 0; i < 8; i++) { | |
208 | comp0_bit[i] = *ecc_calc % 2; | |
209 | *ecc_calc = *ecc_calc / 2; | |
210 | } | |
211 | ||
212 | for (i = 0; i < 8; i++) { | |
213 | comp1_bit[i] = *(ecc_calc + 1) % 2; | |
214 | *(ecc_calc + 1) = *(ecc_calc + 1) / 2; | |
215 | } | |
216 | ||
217 | for (i = 0; i < 8; i++) { | |
218 | comp2_bit[i] = *(ecc_calc + 2) % 2; | |
219 | *(ecc_calc + 2) = *(ecc_calc + 2) / 2; | |
220 | } | |
221 | ||
222 | for (i = 0; i< 6; i++) | |
223 | ecc_bit[i] = tmp2_bit[i + 2] ^ comp2_bit[i + 2]; | |
224 | ||
225 | for (i = 0; i < 8; i++) | |
226 | ecc_bit[i + 6] = tmp0_bit[i] ^ comp0_bit[i]; | |
227 | ||
228 | for (i = 0; i < 8; i++) | |
229 | ecc_bit[i + 14] = tmp1_bit[i] ^ comp1_bit[i]; | |
230 | ||
231 | ecc_bit[22] = tmp2_bit[0] ^ comp2_bit[0]; | |
232 | ecc_bit[23] = tmp2_bit[1] ^ comp2_bit[1]; | |
233 | ||
234 | for (i = 0; i < 24; i++) | |
235 | ecc_sum += ecc_bit[i]; | |
236 | ||
237 | switch (ecc_sum) { | |
238 | case 0: | |
239 | /* Not reached because this function is not called if | |
240 | ECC values are equal */ | |
241 | return 0; | |
242 | case 1: | |
243 | /* Uncorrectable error */ | |
3167c538 SW |
244 | MTDDEBUG (MTD_DEBUG_LEVEL0, |
245 | "ECC UNCORRECTED_ERROR 1\n"); | |
c74b2108 SK |
246 | return(-1); |
247 | case 12: | |
248 | /* Correctable error */ | |
249 | find_byte = (ecc_bit[23] << 8) + | |
250 | (ecc_bit[21] << 7) + | |
251 | (ecc_bit[19] << 6) + | |
252 | (ecc_bit[17] << 5) + | |
253 | (ecc_bit[15] << 4) + | |
254 | (ecc_bit[13] << 3) + | |
255 | (ecc_bit[11] << 2) + | |
256 | (ecc_bit[9] << 1) + | |
257 | ecc_bit[7]; | |
258 | ||
259 | find_bit = (ecc_bit[5] << 2) + (ecc_bit[3] << 1) + ecc_bit[1]; | |
260 | ||
3167c538 SW |
261 | MTDDEBUG (MTD_DEBUG_LEVEL0, "Correcting single bit ECC " |
262 | "error at offset: %d, bit: %d\n", | |
263 | find_byte, find_bit); | |
c74b2108 SK |
264 | |
265 | page_data[find_byte] ^= (1 << find_bit); | |
266 | ||
267 | return(0); | |
268 | default: | |
269 | if (is_ecc_ff) { | |
270 | if (ecc_calc[0] == 0 && ecc_calc[1] == 0 && ecc_calc[2] == 0) | |
271 | return(0); | |
272 | } | |
3167c538 SW |
273 | MTDDEBUG (MTD_DEBUG_LEVEL0, |
274 | "UNCORRECTED_ERROR default\n"); | |
c74b2108 SK |
275 | return(-1); |
276 | } | |
277 | } | |
278 | ||
279 | static int nand_davinci_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc) | |
280 | { | |
281 | struct nand_chip *this; | |
282 | int block_count = 0, i, rc; | |
283 | ||
284 | this = mtd->priv; | |
cfa460ad | 285 | block_count = (this->ecc.size/512); |
c74b2108 SK |
286 | for (i = 0; i < block_count; i++) { |
287 | if (memcmp(read_ecc, calc_ecc, 3) != 0) { | |
288 | rc = nand_davinci_compare_ecc(read_ecc, calc_ecc, dat); | |
289 | if (rc < 0) { | |
290 | return(rc); | |
291 | } | |
292 | } | |
293 | read_ecc += 3; | |
294 | calc_ecc += 3; | |
295 | dat += 512; | |
296 | } | |
297 | return(0); | |
298 | } | |
299 | #endif | |
300 | ||
301 | static int nand_davinci_dev_ready(struct mtd_info *mtd) | |
302 | { | |
303 | emifregs emif_addr; | |
304 | ||
305 | emif_addr = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE; | |
306 | ||
307 | return(emif_addr->NANDFSR & 0x1); | |
308 | } | |
309 | ||
cfa460ad | 310 | static int nand_davinci_waitfunc(struct mtd_info *mtd, struct nand_chip *this) |
c74b2108 SK |
311 | { |
312 | while(!nand_davinci_dev_ready(mtd)) {;} | |
313 | *NAND_CE0CLE = NAND_STATUS; | |
314 | return(*NAND_CE0DATA); | |
315 | } | |
316 | ||
317 | static void nand_flash_init(void) | |
318 | { | |
950a3924 WD |
319 | u_int32_t acfg1 = 0x3ffffffc; |
320 | u_int32_t acfg2 = 0x3ffffffc; | |
321 | u_int32_t acfg3 = 0x3ffffffc; | |
322 | u_int32_t acfg4 = 0x3ffffffc; | |
323 | emifregs emif_regs; | |
324 | ||
325 | /*------------------------------------------------------------------* | |
326 | * NAND FLASH CHIP TIMEOUT @ 459 MHz * | |
327 | * * | |
328 | * AEMIF.CLK freq = PLL1/6 = 459/6 = 76.5 MHz * | |
329 | * AEMIF.CLK period = 1/76.5 MHz = 13.1 ns * | |
330 | * * | |
331 | *------------------------------------------------------------------*/ | |
332 | acfg1 = 0 | |
53677ef1 WD |
333 | | (0 << 31 ) /* selectStrobe */ |
334 | | (0 << 30 ) /* extWait */ | |
335 | | (1 << 26 ) /* writeSetup 10 ns */ | |
336 | | (3 << 20 ) /* writeStrobe 40 ns */ | |
337 | | (1 << 17 ) /* writeHold 10 ns */ | |
338 | | (1 << 13 ) /* readSetup 10 ns */ | |
339 | | (5 << 7 ) /* readStrobe 60 ns */ | |
340 | | (1 << 4 ) /* readHold 10 ns */ | |
341 | | (3 << 2 ) /* turnAround ?? ns */ | |
342 | | (0 << 0 ) /* asyncSize 8-bit bus */ | |
343 | ; | |
950a3924 WD |
344 | |
345 | emif_regs = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE; | |
346 | ||
347 | emif_regs->AWCCR |= 0x10000000; | |
348 | emif_regs->AB1CR = acfg1; /* 0x08244128 */; | |
349 | emif_regs->AB2CR = acfg2; | |
350 | emif_regs->AB3CR = acfg3; | |
351 | emif_regs->AB4CR = acfg4; | |
352 | emif_regs->NANDFCR = 0x00000101; | |
c74b2108 SK |
353 | } |
354 | ||
355 | int board_nand_init(struct nand_chip *nand) | |
356 | { | |
357 | nand->IO_ADDR_R = (void __iomem *)NAND_CE0DATA; | |
358 | nand->IO_ADDR_W = (void __iomem *)NAND_CE0DATA; | |
359 | nand->chip_delay = 0; | |
360 | nand->select_chip = nand_davinci_select_chip; | |
361 | #ifdef CFG_NAND_USE_FLASH_BBT | |
362 | nand->options = NAND_USE_FLASH_BBT; | |
363 | #endif | |
364 | #ifdef CFG_NAND_HW_ECC | |
365 | #ifdef CFG_NAND_LARGEPAGE | |
cfa460ad WJ |
366 | nand->ecc.mode = NAND_ECC_HW; |
367 | nand->ecc.size = 2048; | |
368 | nand->ecc.bytes = 12; | |
c74b2108 | 369 | #elif defined(CFG_NAND_SMALLPAGE) |
cfa460ad WJ |
370 | nand->ecc.mode = NAND_ECC_HW; |
371 | nand->ecc.size = 512; | |
372 | nand->ecc.bytes = 3; | |
c74b2108 SK |
373 | #else |
374 | #error "Either CFG_NAND_LARGEPAGE or CFG_NAND_SMALLPAGE must be defined!" | |
375 | #endif | |
cfa460ad WJ |
376 | // nand->autooob = &davinci_nand_oobinfo; |
377 | nand->ecc.calculate = nand_davinci_calculate_ecc; | |
378 | nand->ecc.correct = nand_davinci_correct_data; | |
379 | nand->ecc.hwctl = nand_davinci_enable_hwecc; | |
c74b2108 | 380 | #else |
cfa460ad | 381 | nand->ecc.mode = NAND_ECC_SOFT; |
c74b2108 SK |
382 | #endif |
383 | ||
384 | /* Set address of hardware control function */ | |
cfa460ad | 385 | nand->cmd_ctrl = nand_davinci_hwcontrol; |
c74b2108 SK |
386 | |
387 | nand->dev_ready = nand_davinci_dev_ready; | |
388 | nand->waitfunc = nand_davinci_waitfunc; | |
389 | ||
390 | nand_flash_init(); | |
391 | ||
392 | return(0); | |
393 | } | |
394 | ||
395 | #else | |
396 | #error "U-Boot legacy NAND support not available for DaVinci chips" | |
397 | #endif | |
398 | #endif /* CFG_USE_NAND */ |