crc32: activate crc32_no_comp (needed for jffs2 and UBI)
[barebox-mini2440.git] / drivers / nand / nand_s3c2410.c
blobb98958305029093dcaba6cefaf2f320ef742a4f4
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
26 #include <config.h>
27 #include <common.h>
28 #include <driver.h>
29 #include <malloc.h>
30 #include <init.h>
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>
36 #include <asm/io.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
43 # endif
44 #else
45 # define __nand_boot_init
46 #endif
48 /**
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 */
56 #define NFCONF 0x00
58 #ifdef CONFIG_CPU_S3C2410
60 #define NFCMD 0x04
61 #define NFADDR 0x08
62 #define NFDATA 0x0c
63 #define NFSTAT 0x10
64 #define NFECC 0x14
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
76 #define NFCONT 0x04
77 #define NFCMD 0x08
78 #define NFADDR 0x0C
79 #define NFDATA 0x10
81 #define NFECC 0x1C
82 #define NFSTAT 0x20
84 /* S3C2440 specific bits */
85 #define NFSTAT_BUSY (1)
86 #define NFCONT_nFCE (1 << 1)
87 #define NFCONF_INITECC (1 << 12)
88 #define NFCONT_EN (1)
90 #endif /* CONFIG_CPU_S3C2440 */
93 struct s3c24x0_nand_host {
94 struct mtd_info mtd;
95 struct nand_chip nand;
96 struct mtd_partition *parts;
97 struct device_d *dev;
99 unsigned long base;
103 * oob placement block for use with hardware ecc generation
105 static struct nand_ecclayout nand_hw_eccoob = {
106 .eccbytes = 3,
107 .eccpos = { 0, 1, 2},
108 .oobfree = {
110 .offset = 8,
111 .length = 8
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);
146 #endif
147 #ifdef CONFIG_CPU_S3C2440
148 writew(readw(host + NFCONT) & ~NFCONT_nFCE, host + NFCONT);
149 #endif
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);
160 #endif
161 #ifdef CONFIG_CPU_S3C2440
162 writew(readw(host + NFCONT) | NFCONT_nFCE, host + NFCONT);
163 #endif
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);
175 #endif
176 #ifdef CONFIG_CPU_S3C2440
177 writew(NFCONT_EN + NFCONT_nFCE, host + NFCONT);
178 writew(timing, host + NFCONF);
179 #endif
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);
190 #endif
191 #ifdef CONFIG_CPU_S3C2440
192 writew(NFCONT_nFCE, host + NFCONT);
193 #endif
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 */)
227 return 0;
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) |
238 ((diff2 >> 4) & 2) |
239 ((diff2 >> 5) & 4);
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);
254 return 1;
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)
265 return 1;
267 return -1;
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);
287 return 0;
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;
295 if (chip == -1)
296 disable_cs(host->base);
297 else
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,
310 unsigned int ctrl)
312 struct nand_chip *nand_chip = mtd->priv;
313 struct s3c24x0_nand_host *host = nand_chip->priv;
315 if (cmd == NAND_CMD_NONE)
316 return;
318 * If the CLE should be active, this call is a NAND command
320 if (ctrl & NAND_CLE)
321 send_cmd(host->base, cmd);
323 * If the ALE should be active, this call is a NAND address
325 if (ctrl & NAND_ALE)
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;
332 uint32_t tmp;
334 /* reset the NAND controller */
335 disable_nand_controller(host->base);
337 if (pdata != NULL)
338 tmp = pdata->nand_timing;
339 else
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);
346 return 0;
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;
354 int ret;
356 /* Allocate memory for MTD device structure and private data */
357 host = kzalloc(sizeof(struct s3c24x0_nand_host), GFP_KERNEL);
358 if (!host)
359 return -ENOMEM;
361 host->dev = dev;
362 host->base = dev->map_base;
364 /* structures must be linked */
365 chip = &host->nand;
366 mtd = &host->mtd;
367 mtd->priv = chip;
369 /* init the default settings */
370 #if 0
371 /* TODO: Will follow later */
372 init_nand_chip_bw8(chip);
373 #endif
374 /* 50 us command delay time */
375 chip->chip_delay = 50;
376 chip->priv = host;
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;
393 chip->ecc.bytes = 3;
394 chip->ecc.layout = &nand_hw_eccoob;
396 ret = s3c24x0_nand_inithw(host);
397 if (ret != 0)
398 goto on_error;
400 /* Scan to find existence of the device */
401 ret = nand_scan(mtd, 1);
402 if (ret != 0) {
403 ret = -ENXIO;
404 goto on_error;
407 return add_mtd_device(mtd);
409 on_error:
410 free(host);
411 return ret;
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;
451 int i;
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);
458 enable_cs(host);
460 /* Reset the NAND device */
461 send_cmd(host, NAND_CMD_RESET);
462 wait_for_completion(host);
463 disable_cs(host);
465 do {
466 enable_cs(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));
473 disable_cs(host);
475 page++;
476 dest += pagesize;
477 size -= pagesize;
478 } while (size >= 0);
480 /* disable the controller again */
481 disable_nand_controller(host);
484 #ifdef CONFIG_NAND_S3C24XX_BOOT_DEBUG
485 #include <command.h>
487 static int do_nand_boot_test(struct command *cmdtp, int argc, char *argv[])
489 void *dest;
490 int size, pagesize;
492 if (argc < 3)
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);
501 return 0;
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)
511 BAREBOX_CMD_END
512 #endif
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);