aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/onenand
diff options
context:
space:
mode:
authorKyungmin Park <kyungmin.park@samsung.com>2006-11-15 21:29:39 -0500
committerKyungmin Park <kyungmin.park@samsung.com>2006-11-15 21:29:39 -0500
commit08f782b60a633cbd926ef5e49de303a752390719 (patch)
tree927c3269661438faf438e7c3096edd9fa02086dd /drivers/mtd/onenand
parent2c22120fbd017d78ad2b6825ba573db3ef539bca (diff)
[MTD] OneNAND: lock support
Now you can use mtd lock inferface on OneNAND The idea is from Nemakal, Vijaya, thanks Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Diffstat (limited to 'drivers/mtd/onenand')
-rw-r--r--drivers/mtd/onenand/onenand_base.c63
1 files changed, 48 insertions, 15 deletions
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index aea13a388868..bef4f26ad2ed 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -1301,32 +1301,38 @@ static int onenand_block_markbad(struct mtd_info *mtd, loff_t ofs)
1301} 1301}
1302 1302
1303/** 1303/**
1304 * onenand_unlock - [MTD Interface] Unlock block(s) 1304 * onenand_do_lock_cmd - [OneNAND Interface] Lock or unlock block(s)
1305 * @param mtd MTD device structure 1305 * @param mtd MTD device structure
1306 * @param ofs offset relative to mtd start 1306 * @param ofs offset relative to mtd start
1307 * @param len number of bytes to unlock 1307 * @param len number of bytes to lock or unlock
1308 * 1308 *
1309 * Unlock one or more blocks 1309 * Lock or unlock one or more blocks
1310 */ 1310 */
1311static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) 1311static int onenand_do_lock_cmd(struct mtd_info *mtd, loff_t ofs, size_t len, int cmd)
1312{ 1312{
1313 struct onenand_chip *this = mtd->priv; 1313 struct onenand_chip *this = mtd->priv;
1314 int start, end, block, value, status; 1314 int start, end, block, value, status;
1315 int wp_status_mask;
1315 1316
1316 start = ofs >> this->erase_shift; 1317 start = ofs >> this->erase_shift;
1317 end = len >> this->erase_shift; 1318 end = len >> this->erase_shift;
1318 1319
1320 if (cmd == ONENAND_CMD_LOCK)
1321 wp_status_mask = ONENAND_WP_LS;
1322 else
1323 wp_status_mask = ONENAND_WP_US;
1324
1319 /* Continuous lock scheme */ 1325 /* Continuous lock scheme */
1320 if (this->options & ONENAND_HAS_CONT_LOCK) { 1326 if (this->options & ONENAND_HAS_CONT_LOCK) {
1321 /* Set start block address */ 1327 /* Set start block address */
1322 this->write_word(start, this->base + ONENAND_REG_START_BLOCK_ADDRESS); 1328 this->write_word(start, this->base + ONENAND_REG_START_BLOCK_ADDRESS);
1323 /* Set end block address */ 1329 /* Set end block address */
1324 this->write_word(start + end - 1, this->base + ONENAND_REG_END_BLOCK_ADDRESS); 1330 this->write_word(start + end - 1, this->base + ONENAND_REG_END_BLOCK_ADDRESS);
1325 /* Write unlock command */ 1331 /* Write lock command */
1326 this->command(mtd, ONENAND_CMD_UNLOCK, 0, 0); 1332 this->command(mtd, cmd, 0, 0);
1327 1333
1328 /* There's no return value */ 1334 /* There's no return value */
1329 this->wait(mtd, FL_UNLOCKING); 1335 this->wait(mtd, FL_LOCKING);
1330 1336
1331 /* Sanity check */ 1337 /* Sanity check */
1332 while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS) 1338 while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS)
@@ -1335,7 +1341,7 @@ static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
1335 1341
1336 /* Check lock status */ 1342 /* Check lock status */
1337 status = this->read_word(this->base + ONENAND_REG_WP_STATUS); 1343 status = this->read_word(this->base + ONENAND_REG_WP_STATUS);
1338 if (!(status & ONENAND_WP_US)) 1344 if (!(status & wp_status_mask))
1339 printk(KERN_ERR "wp status = 0x%x\n", status); 1345 printk(KERN_ERR "wp status = 0x%x\n", status);
1340 1346
1341 return 0; 1347 return 0;
@@ -1351,11 +1357,11 @@ static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
1351 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2); 1357 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);
1352 /* Set start block address */ 1358 /* Set start block address */
1353 this->write_word(block, this->base + ONENAND_REG_START_BLOCK_ADDRESS); 1359 this->write_word(block, this->base + ONENAND_REG_START_BLOCK_ADDRESS);
1354 /* Write unlock command */ 1360 /* Write lock command */
1355 this->command(mtd, ONENAND_CMD_UNLOCK, 0, 0); 1361 this->command(mtd, cmd, 0, 0);
1356 1362
1357 /* There's no return value */ 1363 /* There's no return value */
1358 this->wait(mtd, FL_UNLOCKING); 1364 this->wait(mtd, FL_LOCKING);
1359 1365
1360 /* Sanity check */ 1366 /* Sanity check */
1361 while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS) 1367 while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS)
@@ -1364,7 +1370,7 @@ static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
1364 1370
1365 /* Check lock status */ 1371 /* Check lock status */
1366 status = this->read_word(this->base + ONENAND_REG_WP_STATUS); 1372 status = this->read_word(this->base + ONENAND_REG_WP_STATUS);
1367 if (!(status & ONENAND_WP_US)) 1373 if (!(status & wp_status_mask))
1368 printk(KERN_ERR "block = %d, wp status = 0x%x\n", block, status); 1374 printk(KERN_ERR "block = %d, wp status = 0x%x\n", block, status);
1369 } 1375 }
1370 1376
@@ -1372,6 +1378,33 @@ static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
1372} 1378}
1373 1379
1374/** 1380/**
1381 * onenand_lock - [MTD Interface] Lock block(s)
1382 * @param mtd MTD device structure
1383 * @param ofs offset relative to mtd start
1384 * @param len number of bytes to unlock
1385 *
1386 * Lock one or more blocks
1387 */
1388static int onenand_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
1389{
1390 return onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_LOCK);
1391}
1392
1393
1394/**
1395 * onenand_unlock - [MTD Interface] Unlock block(s)
1396 * @param mtd MTD device structure
1397 * @param ofs offset relative to mtd start
1398 * @param len number of bytes to unlock
1399 *
1400 * Unlock one or more blocks
1401 */
1402static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
1403{
1404 return onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_UNLOCK);
1405}
1406
1407/**
1375 * onenand_check_lock_status - [OneNAND Interface] Check lock status 1408 * onenand_check_lock_status - [OneNAND Interface] Check lock status
1376 * @param this onenand chip data structure 1409 * @param this onenand chip data structure
1377 * 1410 *
@@ -1415,7 +1448,7 @@ static int onenand_unlock_all(struct mtd_info *mtd)
1415 this->command(mtd, ONENAND_CMD_UNLOCK_ALL, 0, 0); 1448 this->command(mtd, ONENAND_CMD_UNLOCK_ALL, 0, 0);
1416 1449
1417 /* There's no return value */ 1450 /* There's no return value */
1418 this->wait(mtd, FL_UNLOCKING); 1451 this->wait(mtd, FL_LOCKING);
1419 1452
1420 /* Sanity check */ 1453 /* Sanity check */
1421 while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS) 1454 while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS)
@@ -1439,7 +1472,7 @@ static int onenand_unlock_all(struct mtd_info *mtd)
1439 return 0; 1472 return 0;
1440 } 1473 }
1441 1474
1442 mtd->unlock(mtd, 0x0, this->chipsize); 1475 onenand_unlock(mtd, 0x0, this->chipsize);
1443 1476
1444 return 0; 1477 return 0;
1445} 1478}
@@ -2027,7 +2060,7 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
2027 mtd->lock_user_prot_reg = onenand_lock_user_prot_reg; 2060 mtd->lock_user_prot_reg = onenand_lock_user_prot_reg;
2028#endif 2061#endif
2029 mtd->sync = onenand_sync; 2062 mtd->sync = onenand_sync;
2030 mtd->lock = NULL; 2063 mtd->lock = onenand_lock;
2031 mtd->unlock = onenand_unlock; 2064 mtd->unlock = onenand_unlock;
2032 mtd->suspend = onenand_suspend; 2065 mtd->suspend = onenand_suspend;
2033 mtd->resume = onenand_resume; 2066 mtd->resume = onenand_resume;