aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilip Avinash <avinashphilip@ti.com>2013-01-04 02:56:51 -0500
committerArtem Bityutskiy <artem.bityutskiy@linux.intel.com>2013-02-04 02:26:29 -0500
commit62116e5171e00f85a8d53f76e45b84423c89ff34 (patch)
treed7b4b6c16ce14c991bcb4473a209f6a8e44da874
parentbf22433575ef30a4807f0620498017df0f27df67 (diff)
mtd: nand: omap2: Support for hardware BCH error correction.
ELM module can be used for hardware error correction of BCH 4 & 8 bit. ELM module functionality is verified by checking the availability of handle for ELM module in device tree. Hence supporting 1. ELM module available, BCH error correction done by ELM module. Also support read & write page in one shot by adding custom read_page and write_page methods. This helps in optimizing code for NAND flashes with page size less than 4 KB. 2. If ELM module not available fall back to software BCH error correction support. New structure member is added to omap_nand_info 1. "is_elm_used" to know the status of whether the ELM module is used for error correction or not. 2. "elm_dev" device pointer to elm device on detection of ELM module. Also being here update the device tree documentation of gpmc-nand for adding optional property elm_id. Note: ECC layout uses 1 extra bytes for 512 byte of data to handle erased pages. Extra byte programmed to zero for programmed pages. Also BCH8 requires 14 byte ecc to maintain compatibility with RBL ECC layout. This results a common ecc layout across RBL, U-boot & Linux with BCH8. Signed-off-by: Philip Avinash <avinashphilip@ti.com> Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
-rw-r--r--drivers/mtd/nand/omap2.c573
-rw-r--r--include/linux/platform_data/elm.h3
2 files changed, 536 insertions, 40 deletions
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index ec20f67e8949..1a88bd062ac1 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -22,9 +22,12 @@
22#include <linux/omap-dma.h> 22#include <linux/omap-dma.h>
23#include <linux/io.h> 23#include <linux/io.h>
24#include <linux/slab.h> 24#include <linux/slab.h>
25#include <linux/of.h>
26#include <linux/of_device.h>
25 27
26#ifdef CONFIG_MTD_NAND_OMAP_BCH 28#ifdef CONFIG_MTD_NAND_OMAP_BCH
27#include <linux/bch.h> 29#include <linux/bch.h>
30#include <linux/platform_data/elm.h>
28#endif 31#endif
29 32
30#include <linux/platform_data/mtd-nand-omap2.h> 33#include <linux/platform_data/mtd-nand-omap2.h>
@@ -120,6 +123,30 @@
120#define BCH8_MAX_ERROR 8 /* upto 8 bit correctable */ 123#define BCH8_MAX_ERROR 8 /* upto 8 bit correctable */
121#define BCH4_MAX_ERROR 4 /* upto 4 bit correctable */ 124#define BCH4_MAX_ERROR 4 /* upto 4 bit correctable */
122 125
126#define SECTOR_BYTES 512
127/* 4 bit padding to make byte aligned, 56 = 52 + 4 */
128#define BCH4_BIT_PAD 4
129#define BCH8_ECC_MAX ((SECTOR_BYTES + BCH8_ECC_OOB_BYTES) * 8)
130#define BCH4_ECC_MAX ((SECTOR_BYTES + BCH4_ECC_OOB_BYTES) * 8)
131
132/* GPMC ecc engine settings for read */
133#define BCH_WRAPMODE_1 1 /* BCH wrap mode 1 */
134#define BCH8R_ECC_SIZE0 0x1a /* ecc_size0 = 26 */
135#define BCH8R_ECC_SIZE1 0x2 /* ecc_size1 = 2 */
136#define BCH4R_ECC_SIZE0 0xd /* ecc_size0 = 13 */
137#define BCH4R_ECC_SIZE1 0x3 /* ecc_size1 = 3 */
138
139/* GPMC ecc engine settings for write */
140#define BCH_WRAPMODE_6 6 /* BCH wrap mode 6 */
141#define BCH_ECC_SIZE0 0x0 /* ecc_size0 = 0, no oob protection */
142#define BCH_ECC_SIZE1 0x20 /* ecc_size1 = 32 */
143
144#ifdef CONFIG_MTD_NAND_OMAP_BCH
145static u_char bch8_vector[] = {0xf3, 0xdb, 0x14, 0x16, 0x8b, 0xd2, 0xbe, 0xcc,
146 0xac, 0x6b, 0xff, 0x99, 0x7b};
147static u_char bch4_vector[] = {0x00, 0x6b, 0x31, 0xdd, 0x41, 0xbc, 0x10};
148#endif
149
123/* oob info generated runtime depending on ecc algorithm and layout selected */ 150/* oob info generated runtime depending on ecc algorithm and layout selected */
124static struct nand_ecclayout omap_oobinfo; 151static struct nand_ecclayout omap_oobinfo;
125/* Define some generic bad / good block scan pattern which are used 152/* Define some generic bad / good block scan pattern which are used
@@ -159,6 +186,9 @@ struct omap_nand_info {
159#ifdef CONFIG_MTD_NAND_OMAP_BCH 186#ifdef CONFIG_MTD_NAND_OMAP_BCH
160 struct bch_control *bch; 187 struct bch_control *bch;
161 struct nand_ecclayout ecclayout; 188 struct nand_ecclayout ecclayout;
189 bool is_elm_used;
190 struct device *elm_dev;
191 struct device_node *of_node;
162#endif 192#endif
163}; 193};
164 194
@@ -1034,6 +1064,13 @@ static int omap_dev_ready(struct mtd_info *mtd)
1034 * omap3_enable_hwecc_bch - Program OMAP3 GPMC to perform BCH ECC correction 1064 * omap3_enable_hwecc_bch - Program OMAP3 GPMC to perform BCH ECC correction
1035 * @mtd: MTD device structure 1065 * @mtd: MTD device structure
1036 * @mode: Read/Write mode 1066 * @mode: Read/Write mode
1067 *
1068 * When using BCH, sector size is hardcoded to 512 bytes.
1069 * Using wrapping mode 6 both for reading and writing if ELM module not uses
1070 * for error correction.
1071 * On writing,
1072 * eccsize0 = 0 (no additional protected byte in spare area)
1073 * eccsize1 = 32 (skip 32 nibbles = 16 bytes per sector in spare area)
1037 */ 1074 */
1038static void omap3_enable_hwecc_bch(struct mtd_info *mtd, int mode) 1075static void omap3_enable_hwecc_bch(struct mtd_info *mtd, int mode)
1039{ 1076{
@@ -1042,32 +1079,57 @@ static void omap3_enable_hwecc_bch(struct mtd_info *mtd, int mode)
1042 struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, 1079 struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
1043 mtd); 1080 mtd);
1044 struct nand_chip *chip = mtd->priv; 1081 struct nand_chip *chip = mtd->priv;
1045 u32 val; 1082 u32 val, wr_mode;
1083 unsigned int ecc_size1, ecc_size0;
1084
1085 /* Using wrapping mode 6 for writing */
1086 wr_mode = BCH_WRAPMODE_6;
1046 1087
1047 nerrors = info->nand.ecc.strength;
1048 dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0;
1049 nsectors = 1;
1050 /* 1088 /*
1051 * Program GPMC to perform correction on one 512-byte sector at a time. 1089 * ECC engine enabled for valid ecc_size0 nibbles
1052 * Using 4 sectors at a time (i.e. ecc.size = 2048) is also possible and 1090 * and disabled for ecc_size1 nibbles.
1053 * gives a slight (5%) performance gain (but requires additional code).
1054 */ 1091 */
1092 ecc_size0 = BCH_ECC_SIZE0;
1093 ecc_size1 = BCH_ECC_SIZE1;
1094
1095 /* Perform ecc calculation on 512-byte sector */
1096 nsectors = 1;
1097
1098 /* Update number of error correction */
1099 nerrors = info->nand.ecc.strength;
1100
1101 /* Multi sector reading/writing for NAND flash with page size < 4096 */
1102 if (info->is_elm_used && (mtd->writesize <= 4096)) {
1103 if (mode == NAND_ECC_READ) {
1104 /* Using wrapping mode 1 for reading */
1105 wr_mode = BCH_WRAPMODE_1;
1106
1107 /*
1108 * ECC engine enabled for ecc_size0 nibbles
1109 * and disabled for ecc_size1 nibbles.
1110 */
1111 ecc_size0 = (nerrors == 8) ?
1112 BCH8R_ECC_SIZE0 : BCH4R_ECC_SIZE0;
1113 ecc_size1 = (nerrors == 8) ?
1114 BCH8R_ECC_SIZE1 : BCH4R_ECC_SIZE1;
1115 }
1116
1117 /* Perform ecc calculation for one page (< 4096) */
1118 nsectors = info->nand.ecc.steps;
1119 }
1055 1120
1056 writel(ECC1, info->reg.gpmc_ecc_control); 1121 writel(ECC1, info->reg.gpmc_ecc_control);
1057 1122
1058 /* 1123 /* Configure ecc size for BCH */
1059 * When using BCH, sector size is hardcoded to 512 bytes. 1124 val = (ecc_size1 << ECCSIZE1_SHIFT) | (ecc_size0 << ECCSIZE0_SHIFT);
1060 * Here we are using wrapping mode 6 both for reading and writing, with:
1061 * size0 = 0 (no additional protected byte in spare area)
1062 * size1 = 32 (skip 32 nibbles = 16 bytes per sector in spare area)
1063 */
1064 val = (32 << ECCSIZE1_SHIFT) | (0 << ECCSIZE0_SHIFT);
1065 writel(val, info->reg.gpmc_ecc_size_config); 1125 writel(val, info->reg.gpmc_ecc_size_config);
1066 1126
1127 dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0;
1128
1067 /* BCH configuration */ 1129 /* BCH configuration */
1068 val = ((1 << 16) | /* enable BCH */ 1130 val = ((1 << 16) | /* enable BCH */
1069 (((nerrors == 8) ? 1 : 0) << 12) | /* 8 or 4 bits */ 1131 (((nerrors == 8) ? 1 : 0) << 12) | /* 8 or 4 bits */
1070 (0x06 << 8) | /* wrap mode = 6 */ 1132 (wr_mode << 8) | /* wrap mode */
1071 (dev_width << 7) | /* bus width */ 1133 (dev_width << 7) | /* bus width */
1072 (((nsectors-1) & 0x7) << 4) | /* number of sectors */ 1134 (((nsectors-1) & 0x7) << 4) | /* number of sectors */
1073 (info->gpmc_cs << 1) | /* ECC CS */ 1135 (info->gpmc_cs << 1) | /* ECC CS */
@@ -1075,7 +1137,7 @@ static void omap3_enable_hwecc_bch(struct mtd_info *mtd, int mode)
1075 1137
1076 writel(val, info->reg.gpmc_ecc_config); 1138 writel(val, info->reg.gpmc_ecc_config);
1077 1139
1078 /* clear ecc and enable bits */ 1140 /* Clear ecc and enable bits */
1079 writel(ECCCLEAR | ECC1, info->reg.gpmc_ecc_control); 1141 writel(ECCCLEAR | ECC1, info->reg.gpmc_ecc_control);
1080} 1142}
1081 1143
@@ -1165,6 +1227,298 @@ static int omap3_calculate_ecc_bch8(struct mtd_info *mtd, const u_char *dat,
1165} 1227}
1166 1228
1167/** 1229/**
1230 * omap3_calculate_ecc_bch - Generate bytes of ECC bytes
1231 * @mtd: MTD device structure
1232 * @dat: The pointer to data on which ecc is computed
1233 * @ecc_code: The ecc_code buffer
1234 *
1235 * Support calculating of BCH4/8 ecc vectors for the page
1236 */
1237static int omap3_calculate_ecc_bch(struct mtd_info *mtd, const u_char *dat,
1238 u_char *ecc_code)
1239{
1240 struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
1241 mtd);
1242 unsigned long nsectors, bch_val1, bch_val2, bch_val3, bch_val4;
1243 int i, eccbchtsel;
1244
1245 nsectors = ((readl(info->reg.gpmc_ecc_config) >> 4) & 0x7) + 1;
1246 /*
1247 * find BCH scheme used
1248 * 0 -> BCH4
1249 * 1 -> BCH8
1250 */
1251 eccbchtsel = ((readl(info->reg.gpmc_ecc_config) >> 12) & 0x3);
1252
1253 for (i = 0; i < nsectors; i++) {
1254
1255 /* Read hw-computed remainder */
1256 bch_val1 = readl(info->reg.gpmc_bch_result0[i]);
1257 bch_val2 = readl(info->reg.gpmc_bch_result1[i]);
1258 if (eccbchtsel) {
1259 bch_val3 = readl(info->reg.gpmc_bch_result2[i]);
1260 bch_val4 = readl(info->reg.gpmc_bch_result3[i]);
1261 }
1262
1263 if (eccbchtsel) {
1264 /* BCH8 ecc scheme */
1265 *ecc_code++ = (bch_val4 & 0xFF);
1266 *ecc_code++ = ((bch_val3 >> 24) & 0xFF);
1267 *ecc_code++ = ((bch_val3 >> 16) & 0xFF);
1268 *ecc_code++ = ((bch_val3 >> 8) & 0xFF);
1269 *ecc_code++ = (bch_val3 & 0xFF);
1270 *ecc_code++ = ((bch_val2 >> 24) & 0xFF);
1271 *ecc_code++ = ((bch_val2 >> 16) & 0xFF);
1272 *ecc_code++ = ((bch_val2 >> 8) & 0xFF);
1273 *ecc_code++ = (bch_val2 & 0xFF);
1274 *ecc_code++ = ((bch_val1 >> 24) & 0xFF);
1275 *ecc_code++ = ((bch_val1 >> 16) & 0xFF);
1276 *ecc_code++ = ((bch_val1 >> 8) & 0xFF);
1277 *ecc_code++ = (bch_val1 & 0xFF);
1278 /*
1279 * Setting 14th byte to zero to handle
1280 * erased page & maintain compatibility
1281 * with RBL
1282 */
1283 *ecc_code++ = 0x0;
1284 } else {
1285 /* BCH4 ecc scheme */
1286 *ecc_code++ = ((bch_val2 >> 12) & 0xFF);
1287 *ecc_code++ = ((bch_val2 >> 4) & 0xFF);
1288 *ecc_code++ = ((bch_val2 & 0xF) << 4) |
1289 ((bch_val1 >> 28) & 0xF);
1290 *ecc_code++ = ((bch_val1 >> 20) & 0xFF);
1291 *ecc_code++ = ((bch_val1 >> 12) & 0xFF);
1292 *ecc_code++ = ((bch_val1 >> 4) & 0xFF);
1293 *ecc_code++ = ((bch_val1 & 0xF) << 4);
1294 /*
1295 * Setting 8th byte to zero to handle
1296 * erased page
1297 */
1298 *ecc_code++ = 0x0;
1299 }
1300 }
1301
1302 return 0;
1303}
1304
1305/**
1306 * erased_sector_bitflips - count bit flips
1307 * @data: data sector buffer
1308 * @oob: oob buffer
1309 * @info: omap_nand_info
1310 *
1311 * Check the bit flips in erased page falls below correctable level.
1312 * If falls below, report the page as erased with correctable bit
1313 * flip, else report as uncorrectable page.
1314 */
1315static int erased_sector_bitflips(u_char *data, u_char *oob,
1316 struct omap_nand_info *info)
1317{
1318 int flip_bits = 0, i;
1319
1320 for (i = 0; i < info->nand.ecc.size; i++) {
1321 flip_bits += hweight8(~data[i]);
1322 if (flip_bits > info->nand.ecc.strength)
1323 return 0;
1324 }
1325
1326 for (i = 0; i < info->nand.ecc.bytes - 1; i++) {
1327 flip_bits += hweight8(~oob[i]);
1328 if (flip_bits > info->nand.ecc.strength)
1329 return 0;
1330 }
1331
1332 /*
1333 * Bit flips falls in correctable level.
1334 * Fill data area with 0xFF
1335 */
1336 if (flip_bits) {
1337 memset(data, 0xFF, info->nand.ecc.size);
1338 memset(oob, 0xFF, info->nand.ecc.bytes);
1339 }
1340
1341 return flip_bits;
1342}
1343
1344/**
1345 * omap_elm_correct_data - corrects page data area in case error reported
1346 * @mtd: MTD device structure
1347 * @data: page data
1348 * @read_ecc: ecc read from nand flash
1349 * @calc_ecc: ecc read from HW ECC registers
1350 *
1351 * Calculated ecc vector reported as zero in case of non-error pages.
1352 * In case of error/erased pages non-zero error vector is reported.
1353 * In case of non-zero ecc vector, check read_ecc at fixed offset
1354 * (x = 13/7 in case of BCH8/4 == 0) to find page programmed or not.
1355 * To handle bit flips in this data, count the number of 0's in
1356 * read_ecc[x] and check if it greater than 4. If it is less, it is
1357 * programmed page, else erased page.
1358 *
1359 * 1. If page is erased, check with standard ecc vector (ecc vector
1360 * for erased page to find any bit flip). If check fails, bit flip
1361 * is present in erased page. Count the bit flips in erased page and
1362 * if it falls under correctable level, report page with 0xFF and
1363 * update the correctable bit information.
1364 * 2. If error is reported on programmed page, update elm error
1365 * vector and correct the page with ELM error correction routine.
1366 *
1367 */
1368static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data,
1369 u_char *read_ecc, u_char *calc_ecc)
1370{
1371 struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
1372 mtd);
1373 int eccsteps = info->nand.ecc.steps;
1374 int i , j, stat = 0;
1375 int eccsize, eccflag, ecc_vector_size;
1376 struct elm_errorvec err_vec[ERROR_VECTOR_MAX];
1377 u_char *ecc_vec = calc_ecc;
1378 u_char *spare_ecc = read_ecc;
1379 u_char *erased_ecc_vec;
1380 enum bch_ecc type;
1381 bool is_error_reported = false;
1382
1383 /* Initialize elm error vector to zero */
1384 memset(err_vec, 0, sizeof(err_vec));
1385
1386 if (info->nand.ecc.strength == BCH8_MAX_ERROR) {
1387 type = BCH8_ECC;
1388 erased_ecc_vec = bch8_vector;
1389 } else {
1390 type = BCH4_ECC;
1391 erased_ecc_vec = bch4_vector;
1392 }
1393
1394 ecc_vector_size = info->nand.ecc.bytes;
1395
1396 /*
1397 * Remove extra byte padding for BCH8 RBL
1398 * compatibility and erased page handling
1399 */
1400 eccsize = ecc_vector_size - 1;
1401
1402 for (i = 0; i < eccsteps ; i++) {
1403 eccflag = 0; /* initialize eccflag */
1404
1405 /*
1406 * Check any error reported,
1407 * In case of error, non zero ecc reported.
1408 */
1409
1410 for (j = 0; (j < eccsize); j++) {
1411 if (calc_ecc[j] != 0) {
1412 eccflag = 1; /* non zero ecc, error present */
1413 break;
1414 }
1415 }
1416
1417 if (eccflag == 1) {
1418 /*
1419 * Set threshold to minimum of 4, half of ecc.strength/2
1420 * to allow max bit flip in byte to 4
1421 */
1422 unsigned int threshold = min_t(unsigned int, 4,
1423 info->nand.ecc.strength / 2);
1424
1425 /*
1426 * Check data area is programmed by counting
1427 * number of 0's at fixed offset in spare area.
1428 * Checking count of 0's against threshold.
1429 * In case programmed page expects at least threshold
1430 * zeros in byte.
1431 * If zeros are less than threshold for programmed page/
1432 * zeros are more than threshold erased page, either
1433 * case page reported as uncorrectable.
1434 */
1435 if (hweight8(~read_ecc[eccsize]) >= threshold) {
1436 /*
1437 * Update elm error vector as
1438 * data area is programmed
1439 */
1440 err_vec[i].error_reported = true;
1441 is_error_reported = true;
1442 } else {
1443 /* Error reported in erased page */
1444 int bitflip_count;
1445 u_char *buf = &data[info->nand.ecc.size * i];
1446
1447 if (memcmp(calc_ecc, erased_ecc_vec, eccsize)) {
1448 bitflip_count = erased_sector_bitflips(
1449 buf, read_ecc, info);
1450
1451 if (bitflip_count)
1452 stat += bitflip_count;
1453 else
1454 return -EINVAL;
1455 }
1456 }
1457 }
1458
1459 /* Update the ecc vector */
1460 calc_ecc += ecc_vector_size;
1461 read_ecc += ecc_vector_size;
1462 }
1463
1464 /* Check if any error reported */
1465 if (!is_error_reported)
1466 return 0;
1467
1468 /* Decode BCH error using ELM module */
1469 elm_decode_bch_error_page(info->elm_dev, ecc_vec, err_vec);
1470
1471 for (i = 0; i < eccsteps; i++) {
1472 if (err_vec[i].error_reported) {
1473 for (j = 0; j < err_vec[i].error_count; j++) {
1474 u32 bit_pos, byte_pos, error_max, pos;
1475
1476 if (type == BCH8_ECC)
1477 error_max = BCH8_ECC_MAX;
1478 else
1479 error_max = BCH4_ECC_MAX;
1480
1481 if (info->nand.ecc.strength == BCH8_MAX_ERROR)
1482 pos = err_vec[i].error_loc[j];
1483 else
1484 /* Add 4 to take care 4 bit padding */
1485 pos = err_vec[i].error_loc[j] +
1486 BCH4_BIT_PAD;
1487
1488 /* Calculate bit position of error */
1489 bit_pos = pos % 8;
1490
1491 /* Calculate byte position of error */
1492 byte_pos = (error_max - pos - 1) / 8;
1493
1494 if (pos < error_max) {
1495 if (byte_pos < 512)
1496 data[byte_pos] ^= 1 << bit_pos;
1497 else
1498 spare_ecc[byte_pos - 512] ^=
1499 1 << bit_pos;
1500 }
1501 /* else, not interested to correct ecc */
1502 }
1503 }
1504
1505 /* Update number of correctable errors */
1506 stat += err_vec[i].error_count;
1507
1508 /* Update page data with sector size */
1509 data += info->nand.ecc.size;
1510 spare_ecc += ecc_vector_size;
1511 }
1512
1513 for (i = 0; i < eccsteps; i++)
1514 /* Return error if uncorrectable error present */
1515 if (err_vec[i].error_uncorrectable)
1516 return -EINVAL;
1517
1518 return stat;
1519}
1520
1521/**
1168 * omap3_correct_data_bch - Decode received data and correct errors 1522 * omap3_correct_data_bch - Decode received data and correct errors
1169 * @mtd: MTD device structure 1523 * @mtd: MTD device structure
1170 * @data: page data 1524 * @data: page data
@@ -1197,6 +1551,92 @@ static int omap3_correct_data_bch(struct mtd_info *mtd, u_char *data,
1197} 1551}
1198 1552
1199/** 1553/**
1554 * omap_write_page_bch - BCH ecc based write page function for entire page
1555 * @mtd: mtd info structure
1556 * @chip: nand chip info structure
1557 * @buf: data buffer
1558 * @oob_required: must write chip->oob_poi to OOB
1559 *
1560 * Custom write page method evolved to support multi sector writing in one shot
1561 */
1562static int omap_write_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
1563 const uint8_t *buf, int oob_required)
1564{
1565 int i;
1566 uint8_t *ecc_calc = chip->buffers->ecccalc;
1567 uint32_t *eccpos = chip->ecc.layout->eccpos;
1568
1569 /* Enable GPMC ecc engine */
1570 chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
1571
1572 /* Write data */
1573 chip->write_buf(mtd, buf, mtd->writesize);
1574
1575 /* Update ecc vector from GPMC result registers */
1576 chip->ecc.calculate(mtd, buf, &ecc_calc[0]);
1577
1578 for (i = 0; i < chip->ecc.total; i++)
1579 chip->oob_poi[eccpos[i]] = ecc_calc[i];
1580
1581 /* Write ecc vector to OOB area */
1582 chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
1583 return 0;
1584}
1585
1586/**
1587 * omap_read_page_bch - BCH ecc based page read function for entire page
1588 * @mtd: mtd info structure
1589 * @chip: nand chip info structure
1590 * @buf: buffer to store read data
1591 * @oob_required: caller requires OOB data read to chip->oob_poi
1592 * @page: page number to read
1593 *
1594 * For BCH ecc scheme, GPMC used for syndrome calculation and ELM module
1595 * used for error correction.
1596 * Custom method evolved to support ELM error correction & multi sector
1597 * reading. On reading page data area is read along with OOB data with
1598 * ecc engine enabled. ecc vector updated after read of OOB data.
1599 * For non error pages ecc vector reported as zero.
1600 */
1601static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
1602 uint8_t *buf, int oob_required, int page)
1603{
1604 uint8_t *ecc_calc = chip->buffers->ecccalc;
1605 uint8_t *ecc_code = chip->buffers->ecccode;
1606 uint32_t *eccpos = chip->ecc.layout->eccpos;
1607 uint8_t *oob = &chip->oob_poi[eccpos[0]];
1608 uint32_t oob_pos = mtd->writesize + chip->ecc.layout->eccpos[0];
1609 int stat;
1610 unsigned int max_bitflips = 0;
1611
1612 /* Enable GPMC ecc engine */
1613 chip->ecc.hwctl(mtd, NAND_ECC_READ);
1614
1615 /* Read data */
1616 chip->read_buf(mtd, buf, mtd->writesize);
1617
1618 /* Read oob bytes */
1619 chip->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_pos, -1);
1620 chip->read_buf(mtd, oob, chip->ecc.total);
1621
1622 /* Calculate ecc bytes */
1623 chip->ecc.calculate(mtd, buf, ecc_calc);
1624
1625 memcpy(ecc_code, &chip->oob_poi[eccpos[0]], chip->ecc.total);
1626
1627 stat = chip->ecc.correct(mtd, buf, ecc_code, ecc_calc);
1628
1629 if (stat < 0) {
1630 mtd->ecc_stats.failed++;
1631 } else {
1632 mtd->ecc_stats.corrected += stat;
1633 max_bitflips = max_t(unsigned int, max_bitflips, stat);
1634 }
1635
1636 return max_bitflips;
1637}
1638
1639/**
1200 * omap3_free_bch - Release BCH ecc resources 1640 * omap3_free_bch - Release BCH ecc resources
1201 * @mtd: MTD device structure 1641 * @mtd: MTD device structure
1202 */ 1642 */
@@ -1225,6 +1665,11 @@ static int omap3_init_bch(struct mtd_info *mtd, int ecc_opt)
1225#else 1665#else
1226 const int hw_errors = BCH4_MAX_ERROR; 1666 const int hw_errors = BCH4_MAX_ERROR;
1227#endif 1667#endif
1668 enum bch_ecc bch_type;
1669 const __be32 *parp;
1670 int lenp;
1671 struct device_node *elm_node;
1672
1228 info->bch = NULL; 1673 info->bch = NULL;
1229 1674
1230 max_errors = (ecc_opt == OMAP_ECC_BCH8_CODE_HW) ? 1675 max_errors = (ecc_opt == OMAP_ECC_BCH8_CODE_HW) ?
@@ -1235,30 +1680,67 @@ static int omap3_init_bch(struct mtd_info *mtd, int ecc_opt)
1235 goto fail; 1680 goto fail;
1236 } 1681 }
1237 1682
1238 /* software bch library is only used to detect and locate errors */ 1683 info->nand.ecc.size = 512;
1239 info->bch = init_bch(13, max_errors, 0x201b /* hw polynomial */); 1684 info->nand.ecc.hwctl = omap3_enable_hwecc_bch;
1240 if (!info->bch) 1685 info->nand.ecc.mode = NAND_ECC_HW;
1241 goto fail; 1686 info->nand.ecc.strength = max_errors;
1242 1687
1243 info->nand.ecc.size = 512; 1688 if (hw_errors == BCH8_MAX_ERROR)
1244 info->nand.ecc.hwctl = omap3_enable_hwecc_bch; 1689 bch_type = BCH8_ECC;
1245 info->nand.ecc.correct = omap3_correct_data_bch; 1690 else
1246 info->nand.ecc.mode = NAND_ECC_HW; 1691 bch_type = BCH4_ECC;
1247 1692
1248 /* 1693 /* Detect availability of ELM module */
1249 * The number of corrected errors in an ecc block that will trigger 1694 parp = of_get_property(info->of_node, "elm_id", &lenp);
1250 * block scrubbing defaults to the ecc strength (4 or 8). 1695 if ((parp == NULL) && (lenp != (sizeof(void *) * 2))) {
1251 * Set mtd->bitflip_threshold here to define a custom threshold. 1696 pr_err("Missing elm_id property, fall back to Software BCH\n");
1252 */ 1697 info->is_elm_used = false;
1698 } else {
1699 struct platform_device *pdev;
1253 1700
1254 if (max_errors == 8) { 1701 elm_node = of_find_node_by_phandle(be32_to_cpup(parp));
1255 info->nand.ecc.strength = 8; 1702 pdev = of_find_device_by_node(elm_node);
1256 info->nand.ecc.bytes = 13; 1703 info->elm_dev = &pdev->dev;
1257 info->nand.ecc.calculate = omap3_calculate_ecc_bch8; 1704 elm_config(info->elm_dev, bch_type);
1705 info->is_elm_used = true;
1706 }
1707
1708 if (info->is_elm_used && (mtd->writesize <= 4096)) {
1709
1710 if (hw_errors == BCH8_MAX_ERROR)
1711 info->nand.ecc.bytes = BCH8_SIZE;
1712 else
1713 info->nand.ecc.bytes = BCH4_SIZE;
1714
1715 info->nand.ecc.correct = omap_elm_correct_data;
1716 info->nand.ecc.calculate = omap3_calculate_ecc_bch;
1717 info->nand.ecc.read_page = omap_read_page_bch;
1718 info->nand.ecc.write_page = omap_write_page_bch;
1258 } else { 1719 } else {
1259 info->nand.ecc.strength = 4; 1720 /*
1260 info->nand.ecc.bytes = 7; 1721 * software bch library is only used to detect and
1261 info->nand.ecc.calculate = omap3_calculate_ecc_bch4; 1722 * locate errors
1723 */
1724 info->bch = init_bch(13, max_errors,
1725 0x201b /* hw polynomial */);
1726 if (!info->bch)
1727 goto fail;
1728
1729 info->nand.ecc.correct = omap3_correct_data_bch;
1730
1731 /*
1732 * The number of corrected errors in an ecc block that will
1733 * trigger block scrubbing defaults to the ecc strength (4 or 8)
1734 * Set mtd->bitflip_threshold here to define a custom threshold.
1735 */
1736
1737 if (max_errors == 8) {
1738 info->nand.ecc.bytes = 13;
1739 info->nand.ecc.calculate = omap3_calculate_ecc_bch8;
1740 } else {
1741 info->nand.ecc.bytes = 7;
1742 info->nand.ecc.calculate = omap3_calculate_ecc_bch4;
1743 }
1262 } 1744 }
1263 1745
1264 pr_info("enabling NAND BCH ecc with %d-bit correction\n", max_errors); 1746 pr_info("enabling NAND BCH ecc with %d-bit correction\n", max_errors);
@@ -1274,7 +1756,7 @@ fail:
1274 */ 1756 */
1275static int omap3_init_bch_tail(struct mtd_info *mtd) 1757static int omap3_init_bch_tail(struct mtd_info *mtd)
1276{ 1758{
1277 int i, steps; 1759 int i, steps, offset;
1278 struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, 1760 struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
1279 mtd); 1761 mtd);
1280 struct nand_ecclayout *layout = &info->ecclayout; 1762 struct nand_ecclayout *layout = &info->ecclayout;
@@ -1296,11 +1778,21 @@ static int omap3_init_bch_tail(struct mtd_info *mtd)
1296 goto fail; 1778 goto fail;
1297 } 1779 }
1298 1780
1781 /* ECC layout compatible with RBL for BCH8 */
1782 if (info->is_elm_used && (info->nand.ecc.bytes == BCH8_SIZE))
1783 offset = 2;
1784 else
1785 offset = mtd->oobsize - layout->eccbytes;
1786
1299 /* put ecc bytes at oob tail */ 1787 /* put ecc bytes at oob tail */
1300 for (i = 0; i < layout->eccbytes; i++) 1788 for (i = 0; i < layout->eccbytes; i++)
1301 layout->eccpos[i] = mtd->oobsize-layout->eccbytes+i; 1789 layout->eccpos[i] = offset + i;
1790
1791 if (info->is_elm_used && (info->nand.ecc.bytes == BCH8_SIZE))
1792 layout->oobfree[0].offset = 2 + layout->eccbytes * steps;
1793 else
1794 layout->oobfree[0].offset = 2;
1302 1795
1303 layout->oobfree[0].offset = 2;
1304 layout->oobfree[0].length = mtd->oobsize-2-layout->eccbytes; 1796 layout->oobfree[0].length = mtd->oobsize-2-layout->eccbytes;
1305 info->nand.ecc.layout = layout; 1797 info->nand.ecc.layout = layout;
1306 1798
@@ -1363,6 +1855,9 @@ static int omap_nand_probe(struct platform_device *pdev)
1363 1855
1364 info->nand.options = pdata->devsize; 1856 info->nand.options = pdata->devsize;
1365 info->nand.options |= NAND_SKIP_BBTSCAN; 1857 info->nand.options |= NAND_SKIP_BBTSCAN;
1858#ifdef CONFIG_MTD_NAND_OMAP_BCH
1859 info->of_node = pdata->of_node;
1860#endif
1366 1861
1367 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1862 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1368 if (res == NULL) { 1863 if (res == NULL) {
diff --git a/include/linux/platform_data/elm.h b/include/linux/platform_data/elm.h
index 11ab6aaf2431..1bd5244d1dcd 100644
--- a/include/linux/platform_data/elm.h
+++ b/include/linux/platform_data/elm.h
@@ -30,7 +30,8 @@ enum bch_ecc {
30#define BCH4_ECC_OOB_BYTES 7 30#define BCH4_ECC_OOB_BYTES 7
31/* RBL requires 14 byte even though BCH8 uses only 13 byte */ 31/* RBL requires 14 byte even though BCH8 uses only 13 byte */
32#define BCH8_SIZE (BCH8_ECC_OOB_BYTES + 1) 32#define BCH8_SIZE (BCH8_ECC_OOB_BYTES + 1)
33#define BCH4_SIZE (BCH4_ECC_OOB_BYTES) 33/* Uses 1 extra byte to handle erased pages */
34#define BCH4_SIZE (BCH4_ECC_OOB_BYTES + 1)
34 35
35/** 36/**
36 * struct elm_errorvec - error vector for elm 37 * struct elm_errorvec - error vector for elm