mtd: s3c2410: make ecc mode configurable via platform data
authorSergio Prado <sergio.prado@e-labworks.com>
Thu, 20 Oct 2016 21:42:44 +0000 (19:42 -0200)
committerBoris Brezillon <boris.brezillon@free-electrons.com>
Mon, 7 Nov 2016 13:48:35 +0000 (14:48 +0100)
Removing CONFIG_MTD_NAND_S3C2410_HWECC option and adding a ecc_mode
field in the drivers's platform data structure so it can be selectable
via platform data.

Also setting this field to NAND_ECC_SOFT in all boards using this
driver since none of them had CONFIG_MTD_NAND_S3C2410_HWECC enabled.

Signed-off-by: Sergio Prado <sergio.prado@e-labworks.com>
Acked-by: Krzysztof Kozlowski <krzk@kernel.org>
Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
18 files changed:
arch/arm/mach-s3c24xx/common-smdk.c
arch/arm/mach-s3c24xx/mach-anubis.c
arch/arm/mach-s3c24xx/mach-at2440evb.c
arch/arm/mach-s3c24xx/mach-bast.c
arch/arm/mach-s3c24xx/mach-gta02.c
arch/arm/mach-s3c24xx/mach-jive.c
arch/arm/mach-s3c24xx/mach-mini2440.c
arch/arm/mach-s3c24xx/mach-osiris.c
arch/arm/mach-s3c24xx/mach-qt2410.c
arch/arm/mach-s3c24xx/mach-rx1950.c
arch/arm/mach-s3c24xx/mach-rx3715.c
arch/arm/mach-s3c24xx/mach-vstms.c
arch/arm/mach-s3c64xx/mach-hmt.c
arch/arm/mach-s3c64xx/mach-mini6410.c
arch/arm/mach-s3c64xx/mach-real6410.c
drivers/mtd/nand/Kconfig
drivers/mtd/nand/s3c2410.c
include/linux/platform_data/mtd-nand-s3c2410.h

index e9fbcc91c5c0214811b41cd73c54cc41d18964ab..9e0bc46e90ecf54ad7ee0c42ea2326eec3992b3a 100644 (file)
@@ -171,6 +171,7 @@ static struct s3c2410_platform_nand smdk_nand_info = {
        .twrph1         = 20,
        .nr_sets        = ARRAY_SIZE(smdk_nand_sets),
        .sets           = smdk_nand_sets,
+       .ecc_mode       = NAND_ECC_SOFT,
 };
 
 /* devices we initialise */
index d03df0df01fa204cea8f172e6cf681984d3b664d..029ef1b58925499bbe657c267dab534a657e2d0b 100644 (file)
@@ -223,6 +223,7 @@ static struct s3c2410_platform_nand __initdata anubis_nand_info = {
        .nr_sets        = ARRAY_SIZE(anubis_nand_sets),
        .sets           = anubis_nand_sets,
        .select_chip    = anubis_nand_select,
+       .ecc_mode       = NAND_ECC_SOFT,
 };
 
 /* IDE channels */
index 9ae170fef2a7b89ca53c60f4ca3b2c48e5975c29..7b28eb623fc1ff745baf5d88fc138179c174855c 100644 (file)
@@ -114,6 +114,7 @@ static struct s3c2410_platform_nand __initdata at2440evb_nand_info = {
        .twrph1         = 40,
        .nr_sets        = ARRAY_SIZE(at2440evb_nand_sets),
        .sets           = at2440evb_nand_sets,
+       .ecc_mode       = NAND_ECC_SOFT,
 };
 
 /* DM9000AEP 10/100 ethernet controller */
index ed07cf392d4bb9e2d6321a6c2c85ce0d91c52a3a..5185036765db2d096ee057774dbeadaafff11304 100644 (file)
@@ -299,6 +299,7 @@ static struct s3c2410_platform_nand __initdata bast_nand_info = {
        .nr_sets        = ARRAY_SIZE(bast_nand_sets),
        .sets           = bast_nand_sets,
        .select_chip    = bast_nand_select,
+       .ecc_mode       = NAND_ECC_SOFT,
 };
 
 /* DM9000 */
index 27ae6877550f7b8972c288ee32fa43a7e9a3a07c..b0ed401da3a3aaa4a901c92159cfe585cf054284 100644 (file)
@@ -443,6 +443,7 @@ static struct s3c2410_platform_nand __initdata gta02_nand_info = {
        .twrph1         = 15,
        .nr_sets        = ARRAY_SIZE(gta02_nand_sets),
        .sets           = gta02_nand_sets,
+       .ecc_mode       = NAND_ECC_SOFT,
 };
 
 
index 7d99fe8f6157612767b667d8a2360178d4c065ab..895aca225952d62f137aae798f603fa2006fc60e 100644 (file)
@@ -232,6 +232,7 @@ static struct s3c2410_platform_nand __initdata jive_nand_info = {
        .twrph1         = 40,
        .sets           = jive_nand_sets,
        .nr_sets        = ARRAY_SIZE(jive_nand_sets),
+       .ecc_mode       = NAND_ECC_SOFT,
 };
 
 static int __init jive_mtdset(char *options)
index ec60bd4a1646f094edead1037483b5ed3aea3fba..71af8d2fd3201ffd95fa8588a440905d6a44abad 100644 (file)
@@ -287,6 +287,7 @@ static struct s3c2410_platform_nand mini2440_nand_info __initdata = {
        .nr_sets        = ARRAY_SIZE(mini2440_nand_sets),
        .sets           = mini2440_nand_sets,
        .ignore_unset_ecc = 1,
+       .ecc_mode       = NAND_ECC_SOFT,
 };
 
 /* DM9000AEP 10/100 ethernet controller */
index 2f6fdc32683524b45933f3173ee3fd7d6aacbda1..70b0eb7d31347f8fbb6371148bbcc8de89a2aae0 100644 (file)
@@ -238,6 +238,7 @@ static struct s3c2410_platform_nand __initdata osiris_nand_info = {
        .nr_sets        = ARRAY_SIZE(osiris_nand_sets),
        .sets           = osiris_nand_sets,
        .select_chip    = osiris_nand_select,
+       .ecc_mode       = NAND_ECC_SOFT,
 };
 
 /* PCMCIA control and configuration */
index 984516e8307aa599272cdc3bee33142567e0069a..868c8208740396f649163882c238469e6a45ee7a 100644 (file)
@@ -284,6 +284,7 @@ static struct s3c2410_platform_nand __initdata qt2410_nand_info = {
        .twrph1         = 20,
        .nr_sets        = ARRAY_SIZE(qt2410_nand_sets),
        .sets           = qt2410_nand_sets,
+       .ecc_mode       = NAND_ECC_SOFT,
 };
 
 /* UDC */
index 25a139bb9826dadfafd327bb1f2e1e4163993566..e86ad6a68a0b8f3f7c22e5ae6a5a595a611bec0e 100644 (file)
@@ -611,6 +611,7 @@ static struct s3c2410_platform_nand rx1950_nand_info = {
        .twrph1 = 15,
        .nr_sets = ARRAY_SIZE(rx1950_nand_sets),
        .sets = rx1950_nand_sets,
+       .ecc_mode = NAND_ECC_SOFT,
 };
 
 static struct s3c2410_udc_mach_info rx1950_udc_cfg __initdata = {
index cf55196f89ca34ae4139ede777bc6a35af05fead..a39fb9780dd30649aaf7a9890c46083914f0e6ba 100644 (file)
@@ -164,6 +164,7 @@ static struct s3c2410_platform_nand __initdata rx3715_nand_info = {
        .twrph1         = 15,
        .nr_sets        = ARRAY_SIZE(rx3715_nand_sets),
        .sets           = rx3715_nand_sets,
+       .ecc_mode       = NAND_ECC_SOFT,
 };
 
 static struct platform_device *rx3715_devices[] __initdata = {
index b4460d5f70112354e702ad799929db0d87d47aa3..f5e6322145fa9343d2a04d8d9aa9a088423054c0 100644 (file)
@@ -117,6 +117,7 @@ static struct s3c2410_platform_nand __initdata vstms_nand_info = {
        .twrph1         = 20,
        .nr_sets        = ARRAY_SIZE(vstms_nand_sets),
        .sets           = vstms_nand_sets,
+       .ecc_mode       = NAND_ECC_SOFT,
 };
 
 static struct platform_device *vstms_devices[] __initdata = {
index bc7dc1fcbf7dca8874e63a2bbbb9c24782f9bda1..59b5531f198743363eed55b3a316744eaae6d491 100644 (file)
@@ -204,6 +204,7 @@ static struct s3c2410_platform_nand hmt_nand_info = {
        .twrph1         = 40,
        .nr_sets        = ARRAY_SIZE(hmt_nand_sets),
        .sets           = hmt_nand_sets,
+       .ecc_mode       = NAND_ECC_SOFT,
 };
 
 static struct gpio_led hmt_leds[] = {
index ae999fb3fe6df564083391ba6f5a69f97bf7edb2..a3e3e25728b41f10e9c8e92908f60bda3c6b47fc 100644 (file)
@@ -142,6 +142,7 @@ static struct s3c2410_platform_nand mini6410_nand_info = {
        .twrph1         = 40,
        .nr_sets        = ARRAY_SIZE(mini6410_nand_sets),
        .sets           = mini6410_nand_sets,
+       .ecc_mode       = NAND_ECC_SOFT,
 };
 
 static struct s3c_fb_pd_win mini6410_lcd_type0_fb_win = {
index 4e240ffa7ac7fbf3227141019141edf23c85ab72..d6b3ffd7704bdf7c18d48a42b6f67969dc755a8f 100644 (file)
@@ -194,6 +194,7 @@ static struct s3c2410_platform_nand real6410_nand_info = {
        .twrph1         = 40,
        .nr_sets        = ARRAY_SIZE(real6410_nand_sets),
        .sets           = real6410_nand_sets,
+       .ecc_mode       = NAND_ECC_SOFT,
 };
 
 static struct platform_device *real6410_devices[] __initdata = {
index c023125989cfdb0967831119cb9c769f7b784305..60757af314d35392e8a600e79f5b6d47ad4016b1 100644 (file)
@@ -179,15 +179,6 @@ config MTD_NAND_S3C2410_DEBUG
        help
          Enable debugging of the S3C NAND driver
 
-config MTD_NAND_S3C2410_HWECC
-       bool "Samsung S3C NAND Hardware ECC"
-       depends on MTD_NAND_S3C2410
-       help
-         Enable the use of the controller's internal ECC generator when
-         using NAND. Early versions of the chips have had problems with
-         incorrect ECC generation, and if using these, the default of
-         software ECC is preferable.
-
 config MTD_NAND_NDFC
        tristate "NDFC NanD Flash Controller"
        depends on 4xx
index d459c19d78de383c1c2a88a1bcda0d1301b3c003..bb4ac3179d17f92360a3a0df1d9f49d9f3e857ac 100644 (file)
@@ -497,7 +497,6 @@ static int s3c2412_nand_devready(struct mtd_info *mtd)
 
 /* ECC handling functions */
 
-#ifdef CONFIG_MTD_NAND_S3C2410_HWECC
 static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat,
                                     u_char *read_ecc, u_char *calc_ecc)
 {
@@ -649,7 +648,6 @@ static int s3c2440_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
 
        return 0;
 }
-#endif
 
 /* over-ride the standard functions for a little more speed. We can
  * use read/write block to move the data buffers to/from the controller
@@ -858,50 +856,7 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
        nmtd->info         = info;
        nmtd->set          = set;
 
-#ifdef CONFIG_MTD_NAND_S3C2410_HWECC
-       chip->ecc.calculate = s3c2410_nand_calculate_ecc;
-       chip->ecc.correct   = s3c2410_nand_correct_data;
-       chip->ecc.mode      = NAND_ECC_HW;
-       chip->ecc.strength  = 1;
-
-       switch (info->cpu_type) {
-       case TYPE_S3C2410:
-               chip->ecc.hwctl     = s3c2410_nand_enable_hwecc;
-               chip->ecc.calculate = s3c2410_nand_calculate_ecc;
-               break;
-
-       case TYPE_S3C2412:
-               chip->ecc.hwctl     = s3c2412_nand_enable_hwecc;
-               chip->ecc.calculate = s3c2412_nand_calculate_ecc;
-               break;
-
-       case TYPE_S3C2440:
-               chip->ecc.hwctl     = s3c2440_nand_enable_hwecc;
-               chip->ecc.calculate = s3c2440_nand_calculate_ecc;
-               break;
-       }
-#else
-       chip->ecc.mode      = NAND_ECC_SOFT;
-       chip->ecc.algo  = NAND_ECC_HAMMING;
-#endif
-
-       if (set->disable_ecc)
-               chip->ecc.mode  = NAND_ECC_NONE;
-
-       switch (chip->ecc.mode) {
-       case NAND_ECC_NONE:
-               dev_info(info->device, "NAND ECC disabled\n");
-               break;
-       case NAND_ECC_SOFT:
-               dev_info(info->device, "NAND soft ECC\n");
-               break;
-       case NAND_ECC_HW:
-               dev_info(info->device, "NAND hardware ECC\n");
-               break;
-       default:
-               dev_info(info->device, "NAND ECC UNKNOWN\n");
-               break;
-       }
+       chip->ecc.mode = info->platform->ecc_mode;
 
        /* If you use u-boot BBT creation code, specifying this flag will
         * let the kernel fish out the BBT from the NAND, and also skip the
@@ -923,28 +878,74 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
  *
  * The internal state is currently limited to the ECC state information.
 */
-static void s3c2410_nand_update_chip(struct s3c2410_nand_info *info,
-                                    struct s3c2410_nand_mtd *nmtd)
+static int s3c2410_nand_update_chip(struct s3c2410_nand_info *info,
+                                   struct s3c2410_nand_mtd *nmtd)
 {
        struct nand_chip *chip = &nmtd->chip;
 
-       dev_dbg(info->device, "chip %p => page shift %d\n",
-               chip, chip->page_shift);
+       switch (chip->ecc.mode) {
 
-       if (chip->ecc.mode != NAND_ECC_HW)
-               return;
+       case NAND_ECC_NONE:
+               dev_info(info->device, "ECC disabled\n");
+               break;
+
+       case NAND_ECC_SOFT:
+               /*
+                * This driver expects Hamming based ECC when ecc_mode is set
+                * to NAND_ECC_SOFT. Force ecc.algo to NAND_ECC_HAMMING to
+                * avoid adding an extra ecc_algo field to
+                * s3c2410_platform_nand.
+                */
+               chip->ecc.algo = NAND_ECC_HAMMING;
+               dev_info(info->device, "soft ECC\n");
+               break;
+
+       case NAND_ECC_HW:
+               chip->ecc.calculate = s3c2410_nand_calculate_ecc;
+               chip->ecc.correct   = s3c2410_nand_correct_data;
+               chip->ecc.strength  = 1;
+
+               switch (info->cpu_type) {
+               case TYPE_S3C2410:
+                       chip->ecc.hwctl     = s3c2410_nand_enable_hwecc;
+                       chip->ecc.calculate = s3c2410_nand_calculate_ecc;
+                       break;
+
+               case TYPE_S3C2412:
+                       chip->ecc.hwctl     = s3c2412_nand_enable_hwecc;
+                       chip->ecc.calculate = s3c2412_nand_calculate_ecc;
+                       break;
+
+               case TYPE_S3C2440:
+                       chip->ecc.hwctl     = s3c2440_nand_enable_hwecc;
+                       chip->ecc.calculate = s3c2440_nand_calculate_ecc;
+                       break;
+               }
+
+               dev_dbg(info->device, "chip %p => page shift %d\n",
+                       chip, chip->page_shift);
 
                /* change the behaviour depending on whether we are using
                 * the large or small page nand device */
+               if (chip->page_shift > 10) {
+                       chip->ecc.size      = 256;
+                       chip->ecc.bytes     = 3;
+               } else {
+                       chip->ecc.size      = 512;
+                       chip->ecc.bytes     = 3;
+                       mtd_set_ooblayout(nand_to_mtd(chip),
+                                         &s3c2410_ooblayout_ops);
+               }
 
-       if (chip->page_shift > 10) {
-               chip->ecc.size      = 256;
-               chip->ecc.bytes     = 3;
-       } else {
-               chip->ecc.size      = 512;
-               chip->ecc.bytes     = 3;
-               mtd_set_ooblayout(nand_to_mtd(chip), &s3c2410_ooblayout_ops);
+               dev_info(info->device, "hardware ECC\n");
+               break;
+
+       default:
+               dev_err(info->device, "invalid ECC mode!\n");
+               return -EINVAL;
        }
+
+       return 0;
 }
 
 /* s3c24xx_nand_probe
@@ -1046,7 +1047,9 @@ static int s3c24xx_nand_probe(struct platform_device *pdev)
                                                 NULL);
 
                if (nmtd->scan_res == 0) {
-                       s3c2410_nand_update_chip(info, nmtd);
+                       err = s3c2410_nand_update_chip(info, nmtd);
+                       if (err < 0)
+                               goto exit_error;
                        nand_scan_tail(mtd);
                        s3c2410_nand_add_partition(info, nmtd, sets);
                }
index c55e42ee57fa0c9ba3083d6bf03b04fae275d13c..729af13d177351efc6369d40efc1206c60b91e15 100644 (file)
 #ifndef __MTD_NAND_S3C2410_H
 #define __MTD_NAND_S3C2410_H
 
+#include <linux/mtd/nand.h>
+
 /**
  * struct s3c2410_nand_set - define a set of one or more nand chips
- * @disable_ecc:       Entirely disable ECC - Dangerous
  * @flash_bbt:                 Openmoko u-boot can create a Bad Block Table
  *                     Setting this flag will allow the kernel to
  *                     look for it at boot time and also skip the NAND
@@ -31,7 +32,6 @@
  * a warning at boot time.
  */
 struct s3c2410_nand_set {
-       unsigned int            disable_ecc:1;
        unsigned int            flash_bbt:1;
 
        unsigned int            options;
@@ -51,6 +51,8 @@ struct s3c2410_platform_nand {
 
        unsigned int    ignore_unset_ecc:1;
 
+       nand_ecc_modes_t        ecc_mode;
+
        int                     nr_sets;
        struct s3c2410_nand_set *sets;