]> git.ipfire.org Git - people/ms/u-boot.git/blob - drivers/mtd/nand/atmel_nand.c
d5eb54ad84135924b93b4050e09f74b09fcad749
[people/ms/u-boot.git] / drivers / mtd / nand / atmel_nand.c
1 /*
2 * (C) Copyright 2007-2008
3 * Stelian Pop <stelian.pop@leadtechdesign.com>
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 #endif
236
237 static void at91_nand_hwcontrol(struct mtd_info *mtd,
238 int cmd, unsigned int ctrl)
239 {
240 struct nand_chip *this = mtd->priv;
241
242 if (ctrl & NAND_CTRL_CHANGE) {
243 ulong IO_ADDR_W = (ulong) this->IO_ADDR_W;
244 IO_ADDR_W &= ~(CONFIG_SYS_NAND_MASK_ALE
245 | CONFIG_SYS_NAND_MASK_CLE);
246
247 if (ctrl & NAND_CLE)
248 IO_ADDR_W |= CONFIG_SYS_NAND_MASK_CLE;
249 if (ctrl & NAND_ALE)
250 IO_ADDR_W |= CONFIG_SYS_NAND_MASK_ALE;
251
252 at91_set_gpio_value(CONFIG_SYS_NAND_ENABLE_PIN,
253 !(ctrl & NAND_NCE));
254 this->IO_ADDR_W = (void *) IO_ADDR_W;
255 }
256
257 if (cmd != NAND_CMD_NONE)
258 writeb(cmd, this->IO_ADDR_W);
259 }
260
261 #ifdef CONFIG_SYS_NAND_READY_PIN
262 static int at91_nand_ready(struct mtd_info *mtd)
263 {
264 return at91_get_gpio_value(CONFIG_SYS_NAND_READY_PIN);
265 }
266 #endif
267
268 int board_nand_init(struct nand_chip *nand)
269 {
270 #ifdef CONFIG_ATMEL_NAND_HWECC
271 static int chip_nr = 0;
272 struct mtd_info *mtd;
273 #endif
274
275 nand->ecc.mode = NAND_ECC_SOFT;
276 #ifdef CONFIG_SYS_NAND_DBW_16
277 nand->options = NAND_BUSWIDTH_16;
278 #endif
279 nand->cmd_ctrl = at91_nand_hwcontrol;
280 #ifdef CONFIG_SYS_NAND_READY_PIN
281 nand->dev_ready = at91_nand_ready;
282 #endif
283 nand->chip_delay = 20;
284
285 #ifdef CONFIG_ATMEL_NAND_HWECC
286 nand->ecc.mode = NAND_ECC_HW;
287 nand->ecc.calculate = atmel_nand_calculate;
288 nand->ecc.correct = atmel_nand_correct;
289 nand->ecc.hwctl = atmel_nand_hwctl;
290 nand->ecc.read_page = atmel_nand_read_page;
291 nand->ecc.bytes = 4;
292 #endif
293
294 #ifdef CONFIG_ATMEL_NAND_HWECC
295 mtd = &nand_info[chip_nr++];
296 mtd->priv = nand;
297
298 /* Detect NAND chips */
299 if (nand_scan_ident(mtd, 1)) {
300 printk(KERN_WARNING "NAND Flash not found !\n");
301 return -ENXIO;
302 }
303
304 if (nand->ecc.mode == NAND_ECC_HW) {
305 /* ECC is calculated for the whole page (1 step) */
306 nand->ecc.size = mtd->writesize;
307
308 /* set ECC page size and oob layout */
309 switch (mtd->writesize) {
310 case 512:
311 nand->ecc.layout = &atmel_oobinfo_small;
312 ecc_writel(CONFIG_SYS_NAND_ECC_BASE, MR, ATMEL_ECC_PAGESIZE_528);
313 break;
314 case 1024:
315 nand->ecc.layout = &atmel_oobinfo_large;
316 ecc_writel(CONFIG_SYS_NAND_ECC_BASE, MR, ATMEL_ECC_PAGESIZE_1056);
317 break;
318 case 2048:
319 nand->ecc.layout = &atmel_oobinfo_large;
320 ecc_writel(CONFIG_SYS_NAND_ECC_BASE, MR, ATMEL_ECC_PAGESIZE_2112);
321 break;
322 case 4096:
323 nand->ecc.layout = &atmel_oobinfo_large;
324 ecc_writel(CONFIG_SYS_NAND_ECC_BASE, MR, ATMEL_ECC_PAGESIZE_4224);
325 break;
326 default:
327 /* page size not handled by HW ECC */
328 /* switching back to soft ECC */
329 nand->ecc.mode = NAND_ECC_SOFT;
330 nand->ecc.calculate = NULL;
331 nand->ecc.correct = NULL;
332 nand->ecc.hwctl = NULL;
333 nand->ecc.read_page = NULL;
334 nand->ecc.postpad = 0;
335 nand->ecc.prepad = 0;
336 nand->ecc.bytes = 0;
337 break;
338 }
339 }
340 #endif
341
342 return 0;
343 }