diff options
author | Pekon Gupta <pekon@ti.com> | 2014-02-26 05:23:12 -0500 |
---|---|---|
committer | Brian Norris <computersforpeace@gmail.com> | 2014-03-20 05:30:27 -0400 |
commit | f5dc06fb71ae10c4f205a08f5ef26fd90fc122fc (patch) | |
tree | 24547188b4066545021652471bcc695c8b1ecdb9 | |
parent | a4c7ca004d984306c33df6d89c76ccd232317c21 (diff) |
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, | |||
1219 | * Support calculating of BCH4/8 ecc vectors for the page | 1219 | * Support calculating of BCH4/8 ecc vectors for the page |
1220 | */ | 1220 | */ |
1221 | static int __maybe_unused omap_calculate_ecc_bch(struct mtd_info *mtd, | 1221 | static int __maybe_unused omap_calculate_ecc_bch(struct mtd_info *mtd, |
1222 | const u_char *dat, u_char *ecc_code) | 1222 | const u_char *dat, u_char *ecc_calc) |
1223 | { | 1223 | { |
1224 | struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, | 1224 | struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, |
1225 | mtd); | 1225 | mtd); |
1226 | int eccbytes = info->nand.ecc.bytes; | ||
1227 | struct gpmc_nand_regs *gpmc_regs = &info->reg; | ||
1228 | u8 *ecc_code; | ||
1226 | unsigned long nsectors, bch_val1, bch_val2, bch_val3, bch_val4; | 1229 | unsigned long nsectors, bch_val1, bch_val2, bch_val3, bch_val4; |
1227 | int i, eccbchtsel; | 1230 | int i; |
1228 | 1231 | ||
1229 | nsectors = ((readl(info->reg.gpmc_ecc_config) >> 4) & 0x7) + 1; | 1232 | nsectors = ((readl(info->reg.gpmc_ecc_config) >> 4) & 0x7) + 1; |
1230 | /* | ||
1231 | * find BCH scheme used | ||
1232 | * 0 -> BCH4 | ||
1233 | * 1 -> BCH8 | ||
1234 | */ | ||
1235 | eccbchtsel = ((readl(info->reg.gpmc_ecc_config) >> 12) & 0x3); | ||
1236 | |||
1237 | for (i = 0; i < nsectors; i++) { | 1233 | for (i = 0; i < nsectors; i++) { |
1238 | 1234 | ecc_code = ecc_calc; | |
1239 | /* Read hw-computed remainder */ | 1235 | switch (info->ecc_opt) { |
1240 | bch_val1 = readl(info->reg.gpmc_bch_result0[i]); | 1236 | case OMAP_ECC_BCH8_CODE_HW: |
1241 | bch_val2 = readl(info->reg.gpmc_bch_result1[i]); | 1237 | bch_val1 = readl(gpmc_regs->gpmc_bch_result0[i]); |
1242 | if (eccbchtsel) { | 1238 | bch_val2 = readl(gpmc_regs->gpmc_bch_result1[i]); |
1243 | bch_val3 = readl(info->reg.gpmc_bch_result2[i]); | 1239 | bch_val3 = readl(gpmc_regs->gpmc_bch_result2[i]); |
1244 | bch_val4 = readl(info->reg.gpmc_bch_result3[i]); | 1240 | bch_val4 = readl(gpmc_regs->gpmc_bch_result3[i]); |
1245 | } | ||
1246 | |||
1247 | if (eccbchtsel) { | ||
1248 | /* BCH8 ecc scheme */ | ||
1249 | *ecc_code++ = (bch_val4 & 0xFF); | 1241 | *ecc_code++ = (bch_val4 & 0xFF); |
1250 | *ecc_code++ = ((bch_val3 >> 24) & 0xFF); | 1242 | *ecc_code++ = ((bch_val3 >> 24) & 0xFF); |
1251 | *ecc_code++ = ((bch_val3 >> 16) & 0xFF); | 1243 | *ecc_code++ = ((bch_val3 >> 16) & 0xFF); |
@@ -1259,14 +1251,10 @@ static int __maybe_unused omap_calculate_ecc_bch(struct mtd_info *mtd, | |||
1259 | *ecc_code++ = ((bch_val1 >> 16) & 0xFF); | 1251 | *ecc_code++ = ((bch_val1 >> 16) & 0xFF); |
1260 | *ecc_code++ = ((bch_val1 >> 8) & 0xFF); | 1252 | *ecc_code++ = ((bch_val1 >> 8) & 0xFF); |
1261 | *ecc_code++ = (bch_val1 & 0xFF); | 1253 | *ecc_code++ = (bch_val1 & 0xFF); |
1262 | /* | 1254 | break; |
1263 | * Setting 14th byte to zero to handle | 1255 | case OMAP_ECC_BCH4_CODE_HW: |
1264 | * erased page & maintain compatibility | 1256 | bch_val1 = readl(gpmc_regs->gpmc_bch_result0[i]); |
1265 | * with RBL | 1257 | bch_val2 = readl(gpmc_regs->gpmc_bch_result1[i]); |
1266 | */ | ||
1267 | *ecc_code++ = 0x0; | ||
1268 | } else { | ||
1269 | /* BCH4 ecc scheme */ | ||
1270 | *ecc_code++ = ((bch_val2 >> 12) & 0xFF); | 1258 | *ecc_code++ = ((bch_val2 >> 12) & 0xFF); |
1271 | *ecc_code++ = ((bch_val2 >> 4) & 0xFF); | 1259 | *ecc_code++ = ((bch_val2 >> 4) & 0xFF); |
1272 | *ecc_code++ = ((bch_val2 & 0xF) << 4) | | 1260 | *ecc_code++ = ((bch_val2 & 0xF) << 4) | |
@@ -1275,12 +1263,26 @@ static int __maybe_unused omap_calculate_ecc_bch(struct mtd_info *mtd, | |||
1275 | *ecc_code++ = ((bch_val1 >> 12) & 0xFF); | 1263 | *ecc_code++ = ((bch_val1 >> 12) & 0xFF); |
1276 | *ecc_code++ = ((bch_val1 >> 4) & 0xFF); | 1264 | *ecc_code++ = ((bch_val1 >> 4) & 0xFF); |
1277 | *ecc_code++ = ((bch_val1 & 0xF) << 4); | 1265 | *ecc_code++ = ((bch_val1 & 0xF) << 4); |
1278 | /* | 1266 | break; |
1279 | * Setting 8th byte to zero to handle | 1267 | default: |
1280 | * erased page | 1268 | return -EINVAL; |
1281 | */ | ||
1282 | *ecc_code++ = 0x0; | ||
1283 | } | 1269 | } |
1270 | |||
1271 | /* ECC scheme specific syndrome customizations */ | ||
1272 | switch (info->ecc_opt) { | ||
1273 | case OMAP_ECC_BCH4_CODE_HW: | ||
1274 | /* Set 8th ECC byte as 0x0 for ROM compatibility */ | ||
1275 | ecc_calc[eccbytes - 1] = 0x0; | ||
1276 | break; | ||
1277 | case OMAP_ECC_BCH8_CODE_HW: | ||
1278 | /* Set 14th ECC byte as 0x0 for ROM compatibility */ | ||
1279 | ecc_calc[eccbytes - 1] = 0x0; | ||
1280 | break; | ||
1281 | default: | ||
1282 | return -EINVAL; | ||
1283 | } | ||
1284 | |||
1285 | ecc_calc += eccbytes; | ||
1284 | } | 1286 | } |
1285 | 1287 | ||
1286 | return 0; | 1288 | return 0; |