]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/mtd/nand/atmel_nand.c
at91: atmel_nand: remove unused variables.
[karo-tx-uboot.git] / 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         unsigned int ecc_value;
83
84         /* get the first 2 ECC bytes */
85         ecc_value = ecc_readl(CONFIG_SYS_NAND_ECC_BASE, PR);
86
87         ecc_code[0] = ecc_value & 0xFF;
88         ecc_code[1] = (ecc_value >> 8) & 0xFF;
89
90         /* get the last 2 ECC bytes */
91         ecc_value = ecc_readl(CONFIG_SYS_NAND_ECC_BASE, NPR) & ATMEL_ECC_NPARITY;
92
93         ecc_code[2] = ecc_value & 0xFF;
94         ecc_code[3] = (ecc_value >> 8) & 0xFF;
95
96         return 0;
97 }
98
99 /*
100  * HW ECC read page function
101  *
102  * mtd:        mtd info structure
103  * chip:       nand chip info structure
104  * buf:        buffer to store read data
105  */
106 static int atmel_nand_read_page(struct mtd_info *mtd,
107                 struct nand_chip *chip, uint8_t *buf, int page)
108 {
109         int eccsize = chip->ecc.size;
110         int eccbytes = chip->ecc.bytes;
111         uint32_t *eccpos = chip->ecc.layout->eccpos;
112         uint8_t *p = buf;
113         uint8_t *oob = chip->oob_poi;
114         uint8_t *ecc_pos;
115         int stat;
116
117         /* read the page */
118         chip->read_buf(mtd, p, eccsize);
119
120         /* move to ECC position if needed */
121         if (eccpos[0] != 0) {
122                 /* This only works on large pages
123                  * because the ECC controller waits for
124                  * NAND_CMD_RNDOUTSTART after the
125                  * NAND_CMD_RNDOUT.
126                  * anyway, for small pages, the eccpos[0] == 0
127                  */
128                 chip->cmdfunc(mtd, NAND_CMD_RNDOUT,
129                                 mtd->writesize + eccpos[0], -1);
130         }
131
132         /* the ECC controller needs to read the ECC just after the data */
133         ecc_pos = oob + eccpos[0];
134         chip->read_buf(mtd, ecc_pos, eccbytes);
135
136         /* check if there's an error */
137         stat = chip->ecc.correct(mtd, p, oob, NULL);
138
139         if (stat < 0)
140                 mtd->ecc_stats.failed++;
141         else
142                 mtd->ecc_stats.corrected += stat;
143
144         /* get back to oob start (end of page) */
145         chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1);
146
147         /* read the oob */
148         chip->read_buf(mtd, oob, mtd->oobsize);
149
150         return 0;
151 }
152
153 /*
154  * HW ECC Correction
155  *
156  * function called after a read
157  *
158  * mtd:        MTD block structure
159  * dat:        raw data read from the chip
160  * read_ecc:   ECC from the chip (unused)
161  * isnull:     unused
162  *
163  * Detect and correct a 1 bit error for a page
164  */
165 static int atmel_nand_correct(struct mtd_info *mtd, u_char *dat,
166                 u_char *read_ecc, u_char *isnull)
167 {
168         struct nand_chip *nand_chip = mtd->priv;
169         unsigned int ecc_status;
170         unsigned int ecc_word, ecc_bit;
171
172         /* get the status from the Status Register */
173         ecc_status = ecc_readl(CONFIG_SYS_NAND_ECC_BASE, SR);
174
175         /* if there's no error */
176         if (likely(!(ecc_status & ATMEL_ECC_RECERR)))
177                 return 0;
178
179         /* get error bit offset (4 bits) */
180         ecc_bit = ecc_readl(CONFIG_SYS_NAND_ECC_BASE, PR) & ATMEL_ECC_BITADDR;
181         /* get word address (12 bits) */
182         ecc_word = ecc_readl(CONFIG_SYS_NAND_ECC_BASE, PR) & ATMEL_ECC_WORDADDR;
183         ecc_word >>= 4;
184
185         /* if there are multiple errors */
186         if (ecc_status & ATMEL_ECC_MULERR) {
187                 /* check if it is a freshly erased block
188                  * (filled with 0xff) */
189                 if ((ecc_bit == ATMEL_ECC_BITADDR)
190                                 && (ecc_word == (ATMEL_ECC_WORDADDR >> 4))) {
191                         /* the block has just been erased, return OK */
192                         return 0;
193                 }
194                 /* it doesn't seems to be a freshly
195                  * erased block.
196                  * We can't correct so many errors */
197                 printk(KERN_WARNING "atmel_nand : multiple errors detected."
198                                 " Unable to correct.\n");
199                 return -EIO;
200         }
201
202         /* if there's a single bit error : we can correct it */
203         if (ecc_status & ATMEL_ECC_ECCERR) {
204                 /* there's nothing much to do here.
205                  * the bit error is on the ECC itself.
206                  */
207                 printk(KERN_WARNING "atmel_nand : one bit error on ECC code."
208                                 " Nothing to correct\n");
209                 return 0;
210         }
211
212         printk(KERN_WARNING "atmel_nand : one bit error on data."
213                         " (word offset in the page :"
214                         " 0x%x bit offset : 0x%x)\n",
215                         ecc_word, ecc_bit);
216         /* correct the error */
217         if (nand_chip->options & NAND_BUSWIDTH_16) {
218                 /* 16 bits words */
219                 ((unsigned short *) dat)[ecc_word] ^= (1 << ecc_bit);
220         } else {
221                 /* 8 bits words */
222                 dat[ecc_word] ^= (1 << ecc_bit);
223         }
224         printk(KERN_WARNING "atmel_nand : error corrected\n");
225         return 1;
226 }
227
228 /*
229  * Enable HW ECC : unused on most chips
230  */
231 static void atmel_nand_hwctl(struct mtd_info *mtd, int mode)
232 {
233 }
234
235 int atmel_hwecc_nand_init_param(struct nand_chip *nand, struct mtd_info *mtd)
236 {
237         nand->ecc.mode = NAND_ECC_HW;
238         nand->ecc.calculate = atmel_nand_calculate;
239         nand->ecc.correct = atmel_nand_correct;
240         nand->ecc.hwctl = atmel_nand_hwctl;
241         nand->ecc.read_page = atmel_nand_read_page;
242         nand->ecc.bytes = 4;
243
244         if (nand->ecc.mode == NAND_ECC_HW) {
245                 /* ECC is calculated for the whole page (1 step) */
246                 nand->ecc.size = mtd->writesize;
247
248                 /* set ECC page size and oob layout */
249                 switch (mtd->writesize) {
250                 case 512:
251                         nand->ecc.layout = &atmel_oobinfo_small;
252                         ecc_writel(CONFIG_SYS_NAND_ECC_BASE, MR,
253                                         ATMEL_ECC_PAGESIZE_528);
254                         break;
255                 case 1024:
256                         nand->ecc.layout = &atmel_oobinfo_large;
257                         ecc_writel(CONFIG_SYS_NAND_ECC_BASE, MR,
258                                         ATMEL_ECC_PAGESIZE_1056);
259                         break;
260                 case 2048:
261                         nand->ecc.layout = &atmel_oobinfo_large;
262                         ecc_writel(CONFIG_SYS_NAND_ECC_BASE, MR,
263                                         ATMEL_ECC_PAGESIZE_2112);
264                         break;
265                 case 4096:
266                         nand->ecc.layout = &atmel_oobinfo_large;
267                         ecc_writel(CONFIG_SYS_NAND_ECC_BASE, MR,
268                                         ATMEL_ECC_PAGESIZE_4224);
269                         break;
270                 default:
271                         /* page size not handled by HW ECC */
272                         /* switching back to soft ECC */
273                         nand->ecc.mode = NAND_ECC_SOFT;
274                         nand->ecc.calculate = NULL;
275                         nand->ecc.correct = NULL;
276                         nand->ecc.hwctl = NULL;
277                         nand->ecc.read_page = NULL;
278                         nand->ecc.postpad = 0;
279                         nand->ecc.prepad = 0;
280                         nand->ecc.bytes = 0;
281                         break;
282                 }
283         }
284
285         return 0;
286 }
287
288 #endif
289
290 static void at91_nand_hwcontrol(struct mtd_info *mtd,
291                                          int cmd, unsigned int ctrl)
292 {
293         struct nand_chip *this = mtd->priv;
294
295         if (ctrl & NAND_CTRL_CHANGE) {
296                 ulong IO_ADDR_W = (ulong) this->IO_ADDR_W;
297                 IO_ADDR_W &= ~(CONFIG_SYS_NAND_MASK_ALE
298                              | CONFIG_SYS_NAND_MASK_CLE);
299
300                 if (ctrl & NAND_CLE)
301                         IO_ADDR_W |= CONFIG_SYS_NAND_MASK_CLE;
302                 if (ctrl & NAND_ALE)
303                         IO_ADDR_W |= CONFIG_SYS_NAND_MASK_ALE;
304
305 #ifdef CONFIG_SYS_NAND_ENABLE_PIN
306                 at91_set_gpio_value(CONFIG_SYS_NAND_ENABLE_PIN,
307                                     !(ctrl & NAND_NCE));
308 #endif
309                 this->IO_ADDR_W = (void *) IO_ADDR_W;
310         }
311
312         if (cmd != NAND_CMD_NONE)
313                 writeb(cmd, this->IO_ADDR_W);
314 }
315
316 #ifdef CONFIG_SYS_NAND_READY_PIN
317 static int at91_nand_ready(struct mtd_info *mtd)
318 {
319         return at91_get_gpio_value(CONFIG_SYS_NAND_READY_PIN);
320 }
321 #endif
322
323 #ifndef CONFIG_SYS_NAND_BASE_LIST
324 #define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND_BASE }
325 #endif
326 static struct nand_chip nand_chip[CONFIG_SYS_MAX_NAND_DEVICE];
327 static ulong base_addr[CONFIG_SYS_MAX_NAND_DEVICE] = CONFIG_SYS_NAND_BASE_LIST;
328
329 int atmel_nand_chip_init(int devnum, ulong base_addr)
330 {
331         int ret;
332         struct mtd_info *mtd = &nand_info[devnum];
333         struct nand_chip *nand = &nand_chip[devnum];
334
335         mtd->priv = nand;
336         nand->IO_ADDR_R = nand->IO_ADDR_W = (void  __iomem *)base_addr;
337
338         nand->ecc.mode = NAND_ECC_SOFT;
339 #ifdef CONFIG_SYS_NAND_DBW_16
340         nand->options = NAND_BUSWIDTH_16;
341 #endif
342         nand->cmd_ctrl = at91_nand_hwcontrol;
343 #ifdef CONFIG_SYS_NAND_READY_PIN
344         nand->dev_ready = at91_nand_ready;
345 #endif
346         nand->chip_delay = 20;
347
348         ret = nand_scan_ident(mtd, CONFIG_SYS_NAND_MAX_CHIPS, NULL);
349         if (ret)
350                 return ret;
351
352 #ifdef CONFIG_ATMEL_NAND_HWECC
353         ret = atmel_hwecc_nand_init_param(nand, mtd);
354         if (ret)
355                 return ret;
356 #endif
357
358         ret = nand_scan_tail(mtd);
359         if (!ret)
360                 nand_register(devnum);
361
362         return ret;
363 }
364
365 void board_nand_init(void)
366 {
367         int i;
368         for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
369                 if (atmel_nand_chip_init(i, base_addr[i]))
370                         printk(KERN_ERR "atmel_nand: Fail to initialize #%d chip",
371                                 i);
372 }