aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand/omap2.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/nand/omap2.c')
-rw-r--r--drivers/mtd/nand/omap2.c108
1 files changed, 101 insertions, 7 deletions
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 1ff49b80bdaf..f0ed92e210a1 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -137,6 +137,10 @@
137#define BADBLOCK_MARKER_LENGTH 2 137#define BADBLOCK_MARKER_LENGTH 2
138 138
139#ifdef CONFIG_MTD_NAND_OMAP_BCH 139#ifdef CONFIG_MTD_NAND_OMAP_BCH
140static u_char bch16_vector[] = {0xf5, 0x24, 0x1c, 0xd0, 0x61, 0xb3, 0xf1, 0x55,
141 0x2e, 0x2c, 0x86, 0xa3, 0xed, 0x36, 0x1b, 0x78,
142 0x48, 0x76, 0xa9, 0x3b, 0x97, 0xd1, 0x7a, 0x93,
143 0x07, 0x0e};
140static u_char bch8_vector[] = {0xf3, 0xdb, 0x14, 0x16, 0x8b, 0xd2, 0xbe, 0xcc, 144static u_char bch8_vector[] = {0xf3, 0xdb, 0x14, 0x16, 0x8b, 0xd2, 0xbe, 0xcc,
141 0xac, 0x6b, 0xff, 0x99, 0x7b}; 145 0xac, 0x6b, 0xff, 0x99, 0x7b};
142static u_char bch4_vector[] = {0x00, 0x6b, 0x31, 0xdd, 0x41, 0xbc, 0x10}; 146static u_char bch4_vector[] = {0x00, 0x6b, 0x31, 0xdd, 0x41, 0xbc, 0x10};
@@ -1114,6 +1118,19 @@ static void __maybe_unused omap_enable_hwecc_bch(struct mtd_info *mtd, int mode)
1114 ecc_size1 = BCH_ECC_SIZE1; 1118 ecc_size1 = BCH_ECC_SIZE1;
1115 } 1119 }
1116 break; 1120 break;
1121 case OMAP_ECC_BCH16_CODE_HW:
1122 bch_type = 0x2;
1123 nsectors = chip->ecc.steps;
1124 if (mode == NAND_ECC_READ) {
1125 wr_mode = 0x01;
1126 ecc_size0 = 52; /* ECC bits in nibbles per sector */
1127 ecc_size1 = 0; /* non-ECC bits in nibbles per sector */
1128 } else {
1129 wr_mode = 0x01;
1130 ecc_size0 = 0; /* extra bits in nibbles per sector */
1131 ecc_size1 = 52; /* OOB bits in nibbles per sector */
1132 }
1133 break;
1117 default: 1134 default:
1118 return; 1135 return;
1119 } 1136 }
@@ -1162,7 +1179,8 @@ static int __maybe_unused omap_calculate_ecc_bch(struct mtd_info *mtd,
1162 struct gpmc_nand_regs *gpmc_regs = &info->reg; 1179 struct gpmc_nand_regs *gpmc_regs = &info->reg;
1163 u8 *ecc_code; 1180 u8 *ecc_code;
1164 unsigned long nsectors, bch_val1, bch_val2, bch_val3, bch_val4; 1181 unsigned long nsectors, bch_val1, bch_val2, bch_val3, bch_val4;
1165 int i; 1182 u32 val;
1183 int i, j;
1166 1184
1167 nsectors = ((readl(info->reg.gpmc_ecc_config) >> 4) & 0x7) + 1; 1185 nsectors = ((readl(info->reg.gpmc_ecc_config) >> 4) & 0x7) + 1;
1168 for (i = 0; i < nsectors; i++) { 1186 for (i = 0; i < nsectors; i++) {
@@ -1201,6 +1219,41 @@ static int __maybe_unused omap_calculate_ecc_bch(struct mtd_info *mtd,
1201 *ecc_code++ = ((bch_val1 >> 4) & 0xFF); 1219 *ecc_code++ = ((bch_val1 >> 4) & 0xFF);
1202 *ecc_code++ = ((bch_val1 & 0xF) << 4); 1220 *ecc_code++ = ((bch_val1 & 0xF) << 4);
1203 break; 1221 break;
1222 case OMAP_ECC_BCH16_CODE_HW:
1223 val = readl(gpmc_regs->gpmc_bch_result6[i]);
1224 ecc_code[0] = ((val >> 8) & 0xFF);
1225 ecc_code[1] = ((val >> 0) & 0xFF);
1226 val = readl(gpmc_regs->gpmc_bch_result5[i]);
1227 ecc_code[2] = ((val >> 24) & 0xFF);
1228 ecc_code[3] = ((val >> 16) & 0xFF);
1229 ecc_code[4] = ((val >> 8) & 0xFF);
1230 ecc_code[5] = ((val >> 0) & 0xFF);
1231 val = readl(gpmc_regs->gpmc_bch_result4[i]);
1232 ecc_code[6] = ((val >> 24) & 0xFF);
1233 ecc_code[7] = ((val >> 16) & 0xFF);
1234 ecc_code[8] = ((val >> 8) & 0xFF);
1235 ecc_code[9] = ((val >> 0) & 0xFF);
1236 val = readl(gpmc_regs->gpmc_bch_result3[i]);
1237 ecc_code[10] = ((val >> 24) & 0xFF);
1238 ecc_code[11] = ((val >> 16) & 0xFF);
1239 ecc_code[12] = ((val >> 8) & 0xFF);
1240 ecc_code[13] = ((val >> 0) & 0xFF);
1241 val = readl(gpmc_regs->gpmc_bch_result2[i]);
1242 ecc_code[14] = ((val >> 24) & 0xFF);
1243 ecc_code[15] = ((val >> 16) & 0xFF);
1244 ecc_code[16] = ((val >> 8) & 0xFF);
1245 ecc_code[17] = ((val >> 0) & 0xFF);
1246 val = readl(gpmc_regs->gpmc_bch_result1[i]);
1247 ecc_code[18] = ((val >> 24) & 0xFF);
1248 ecc_code[19] = ((val >> 16) & 0xFF);
1249 ecc_code[20] = ((val >> 8) & 0xFF);
1250 ecc_code[21] = ((val >> 0) & 0xFF);
1251 val = readl(gpmc_regs->gpmc_bch_result0[i]);
1252 ecc_code[22] = ((val >> 24) & 0xFF);
1253 ecc_code[23] = ((val >> 16) & 0xFF);
1254 ecc_code[24] = ((val >> 8) & 0xFF);
1255 ecc_code[25] = ((val >> 0) & 0xFF);
1256 break;
1204 default: 1257 default:
1205 return -EINVAL; 1258 return -EINVAL;
1206 } 1259 }
@@ -1210,8 +1263,8 @@ static int __maybe_unused omap_calculate_ecc_bch(struct mtd_info *mtd,
1210 case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW: 1263 case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW:
1211 /* Add constant polynomial to remainder, so that 1264 /* Add constant polynomial to remainder, so that
1212 * ECC of blank pages results in 0x0 on reading back */ 1265 * ECC of blank pages results in 0x0 on reading back */
1213 for (i = 0; i < eccbytes; i++) 1266 for (j = 0; j < eccbytes; j++)
1214 ecc_calc[i] ^= bch4_polynomial[i]; 1267 ecc_calc[j] ^= bch4_polynomial[j];
1215 break; 1268 break;
1216 case OMAP_ECC_BCH4_CODE_HW: 1269 case OMAP_ECC_BCH4_CODE_HW:
1217 /* Set 8th ECC byte as 0x0 for ROM compatibility */ 1270 /* Set 8th ECC byte as 0x0 for ROM compatibility */
@@ -1220,13 +1273,15 @@ static int __maybe_unused omap_calculate_ecc_bch(struct mtd_info *mtd,
1220 case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW: 1273 case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
1221 /* Add constant polynomial to remainder, so that 1274 /* Add constant polynomial to remainder, so that
1222 * ECC of blank pages results in 0x0 on reading back */ 1275 * ECC of blank pages results in 0x0 on reading back */
1223 for (i = 0; i < eccbytes; i++) 1276 for (j = 0; j < eccbytes; j++)
1224 ecc_calc[i] ^= bch8_polynomial[i]; 1277 ecc_calc[j] ^= bch8_polynomial[j];
1225 break; 1278 break;
1226 case OMAP_ECC_BCH8_CODE_HW: 1279 case OMAP_ECC_BCH8_CODE_HW:
1227 /* Set 14th ECC byte as 0x0 for ROM compatibility */ 1280 /* Set 14th ECC byte as 0x0 for ROM compatibility */
1228 ecc_calc[eccbytes - 1] = 0x0; 1281 ecc_calc[eccbytes - 1] = 0x0;
1229 break; 1282 break;
1283 case OMAP_ECC_BCH16_CODE_HW:
1284 break;
1230 default: 1285 default:
1231 return -EINVAL; 1286 return -EINVAL;
1232 } 1287 }
@@ -1237,6 +1292,7 @@ static int __maybe_unused omap_calculate_ecc_bch(struct mtd_info *mtd,
1237 return 0; 1292 return 0;
1238} 1293}
1239 1294
1295#ifdef CONFIG_MTD_NAND_OMAP_BCH
1240/** 1296/**
1241 * erased_sector_bitflips - count bit flips 1297 * erased_sector_bitflips - count bit flips
1242 * @data: data sector buffer 1298 * @data: data sector buffer
@@ -1276,7 +1332,6 @@ static int erased_sector_bitflips(u_char *data, u_char *oob,
1276 return flip_bits; 1332 return flip_bits;
1277} 1333}
1278 1334
1279#ifdef CONFIG_MTD_NAND_OMAP_BCH
1280/** 1335/**
1281 * omap_elm_correct_data - corrects page data area in case error reported 1336 * omap_elm_correct_data - corrects page data area in case error reported
1282 * @mtd: MTD device structure 1337 * @mtd: MTD device structure
@@ -1318,6 +1373,10 @@ static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data,
1318 actual_eccbytes = ecc->bytes - 1; 1373 actual_eccbytes = ecc->bytes - 1;
1319 erased_ecc_vec = bch8_vector; 1374 erased_ecc_vec = bch8_vector;
1320 break; 1375 break;
1376 case OMAP_ECC_BCH16_CODE_HW:
1377 actual_eccbytes = ecc->bytes;
1378 erased_ecc_vec = bch16_vector;
1379 break;
1321 default: 1380 default:
1322 pr_err("invalid driver configuration\n"); 1381 pr_err("invalid driver configuration\n");
1323 return -EINVAL; 1382 return -EINVAL;
@@ -1382,7 +1441,7 @@ static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data,
1382 1441
1383 /* Check if any error reported */ 1442 /* Check if any error reported */
1384 if (!is_error_reported) 1443 if (!is_error_reported)
1385 return 0; 1444 return stat;
1386 1445
1387 /* Decode BCH error using ELM module */ 1446 /* Decode BCH error using ELM module */
1388 elm_decode_bch_error_page(info->elm_dev, ecc_vec, err_vec); 1447 elm_decode_bch_error_page(info->elm_dev, ecc_vec, err_vec);
@@ -1401,6 +1460,7 @@ static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data,
1401 BCH4_BIT_PAD; 1460 BCH4_BIT_PAD;
1402 break; 1461 break;
1403 case OMAP_ECC_BCH8_CODE_HW: 1462 case OMAP_ECC_BCH8_CODE_HW:
1463 case OMAP_ECC_BCH16_CODE_HW:
1404 pos = err_vec[i].error_loc[j]; 1464 pos = err_vec[i].error_loc[j];
1405 break; 1465 break;
1406 default: 1466 default:
@@ -1912,6 +1972,40 @@ static int omap_nand_probe(struct platform_device *pdev)
1912 goto return_error; 1972 goto return_error;
1913#endif 1973#endif
1914 1974
1975 case OMAP_ECC_BCH16_CODE_HW:
1976#ifdef CONFIG_MTD_NAND_OMAP_BCH
1977 pr_info("using OMAP_ECC_BCH16_CODE_HW ECC scheme\n");
1978 nand_chip->ecc.mode = NAND_ECC_HW;
1979 nand_chip->ecc.size = 512;
1980 nand_chip->ecc.bytes = 26;
1981 nand_chip->ecc.strength = 16;
1982 nand_chip->ecc.hwctl = omap_enable_hwecc_bch;
1983 nand_chip->ecc.correct = omap_elm_correct_data;
1984 nand_chip->ecc.calculate = omap_calculate_ecc_bch;
1985 nand_chip->ecc.read_page = omap_read_page_bch;
1986 nand_chip->ecc.write_page = omap_write_page_bch;
1987 /* This ECC scheme requires ELM H/W block */
1988 err = is_elm_present(info, pdata->elm_of_node, BCH16_ECC);
1989 if (err < 0) {
1990 pr_err("ELM is required for this ECC scheme\n");
1991 goto return_error;
1992 }
1993 /* define ECC layout */
1994 ecclayout->eccbytes = nand_chip->ecc.bytes *
1995 (mtd->writesize /
1996 nand_chip->ecc.size);
1997 oob_index = BADBLOCK_MARKER_LENGTH;
1998 for (i = 0; i < ecclayout->eccbytes; i++, oob_index++)
1999 ecclayout->eccpos[i] = oob_index;
2000 /* reserved marker already included in ecclayout->eccbytes */
2001 ecclayout->oobfree->offset =
2002 ecclayout->eccpos[ecclayout->eccbytes - 1] + 1;
2003 break;
2004#else
2005 pr_err("nand: error: CONFIG_MTD_NAND_OMAP_BCH not enabled\n");
2006 err = -EINVAL;
2007 goto return_error;
2008#endif
1915 default: 2009 default:
1916 pr_err("nand: error: invalid or unsupported ECC scheme\n"); 2010 pr_err("nand: error: invalid or unsupported ECC scheme\n");
1917 err = -EINVAL; 2011 err = -EINVAL;