aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/onenand/onenand_base.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/onenand/onenand_base.c')
-rw-r--r--drivers/mtd/onenand/onenand_base.c199
1 files changed, 158 insertions, 41 deletions
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index 1b0b32011415..8d7d21be1541 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -18,6 +18,7 @@
18#include <linux/module.h> 18#include <linux/module.h>
19#include <linux/init.h> 19#include <linux/init.h>
20#include <linux/sched.h> 20#include <linux/sched.h>
21#include <linux/delay.h>
21#include <linux/interrupt.h> 22#include <linux/interrupt.h>
22#include <linux/jiffies.h> 23#include <linux/jiffies.h>
23#include <linux/mtd/mtd.h> 24#include <linux/mtd/mtd.h>
@@ -170,6 +171,18 @@ static int onenand_buffer_address(int dataram1, int sectors, int count)
170} 171}
171 172
172/** 173/**
174 * onenand_get_density - [DEFAULT] Get OneNAND density
175 * @param dev_id OneNAND device ID
176 *
177 * Get OneNAND density from device ID
178 */
179static inline int onenand_get_density(int dev_id)
180{
181 int density = dev_id >> ONENAND_DEVICE_DENSITY_SHIFT;
182 return (density & ONENAND_DEVICE_DENSITY_MASK);
183}
184
185/**
173 * onenand_command - [DEFAULT] Send command to OneNAND device 186 * onenand_command - [DEFAULT] Send command to OneNAND device
174 * @param mtd MTD device structure 187 * @param mtd MTD device structure
175 * @param cmd the command to be sent 188 * @param cmd the command to be sent
@@ -182,8 +195,7 @@ static int onenand_buffer_address(int dataram1, int sectors, int count)
182static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t len) 195static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t len)
183{ 196{
184 struct onenand_chip *this = mtd->priv; 197 struct onenand_chip *this = mtd->priv;
185 int value, readcmd = 0, block_cmd = 0; 198 int value, block, page;
186 int block, page;
187 199
188 /* Address translation */ 200 /* Address translation */
189 switch (cmd) { 201 switch (cmd) {
@@ -198,7 +210,6 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le
198 case ONENAND_CMD_ERASE: 210 case ONENAND_CMD_ERASE:
199 case ONENAND_CMD_BUFFERRAM: 211 case ONENAND_CMD_BUFFERRAM:
200 case ONENAND_CMD_OTP_ACCESS: 212 case ONENAND_CMD_OTP_ACCESS:
201 block_cmd = 1;
202 block = (int) (addr >> this->erase_shift); 213 block = (int) (addr >> this->erase_shift);
203 page = -1; 214 page = -1;
204 break; 215 break;
@@ -240,11 +251,9 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le
240 value = onenand_block_address(this, block); 251 value = onenand_block_address(this, block);
241 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1); 252 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1);
242 253
243 if (block_cmd) { 254 /* Select DataRAM for DDP */
244 /* Select DataRAM for DDP */ 255 value = onenand_bufferram_address(this, block);
245 value = onenand_bufferram_address(this, block); 256 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);
246 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);
247 }
248 } 257 }
249 258
250 if (page != -1) { 259 if (page != -1) {
@@ -256,7 +265,6 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le
256 case ONENAND_CMD_READ: 265 case ONENAND_CMD_READ:
257 case ONENAND_CMD_READOOB: 266 case ONENAND_CMD_READOOB:
258 dataram = ONENAND_SET_NEXT_BUFFERRAM(this); 267 dataram = ONENAND_SET_NEXT_BUFFERRAM(this);
259 readcmd = 1;
260 break; 268 break;
261 269
262 default: 270 default:
@@ -273,12 +281,6 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le
273 /* Write 'BSA, BSC' of DataRAM */ 281 /* Write 'BSA, BSC' of DataRAM */
274 value = onenand_buffer_address(dataram, sectors, count); 282 value = onenand_buffer_address(dataram, sectors, count);
275 this->write_word(value, this->base + ONENAND_REG_START_BUFFER); 283 this->write_word(value, this->base + ONENAND_REG_START_BUFFER);
276
277 if (readcmd) {
278 /* Select DataRAM for DDP */
279 value = onenand_bufferram_address(this, block);
280 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);
281 }
282 } 284 }
283 285
284 /* Interrupt clear */ 286 /* Interrupt clear */
@@ -855,6 +857,8 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from,
855 this->command(mtd, ONENAND_CMD_READ, from, writesize); 857 this->command(mtd, ONENAND_CMD_READ, from, writesize);
856 ret = this->wait(mtd, FL_READING); 858 ret = this->wait(mtd, FL_READING);
857 onenand_update_bufferram(mtd, from, !ret); 859 onenand_update_bufferram(mtd, from, !ret);
860 if (ret == -EBADMSG)
861 ret = 0;
858 } 862 }
859 } 863 }
860 864
@@ -913,6 +917,8 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from,
913 /* Now wait for load */ 917 /* Now wait for load */
914 ret = this->wait(mtd, FL_READING); 918 ret = this->wait(mtd, FL_READING);
915 onenand_update_bufferram(mtd, from, !ret); 919 onenand_update_bufferram(mtd, from, !ret);
920 if (ret == -EBADMSG)
921 ret = 0;
916 } 922 }
917 923
918 /* 924 /*
@@ -923,12 +929,12 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from,
923 ops->retlen = read; 929 ops->retlen = read;
924 ops->oobretlen = oobread; 930 ops->oobretlen = oobread;
925 931
926 if (mtd->ecc_stats.failed - stats.failed)
927 return -EBADMSG;
928
929 if (ret) 932 if (ret)
930 return ret; 933 return ret;
931 934
935 if (mtd->ecc_stats.failed - stats.failed)
936 return -EBADMSG;
937
932 return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0; 938 return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0;
933} 939}
934 940
@@ -944,6 +950,7 @@ static int onenand_read_oob_nolock(struct mtd_info *mtd, loff_t from,
944 struct mtd_oob_ops *ops) 950 struct mtd_oob_ops *ops)
945{ 951{
946 struct onenand_chip *this = mtd->priv; 952 struct onenand_chip *this = mtd->priv;
953 struct mtd_ecc_stats stats;
947 int read = 0, thislen, column, oobsize; 954 int read = 0, thislen, column, oobsize;
948 size_t len = ops->ooblen; 955 size_t len = ops->ooblen;
949 mtd_oob_mode_t mode = ops->mode; 956 mtd_oob_mode_t mode = ops->mode;
@@ -977,6 +984,8 @@ static int onenand_read_oob_nolock(struct mtd_info *mtd, loff_t from,
977 return -EINVAL; 984 return -EINVAL;
978 } 985 }
979 986
987 stats = mtd->ecc_stats;
988
980 while (read < len) { 989 while (read < len) {
981 cond_resched(); 990 cond_resched();
982 991
@@ -988,18 +997,16 @@ static int onenand_read_oob_nolock(struct mtd_info *mtd, loff_t from,
988 onenand_update_bufferram(mtd, from, 0); 997 onenand_update_bufferram(mtd, from, 0);
989 998
990 ret = this->wait(mtd, FL_READING); 999 ret = this->wait(mtd, FL_READING);
991 /* First copy data and check return value for ECC handling */ 1000 if (ret && ret != -EBADMSG) {
1001 printk(KERN_ERR "onenand_read_oob_nolock: read failed = 0x%x\n", ret);
1002 break;
1003 }
992 1004
993 if (mode == MTD_OOB_AUTO) 1005 if (mode == MTD_OOB_AUTO)
994 onenand_transfer_auto_oob(mtd, buf, column, thislen); 1006 onenand_transfer_auto_oob(mtd, buf, column, thislen);
995 else 1007 else
996 this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen); 1008 this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen);
997 1009
998 if (ret) {
999 printk(KERN_ERR "onenand_read_oob_nolock: read failed = 0x%x\n", ret);
1000 break;
1001 }
1002
1003 read += thislen; 1010 read += thislen;
1004 1011
1005 if (read == len) 1012 if (read == len)
@@ -1016,7 +1023,14 @@ static int onenand_read_oob_nolock(struct mtd_info *mtd, loff_t from,
1016 } 1023 }
1017 1024
1018 ops->oobretlen = read; 1025 ops->oobretlen = read;
1019 return ret; 1026
1027 if (ret)
1028 return ret;
1029
1030 if (mtd->ecc_stats.failed - stats.failed)
1031 return -EBADMSG;
1032
1033 return 0;
1020} 1034}
1021 1035
1022/** 1036/**
@@ -1106,12 +1120,10 @@ static int onenand_bbt_wait(struct mtd_info *mtd, int state)
1106 interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT); 1120 interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT);
1107 ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS); 1121 ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS);
1108 1122
1123 /* Initial bad block case: 0x2400 or 0x0400 */
1109 if (ctrl & ONENAND_CTRL_ERROR) { 1124 if (ctrl & ONENAND_CTRL_ERROR) {
1110 printk(KERN_DEBUG "onenand_bbt_wait: controller error = 0x%04x\n", ctrl); 1125 printk(KERN_DEBUG "onenand_bbt_wait: controller error = 0x%04x\n", ctrl);
1111 /* Initial bad block case */ 1126 return ONENAND_BBT_READ_ERROR;
1112 if (ctrl & ONENAND_CTRL_LOAD)
1113 return ONENAND_BBT_READ_ERROR;
1114 return ONENAND_BBT_READ_FATAL_ERROR;
1115 } 1127 }
1116 1128
1117 if (interrupt & ONENAND_INT_READ) { 1129 if (interrupt & ONENAND_INT_READ) {
@@ -1206,7 +1218,7 @@ int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from,
1206static int onenand_verify_oob(struct mtd_info *mtd, const u_char *buf, loff_t to) 1218static int onenand_verify_oob(struct mtd_info *mtd, const u_char *buf, loff_t to)
1207{ 1219{
1208 struct onenand_chip *this = mtd->priv; 1220 struct onenand_chip *this = mtd->priv;
1209 char oobbuf[64]; 1221 u_char *oob_buf = this->oob_buf;
1210 int status, i; 1222 int status, i;
1211 1223
1212 this->command(mtd, ONENAND_CMD_READOOB, to, mtd->oobsize); 1224 this->command(mtd, ONENAND_CMD_READOOB, to, mtd->oobsize);
@@ -1215,9 +1227,9 @@ static int onenand_verify_oob(struct mtd_info *mtd, const u_char *buf, loff_t to
1215 if (status) 1227 if (status)
1216 return status; 1228 return status;
1217 1229
1218 this->read_bufferram(mtd, ONENAND_SPARERAM, oobbuf, 0, mtd->oobsize); 1230 this->read_bufferram(mtd, ONENAND_SPARERAM, oob_buf, 0, mtd->oobsize);
1219 for (i = 0; i < mtd->oobsize; i++) 1231 for (i = 0; i < mtd->oobsize; i++)
1220 if (buf[i] != 0xFF && buf[i] != oobbuf[i]) 1232 if (buf[i] != 0xFF && buf[i] != oob_buf[i])
1221 return -EBADMSG; 1233 return -EBADMSG;
1222 1234
1223 return 0; 1235 return 0;
@@ -1273,6 +1285,112 @@ static int onenand_verify(struct mtd_info *mtd, const u_char *buf, loff_t addr,
1273 1285
1274#define NOTALIGNED(x) ((x & (this->subpagesize - 1)) != 0) 1286#define NOTALIGNED(x) ((x & (this->subpagesize - 1)) != 0)
1275 1287
1288static void onenand_panic_wait(struct mtd_info *mtd)
1289{
1290 struct onenand_chip *this = mtd->priv;
1291 unsigned int interrupt;
1292 int i;
1293
1294 for (i = 0; i < 2000; i++) {
1295 interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT);
1296 if (interrupt & ONENAND_INT_MASTER)
1297 break;
1298 udelay(10);
1299 }
1300}
1301
1302/**
1303 * onenand_panic_write - [MTD Interface] write buffer to FLASH in a panic context
1304 * @param mtd MTD device structure
1305 * @param to offset to write to
1306 * @param len number of bytes to write
1307 * @param retlen pointer to variable to store the number of written bytes
1308 * @param buf the data to write
1309 *
1310 * Write with ECC
1311 */
1312static int onenand_panic_write(struct mtd_info *mtd, loff_t to, size_t len,
1313 size_t *retlen, const u_char *buf)
1314{
1315 struct onenand_chip *this = mtd->priv;
1316 int column, subpage;
1317 int written = 0;
1318 int ret = 0;
1319
1320 if (this->state == FL_PM_SUSPENDED)
1321 return -EBUSY;
1322
1323 /* Wait for any existing operation to clear */
1324 onenand_panic_wait(mtd);
1325
1326 DEBUG(MTD_DEBUG_LEVEL3, "onenand_panic_write: to = 0x%08x, len = %i\n",
1327 (unsigned int) to, (int) len);
1328
1329 /* Initialize retlen, in case of early exit */
1330 *retlen = 0;
1331
1332 /* Do not allow writes past end of device */
1333 if (unlikely((to + len) > mtd->size)) {
1334 printk(KERN_ERR "onenand_panic_write: Attempt write to past end of device\n");
1335 return -EINVAL;
1336 }
1337
1338 /* Reject writes, which are not page aligned */
1339 if (unlikely(NOTALIGNED(to)) || unlikely(NOTALIGNED(len))) {
1340 printk(KERN_ERR "onenand_panic_write: Attempt to write not page aligned data\n");
1341 return -EINVAL;
1342 }
1343
1344 column = to & (mtd->writesize - 1);
1345
1346 /* Loop until all data write */
1347 while (written < len) {
1348 int thislen = min_t(int, mtd->writesize - column, len - written);
1349 u_char *wbuf = (u_char *) buf;
1350
1351 this->command(mtd, ONENAND_CMD_BUFFERRAM, to, thislen);
1352
1353 /* Partial page write */
1354 subpage = thislen < mtd->writesize;
1355 if (subpage) {
1356 memset(this->page_buf, 0xff, mtd->writesize);
1357 memcpy(this->page_buf + column, buf, thislen);
1358 wbuf = this->page_buf;
1359 }
1360
1361 this->write_bufferram(mtd, ONENAND_DATARAM, wbuf, 0, mtd->writesize);
1362 this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0, mtd->oobsize);
1363
1364 this->command(mtd, ONENAND_CMD_PROG, to, mtd->writesize);
1365
1366 onenand_panic_wait(mtd);
1367
1368 /* In partial page write we don't update bufferram */
1369 onenand_update_bufferram(mtd, to, !ret && !subpage);
1370 if (ONENAND_IS_2PLANE(this)) {
1371 ONENAND_SET_BUFFERRAM1(this);
1372 onenand_update_bufferram(mtd, to + this->writesize, !ret && !subpage);
1373 }
1374
1375 if (ret) {
1376 printk(KERN_ERR "onenand_panic_write: write failed %d\n", ret);
1377 break;
1378 }
1379
1380 written += thislen;
1381
1382 if (written == len)
1383 break;
1384
1385 column = 0;
1386 to += thislen;
1387 buf += thislen;
1388 }
1389
1390 *retlen = written;
1391 return ret;
1392}
1393
1276/** 1394/**
1277 * onenand_fill_auto_oob - [Internal] oob auto-placement transfer 1395 * onenand_fill_auto_oob - [Internal] oob auto-placement transfer
1278 * @param mtd MTD device structure 1396 * @param mtd MTD device structure
@@ -1419,7 +1537,7 @@ static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to,
1419 } 1537 }
1420 1538
1421 /* Only check verify write turn on */ 1539 /* Only check verify write turn on */
1422 ret = onenand_verify(mtd, (u_char *) wbuf, to, thislen); 1540 ret = onenand_verify(mtd, buf, to, thislen);
1423 if (ret) { 1541 if (ret) {
1424 printk(KERN_ERR "onenand_write_ops_nolock: verify failed %d\n", ret); 1542 printk(KERN_ERR "onenand_write_ops_nolock: verify failed %d\n", ret);
1425 break; 1543 break;
@@ -1435,9 +1553,6 @@ static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to,
1435 buf += thislen; 1553 buf += thislen;
1436 } 1554 }
1437 1555
1438 /* Deselect and wake up anyone waiting on the device */
1439 onenand_release_device(mtd);
1440
1441 ops->retlen = written; 1556 ops->retlen = written;
1442 1557
1443 return ret; 1558 return ret;
@@ -2148,7 +2263,7 @@ static int onenand_otp_walk(struct mtd_info *mtd, loff_t from, size_t len,
2148 2263
2149 *retlen = 0; 2264 *retlen = 0;
2150 2265
2151 density = this->device_id >> ONENAND_DEVICE_DENSITY_SHIFT; 2266 density = onenand_get_density(this->device_id);
2152 if (density < ONENAND_DEVICE_DENSITY_512Mb) 2267 if (density < ONENAND_DEVICE_DENSITY_512Mb)
2153 otp_pages = 20; 2268 otp_pages = 20;
2154 else 2269 else
@@ -2299,7 +2414,8 @@ static int onenand_write_user_prot_reg(struct mtd_info *mtd, loff_t from,
2299static int onenand_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, 2414static int onenand_lock_user_prot_reg(struct mtd_info *mtd, loff_t from,
2300 size_t len) 2415 size_t len)
2301{ 2416{
2302 unsigned char oob_buf[64]; 2417 struct onenand_chip *this = mtd->priv;
2418 u_char *oob_buf = this->oob_buf;
2303 size_t retlen; 2419 size_t retlen;
2304 int ret; 2420 int ret;
2305 2421
@@ -2339,7 +2455,7 @@ static void onenand_check_features(struct mtd_info *mtd)
2339 unsigned int density, process; 2455 unsigned int density, process;
2340 2456
2341 /* Lock scheme depends on density and process */ 2457 /* Lock scheme depends on density and process */
2342 density = this->device_id >> ONENAND_DEVICE_DENSITY_SHIFT; 2458 density = onenand_get_density(this->device_id);
2343 process = this->version_id >> ONENAND_VERSION_PROCESS_SHIFT; 2459 process = this->version_id >> ONENAND_VERSION_PROCESS_SHIFT;
2344 2460
2345 /* Lock scheme */ 2461 /* Lock scheme */
@@ -2388,7 +2504,7 @@ static void onenand_print_device_info(int device, int version)
2388 vcc = device & ONENAND_DEVICE_VCC_MASK; 2504 vcc = device & ONENAND_DEVICE_VCC_MASK;
2389 demuxed = device & ONENAND_DEVICE_IS_DEMUX; 2505 demuxed = device & ONENAND_DEVICE_IS_DEMUX;
2390 ddp = device & ONENAND_DEVICE_IS_DDP; 2506 ddp = device & ONENAND_DEVICE_IS_DDP;
2391 density = device >> ONENAND_DEVICE_DENSITY_SHIFT; 2507 density = onenand_get_density(device);
2392 printk(KERN_INFO "%sOneNAND%s %dMB %sV 16-bit (0x%02x)\n", 2508 printk(KERN_INFO "%sOneNAND%s %dMB %sV 16-bit (0x%02x)\n",
2393 demuxed ? "" : "Muxed ", 2509 demuxed ? "" : "Muxed ",
2394 ddp ? "(DDP)" : "", 2510 ddp ? "(DDP)" : "",
@@ -2480,7 +2596,7 @@ static int onenand_probe(struct mtd_info *mtd)
2480 this->device_id = dev_id; 2596 this->device_id = dev_id;
2481 this->version_id = ver_id; 2597 this->version_id = ver_id;
2482 2598
2483 density = dev_id >> ONENAND_DEVICE_DENSITY_SHIFT; 2599 density = onenand_get_density(dev_id);
2484 this->chipsize = (16 << density) << 20; 2600 this->chipsize = (16 << density) << 20;
2485 /* Set density mask. it is used for DDP */ 2601 /* Set density mask. it is used for DDP */
2486 if (ONENAND_IS_DDP(this)) 2602 if (ONENAND_IS_DDP(this))
@@ -2664,6 +2780,7 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
2664 mtd->write = onenand_write; 2780 mtd->write = onenand_write;
2665 mtd->read_oob = onenand_read_oob; 2781 mtd->read_oob = onenand_read_oob;
2666 mtd->write_oob = onenand_write_oob; 2782 mtd->write_oob = onenand_write_oob;
2783 mtd->panic_write = onenand_panic_write;
2667#ifdef CONFIG_MTD_ONENAND_OTP 2784#ifdef CONFIG_MTD_ONENAND_OTP
2668 mtd->get_fact_prot_info = onenand_get_fact_prot_info; 2785 mtd->get_fact_prot_info = onenand_get_fact_prot_info;
2669 mtd->read_fact_prot_reg = onenand_read_fact_prot_reg; 2786 mtd->read_fact_prot_reg = onenand_read_fact_prot_reg;