diff options
author | Pekon Gupta <pekon@ti.com> | 2014-02-26 14:23:12 +0400 |
---|---|---|
committer | Brian Norris <computersforpeace@gmail.com> | 2014-03-20 13:30:27 +0400 |
commit | f5dc06fb71ae10c4f205a08f5ef26fd90fc122fc (patch) | |
tree | 24547188b4066545021652471bcc695c8b1ecdb9 | |
parent | a4c7ca004d984306c33df6d89c76ccd232317c21 (diff) | |
download | linux-f5dc06fb71ae10c4f205a08f5ef26fd90fc122fc.tar.xz |
mtd: nand: omap: ecc.calculate: refactor omap_calculate_ecc_bch for BCHx_HW ecc-scheme
OMAP NAND driver supports multiple flavours of BCH4 and BCH8 ECC algorithms.
+------+------------------------------------+---------------+---------------+
| Algo | ECC scheme |ECC calculation|Error detection|
+------+------------------------------------+---------------+---------------+
| |OMAP_ECC_BCH4_CODE_HW_DETECTION_SW |H/W (GPMC) |S/W |
| BCH4 |OMAP_ECC_BCH4_CODE_HW |H/W (GPMC) |H/W (ELM) |
+------+------------------------------------+---------------+---------------+
| |OMAP_ECC_BCH8_CODE_HW_DETECTION_SW |H/W (GPMC) |S/W |
| BCH8 |OMAP_ECC_BCH8_CODE_HW |H/W (GPMC) |H/W (ELM) |
+------+------------------------------------+---------------+---------------+
This patch refactors omap_calculate_ecc_bch() so that
- separate out ecc-scheme specific code so that common-code can be reused
between different implementations of same ECC algorithm.
- new ecc-schemes can be added with ease in future.
Tested-by: Stefan Roese <sr@denx.de>
Signed-off-by: Pekon Gupta <pekon@ti.com>
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
-rw-r--r-- | drivers/mtd/nand/omap2.c | 68 |
1 files changed, 35 insertions, 33 deletions
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 4b98ee52e5e1..2ccd557bf77d 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -1219,33 +1219,25 @@ static int omap3_calculate_ecc_bch8(struct mtd_info *mtd, const u_char *dat, * Support calculating of BCH4/8 ecc vectors for the page */ static int __maybe_unused omap_calculate_ecc_bch(struct mtd_info *mtd, - const u_char *dat, u_char *ecc_code) + const u_char *dat, u_char *ecc_calc) { struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, mtd); + int eccbytes = info->nand.ecc.bytes; + struct gpmc_nand_regs *gpmc_regs = &info->reg; + u8 *ecc_code; unsigned long nsectors, bch_val1, bch_val2, bch_val3, bch_val4; - int i, eccbchtsel; + int i; nsectors = ((readl(info->reg.gpmc_ecc_config) >> 4) & 0x7) + 1; - /* - * find BCH scheme used - * 0 -> BCH4 - * 1 -> BCH8 - */ - eccbchtsel = ((readl(info->reg.gpmc_ecc_config) >> 12) & 0x3); - for (i = 0; i < nsectors; i++) { - - /* Read hw-computed remainder */ - bch_val1 = readl(info->reg.gpmc_bch_result0[i]); - bch_val2 = readl(info->reg.gpmc_bch_result1[i]); - if (eccbchtsel) { - bch_val3 = readl(info->reg.gpmc_bch_result2[i]); - bch_val4 = readl(info->reg.gpmc_bch_result3[i]); - } - - if (eccbchtsel) { - /* BCH8 ecc scheme */ + ecc_code = ecc_calc; + switch (info->ecc_opt) { + case OMAP_ECC_BCH8_CODE_HW: + bch_val1 = readl(gpmc_regs->gpmc_bch_result0[i]); + bch_val2 = readl(gpmc_regs->gpmc_bch_result1[i]); + bch_val3 = readl(gpmc_regs->gpmc_bch_result2[i]); + bch_val4 = readl(gpmc_regs->gpmc_bch_result3[i]); *ecc_code++ = (bch_val4 & 0xFF); *ecc_code++ = ((bch_val3 >> 24) & 0xFF); *ecc_code++ = ((bch_val3 >> 16) & 0xFF); @@ -1259,14 +1251,10 @@ static int __maybe_unused omap_calculate_ecc_bch(struct mtd_info *mtd, *ecc_code++ = ((bch_val1 >> 16) & 0xFF); *ecc_code++ = ((bch_val1 >> 8) & 0xFF); *ecc_code++ = (bch_val1 & 0xFF); - /* - * Setting 14th byte to zero to handle - * erased page & maintain compatibility - * with RBL - */ - *ecc_code++ = 0x0; - } else { - /* BCH4 ecc scheme */ + break; + case OMAP_ECC_BCH4_CODE_HW: + bch_val1 = readl(gpmc_regs->gpmc_bch_result0[i]); + bch_val2 = readl(gpmc_regs->gpmc_bch_result1[i]); *ecc_code++ = ((bch_val2 >> 12) & 0xFF); *ecc_code++ = ((bch_val2 >> 4) & 0xFF); *ecc_code++ = ((bch_val2 & 0xF) << 4) | @@ -1275,12 +1263,26 @@ static int __maybe_unused omap_calculate_ecc_bch(struct mtd_info *mtd, *ecc_code++ = ((bch_val1 >> 12) & 0xFF); *ecc_code++ = ((bch_val1 >> 4) & 0xFF); *ecc_code++ = ((bch_val1 & 0xF) << 4); - /* - * Setting 8th byte to zero to handle - * erased page - */ - *ecc_code++ = 0x0; + break; + default: + return -EINVAL; } + + /* ECC scheme specific syndrome customizations */ + switch (info->ecc_opt) { + case OMAP_ECC_BCH4_CODE_HW: + /* Set 8th ECC byte as 0x0 for ROM compatibility */ + ecc_calc[eccbytes - 1] = 0x0; + break; + case OMAP_ECC_BCH8_CODE_HW: + /* Set 14th ECC byte as 0x0 for ROM compatibility */ + ecc_calc[eccbytes - 1] = 0x0; + break; + default: + return -EINVAL; + } + + ecc_calc += eccbytes; } return 0; |