Commit e9f66ae2 authored by Sergio Prado's avatar Sergio Prado Committed by Boris Brezillon

mtd: s3c2410: make ecc mode configurable via platform data

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: default avatarSergio Prado <sergio.prado@e-labworks.com>
Acked-by: default avatarKrzysztof Kozlowski <krzk@kernel.org>
Signed-off-by: default avatarBoris Brezillon <boris.brezillon@free-electrons.com>
parent 66859249
...@@ -171,6 +171,7 @@ static struct s3c2410_platform_nand smdk_nand_info = { ...@@ -171,6 +171,7 @@ static struct s3c2410_platform_nand smdk_nand_info = {
.twrph1 = 20, .twrph1 = 20,
.nr_sets = ARRAY_SIZE(smdk_nand_sets), .nr_sets = ARRAY_SIZE(smdk_nand_sets),
.sets = smdk_nand_sets, .sets = smdk_nand_sets,
.ecc_mode = NAND_ECC_SOFT,
}; };
/* devices we initialise */ /* devices we initialise */
......
...@@ -223,6 +223,7 @@ static struct s3c2410_platform_nand __initdata anubis_nand_info = { ...@@ -223,6 +223,7 @@ static struct s3c2410_platform_nand __initdata anubis_nand_info = {
.nr_sets = ARRAY_SIZE(anubis_nand_sets), .nr_sets = ARRAY_SIZE(anubis_nand_sets),
.sets = anubis_nand_sets, .sets = anubis_nand_sets,
.select_chip = anubis_nand_select, .select_chip = anubis_nand_select,
.ecc_mode = NAND_ECC_SOFT,
}; };
/* IDE channels */ /* IDE channels */
......
...@@ -114,6 +114,7 @@ static struct s3c2410_platform_nand __initdata at2440evb_nand_info = { ...@@ -114,6 +114,7 @@ static struct s3c2410_platform_nand __initdata at2440evb_nand_info = {
.twrph1 = 40, .twrph1 = 40,
.nr_sets = ARRAY_SIZE(at2440evb_nand_sets), .nr_sets = ARRAY_SIZE(at2440evb_nand_sets),
.sets = at2440evb_nand_sets, .sets = at2440evb_nand_sets,
.ecc_mode = NAND_ECC_SOFT,
}; };
/* DM9000AEP 10/100 ethernet controller */ /* DM9000AEP 10/100 ethernet controller */
......
...@@ -299,6 +299,7 @@ static struct s3c2410_platform_nand __initdata bast_nand_info = { ...@@ -299,6 +299,7 @@ static struct s3c2410_platform_nand __initdata bast_nand_info = {
.nr_sets = ARRAY_SIZE(bast_nand_sets), .nr_sets = ARRAY_SIZE(bast_nand_sets),
.sets = bast_nand_sets, .sets = bast_nand_sets,
.select_chip = bast_nand_select, .select_chip = bast_nand_select,
.ecc_mode = NAND_ECC_SOFT,
}; };
/* DM9000 */ /* DM9000 */
......
...@@ -443,6 +443,7 @@ static struct s3c2410_platform_nand __initdata gta02_nand_info = { ...@@ -443,6 +443,7 @@ static struct s3c2410_platform_nand __initdata gta02_nand_info = {
.twrph1 = 15, .twrph1 = 15,
.nr_sets = ARRAY_SIZE(gta02_nand_sets), .nr_sets = ARRAY_SIZE(gta02_nand_sets),
.sets = gta02_nand_sets, .sets = gta02_nand_sets,
.ecc_mode = NAND_ECC_SOFT,
}; };
......
...@@ -232,6 +232,7 @@ static struct s3c2410_platform_nand __initdata jive_nand_info = { ...@@ -232,6 +232,7 @@ static struct s3c2410_platform_nand __initdata jive_nand_info = {
.twrph1 = 40, .twrph1 = 40,
.sets = jive_nand_sets, .sets = jive_nand_sets,
.nr_sets = ARRAY_SIZE(jive_nand_sets), .nr_sets = ARRAY_SIZE(jive_nand_sets),
.ecc_mode = NAND_ECC_SOFT,
}; };
static int __init jive_mtdset(char *options) static int __init jive_mtdset(char *options)
......
...@@ -287,6 +287,7 @@ static struct s3c2410_platform_nand mini2440_nand_info __initdata = { ...@@ -287,6 +287,7 @@ static struct s3c2410_platform_nand mini2440_nand_info __initdata = {
.nr_sets = ARRAY_SIZE(mini2440_nand_sets), .nr_sets = ARRAY_SIZE(mini2440_nand_sets),
.sets = mini2440_nand_sets, .sets = mini2440_nand_sets,
.ignore_unset_ecc = 1, .ignore_unset_ecc = 1,
.ecc_mode = NAND_ECC_SOFT,
}; };
/* DM9000AEP 10/100 ethernet controller */ /* DM9000AEP 10/100 ethernet controller */
......
...@@ -238,6 +238,7 @@ static struct s3c2410_platform_nand __initdata osiris_nand_info = { ...@@ -238,6 +238,7 @@ static struct s3c2410_platform_nand __initdata osiris_nand_info = {
.nr_sets = ARRAY_SIZE(osiris_nand_sets), .nr_sets = ARRAY_SIZE(osiris_nand_sets),
.sets = osiris_nand_sets, .sets = osiris_nand_sets,
.select_chip = osiris_nand_select, .select_chip = osiris_nand_select,
.ecc_mode = NAND_ECC_SOFT,
}; };
/* PCMCIA control and configuration */ /* PCMCIA control and configuration */
......
...@@ -284,6 +284,7 @@ static struct s3c2410_platform_nand __initdata qt2410_nand_info = { ...@@ -284,6 +284,7 @@ static struct s3c2410_platform_nand __initdata qt2410_nand_info = {
.twrph1 = 20, .twrph1 = 20,
.nr_sets = ARRAY_SIZE(qt2410_nand_sets), .nr_sets = ARRAY_SIZE(qt2410_nand_sets),
.sets = qt2410_nand_sets, .sets = qt2410_nand_sets,
.ecc_mode = NAND_ECC_SOFT,
}; };
/* UDC */ /* UDC */
......
...@@ -611,6 +611,7 @@ static struct s3c2410_platform_nand rx1950_nand_info = { ...@@ -611,6 +611,7 @@ static struct s3c2410_platform_nand rx1950_nand_info = {
.twrph1 = 15, .twrph1 = 15,
.nr_sets = ARRAY_SIZE(rx1950_nand_sets), .nr_sets = ARRAY_SIZE(rx1950_nand_sets),
.sets = rx1950_nand_sets, .sets = rx1950_nand_sets,
.ecc_mode = NAND_ECC_SOFT,
}; };
static struct s3c2410_udc_mach_info rx1950_udc_cfg __initdata = { static struct s3c2410_udc_mach_info rx1950_udc_cfg __initdata = {
......
...@@ -164,6 +164,7 @@ static struct s3c2410_platform_nand __initdata rx3715_nand_info = { ...@@ -164,6 +164,7 @@ static struct s3c2410_platform_nand __initdata rx3715_nand_info = {
.twrph1 = 15, .twrph1 = 15,
.nr_sets = ARRAY_SIZE(rx3715_nand_sets), .nr_sets = ARRAY_SIZE(rx3715_nand_sets),
.sets = rx3715_nand_sets, .sets = rx3715_nand_sets,
.ecc_mode = NAND_ECC_SOFT,
}; };
static struct platform_device *rx3715_devices[] __initdata = { static struct platform_device *rx3715_devices[] __initdata = {
......
...@@ -117,6 +117,7 @@ static struct s3c2410_platform_nand __initdata vstms_nand_info = { ...@@ -117,6 +117,7 @@ static struct s3c2410_platform_nand __initdata vstms_nand_info = {
.twrph1 = 20, .twrph1 = 20,
.nr_sets = ARRAY_SIZE(vstms_nand_sets), .nr_sets = ARRAY_SIZE(vstms_nand_sets),
.sets = vstms_nand_sets, .sets = vstms_nand_sets,
.ecc_mode = NAND_ECC_SOFT,
}; };
static struct platform_device *vstms_devices[] __initdata = { static struct platform_device *vstms_devices[] __initdata = {
......
...@@ -204,6 +204,7 @@ static struct s3c2410_platform_nand hmt_nand_info = { ...@@ -204,6 +204,7 @@ static struct s3c2410_platform_nand hmt_nand_info = {
.twrph1 = 40, .twrph1 = 40,
.nr_sets = ARRAY_SIZE(hmt_nand_sets), .nr_sets = ARRAY_SIZE(hmt_nand_sets),
.sets = hmt_nand_sets, .sets = hmt_nand_sets,
.ecc_mode = NAND_ECC_SOFT,
}; };
static struct gpio_led hmt_leds[] = { static struct gpio_led hmt_leds[] = {
......
...@@ -142,6 +142,7 @@ static struct s3c2410_platform_nand mini6410_nand_info = { ...@@ -142,6 +142,7 @@ static struct s3c2410_platform_nand mini6410_nand_info = {
.twrph1 = 40, .twrph1 = 40,
.nr_sets = ARRAY_SIZE(mini6410_nand_sets), .nr_sets = ARRAY_SIZE(mini6410_nand_sets),
.sets = mini6410_nand_sets, .sets = mini6410_nand_sets,
.ecc_mode = NAND_ECC_SOFT,
}; };
static struct s3c_fb_pd_win mini6410_lcd_type0_fb_win = { static struct s3c_fb_pd_win mini6410_lcd_type0_fb_win = {
......
...@@ -194,6 +194,7 @@ static struct s3c2410_platform_nand real6410_nand_info = { ...@@ -194,6 +194,7 @@ static struct s3c2410_platform_nand real6410_nand_info = {
.twrph1 = 40, .twrph1 = 40,
.nr_sets = ARRAY_SIZE(real6410_nand_sets), .nr_sets = ARRAY_SIZE(real6410_nand_sets),
.sets = real6410_nand_sets, .sets = real6410_nand_sets,
.ecc_mode = NAND_ECC_SOFT,
}; };
static struct platform_device *real6410_devices[] __initdata = { static struct platform_device *real6410_devices[] __initdata = {
......
...@@ -179,15 +179,6 @@ config MTD_NAND_S3C2410_DEBUG ...@@ -179,15 +179,6 @@ config MTD_NAND_S3C2410_DEBUG
help help
Enable debugging of the S3C NAND driver 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 config MTD_NAND_NDFC
tristate "NDFC NanD Flash Controller" tristate "NDFC NanD Flash Controller"
depends on 4xx depends on 4xx
......
...@@ -497,7 +497,6 @@ static int s3c2412_nand_devready(struct mtd_info *mtd) ...@@ -497,7 +497,6 @@ static int s3c2412_nand_devready(struct mtd_info *mtd)
/* ECC handling functions */ /* ECC handling functions */
#ifdef CONFIG_MTD_NAND_S3C2410_HWECC
static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat, static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat,
u_char *read_ecc, u_char *calc_ecc) 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, ...@@ -649,7 +648,6 @@ static int s3c2440_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
return 0; return 0;
} }
#endif
/* over-ride the standard functions for a little more speed. We can /* 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 * 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, ...@@ -858,50 +856,7 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
nmtd->info = info; nmtd->info = info;
nmtd->set = set; nmtd->set = set;
#ifdef CONFIG_MTD_NAND_S3C2410_HWECC chip->ecc.mode = info->platform->ecc_mode;
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;
}
/* If you use u-boot BBT creation code, specifying this flag will /* 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 * 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, ...@@ -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. * The internal state is currently limited to the ECC state information.
*/ */
static void s3c2410_nand_update_chip(struct s3c2410_nand_info *info, static int s3c2410_nand_update_chip(struct s3c2410_nand_info *info,
struct s3c2410_nand_mtd *nmtd) struct s3c2410_nand_mtd *nmtd)
{ {
struct nand_chip *chip = &nmtd->chip; struct nand_chip *chip = &nmtd->chip;
switch (chip->ecc.mode) {
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", dev_dbg(info->device, "chip %p => page shift %d\n",
chip, chip->page_shift); chip, chip->page_shift);
if (chip->ecc.mode != NAND_ECC_HW)
return;
/* change the behaviour depending on whether we are using /* change the behaviour depending on whether we are using
* the large or small page nand device */ * the large or small page nand device */
if (chip->page_shift > 10) { if (chip->page_shift > 10) {
chip->ecc.size = 256; chip->ecc.size = 256;
chip->ecc.bytes = 3; chip->ecc.bytes = 3;
} else { } else {
chip->ecc.size = 512; chip->ecc.size = 512;
chip->ecc.bytes = 3; chip->ecc.bytes = 3;
mtd_set_ooblayout(nand_to_mtd(chip), &s3c2410_ooblayout_ops); 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 /* s3c24xx_nand_probe
...@@ -1046,7 +1047,9 @@ static int s3c24xx_nand_probe(struct platform_device *pdev) ...@@ -1046,7 +1047,9 @@ static int s3c24xx_nand_probe(struct platform_device *pdev)
NULL); NULL);
if (nmtd->scan_res == 0) { 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); nand_scan_tail(mtd);
s3c2410_nand_add_partition(info, nmtd, sets); s3c2410_nand_add_partition(info, nmtd, sets);
} }
......
...@@ -12,9 +12,10 @@ ...@@ -12,9 +12,10 @@
#ifndef __MTD_NAND_S3C2410_H #ifndef __MTD_NAND_S3C2410_H
#define __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 * 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 * @flash_bbt: Openmoko u-boot can create a Bad Block Table
* Setting this flag will allow the kernel to * Setting this flag will allow the kernel to
* look for it at boot time and also skip the NAND * look for it at boot time and also skip the NAND
...@@ -31,7 +32,6 @@ ...@@ -31,7 +32,6 @@
* a warning at boot time. * a warning at boot time.
*/ */
struct s3c2410_nand_set { struct s3c2410_nand_set {
unsigned int disable_ecc:1;
unsigned int flash_bbt:1; unsigned int flash_bbt:1;
unsigned int options; unsigned int options;
...@@ -51,6 +51,8 @@ struct s3c2410_platform_nand { ...@@ -51,6 +51,8 @@ struct s3c2410_platform_nand {
unsigned int ignore_unset_ecc:1; unsigned int ignore_unset_ecc:1;
nand_ecc_modes_t ecc_mode;
int nr_sets; int nr_sets;
struct s3c2410_nand_set *sets; struct s3c2410_nand_set *sets;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment