1 /* linux/drivers/mtd/nand/s3c2410.c
3 * Copyright (C) 2009 Juergen Beisert, Pengutronix
5 * Copyright © 2004-2008 Simtec Electronics
6 * http://armlinux.simtec.co.uk/
7 * Ben Dooks <ben@simtec.co.uk>
9 * Samsung S3C2410 NAND driver
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (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, MA 02111-1307 USA
31 #include <linux/mtd/mtd.h>
32 #include <linux/mtd/nand.h>
33 #include <mach/s3c24xx-generic.h>
34 #include <mach/s3c24x0-iomap.h>
35 #include <mach/s3c24x0-nand.h>
37 #include <asm-generic/errno.h>
39 #ifdef CONFIG_S3C24XX_NAND_BOOT
40 # define __nand_boot_init __bare_init
41 # ifndef BOARD_DEFAULT_NAND_TIMING
42 # define BOARD_DEFAULT_NAND_TIMING 0x0737
45 # define __nand_boot_init
49 * Define this symbol for testing purpose. It will add a command to read an
50 * image from the NAND like it the boot strap code will do.
52 #define CONFIG_NAND_S3C24XX_BOOT_DEBUG
54 /* NAND controller's register */
58 #ifdef CONFIG_CPU_S3C2410
66 /* S3C2410 specific bits */
67 #define NFSTAT_BUSY (1)
68 #define NFCONF_nFCE (1 << 11)
69 #define NFCONF_INITECC (1 << 12)
70 #define NFCONF_EN (1 << 15)
72 #endif /* CONFIG_CPU_S3C2410 */
74 #ifdef CONFIG_CPU_S3C2440
84 /* S3C2440 specific bits */
85 #define NFSTAT_BUSY (1)
86 #define NFCONT_nFCE (1 << 1)
87 #define NFCONF_INITECC (1 << 12)
90 #endif /* CONFIG_CPU_S3C2440 */
93 struct s3c24x0_nand_host
{
95 struct nand_chip nand
;
96 struct mtd_partition
*parts
;
103 * oob placement block for use with hardware ecc generation
105 static struct nand_ecclayout nand_hw_eccoob
= {
107 .eccpos
= { 0, 1, 2},
116 /* - Functions shared between the boot strap code and the regular driver - */
119 * Issue the specified command to the NAND device
120 * @param[in] host Base address of the NAND controller
121 * @param[in] cmd Command for NAND flash
123 static void __nand_boot_init
send_cmd(unsigned long host
, uint8_t cmd
)
125 writeb(cmd
, host
+ NFCMD
);
129 * Issue the specified address to the NAND device
130 * @param[in] host Base address of the NAND controller
131 * @param[in] addr Address for the NAND flash
133 static void __nand_boot_init
send_addr(unsigned long host
, uint8_t addr
)
135 writeb(addr
, host
+ NFADDR
);
139 * Enable the NAND flash access
140 * @param[in] host Base address of the NAND controller
142 static void __nand_boot_init
enable_cs(unsigned long host
)
144 #ifdef CONFIG_CPU_S3C2410
145 writew(readw(host
+ NFCONF
) & ~NFCONF_nFCE
, host
+ NFCONF
);
147 #ifdef CONFIG_CPU_S3C2440
148 writew(readw(host
+ NFCONT
) & ~NFCONT_nFCE
, host
+ NFCONT
);
153 * Disable the NAND flash access
154 * @param[in] host Base address of the NAND controller
156 static void __nand_boot_init
disable_cs(unsigned long host
)
158 #ifdef CONFIG_CPU_S3C2410
159 writew(readw(host
+ NFCONF
) | NFCONF_nFCE
, host
+ NFCONF
);
161 #ifdef CONFIG_CPU_S3C2440
162 writew(readw(host
+ NFCONT
) | NFCONT_nFCE
, host
+ NFCONT
);
167 * Enable the NAND flash controller
168 * @param[in] host Base address of the NAND controller
169 * @param[in] timing Timing to access the NAND memory
171 static void __nand_boot_init
enable_nand_controller(unsigned long host
, uint32_t timing
)
173 #ifdef CONFIG_CPU_S3C2410
174 writew(timing
+ NFCONF_EN
+ NFCONF_nFCE
, host
+ NFCONF
);
176 #ifdef CONFIG_CPU_S3C2440
177 writew(NFCONT_EN
+ NFCONT_nFCE
, host
+ NFCONT
);
178 writew(timing
, host
+ NFCONF
);
183 * Diable the NAND flash controller
184 * @param[in] host Base address of the NAND controller
186 static void __nand_boot_init
disable_nand_controller(unsigned long host
)
188 #ifdef CONFIG_CPU_S3C2410
189 writew(NFCONF_nFCE
, host
+ NFCONF
);
191 #ifdef CONFIG_CPU_S3C2440
192 writew(NFCONT_nFCE
, host
+ NFCONT
);
196 /* ----------------------------------------------------------------------- */
199 * Check the ECC and try to repair the data if possible
200 * @param[in] mtd_info FIXME
201 * @param[inout] dat Pointer to the data buffer that might contain a bit error
202 * @param[in] read_ecc ECC data from the OOB space
203 * @param[in] calc_ecc ECC data calculated from the data
204 * @return 0 no error, 1 repaired error, -1 no way...
206 * @note: Alsways 512 byte of data
208 static int s3c2410_nand_correct_data(struct mtd_info
*mtd
, uint8_t *dat
,
209 uint8_t *read_ecc
, uint8_t *calc_ecc
)
211 unsigned int diff0
, diff1
, diff2
;
212 unsigned int bit
, byte
;
214 diff0
= read_ecc
[0] ^ calc_ecc
[0];
215 diff1
= read_ecc
[1] ^ calc_ecc
[1];
216 diff2
= read_ecc
[2] ^ calc_ecc
[2];
218 if (diff0
== 0 && diff1
== 0 && diff2
== 0)
219 return 0; /* ECC is ok */
221 /* sometimes people do not think about using the ECC, so check
222 * to see if we have an 0xff,0xff,0xff read ECC and then ignore
223 * the error, on the assumption that this is an un-eccd page.
225 if (read_ecc
[0] == 0xff && read_ecc
[1] == 0xff && read_ecc
[2] == 0xff
226 /* && info->platform->ignore_unset_ecc */)
229 /* Can we correct this ECC (ie, one row and column change).
230 * Note, this is similar to the 256 error code on smartmedia */
232 if (((diff0
^ (diff0
>> 1)) & 0x55) == 0x55 &&
233 ((diff1
^ (diff1
>> 1)) & 0x55) == 0x55 &&
234 ((diff2
^ (diff2
>> 1)) & 0x55) == 0x55) {
235 /* calculate the bit position of the error */
237 bit
= ((diff2
>> 3) & 1) |
241 /* calculate the byte position of the error */
243 byte
= ((diff2
<< 7) & 0x100) |
244 ((diff1
<< 0) & 0x80) |
245 ((diff1
<< 1) & 0x40) |
246 ((diff1
<< 2) & 0x20) |
247 ((diff1
<< 3) & 0x10) |
248 ((diff0
>> 4) & 0x08) |
249 ((diff0
>> 3) & 0x04) |
250 ((diff0
>> 2) & 0x02) |
251 ((diff0
>> 1) & 0x01);
253 dat
[byte
] ^= (1 << bit
);
257 /* if there is only one bit difference in the ECC, then
258 * one of only a row or column parity has changed, which
259 * means the error is most probably in the ECC itself */
261 diff0
|= (diff1
<< 8);
262 diff0
|= (diff2
<< 16);
264 if ((diff0
& ~(1<<fls(diff0
))) == 0)
270 static void s3c2410_nand_enable_hwecc(struct mtd_info
*mtd
, int mode
)
272 struct nand_chip
*nand_chip
= mtd
->priv
;
273 struct s3c24x0_nand_host
*host
= nand_chip
->priv
;
275 writel(readl(host
->base
+ NFCONF
) | NFCONF_INITECC
, host
->base
+ NFCONF
);
278 static int s3c2410_nand_calculate_ecc(struct mtd_info
*mtd
, const uint8_t *dat
, uint8_t *ecc_code
)
280 struct nand_chip
*nand_chip
= mtd
->priv
;
281 struct s3c24x0_nand_host
*host
= nand_chip
->priv
;
283 ecc_code
[0] = readb(host
->base
+ NFECC
);
284 ecc_code
[1] = readb(host
->base
+ NFECC
+ 1);
285 ecc_code
[2] = readb(host
->base
+ NFECC
+ 2);
290 static void s3c24x0_nand_select_chip(struct mtd_info
*mtd
, int chip
)
292 struct nand_chip
*nand_chip
= mtd
->priv
;
293 struct s3c24x0_nand_host
*host
= nand_chip
->priv
;
296 disable_cs(host
->base
);
298 enable_cs(host
->base
);
301 static int s3c24x0_nand_devready(struct mtd_info
*mtd
)
303 struct nand_chip
*nand_chip
= mtd
->priv
;
304 struct s3c24x0_nand_host
*host
= nand_chip
->priv
;
306 return readw(host
->base
+ NFSTAT
) & NFSTAT_BUSY
;
309 static void s3c24x0_nand_hwcontrol(struct mtd_info
*mtd
, int cmd
,
312 struct nand_chip
*nand_chip
= mtd
->priv
;
313 struct s3c24x0_nand_host
*host
= nand_chip
->priv
;
315 if (cmd
== NAND_CMD_NONE
)
318 * If the CLE should be active, this call is a NAND command
321 send_cmd(host
->base
, cmd
);
323 * If the ALE should be active, this call is a NAND address
326 send_addr(host
->base
, cmd
);
329 static int s3c24x0_nand_inithw(struct s3c24x0_nand_host
*host
)
331 struct s3c24x0_nand_platform_data
*pdata
= host
->dev
->platform_data
;
334 /* reset the NAND controller */
335 disable_nand_controller(host
->base
);
338 tmp
= pdata
->nand_timing
;
340 /* else slowest possible timing */
341 tmp
= CALC_NFCONF_TIMING(4, 8, 8);
343 /* reenable the NAND controller */
344 enable_nand_controller(host
->base
, tmp
);
349 static int s3c24x0_nand_probe(struct device_d
*dev
)
351 struct nand_chip
*chip
;
352 struct mtd_info
*mtd
;
353 struct s3c24x0_nand_host
*host
;
356 /* Allocate memory for MTD device structure and private data */
357 host
= kzalloc(sizeof(struct s3c24x0_nand_host
), GFP_KERNEL
);
362 host
->base
= dev
->map_base
;
364 /* structures must be linked */
369 /* init the default settings */
371 /* TODO: Will follow later */
372 init_nand_chip_bw8(chip
);
374 /* 50 us command delay time */
375 chip
->chip_delay
= 50;
378 chip
->IO_ADDR_R
= chip
->IO_ADDR_W
= (void*)(dev
->map_base
+ NFDATA
);
380 chip
->cmd_ctrl
= s3c24x0_nand_hwcontrol
;
381 chip
->dev_ready
= s3c24x0_nand_devready
;
382 chip
->select_chip
= s3c24x0_nand_select_chip
;
384 /* we are using the hardware ECC feature of this device */
385 chip
->ecc
.calculate
= s3c2410_nand_calculate_ecc
;
386 chip
->ecc
.correct
= s3c2410_nand_correct_data
;
387 chip
->ecc
.hwctl
= s3c2410_nand_enable_hwecc
;
388 chip
->ecc
.calculate
= s3c2410_nand_calculate_ecc
;
390 /* our hardware capabilities */
391 chip
->ecc
.mode
= NAND_ECC_HW
;
392 chip
->ecc
.size
= 512;
394 chip
->ecc
.layout
= &nand_hw_eccoob
;
396 ret
= s3c24x0_nand_inithw(host
);
400 /* Scan to find existence of the device */
401 ret
= nand_scan(mtd
, 1);
407 return add_mtd_device(mtd
);
414 static struct driver_d s3c24x0_nand_driver
= {
415 .name
= "s3c24x0_nand",
416 .probe
= s3c24x0_nand_probe
,
419 #ifdef CONFIG_S3C24XX_NAND_BOOT
421 static void __nand_boot_init
wait_for_completion(unsigned long host
)
423 while (!(readw(host
+ NFSTAT
) & NFSTAT_BUSY
))
427 static void __nand_boot_init
nfc_addr(unsigned long host
, uint32_t offs
)
429 send_addr(host
, offs
& 0xff);
430 send_addr(host
, (offs
>> 9) & 0xff);
431 send_addr(host
, (offs
>> 17) & 0xff);
432 send_addr(host
, (offs
>> 25) & 0xff);
436 * Load a sequential count of blocks from the NAND into memory
437 * @param[out] dest Pointer to target area (in SDRAM)
438 * @param[in] size Bytes to read from NAND device
439 * @param[in] page Start page to read from
440 * @param[in] pagesize Size of each page in the NAND
442 * This function must be located in the first 4kiB of the barebox image
443 * (guess why). When this routine is running the SDRAM is up and running
444 * and it runs from the correct address (physical=linked address).
445 * TODO Could we access the platform data from the boardfile?
446 * Due to it makes no sense this function does not return in case of failure.
448 void __nand_boot_init
s3c24x0_nand_load_image(void *dest
, int size
, int page
, int pagesize
)
450 unsigned long host
= S3C24X0_NAND_BASE
;
454 * Reenable the NFC and use the default (but slow) access
455 * timing or the board specific setting if provided.
457 enable_nand_controller(host
, BOARD_DEFAULT_NAND_TIMING
);
460 /* Reset the NAND device */
461 send_cmd(host
, NAND_CMD_RESET
);
462 wait_for_completion(host
);
467 send_cmd(host
, NAND_CMD_READ0
);
468 nfc_addr(host
, page
* pagesize
);
469 wait_for_completion(host
);
470 /* copy one page (do *not* use readsb() here!)*/
471 for (i
= 0; i
< pagesize
; i
++)
472 writeb(readb(host
+ NFDATA
), (unsigned long)(dest
+ i
));
480 /* disable the controller again */
481 disable_nand_controller(host
);
484 #ifdef CONFIG_NAND_S3C24XX_BOOT_DEBUG
487 static int do_nand_boot_test(struct command
*cmdtp
, int argc
, char *argv
[])
493 return COMMAND_ERROR_USAGE
;
495 dest
= (void *)strtoul_suffix(argv
[1], NULL
, 0);
496 size
= strtoul_suffix(argv
[2], NULL
, 0);
497 pagesize
= strtoul_suffix(argv
[3], NULL
, 0);
499 s3c24x0_nand_load_image(dest
, size
, 0, pagesize
);
504 static const __maybe_unused
char cmd_nand_boot_test_help
[] =
505 "Usage: nand_boot_test <dest> <size> <pagesize>\n";
507 BAREBOX_CMD_START(nand_boot_test
)
508 .cmd
= do_nand_boot_test
,
509 .usage
= "load an image from NAND",
510 BAREBOX_CMD_HELP(cmd_nand_boot_test_help
)
514 #endif /* CONFIG_S3C24XX_NAND_BOOT */
517 * Main initialization routine
518 * @return 0 if successful; non-zero otherwise
520 static int __init
s3c24x0_nand_init(void)
522 return register_driver(&s3c24x0_nand_driver
);
525 device_initcall(s3c24x0_nand_init
);