]> git.sur5r.net Git - u-boot/blob - drivers/mtd/nand/atmel_nand.c
f8b38f7a18ec09d61016af9868f5984f4c4e56ec
[u-boot] / drivers / mtd / nand / atmel_nand.c
1 /*
2  * (C) Copyright 2007-2008
3  * Stelian Pop <stelian@popies.net>
4  * Lead Tech Design <www.leadtechdesign.com>
5  *
6  * (C) Copyright 2006 ATMEL Rousset, Lacressonniere Nicolas
7  *
8  * See file CREDITS for list of people who contributed to this
9  * project.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License as
13  * published by the Free Software Foundation; either version 2 of
14  * the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
24  * MA 02111-1307 USA
25  */
26
27 #include <common.h>
28 #include <asm/arch/hardware.h>
29 #include <asm/arch/gpio.h>
30 #include <asm/arch/at91_pio.h>
31
32 #include <nand.h>
33
34 #ifdef CONFIG_ATMEL_NAND_HWECC
35
36 /* Register access macros */
37 #define ecc_readl(add, reg)                             \
38         readl(AT91_BASE_SYS + add + ATMEL_ECC_##reg)
39 #define ecc_writel(add, reg, value)                     \
40         writel((value), AT91_BASE_SYS + add + ATMEL_ECC_##reg)
41
42 #include "atmel_nand_ecc.h"     /* Hardware ECC registers */
43
44 /* oob layout for large page size
45  * bad block info is on bytes 0 and 1
46  * the bytes have to be consecutives to avoid
47  * several NAND_CMD_RNDOUT during read
48  */
49 static struct nand_ecclayout atmel_oobinfo_large = {
50         .eccbytes = 4,
51         .eccpos = {60, 61, 62, 63},
52         .oobfree = {
53                 {2, 58}
54         },
55 };
56
57 /* oob layout for small page size
58  * bad block info is on bytes 4 and 5
59  * the bytes have to be consecutives to avoid
60  * several NAND_CMD_RNDOUT during read
61  */
62 static struct nand_ecclayout atmel_oobinfo_small = {
63         .eccbytes = 4,
64         .eccpos = {0, 1, 2, 3},
65         .oobfree = {
66                 {6, 10}
67         },
68 };
69
70 /*
71  * Calculate HW ECC
72  *
73  * function called after a write
74  *
75  * mtd:        MTD block structure
76  * dat:        raw data (unused)
77  * ecc_code:   buffer for ECC
78  */
79 static int atmel_nand_calculate(struct mtd_info *mtd,
80                 const u_char *dat, unsigned char *ecc_code)
81 {
82         struct nand_chip *nand_chip = mtd->priv;
83         unsigned int ecc_value;
84
85         /* get the first 2 ECC bytes */
86         ecc_value = ecc_readl(CONFIG_SYS_NAND_ECC_BASE, PR);
87
88         ecc_code[0] = ecc_value & 0xFF;
89         ecc_code[1] = (ecc_value >> 8) & 0xFF;
90
91         /* get the last 2 ECC bytes */
92         ecc_value = ecc_readl(CONFIG_SYS_NAND_ECC_BASE, NPR) & ATMEL_ECC_NPARITY;
93
94         ecc_code[2] = ecc_value & 0xFF;
95         ecc_code[3] = (ecc_value >> 8) & 0xFF;
96
97         return 0;
98 }
99
100 /*
101  * HW ECC read page function
102  *
103  * mtd:        mtd info structure
104  * chip:       nand chip info structure
105  * buf:        buffer to store read data
106  */
107 static int atmel_nand_read_page(struct mtd_info *mtd,
108                 struct nand_chip *chip, uint8_t *buf, int page)
109 {
110         int eccsize = chip->ecc.size;
111         int eccbytes = chip->ecc.bytes;
112         uint32_t *eccpos = chip->ecc.layout->eccpos;
113         uint8_t *p = buf;
114         uint8_t *oob = chip->oob_poi;
115         uint8_t *ecc_pos;
116         int stat;
117
118         /* read the page */
119         chip->read_buf(mtd, p, eccsize);
120
121         /* move to ECC position if needed */
122         if (eccpos[0] != 0) {
123                 /* This only works on large pages
124                  * because the ECC controller waits for
125                  * NAND_CMD_RNDOUTSTART after the
126                  * NAND_CMD_RNDOUT.
127                  * anyway, for small pages, the eccpos[0] == 0
128                  */
129                 chip->cmdfunc(mtd, NAND_CMD_RNDOUT,
130                                 mtd->writesize + eccpos[0], -1);
131         }
132
133         /* the ECC controller needs to read the ECC just after the data */
134         ecc_pos = oob + eccpos[0];
135         chip->read_buf(mtd, ecc_pos, eccbytes);
136
137         /* check if there's an error */
138         stat = chip->ecc.correct(mtd, p, oob, NULL);
139
140         if (stat < 0)
141                 mtd->ecc_stats.failed++;
142         else
143                 mtd->ecc_stats.corrected += stat;
144
145         /* get back to oob start (end of page) */
146         chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1);
147
148         /* read the oob */
149         chip->read_buf(mtd, oob, mtd->oobsize);
150
151         return 0;
152 }
153
154 /*
155  * HW ECC Correction
156  *
157  * function called after a read
158  *
159  * mtd:        MTD block structure
160  * dat:        raw data read from the chip
161  * read_ecc:   ECC from the chip (unused)
162  * isnull:     unused
163  *
164  * Detect and correct a 1 bit error for a page
165  */
166 static int atmel_nand_correct(struct mtd_info *mtd, u_char *dat,
167                 u_char *read_ecc, u_char *isnull)
168 {
169         struct nand_chip *nand_chip = mtd->priv;
170         unsigned int ecc_status, ecc_parity, ecc_mode;
171         unsigned int ecc_word, ecc_bit;
172
173         /* get the status from the Status Register */
174         ecc_status = ecc_readl(CONFIG_SYS_NAND_ECC_BASE, SR);
175
176         /* if there's no error */
177         if (likely(!(ecc_status & ATMEL_ECC_RECERR)))
178                 return 0;
179
180         /* get error bit offset (4 bits) */
181         ecc_bit = ecc_readl(CONFIG_SYS_NAND_ECC_BASE, PR) & ATMEL_ECC_BITADDR;
182         /* get word address (12 bits) */
183         ecc_word = ecc_readl(CONFIG_SYS_NAND_ECC_BASE, PR) & ATMEL_ECC_WORDADDR;
184         ecc_word >>= 4;
185
186         /* if there are multiple errors */
187         if (ecc_status & ATMEL_ECC_MULERR) {
188                 /* check if it is a freshly erased block
189                  * (filled with 0xff) */
190                 if ((ecc_bit == ATMEL_ECC_BITADDR)
191                                 && (ecc_word == (ATMEL_ECC_WORDADDR >> 4))) {
192                         /* the block has just been erased, return OK */
193                         return 0;
194                 }
195                 /* it doesn't seems to be a freshly
196                  * erased block.
197                  * We can't correct so many errors */
198                 printk(KERN_WARNING "atmel_nand : multiple errors detected."
199                                 " Unable to correct.\n");
200                 return -EIO;
201         }
202
203         /* if there's a single bit error : we can correct it */
204         if (ecc_status & ATMEL_ECC_ECCERR) {
205                 /* there's nothing much to do here.
206                  * the bit error is on the ECC itself.
207                  */
208                 printk(KERN_WARNING "atmel_nand : one bit error on ECC code."
209                                 " Nothing to correct\n");
210                 return 0;
211         }
212
213         printk(KERN_WARNING "atmel_nand : one bit error on data."
214                         " (word offset in the page :"
215                         " 0x%x bit offset : 0x%x)\n",
216                         ecc_word, ecc_bit);
217         /* correct the error */
218         if (nand_chip->options & NAND_BUSWIDTH_16) {
219                 /* 16 bits words */
220                 ((unsigned short *) dat)[ecc_word] ^= (1 << ecc_bit);
221         } else {
222                 /* 8 bits words */
223                 dat[ecc_word] ^= (1 << ecc_bit);
224         }
225         printk(KERN_WARNING "atmel_nand : error corrected\n");
226         return 1;
227 }
228
229 /*
230  * Enable HW ECC : unused on most chips
231  */
232 static void atmel_nand_hwctl(struct mtd_info *mtd, int mode)
233 {
234 }
235
236 int atmel_hwecc_nand_init_param(struct nand_chip *nand, struct mtd_info *mtd)
237 {
238         nand->ecc.mode = NAND_ECC_HW;
239         nand->ecc.calculate = atmel_nand_calculate;
240         nand->ecc.correct = atmel_nand_correct;
241         nand->ecc.hwctl = atmel_nand_hwctl;
242         nand->ecc.read_page = atmel_nand_read_page;
243         nand->ecc.bytes = 4;
244
245         if (nand->ecc.mode == NAND_ECC_HW) {
246                 /* ECC is calculated for the whole page (1 step) */
247                 nand->ecc.size = mtd->writesize;
248
249                 /* set ECC page size and oob layout */
250                 switch (mtd->writesize) {
251                 case 512:
252                         nand->ecc.layout = &atmel_oobinfo_small;
253                         ecc_writel(CONFIG_SYS_NAND_ECC_BASE, MR,
254                                         ATMEL_ECC_PAGESIZE_528);
255                         break;
256                 case 1024:
257                         nand->ecc.layout = &atmel_oobinfo_large;
258                         ecc_writel(CONFIG_SYS_NAND_ECC_BASE, MR,
259                                         ATMEL_ECC_PAGESIZE_1056);
260                         break;
261                 case 2048:
262                         nand->ecc.layout = &atmel_oobinfo_large;
263                         ecc_writel(CONFIG_SYS_NAND_ECC_BASE, MR,
264                                         ATMEL_ECC_PAGESIZE_2112);
265                         break;
266                 case 4096:
267                         nand->ecc.layout = &atmel_oobinfo_large;
268                         ecc_writel(CONFIG_SYS_NAND_ECC_BASE, MR,
269                                         ATMEL_ECC_PAGESIZE_4224);
270                         break;
271                 default:
272                         /* page size not handled by HW ECC */
273                         /* switching back to soft ECC */
274                         nand->ecc.mode = NAND_ECC_SOFT;
275                         nand->ecc.calculate = NULL;
276                         nand->ecc.correct = NULL;
277                         nand->ecc.hwctl = NULL;
278                         nand->ecc.read_page = NULL;
279                         nand->ecc.postpad = 0;
280                         nand->ecc.prepad = 0;
281                         nand->ecc.bytes = 0;
282                         break;
283                 }
284         }
285
286         return 0;
287 }
288
289 #endif
290
291 static void at91_nand_hwcontrol(struct mtd_info *mtd,
292                                          int cmd, unsigned int ctrl)
293 {
294         struct nand_chip *this = mtd->priv;
295
296         if (ctrl & NAND_CTRL_CHANGE) {
297                 ulong IO_ADDR_W = (ulong) this->IO_ADDR_W;
298                 IO_ADDR_W &= ~(CONFIG_SYS_NAND_MASK_ALE
299                              | CONFIG_SYS_NAND_MASK_CLE);
300
301                 if (ctrl & NAND_CLE)
302                         IO_ADDR_W |= CONFIG_SYS_NAND_MASK_CLE;
303                 if (ctrl & NAND_ALE)
304                         IO_ADDR_W |= CONFIG_SYS_NAND_MASK_ALE;
305
306 #ifdef CONFIG_SYS_NAND_ENABLE_PIN
307                 at91_set_gpio_value(CONFIG_SYS_NAND_ENABLE_PIN,
308                                     !(ctrl & NAND_NCE));
309 #endif
310                 this->IO_ADDR_W = (void *) IO_ADDR_W;
311         }
312
313         if (cmd != NAND_CMD_NONE)
314                 writeb(cmd, this->IO_ADDR_W);
315 }
316
317 #ifdef CONFIG_SYS_NAND_READY_PIN
318 static int at91_nand_ready(struct mtd_info *mtd)
319 {
320         return at91_get_gpio_value(CONFIG_SYS_NAND_READY_PIN);
321 }
322 #endif
323
324 #ifndef CONFIG_SYS_NAND_BASE_LIST
325 #define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND_BASE }
326 #endif
327 static struct nand_chip nand_chip[CONFIG_SYS_MAX_NAND_DEVICE];
328 static ulong base_addr[CONFIG_SYS_MAX_NAND_DEVICE] = CONFIG_SYS_NAND_BASE_LIST;
329
330 int atmel_nand_chip_init(int devnum, ulong base_addr)
331 {
332         int ret;
333         struct mtd_info *mtd = &nand_info[devnum];
334         struct nand_chip *nand = &nand_chip[devnum];
335
336         mtd->priv = nand;
337         nand->IO_ADDR_R = nand->IO_ADDR_W = (void  __iomem *)base_addr;
338
339         nand->ecc.mode = NAND_ECC_SOFT;
340 #ifdef CONFIG_SYS_NAND_DBW_16
341         nand->options = NAND_BUSWIDTH_16;
342 #endif
343         nand->cmd_ctrl = at91_nand_hwcontrol;
344 #ifdef CONFIG_SYS_NAND_READY_PIN
345         nand->dev_ready = at91_nand_ready;
346 #endif
347         nand->chip_delay = 20;
348
349         ret = nand_scan_ident(mtd, CONFIG_SYS_NAND_MAX_CHIPS, NULL);
350         if (ret)
351                 return ret;
352
353 #ifdef CONFIG_ATMEL_NAND_HWECC
354         ret = atmel_hwecc_nand_init_param(nand, mtd);
355         if (ret)
356                 return ret;
357 #endif
358
359         ret = nand_scan_tail(mtd);
360         if (!ret)
361                 nand_register(devnum);
362
363         return ret;
364 }
365
366 void board_nand_init(void)
367 {
368         int i;
369         for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
370                 if (atmel_nand_chip_init(i, base_addr[i]))
371                         printk(KERN_ERR "atmel_nand: Fail to initialize #%d chip",
372                                 i);
373 }