aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Dooks <ben-mtd@fluff.org>2008-04-15 06:36:19 -0400
committerDavid Woodhouse <dwmw2@infradead.org>2008-04-22 16:39:16 -0400
commit71d54f3855b4ca98559e8782350336ec2433cc24 (patch)
tree3ea9c792bc9a4bfb2356648e1b719bd24fd03cc5
parent0916083210039bf3d186a87522cc806dc21b7097 (diff)
[MTD] [NAND] S3C2410 Large page NAND support
This adds support for using large page NAND devices with the S3C24XX NAND controller. This also adds the file Documentation/arm/Samsung-S3C24XX/NAND.txt to describe the differences. Signed-off-by: Ben Dooks <ben-linux@fluff.org> Signed-off-by: David Woodhouse <dwmw2@infradead.org>
-rw-r--r--Documentation/arm/Samsung-S3C24XX/NAND.txt30
-rw-r--r--Documentation/arm/Samsung-S3C24XX/Overview.txt2
-rw-r--r--drivers/mtd/nand/s3c2410.c38
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
4Introduction
5------------
6
7Small Page NAND
8---------------
9
10The driver uses a 512 byte (1 page) ECC code for this setup. The
11ECC code is not directly compatible with the default kernel ECC
12code, so the driver enforces its own OOB layout and ECC parameters
13
14Large Page NAND
15---------------
16
17The driver is capable of handling NAND flash with a 2KiB page
18size, with support for hardware ECC generation and correction.
19
20Unlike the 512byte page mode, the driver generates ECC data for
21each 256 byte block in an 2KiB page. This means that more than
22one error in a page can be rectified. It also means that the
23OOB layout remains the default kernel layout for these flashes.
24
25
26Document Author
27---------------
28
29Ben 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
160Serial 162Serial
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
675static 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