]>
git.ipfire.org Git - people/ms/u-boot.git/blob - drivers/mtd/nand/s3c64xx.c
2 * (C) Copyright 2006 DENX Software Engineering
4 * Implementation for U-Boot 1.1.6 by Samsung
7 * Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de>
9 * See file CREDITS for list of people who contributed to this
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License as
14 * published by the Free Software Foundation; either version 2 of
15 * the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
34 #include <asm/errno.h>
37 static int nand_cs
[MAX_CHIPS
] = {0, 1};
39 #ifdef CONFIG_NAND_SPL
40 #define printf(arg...) do {} while (0)
43 /* Nand flash definition values by jsgood */
46 * Function to print out oob buffer for debugging
49 static void print_oob(const char *header
, struct mtd_info
*mtd
)
52 struct nand_chip
*chip
= mtd
->priv
;
54 printf("%s:\t", header
);
56 for (i
= 0; i
< 64; i
++)
57 printf("%02x ", chip
->oob_poi
[i
]);
61 #endif /* S3C_NAND_DEBUG */
63 #ifdef CONFIG_NAND_SPL
64 static u_char
nand_read_byte(struct mtd_info
*mtd
)
66 struct nand_chip
*this = mtd
->priv
;
67 return readb(this->IO_ADDR_R
);
70 static void nand_write_buf(struct mtd_info
*mtd
, const uint8_t *buf
, int len
)
73 struct nand_chip
*this = mtd
->priv
;
75 for (i
= 0; i
< len
; i
++)
76 writeb(buf
[i
], this->IO_ADDR_W
);
79 static void nand_read_buf(struct mtd_info
*mtd
, u_char
*buf
, int len
)
82 struct nand_chip
*this = mtd
->priv
;
84 for (i
= 0; i
< len
; i
++)
85 buf
[i
] = readb(this->IO_ADDR_R
);
89 static void s3c_nand_select_chip(struct mtd_info
*mtd
, int chip
)
91 int ctrl
= readl(NFCONT
);
107 writel(ctrl
, NFCONT
);
111 * Hardware specific access to control-lines function
114 static void s3c_nand_hwcontrol(struct mtd_info
*mtd
, int cmd
, unsigned int ctrl
)
116 struct nand_chip
*this = mtd
->priv
;
118 if (ctrl
& NAND_CTRL_CHANGE
) {
120 this->IO_ADDR_W
= (void __iomem
*)NFCMMD
;
121 else if (ctrl
& NAND_ALE
)
122 this->IO_ADDR_W
= (void __iomem
*)NFADDR
;
124 this->IO_ADDR_W
= (void __iomem
*)NFDATA
;
126 s3c_nand_select_chip(mtd
, *(int *)this->priv
);
128 s3c_nand_select_chip(mtd
, -1);
131 if (cmd
!= NAND_CMD_NONE
)
132 writeb(cmd
, this->IO_ADDR_W
);
136 * Function for checking device ready pin
139 static int s3c_nand_device_ready(struct mtd_info
*mtdinfo
)
141 return !!(readl(NFSTAT
) & NFSTAT_RnB
);
144 #ifdef CONFIG_SYS_S3C_NAND_HWECC
146 * This function is called before encoding ecc codes to ready ecc engine.
149 static void s3c_nand_enable_hwecc(struct mtd_info
*mtd
, int mode
)
151 u_long nfcont
, nfconf
;
154 * The original driver used 4-bit ECC for "new" MLC chips, i.e., for
155 * those with non-zero ID[3][3:2], which anyway only holds for ST
158 nfconf
= readl(NFCONF
) & ~NFCONF_ECC_4BIT
;
160 writel(nfconf
, NFCONF
);
162 /* Initialize & unlock */
163 nfcont
= readl(NFCONT
);
164 nfcont
|= NFCONT_INITECC
;
165 nfcont
&= ~NFCONT_MECCLOCK
;
167 if (mode
== NAND_ECC_WRITE
)
168 nfcont
|= NFCONT_ECC_ENC
;
169 else if (mode
== NAND_ECC_READ
)
170 nfcont
&= ~NFCONT_ECC_ENC
;
172 writel(nfcont
, NFCONT
);
176 * This function is called immediately after encoding ecc codes.
177 * This function returns encoded ecc codes.
180 static int s3c_nand_calculate_ecc(struct mtd_info
*mtd
, const u_char
*dat
,
183 u_long nfcont
, nfmecc0
;
186 nfcont
= readl(NFCONT
);
187 nfcont
|= NFCONT_MECCLOCK
;
188 writel(nfcont
, NFCONT
);
190 nfmecc0
= readl(NFMECC0
);
192 ecc_code
[0] = nfmecc0
& 0xff;
193 ecc_code
[1] = (nfmecc0
>> 8) & 0xff;
194 ecc_code
[2] = (nfmecc0
>> 16) & 0xff;
195 ecc_code
[3] = (nfmecc0
>> 24) & 0xff;
201 * This function determines whether read data is good or not.
202 * If SLC, must write ecc codes to controller before reading status bit.
203 * If MLC, status bit is already set, so only reading is needed.
204 * If status bit is good, return 0.
205 * If correctable errors occured, do that.
206 * If uncorrectable errors occured, return -1.
209 static int s3c_nand_correct_data(struct mtd_info
*mtd
, u_char
*dat
,
210 u_char
*read_ecc
, u_char
*calc_ecc
)
213 u_long nfestat0
, nfmeccdata0
, nfmeccdata1
, err_byte_addr
;
214 u_char err_type
, repaired
;
216 /* SLC: Write ecc to compare */
217 nfmeccdata0
= (calc_ecc
[1] << 16) | calc_ecc
[0];
218 nfmeccdata1
= (calc_ecc
[3] << 16) | calc_ecc
[2];
219 writel(nfmeccdata0
, NFMECCDATA0
);
220 writel(nfmeccdata1
, NFMECCDATA1
);
222 /* Read ecc status */
223 nfestat0
= readl(NFESTAT0
);
224 err_type
= nfestat0
& 0x3;
227 case 0: /* No error */
233 * 1 bit error (Correctable)
234 * (nfestat0 >> 7) & 0x7ff :error byte number
235 * (nfestat0 >> 4) & 0x7 :error bit number
237 err_byte_addr
= (nfestat0
>> 7) & 0x7ff;
238 repaired
= dat
[err_byte_addr
] ^ (1 << ((nfestat0
>> 4) & 0x7));
240 printf("S3C NAND: 1 bit error detected at byte %ld. "
241 "Correcting from 0x%02x to 0x%02x...OK\n",
242 err_byte_addr
, dat
[err_byte_addr
], repaired
);
244 dat
[err_byte_addr
] = repaired
;
249 case 2: /* Multiple error */
250 case 3: /* ECC area error */
251 printf("S3C NAND: ECC uncorrectable error detected. "
252 "Not correctable.\n");
259 #endif /* CONFIG_SYS_S3C_NAND_HWECC */
262 * Board-specific NAND initialization. The following members of the
263 * argument are board-specific (per include/linux/mtd/nand.h):
264 * - IO_ADDR_R?: address to read the 8 I/O lines of the flash device
265 * - IO_ADDR_W?: address to write the 8 I/O lines of the flash device
266 * - hwcontrol: hardwarespecific function for accesing control-lines
267 * - dev_ready: hardwarespecific function for accesing device ready/busy line
268 * - enable_hwecc?: function to enable (reset) hardware ecc generator. Must
269 * only be provided if a hardware ECC is available
270 * - eccmode: mode of ecc, see defines
271 * - chip_delay: chip dependent delay for transfering data from array to
273 * - options: various chip options. They can partly be set to inform
274 * nand_scan about special functionality. See the defines for further
276 * Members with a "?" were not set in the merged testing-NAND branch,
277 * so they are not set here either.
279 int board_nand_init(struct nand_chip
*nand
)
283 if (chip_n
>= MAX_CHIPS
)
286 NFCONT_REG
= (NFCONT_REG
& ~NFCONT_WP
) | NFCONT_ENABLE
| 0x6;
288 nand
->IO_ADDR_R
= (void __iomem
*)NFDATA
;
289 nand
->IO_ADDR_W
= (void __iomem
*)NFDATA
;
290 nand
->cmd_ctrl
= s3c_nand_hwcontrol
;
291 nand
->dev_ready
= s3c_nand_device_ready
;
292 nand
->select_chip
= s3c_nand_select_chip
;
294 #ifdef CONFIG_NAND_SPL
295 nand
->read_byte
= nand_read_byte
;
296 nand
->write_buf
= nand_write_buf
;
297 nand
->read_buf
= nand_read_buf
;
300 #ifdef CONFIG_SYS_S3C_NAND_HWECC
301 nand
->ecc
.hwctl
= s3c_nand_enable_hwecc
;
302 nand
->ecc
.calculate
= s3c_nand_calculate_ecc
;
303 nand
->ecc
.correct
= s3c_nand_correct_data
;
306 * If you get more than 1 NAND-chip with different page-sizes on the
307 * board one day, it will get more complicated...
309 nand
->ecc
.mode
= NAND_ECC_HW
;
310 nand
->ecc
.size
= CONFIG_SYS_NAND_ECCSIZE
;
311 nand
->ecc
.bytes
= CONFIG_SYS_NAND_ECCBYTES
;
313 nand
->ecc
.mode
= NAND_ECC_SOFT
;
314 #endif /* ! CONFIG_SYS_S3C_NAND_HWECC */
316 nand
->priv
= nand_cs
+ chip_n
++;