diff options
Diffstat (limited to 'drivers/mtd/nand/s3c2410.c')
-rw-r--r-- | drivers/mtd/nand/s3c2410.c | 123 |
1 files changed, 63 insertions, 60 deletions
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c index d459c19d78de..bb4ac3179d17 100644 --- a/drivers/mtd/nand/s3c2410.c +++ b/drivers/mtd/nand/s3c2410.c @@ -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); } |