aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/onenand/onenand_base.c
diff options
context:
space:
mode:
authorKyungmin Park <kyungmin.park@samsung.com>2006-11-15 22:03:56 -0500
committerKyungmin Park <kyungmin.park@samsung.com>2006-11-15 22:03:56 -0500
commitf4f91ac3c833abbd7181ff2122c6b48a653b4e55 (patch)
tree16202b5e260e08e0b5401d55352d62b94ef8ad62 /drivers/mtd/onenand/onenand_base.c
parent08f782b60a633cbd926ef5e49de303a752390719 (diff)
[MTD] OneNAND: Single bit error detection
Idea from Jarkko Lavinen Signed-off-by: Jarkko Lavinen <jarkko.lavinen@nokia.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Diffstat (limited to 'drivers/mtd/onenand/onenand_base.c')
-rw-r--r--drivers/mtd/onenand/onenand_base.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index bef4f26ad2ed..fc84ddc4987f 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -331,9 +331,12 @@ static int onenand_wait(struct mtd_info *mtd, int state)
331 331
332 if (interrupt & ONENAND_INT_READ) { 332 if (interrupt & ONENAND_INT_READ) {
333 ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS); 333 ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS);
334 if (ecc & ONENAND_ECC_2BIT_ALL) { 334 if (ecc) {
335 DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: ECC error = 0x%04x\n", ecc); 335 DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: ECC error = 0x%04x\n", ecc);
336 return -EBADMSG; 336 if (ecc & ONENAND_ECC_2BIT_ALL)
337 mtd->ecc_stats.failed++;
338 else if (ecc & ONENAND_ECC_1BIT_ALL)
339 mtd->ecc_stats.corrected++;
337 } 340 }
338 } 341 }
339 342
@@ -715,6 +718,7 @@ static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
715 size_t *retlen, u_char *buf) 718 size_t *retlen, u_char *buf)
716{ 719{
717 struct onenand_chip *this = mtd->priv; 720 struct onenand_chip *this = mtd->priv;
721 struct mtd_ecc_stats stats;
718 int read = 0, column; 722 int read = 0, column;
719 int thislen; 723 int thislen;
720 int ret = 0; 724 int ret = 0;
@@ -733,6 +737,7 @@ static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
733 737
734 /* TODO handling oob */ 738 /* TODO handling oob */
735 739
740 stats = mtd->ecc_stats;
736 while (read < len) { 741 while (read < len) {
737 thislen = min_t(int, mtd->writesize, len - read); 742 thislen = min_t(int, mtd->writesize, len - read);
738 743
@@ -774,7 +779,11 @@ out:
774 * retlen == desired len and result == -EBADMSG 779 * retlen == desired len and result == -EBADMSG
775 */ 780 */
776 *retlen = read; 781 *retlen = read;
777 return ret; 782
783 if (mtd->ecc_stats.failed - stats.failed)
784 return -EBADMSG;
785
786 return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0;
778} 787}
779 788
780/** 789/**
@@ -1390,7 +1399,6 @@ static int onenand_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
1390 return onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_LOCK); 1399 return onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_LOCK);
1391} 1400}
1392 1401
1393
1394/** 1402/**
1395 * onenand_unlock - [MTD Interface] Unlock block(s) 1403 * onenand_unlock - [MTD Interface] Unlock block(s)
1396 * @param mtd MTD device structure 1404 * @param mtd MTD device structure
@@ -1900,7 +1908,7 @@ static int onenand_probe(struct mtd_info *mtd)
1900 /* Read manufacturer and device IDs from Register */ 1908 /* Read manufacturer and device IDs from Register */
1901 maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID); 1909 maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID);
1902 dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID); 1910 dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID);
1903 ver_id= this->read_word(this->base + ONENAND_REG_VERSION_ID); 1911 ver_id = this->read_word(this->base + ONENAND_REG_VERSION_ID);
1904 1912
1905 /* Check OneNAND device */ 1913 /* Check OneNAND device */
1906 if (maf_id != bram_maf_id || dev_id != bram_dev_id) 1914 if (maf_id != bram_maf_id || dev_id != bram_dev_id)