aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mtd/onenand/onenand_base.c157
-rw-r--r--drivers/mtd/onenand/onenand_bbt.c21
-rw-r--r--include/linux/mtd/bbm.h7
3 files changed, 155 insertions, 30 deletions
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index 3d6f880cba9c..f690c1916d1d 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -304,16 +304,16 @@ static int onenand_wait(struct mtd_info *mtd, int state)
304 ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS); 304 ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS);
305 305
306 if (ctrl & ONENAND_CTRL_ERROR) { 306 if (ctrl & ONENAND_CTRL_ERROR) {
307 DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: controller error = 0x%04x\n", ctrl); 307 printk(KERN_ERR "onenand_wait: controller error = 0x%04x\n", ctrl);
308 if (ctrl & ONENAND_CTRL_LOCK) 308 if (ctrl & ONENAND_CTRL_LOCK)
309 DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: it's locked error.\n"); 309 printk(KERN_ERR "onenand_wait: it's locked error.\n");
310 return ctrl; 310 return ctrl;
311 } 311 }
312 312
313 if (interrupt & ONENAND_INT_READ) { 313 if (interrupt & ONENAND_INT_READ) {
314 int ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS); 314 int ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS);
315 if (ecc) { 315 if (ecc) {
316 DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: ECC error = 0x%04x\n", ecc); 316 printk(KERN_ERR "onenand_wait: ECC error = 0x%04x\n", ecc);
317 if (ecc & ONENAND_ECC_2BIT_ALL) { 317 if (ecc & ONENAND_ECC_2BIT_ALL) {
318 mtd->ecc_stats.failed++; 318 mtd->ecc_stats.failed++;
319 return ecc; 319 return ecc;
@@ -703,7 +703,7 @@ static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
703 703
704 /* Do not allow reads past end of device */ 704 /* Do not allow reads past end of device */
705 if ((from + len) > mtd->size) { 705 if ((from + len) > mtd->size) {
706 DEBUG(MTD_DEBUG_LEVEL0, "onenand_read: Attempt read beyond end of device\n"); 706 printk(KERN_ERR "onenand_read: Attempt read beyond end of device\n");
707 *retlen = 0; 707 *retlen = 0;
708 return -EINVAL; 708 return -EINVAL;
709 } 709 }
@@ -834,7 +834,7 @@ static int onenand_transfer_auto_oob(struct mtd_info *mtd, uint8_t *buf, int col
834 * 834 *
835 * OneNAND read out-of-band data from the spare area 835 * OneNAND read out-of-band data from the spare area
836 */ 836 */
837int onenand_do_read_oob(struct mtd_info *mtd, loff_t from, size_t len, 837static int onenand_do_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
838 size_t *retlen, u_char *buf, mtd_oob_mode_t mode) 838 size_t *retlen, u_char *buf, mtd_oob_mode_t mode)
839{ 839{
840 struct onenand_chip *this = mtd->priv; 840 struct onenand_chip *this = mtd->priv;
@@ -854,7 +854,7 @@ int onenand_do_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
854 column = from & (mtd->oobsize - 1); 854 column = from & (mtd->oobsize - 1);
855 855
856 if (unlikely(column >= oobsize)) { 856 if (unlikely(column >= oobsize)) {
857 DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_oob: Attempted to start read outside oob\n"); 857 printk(KERN_ERR "onenand_read_oob: Attempted to start read outside oob\n");
858 return -EINVAL; 858 return -EINVAL;
859 } 859 }
860 860
@@ -862,7 +862,7 @@ int onenand_do_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
862 if (unlikely(from >= mtd->size || 862 if (unlikely(from >= mtd->size ||
863 column + len > ((mtd->size >> this->page_shift) - 863 column + len > ((mtd->size >> this->page_shift) -
864 (from >> this->page_shift)) * oobsize)) { 864 (from >> this->page_shift)) * oobsize)) {
865 DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_oob: Attempted to read beyond end of device\n"); 865 printk(KERN_ERR "onenand_read_oob: Attempted to read beyond end of device\n");
866 return -EINVAL; 866 return -EINVAL;
867 } 867 }
868 868
@@ -888,7 +888,7 @@ int onenand_do_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
888 this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen); 888 this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen);
889 889
890 if (ret) { 890 if (ret) {
891 DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_oob: read failed = 0x%x\n", ret); 891 printk(KERN_ERR "onenand_read_oob: read failed = 0x%x\n", ret);
892 break; 892 break;
893 } 893 }
894 894
@@ -936,6 +936,121 @@ static int onenand_read_oob(struct mtd_info *mtd, loff_t from,
936 &ops->oobretlen, ops->oobbuf, ops->mode); 936 &ops->oobretlen, ops->oobbuf, ops->mode);
937} 937}
938 938
939/**
940 * onenand_bbt_wait - [DEFAULT] wait until the command is done
941 * @param mtd MTD device structure
942 * @param state state to select the max. timeout value
943 *
944 * Wait for command done.
945 */
946static int onenand_bbt_wait(struct mtd_info *mtd, int state)
947{
948 struct onenand_chip *this = mtd->priv;
949 unsigned long timeout;
950 unsigned int interrupt;
951 unsigned int ctrl;
952
953 /* The 20 msec is enough */
954 timeout = jiffies + msecs_to_jiffies(20);
955 while (time_before(jiffies, timeout)) {
956 interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT);
957 if (interrupt & ONENAND_INT_MASTER)
958 break;
959 }
960 /* To get correct interrupt status in timeout case */
961 interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT);
962 ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS);
963
964 if (ctrl & ONENAND_CTRL_ERROR) {
965 printk(KERN_DEBUG "onenand_bbt_wait: controller error = 0x%04x\n", ctrl);
966 /* Initial bad block case */
967 if (ctrl & ONENAND_CTRL_LOAD)
968 return ONENAND_BBT_READ_ERROR;
969 return ONENAND_BBT_READ_FATAL_ERROR;
970 }
971
972 if (interrupt & ONENAND_INT_READ) {
973 int ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS);
974 if (ecc & ONENAND_ECC_2BIT_ALL)
975 return ONENAND_BBT_READ_ERROR;
976 } else {
977 printk(KERN_ERR "onenand_bbt_wait: read timeout!"
978 "ctrl=0x%04x intr=0x%04x\n", ctrl, interrupt);
979 return ONENAND_BBT_READ_FATAL_ERROR;
980 }
981
982 return 0;
983}
984
985/**
986 * onenand_bbt_read_oob - [MTD Interface] OneNAND read out-of-band for bbt scan
987 * @param mtd MTD device structure
988 * @param from offset to read from
989 * @param @ops oob operation description structure
990 *
991 * OneNAND read out-of-band data from the spare area for bbt scan
992 */
993int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from,
994 struct mtd_oob_ops *ops)
995{
996 struct onenand_chip *this = mtd->priv;
997 int read = 0, thislen, column;
998 int ret = 0;
999 size_t len = ops->ooblen;
1000 u_char *buf = ops->oobbuf;
1001
1002 DEBUG(MTD_DEBUG_LEVEL3, "onenand_bbt_read_oob: from = 0x%08x, len = %i\n", (unsigned int) from, len);
1003
1004 /* Initialize return value */
1005 ops->oobretlen = 0;
1006
1007 /* Do not allow reads past end of device */
1008 if (unlikely((from + len) > mtd->size)) {
1009 printk(KERN_ERR "onenand_bbt_read_oob: Attempt read beyond end of device\n");
1010 return ONENAND_BBT_READ_FATAL_ERROR;
1011 }
1012
1013 /* Grab the lock and see if the device is available */
1014 onenand_get_device(mtd, FL_READING);
1015
1016 column = from & (mtd->oobsize - 1);
1017
1018 while (read < len) {
1019 cond_resched();
1020
1021 thislen = mtd->oobsize - column;
1022 thislen = min_t(int, thislen, len);
1023
1024 this->command(mtd, ONENAND_CMD_READOOB, from, mtd->oobsize);
1025
1026 onenand_update_bufferram(mtd, from, 0);
1027
1028 ret = onenand_bbt_wait(mtd, FL_READING);
1029 if (ret)
1030 break;
1031
1032 this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen);
1033 read += thislen;
1034 if (read == len)
1035 break;
1036
1037 buf += thislen;
1038
1039 /* Read more? */
1040 if (read < len) {
1041 /* Update Page size */
1042 from += mtd->writesize;
1043 column = 0;
1044 }
1045 }
1046
1047 /* Deselect and wake up anyone waiting on the device */
1048 onenand_release_device(mtd);
1049
1050 ops->oobretlen = read;
1051 return ret;
1052}
1053
939#ifdef CONFIG_MTD_ONENAND_VERIFY_WRITE 1054#ifdef CONFIG_MTD_ONENAND_VERIFY_WRITE
940/** 1055/**
941 * onenand_verify_oob - [GENERIC] verify the oob contents after a write 1056 * onenand_verify_oob - [GENERIC] verify the oob contents after a write
@@ -1040,13 +1155,13 @@ static int onenand_write(struct mtd_info *mtd, loff_t to, size_t len,
1040 1155
1041 /* Do not allow writes past end of device */ 1156 /* Do not allow writes past end of device */
1042 if (unlikely((to + len) > mtd->size)) { 1157 if (unlikely((to + len) > mtd->size)) {
1043 DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: Attempt write to past end of device\n"); 1158 printk(KERN_ERR "onenand_write: Attempt write to past end of device\n");
1044 return -EINVAL; 1159 return -EINVAL;
1045 } 1160 }
1046 1161
1047 /* Reject writes, which are not page aligned */ 1162 /* Reject writes, which are not page aligned */
1048 if (unlikely(NOTALIGNED(to)) || unlikely(NOTALIGNED(len))) { 1163 if (unlikely(NOTALIGNED(to)) || unlikely(NOTALIGNED(len))) {
1049 DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: Attempt to write not page aligned data\n"); 1164 printk(KERN_ERR "onenand_write: Attempt to write not page aligned data\n");
1050 return -EINVAL; 1165 return -EINVAL;
1051 } 1166 }
1052 1167
@@ -1083,14 +1198,14 @@ static int onenand_write(struct mtd_info *mtd, loff_t to, size_t len,
1083 onenand_update_bufferram(mtd, to, !ret && !subpage); 1198 onenand_update_bufferram(mtd, to, !ret && !subpage);
1084 1199
1085 if (ret) { 1200 if (ret) {
1086 DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: write filaed %d\n", ret); 1201 printk(KERN_ERR "onenand_write: write filaed %d\n", ret);
1087 break; 1202 break;
1088 } 1203 }
1089 1204
1090 /* Only check verify write turn on */ 1205 /* Only check verify write turn on */
1091 ret = onenand_verify(mtd, (u_char *) wbuf, to, thislen); 1206 ret = onenand_verify(mtd, (u_char *) wbuf, to, thislen);
1092 if (ret) { 1207 if (ret) {
1093 DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: verify failed %d\n", ret); 1208 printk(KERN_ERR "onenand_write: verify failed %d\n", ret);
1094 break; 1209 break;
1095 } 1210 }
1096 1211
@@ -1180,13 +1295,13 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
1180 column = to & (mtd->oobsize - 1); 1295 column = to & (mtd->oobsize - 1);
1181 1296
1182 if (unlikely(column >= oobsize)) { 1297 if (unlikely(column >= oobsize)) {
1183 DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_oob: Attempted to start write outside oob\n"); 1298 printk(KERN_ERR "onenand_write_oob: Attempted to start write outside oob\n");
1184 return -EINVAL; 1299 return -EINVAL;
1185 } 1300 }
1186 1301
1187 /* For compatibility with NAND: Do not allow write past end of page */ 1302 /* For compatibility with NAND: Do not allow write past end of page */
1188 if (column + len > oobsize) { 1303 if (column + len > oobsize) {
1189 DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_oob: " 1304 printk(KERN_ERR "onenand_write_oob: "
1190 "Attempt to write past end of page\n"); 1305 "Attempt to write past end of page\n");
1191 return -EINVAL; 1306 return -EINVAL;
1192 } 1307 }
@@ -1195,7 +1310,7 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
1195 if (unlikely(to >= mtd->size || 1310 if (unlikely(to >= mtd->size ||
1196 column + len > ((mtd->size >> this->page_shift) - 1311 column + len > ((mtd->size >> this->page_shift) -
1197 (to >> this->page_shift)) * oobsize)) { 1312 (to >> this->page_shift)) * oobsize)) {
1198 DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_oob: Attempted to write past end of device\n"); 1313 printk(KERN_ERR "onenand_write_oob: Attempted to write past end of device\n");
1199 return -EINVAL; 1314 return -EINVAL;
1200 } 1315 }
1201 1316
@@ -1225,13 +1340,13 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
1225 1340
1226 ret = this->wait(mtd, FL_WRITING); 1341 ret = this->wait(mtd, FL_WRITING);
1227 if (ret) { 1342 if (ret) {
1228 DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_oob: write failed %d\n", ret); 1343 printk(KERN_ERR "onenand_write_oob: write failed %d\n", ret);
1229 break; 1344 break;
1230 } 1345 }
1231 1346
1232 ret = onenand_verify_oob(mtd, this->page_buf, to); 1347 ret = onenand_verify_oob(mtd, this->page_buf, to);
1233 if (ret) { 1348 if (ret) {
1234 DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_oob: verify failed %d\n", ret); 1349 printk(KERN_ERR "onenand_write_oob: verify failed %d\n", ret);
1235 break; 1350 break;
1236 } 1351 }
1237 1352
@@ -1314,19 +1429,19 @@ static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
1314 1429
1315 /* Start address must align on block boundary */ 1430 /* Start address must align on block boundary */
1316 if (unlikely(instr->addr & (block_size - 1))) { 1431 if (unlikely(instr->addr & (block_size - 1))) {
1317 DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Unaligned address\n"); 1432 printk(KERN_ERR "onenand_erase: Unaligned address\n");
1318 return -EINVAL; 1433 return -EINVAL;
1319 } 1434 }
1320 1435
1321 /* Length must align on block boundary */ 1436 /* Length must align on block boundary */
1322 if (unlikely(instr->len & (block_size - 1))) { 1437 if (unlikely(instr->len & (block_size - 1))) {
1323 DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Length not block aligned\n"); 1438 printk(KERN_ERR "onenand_erase: Length not block aligned\n");
1324 return -EINVAL; 1439 return -EINVAL;
1325 } 1440 }
1326 1441
1327 /* Do not allow erase past end of device */ 1442 /* Do not allow erase past end of device */
1328 if (unlikely((instr->len + instr->addr) > mtd->size)) { 1443 if (unlikely((instr->len + instr->addr) > mtd->size)) {
1329 DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Erase past end of device\n"); 1444 printk(KERN_ERR "onenand_erase: Erase past end of device\n");
1330 return -EINVAL; 1445 return -EINVAL;
1331 } 1446 }
1332 1447
@@ -1356,7 +1471,7 @@ static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
1356 ret = this->wait(mtd, FL_ERASING); 1471 ret = this->wait(mtd, FL_ERASING);
1357 /* Check, if it is write protected */ 1472 /* Check, if it is write protected */
1358 if (ret) { 1473 if (ret) {
1359 DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Failed erase, block %d\n", (unsigned) (addr >> this->erase_shift)); 1474 printk(KERN_ERR "onenand_erase: Failed erase, block %d\n", (unsigned) (addr >> this->erase_shift));
1360 instr->state = MTD_ERASE_FAILED; 1475 instr->state = MTD_ERASE_FAILED;
1361 instr->fail_addr = addr; 1476 instr->fail_addr = addr;
1362 goto erase_exit; 1477 goto erase_exit;
diff --git a/drivers/mtd/onenand/onenand_bbt.c b/drivers/mtd/onenand/onenand_bbt.c
index acea9a1a7297..aecdd50a1781 100644
--- a/drivers/mtd/onenand/onenand_bbt.c
+++ b/drivers/mtd/onenand/onenand_bbt.c
@@ -17,8 +17,8 @@
17#include <linux/mtd/onenand.h> 17#include <linux/mtd/onenand.h>
18#include <linux/mtd/compatmac.h> 18#include <linux/mtd/compatmac.h>
19 19
20extern int onenand_do_read_oob(struct mtd_info *mtd, loff_t from, size_t len, 20extern int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from,
21 size_t *retlen, u_char *buf, mtd_oob_mode_t mode); 21 struct mtd_oob_ops *ops);
22 22
23/** 23/**
24 * check_short_pattern - [GENERIC] check if a pattern is in the buffer 24 * check_short_pattern - [GENERIC] check if a pattern is in the buffer
@@ -65,6 +65,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
65 int startblock; 65 int startblock;
66 loff_t from; 66 loff_t from;
67 size_t readlen, ooblen; 67 size_t readlen, ooblen;
68 struct mtd_oob_ops ops;
68 69
69 printk(KERN_INFO "Scanning device for bad blocks\n"); 70 printk(KERN_INFO "Scanning device for bad blocks\n");
70 71
@@ -82,22 +83,24 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
82 startblock = 0; 83 startblock = 0;
83 from = 0; 84 from = 0;
84 85
86 ops.mode = MTD_OOB_PLACE;
87 ops.ooblen = readlen;
88 ops.oobbuf = buf;
89 ops.len = ops.ooboffs = ops.retlen = ops.oobretlen = 0;
90
85 for (i = startblock; i < numblocks; ) { 91 for (i = startblock; i < numblocks; ) {
86 int ret; 92 int ret;
87 93
88 for (j = 0; j < len; j++) { 94 for (j = 0; j < len; j++) {
89 size_t retlen;
90
91 /* No need to read pages fully, 95 /* No need to read pages fully,
92 * just read required OOB bytes */ 96 * just read required OOB bytes */
93 ret = onenand_do_read_oob(mtd, from + j * mtd->writesize + bd->offs, 97 ret = onenand_bbt_read_oob(mtd, from + j * mtd->writesize + bd->offs, &ops);
94 readlen, &retlen, &buf[0], MTD_OOB_PLACE);
95 98
96 /* If it is a initial bad block, just ignore it */ 99 /* If it is a initial bad block, just ignore it */
97 if (ret && !(ret & ONENAND_CTRL_LOAD)) 100 if (ret == ONENAND_BBT_READ_FATAL_ERROR)
98 return ret; 101 return -EIO;
99 102
100 if (check_short_pattern(&buf[j * scanlen], scanlen, mtd->writesize, bd)) { 103 if (ret || check_short_pattern(&buf[j * scanlen], scanlen, mtd->writesize, bd)) {
101 bbm->bbt[i >> 3] |= 0x03 << (i & 0x6); 104 bbm->bbt[i >> 3] |= 0x03 << (i & 0x6);
102 printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n", 105 printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n",
103 i >> 1, (unsigned int) from); 106 i >> 1, (unsigned int) from);
diff --git a/include/linux/mtd/bbm.h b/include/linux/mtd/bbm.h
index 1221b7c44158..fff8c53e5434 100644
--- a/include/linux/mtd/bbm.h
+++ b/include/linux/mtd/bbm.h
@@ -92,6 +92,13 @@ struct nand_bbt_descr {
92 */ 92 */
93#define ONENAND_BADBLOCK_POS 0 93#define ONENAND_BADBLOCK_POS 0
94 94
95/*
96 * Bad block scanning errors
97 */
98#define ONENAND_BBT_READ_ERROR 1
99#define ONENAND_BBT_READ_ECC_ERROR 2
100#define ONENAND_BBT_READ_FATAL_ERROR 4
101
95/** 102/**
96 * struct bbm_info - [GENERIC] Bad Block Table data structure 103 * struct bbm_info - [GENERIC] Bad Block Table data structure
97 * @bbt_erase_shift: [INTERN] number of address bits in a bbt entry 104 * @bbt_erase_shift: [INTERN] number of address bits in a bbt entry