2 * (C) Copyright 2007-2008
3 * Stelian Pop <stelian@popies.net>
4 * Lead Tech Design <www.leadtechdesign.com>
6 * (C) Copyright 2006 ATMEL Rousset, Lacressonniere Nicolas
8 * See file CREDITS for list of people who contributed to this
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.
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.
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,
28 #include <asm/arch/hardware.h>
29 #include <asm/arch/gpio.h>
30 #include <asm/arch/at91_pio.h>
34 #ifdef CONFIG_ATMEL_NAND_HWECC
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)
42 #include "atmel_nand_ecc.h" /* Hardware ECC registers */
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
49 static struct nand_ecclayout atmel_oobinfo_large
= {
51 .eccpos
= {60, 61, 62, 63},
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
62 static struct nand_ecclayout atmel_oobinfo_small
= {
64 .eccpos
= {0, 1, 2, 3},
73 * function called after a write
75 * mtd: MTD block structure
76 * dat: raw data (unused)
77 * ecc_code: buffer for ECC
79 static int atmel_nand_calculate(struct mtd_info
*mtd
,
80 const u_char
*dat
, unsigned char *ecc_code
)
82 struct nand_chip
*nand_chip
= mtd
->priv
;
83 unsigned int ecc_value
;
85 /* get the first 2 ECC bytes */
86 ecc_value
= ecc_readl(CONFIG_SYS_NAND_ECC_BASE
, PR
);
88 ecc_code
[0] = ecc_value
& 0xFF;
89 ecc_code
[1] = (ecc_value
>> 8) & 0xFF;
91 /* get the last 2 ECC bytes */
92 ecc_value
= ecc_readl(CONFIG_SYS_NAND_ECC_BASE
, NPR
) & ATMEL_ECC_NPARITY
;
94 ecc_code
[2] = ecc_value
& 0xFF;
95 ecc_code
[3] = (ecc_value
>> 8) & 0xFF;
101 * HW ECC read page function
103 * mtd: mtd info structure
104 * chip: nand chip info structure
105 * buf: buffer to store read data
107 static int atmel_nand_read_page(struct mtd_info
*mtd
,
108 struct nand_chip
*chip
, uint8_t *buf
, int page
)
110 int eccsize
= chip
->ecc
.size
;
111 int eccbytes
= chip
->ecc
.bytes
;
112 uint32_t *eccpos
= chip
->ecc
.layout
->eccpos
;
114 uint8_t *oob
= chip
->oob_poi
;
119 chip
->read_buf(mtd
, p
, eccsize
);
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
127 * anyway, for small pages, the eccpos[0] == 0
129 chip
->cmdfunc(mtd
, NAND_CMD_RNDOUT
,
130 mtd
->writesize
+ eccpos
[0], -1);
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
);
137 /* check if there's an error */
138 stat
= chip
->ecc
.correct(mtd
, p
, oob
, NULL
);
141 mtd
->ecc_stats
.failed
++;
143 mtd
->ecc_stats
.corrected
+= stat
;
145 /* get back to oob start (end of page) */
146 chip
->cmdfunc(mtd
, NAND_CMD_RNDOUT
, mtd
->writesize
, -1);
149 chip
->read_buf(mtd
, oob
, mtd
->oobsize
);
157 * function called after a read
159 * mtd: MTD block structure
160 * dat: raw data read from the chip
161 * read_ecc: ECC from the chip (unused)
164 * Detect and correct a 1 bit error for a page
166 static int atmel_nand_correct(struct mtd_info
*mtd
, u_char
*dat
,
167 u_char
*read_ecc
, u_char
*isnull
)
169 struct nand_chip
*nand_chip
= mtd
->priv
;
170 unsigned int ecc_status
, ecc_parity
, ecc_mode
;
171 unsigned int ecc_word
, ecc_bit
;
173 /* get the status from the Status Register */
174 ecc_status
= ecc_readl(CONFIG_SYS_NAND_ECC_BASE
, SR
);
176 /* if there's no error */
177 if (likely(!(ecc_status
& ATMEL_ECC_RECERR
)))
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
;
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 */
195 /* it doesn't seems to be a freshly
197 * We can't correct so many errors */
198 printk(KERN_WARNING
"atmel_nand : multiple errors detected."
199 " Unable to correct.\n");
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.
208 printk(KERN_WARNING
"atmel_nand : one bit error on ECC code."
209 " Nothing to correct\n");
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",
217 /* correct the error */
218 if (nand_chip
->options
& NAND_BUSWIDTH_16
) {
220 ((unsigned short *) dat
)[ecc_word
] ^= (1 << ecc_bit
);
223 dat
[ecc_word
] ^= (1 << ecc_bit
);
225 printk(KERN_WARNING
"atmel_nand : error corrected\n");
230 * Enable HW ECC : unused on most chips
232 static void atmel_nand_hwctl(struct mtd_info
*mtd
, int mode
)
237 static void at91_nand_hwcontrol(struct mtd_info
*mtd
,
238 int cmd
, unsigned int ctrl
)
240 struct nand_chip
*this = mtd
->priv
;
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
);
248 IO_ADDR_W
|= CONFIG_SYS_NAND_MASK_CLE
;
250 IO_ADDR_W
|= CONFIG_SYS_NAND_MASK_ALE
;
252 #ifdef CONFIG_SYS_NAND_ENABLE_PIN
253 at91_set_gpio_value(CONFIG_SYS_NAND_ENABLE_PIN
,
256 this->IO_ADDR_W
= (void *) IO_ADDR_W
;
259 if (cmd
!= NAND_CMD_NONE
)
260 writeb(cmd
, this->IO_ADDR_W
);
263 #ifdef CONFIG_SYS_NAND_READY_PIN
264 static int at91_nand_ready(struct mtd_info
*mtd
)
266 return at91_get_gpio_value(CONFIG_SYS_NAND_READY_PIN
);
270 int board_nand_init(struct nand_chip
*nand
)
272 #ifdef CONFIG_ATMEL_NAND_HWECC
273 static int chip_nr
= 0;
274 struct mtd_info
*mtd
;
277 nand
->ecc
.mode
= NAND_ECC_SOFT
;
278 #ifdef CONFIG_SYS_NAND_DBW_16
279 nand
->options
= NAND_BUSWIDTH_16
;
281 nand
->cmd_ctrl
= at91_nand_hwcontrol
;
282 #ifdef CONFIG_SYS_NAND_READY_PIN
283 nand
->dev_ready
= at91_nand_ready
;
285 nand
->chip_delay
= 20;
287 #ifdef CONFIG_ATMEL_NAND_HWECC
288 nand
->ecc
.mode
= NAND_ECC_HW
;
289 nand
->ecc
.calculate
= atmel_nand_calculate
;
290 nand
->ecc
.correct
= atmel_nand_correct
;
291 nand
->ecc
.hwctl
= atmel_nand_hwctl
;
292 nand
->ecc
.read_page
= atmel_nand_read_page
;
296 #ifdef CONFIG_ATMEL_NAND_HWECC
297 mtd
= &nand_info
[chip_nr
++];
300 /* Detect NAND chips */
301 if (nand_scan_ident(mtd
, 1, NULL
)) {
302 printk(KERN_WARNING
"NAND Flash not found !\n");
306 if (nand
->ecc
.mode
== NAND_ECC_HW
) {
307 /* ECC is calculated for the whole page (1 step) */
308 nand
->ecc
.size
= mtd
->writesize
;
310 /* set ECC page size and oob layout */
311 switch (mtd
->writesize
) {
313 nand
->ecc
.layout
= &atmel_oobinfo_small
;
314 ecc_writel(CONFIG_SYS_NAND_ECC_BASE
, MR
, ATMEL_ECC_PAGESIZE_528
);
317 nand
->ecc
.layout
= &atmel_oobinfo_large
;
318 ecc_writel(CONFIG_SYS_NAND_ECC_BASE
, MR
, ATMEL_ECC_PAGESIZE_1056
);
321 nand
->ecc
.layout
= &atmel_oobinfo_large
;
322 ecc_writel(CONFIG_SYS_NAND_ECC_BASE
, MR
, ATMEL_ECC_PAGESIZE_2112
);
325 nand
->ecc
.layout
= &atmel_oobinfo_large
;
326 ecc_writel(CONFIG_SYS_NAND_ECC_BASE
, MR
, ATMEL_ECC_PAGESIZE_4224
);
329 /* page size not handled by HW ECC */
330 /* switching back to soft ECC */
331 nand
->ecc
.mode
= NAND_ECC_SOFT
;
332 nand
->ecc
.calculate
= NULL
;
333 nand
->ecc
.correct
= NULL
;
334 nand
->ecc
.hwctl
= NULL
;
335 nand
->ecc
.read_page
= NULL
;
336 nand
->ecc
.postpad
= 0;
337 nand
->ecc
.prepad
= 0;