Skip to content

Commit

Permalink
mtd: s3c2410: make ecc mode configurable via platform data
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Sergio Prado authored and Boris Brezillon committed Nov 7, 2016
1 parent 6685924 commit e9f66ae
Show file tree
Hide file tree
Showing 18 changed files with 82 additions and 71 deletions.
1 change: 1 addition & 0 deletions arch/arm/mach-s3c24xx/common-smdk.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
1 change: 1 addition & 0 deletions arch/arm/mach-s3c24xx/mach-anubis.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
1 change: 1 addition & 0 deletions arch/arm/mach-s3c24xx/mach-at2440evb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
1 change: 1 addition & 0 deletions arch/arm/mach-s3c24xx/mach-bast.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
1 change: 1 addition & 0 deletions arch/arm/mach-s3c24xx/mach-gta02.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};


Expand Down
1 change: 1 addition & 0 deletions arch/arm/mach-s3c24xx/mach-jive.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions arch/arm/mach-s3c24xx/mach-mini2440.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
1 change: 1 addition & 0 deletions arch/arm/mach-s3c24xx/mach-osiris.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
1 change: 1 addition & 0 deletions arch/arm/mach-s3c24xx/mach-qt2410.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
1 change: 1 addition & 0 deletions arch/arm/mach-s3c24xx/mach-rx1950.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down
1 change: 1 addition & 0 deletions arch/arm/mach-s3c24xx/mach-rx3715.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down
1 change: 1 addition & 0 deletions arch/arm/mach-s3c24xx/mach-vstms.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down
1 change: 1 addition & 0 deletions arch/arm/mach-s3c64xx/mach-hmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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[] = {
Expand Down
1 change: 1 addition & 0 deletions arch/arm/mach-s3c64xx/mach-mini6410.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down
1 change: 1 addition & 0 deletions arch/arm/mach-s3c64xx/mach-real6410.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down
9 changes: 0 additions & 9 deletions drivers/mtd/nand/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
123 changes: 63 additions & 60 deletions drivers/mtd/nand/s3c2410.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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);
}
Expand Down
6 changes: 4 additions & 2 deletions include/linux/platform_data/mtd-nand-s3c2410.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@
#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
Expand All @@ -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;
Expand All @@ -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;

Expand Down

0 comments on commit e9f66ae

Please sign in to comment.