aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPekon Gupta <pekon@ti.com>2014-02-26 05:23:12 -0500
committerBrian Norris <computersforpeace@gmail.com>2014-03-20 05:30:27 -0400
commitf5dc06fb71ae10c4f205a08f5ef26fd90fc122fc (patch)
tree24547188b4066545021652471bcc695c8b1ecdb9
parenta4c7ca004d984306c33df6d89c76ccd232317c21 (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.c68
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 */
1221static int __maybe_unused omap_calculate_ecc_bch(struct mtd_info *mtd, 1221static 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;