diff options
-rw-r--r-- | Documentation/arm/Samsung-S3C24XX/NAND.txt | 30 | ||||
-rw-r--r-- | Documentation/arm/Samsung-S3C24XX/Overview.txt | 2 | ||||
-rw-r--r-- | drivers/mtd/nand/s3c2410.c | 38 |
3 files changed, 65 insertions, 5 deletions
diff --git a/Documentation/arm/Samsung-S3C24XX/NAND.txt b/Documentation/arm/Samsung-S3C24XX/NAND.txt new file mode 100644 index 000000000000..bc478a3409b8 --- /dev/null +++ b/Documentation/arm/Samsung-S3C24XX/NAND.txt | |||
@@ -0,0 +1,30 @@ | |||
1 | S3C24XX NAND Support | ||
2 | ==================== | ||
3 | |||
4 | Introduction | ||
5 | ------------ | ||
6 | |||
7 | Small Page NAND | ||
8 | --------------- | ||
9 | |||
10 | The driver uses a 512 byte (1 page) ECC code for this setup. The | ||
11 | ECC code is not directly compatible with the default kernel ECC | ||
12 | code, so the driver enforces its own OOB layout and ECC parameters | ||
13 | |||
14 | Large Page NAND | ||
15 | --------------- | ||
16 | |||
17 | The driver is capable of handling NAND flash with a 2KiB page | ||
18 | size, with support for hardware ECC generation and correction. | ||
19 | |||
20 | Unlike the 512byte page mode, the driver generates ECC data for | ||
21 | each 256 byte block in an 2KiB page. This means that more than | ||
22 | one error in a page can be rectified. It also means that the | ||
23 | OOB layout remains the default kernel layout for these flashes. | ||
24 | |||
25 | |||
26 | Document Author | ||
27 | --------------- | ||
28 | |||
29 | Ben Dooks, Copyright 2007 Simtec Electronics | ||
30 | |||
diff --git a/Documentation/arm/Samsung-S3C24XX/Overview.txt b/Documentation/arm/Samsung-S3C24XX/Overview.txt index c31b76fa66c4..d04e1e30c47f 100644 --- a/Documentation/arm/Samsung-S3C24XX/Overview.txt +++ b/Documentation/arm/Samsung-S3C24XX/Overview.txt | |||
@@ -156,6 +156,8 @@ NAND | |||
156 | controller. If there are any problems the latest linux-mtd | 156 | controller. If there are any problems the latest linux-mtd |
157 | code can be found from http://www.linux-mtd.infradead.org/ | 157 | code can be found from http://www.linux-mtd.infradead.org/ |
158 | 158 | ||
159 | For more information see Documentation/arm/Samsung-S3C24XX/NAND.txt | ||
160 | |||
159 | 161 | ||
160 | Serial | 162 | Serial |
161 | ------ | 163 | ------ |
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c index 8557c68dbb42..15397e0f3965 100644 --- a/drivers/mtd/nand/s3c2410.c +++ b/drivers/mtd/nand/s3c2410.c | |||
@@ -472,7 +472,7 @@ static int s3c2440_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u | |||
472 | ecc_code[1] = ecc >> 8; | 472 | ecc_code[1] = ecc >> 8; |
473 | ecc_code[2] = ecc >> 16; | 473 | ecc_code[2] = ecc >> 16; |
474 | 474 | ||
475 | pr_debug("%s: returning ecc %06lx\n", __func__, ecc); | 475 | pr_debug("%s: returning ecc %06lx\n", __func__, ecc & 0xffffff); |
476 | 476 | ||
477 | return 0; | 477 | return 0; |
478 | } | 478 | } |
@@ -643,9 +643,6 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info, | |||
643 | chip->ecc.calculate = s3c2410_nand_calculate_ecc; | 643 | chip->ecc.calculate = s3c2410_nand_calculate_ecc; |
644 | chip->ecc.correct = s3c2410_nand_correct_data; | 644 | chip->ecc.correct = s3c2410_nand_correct_data; |
645 | chip->ecc.mode = NAND_ECC_HW; | 645 | chip->ecc.mode = NAND_ECC_HW; |
646 | chip->ecc.size = 512; | ||
647 | chip->ecc.bytes = 3; | ||
648 | chip->ecc.layout = &nand_hw_eccoob; | ||
649 | 646 | ||
650 | switch (info->cpu_type) { | 647 | switch (info->cpu_type) { |
651 | case TYPE_S3C2410: | 648 | case TYPE_S3C2410: |
@@ -669,6 +666,34 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info, | |||
669 | } | 666 | } |
670 | } | 667 | } |
671 | 668 | ||
669 | /* s3c2410_nand_update_chip | ||
670 | * | ||
671 | * post-probe chip update, to change any items, such as the | ||
672 | * layout for large page nand | ||
673 | */ | ||
674 | |||
675 | static void s3c2410_nand_update_chip(struct s3c2410_nand_info *info, | ||
676 | struct s3c2410_nand_mtd *nmtd) | ||
677 | { | ||
678 | struct nand_chip *chip = &nmtd->chip; | ||
679 | |||
680 | printk("%s: chip %p: %d\n", __func__, chip, chip->page_shift); | ||
681 | |||
682 | if (hardware_ecc) { | ||
683 | /* change the behaviour depending on wether we are using | ||
684 | * the large or small page nand device */ | ||
685 | |||
686 | if (chip->page_shift > 10) { | ||
687 | chip->ecc.size = 256; | ||
688 | chip->ecc.bytes = 3; | ||
689 | } else { | ||
690 | chip->ecc.size = 512; | ||
691 | chip->ecc.bytes = 3; | ||
692 | chip->ecc.layout = &nand_hw_eccoob; | ||
693 | } | ||
694 | } | ||
695 | } | ||
696 | |||
672 | /* s3c2410_nand_probe | 697 | /* s3c2410_nand_probe |
673 | * | 698 | * |
674 | * called by device layer when it finds a device matching | 699 | * called by device layer when it finds a device matching |
@@ -775,9 +800,12 @@ static int s3c24xx_nand_probe(struct platform_device *pdev, | |||
775 | 800 | ||
776 | s3c2410_nand_init_chip(info, nmtd, sets); | 801 | s3c2410_nand_init_chip(info, nmtd, sets); |
777 | 802 | ||
778 | nmtd->scan_res = nand_scan(&nmtd->mtd, (sets) ? sets->nr_chips : 1); | 803 | nmtd->scan_res = nand_scan_ident(&nmtd->mtd, |
804 | (sets) ? sets->nr_chips : 1); | ||
779 | 805 | ||
780 | if (nmtd->scan_res == 0) { | 806 | if (nmtd->scan_res == 0) { |
807 | s3c2410_nand_update_chip(info, nmtd); | ||
808 | nand_scan_tail(&nmtd->mtd); | ||
781 | s3c2410_nand_add_partition(info, nmtd, sets); | 809 | s3c2410_nand_add_partition(info, nmtd, sets); |
782 | } | 810 | } |
783 | 811 | ||