From: Sanghee Kim Date: Fri, 30 Apr 2010 05:19:36 +0000 (+0900) Subject: recovery: onenand: add lock-tight X-Git-Tag: JD16_20100430~3 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;ds=sidebyside;h=8bcb7c198158086226c73a95ca18ea58df0d783b;p=kernel%2Fu-boot.git recovery: onenand: add lock-tight --- diff --git a/recovery/drivers/onenand/onenand_base.c b/recovery/drivers/onenand/onenand_base.c index cc16326..d00d515 100644 --- a/recovery/drivers/onenand/onenand_base.c +++ b/recovery/drivers/onenand/onenand_base.c @@ -2051,6 +2051,8 @@ static int onenand_do_lock_cmd(struct mtd_info *mtd, loff_t ofs, size_t len, int if (cmd == ONENAND_CMD_LOCK) wp_status_mask = ONENAND_WP_LS; + else if (cmd == ONENAND_CMD_LOCK_TIGHT) + wp_status_mask = ONENAND_WP_LTS; else wp_status_mask = ONENAND_WP_US; @@ -2062,11 +2064,11 @@ static int onenand_do_lock_cmd(struct mtd_info *mtd, loff_t ofs, size_t len, int /* Set end block address */ this->write_word(end - 1, this->base + ONENAND_REG_END_BLOCK_ADDRESS); - /* Write unlock command */ + /* Write lock command */ this->command(mtd, cmd, 0, 0); /* There's no return value */ - this->wait(mtd, FL_UNLOCKING); + this->wait(mtd, FL_LOCKING); /* Sanity check */ while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS) @@ -2075,7 +2077,7 @@ static int onenand_do_lock_cmd(struct mtd_info *mtd, loff_t ofs, size_t len, int /* Check lock status */ status = this->read_word(this->base + ONENAND_REG_WP_STATUS); - if (!(status & ONENAND_WP_US)) + if (!(status & wp_status_mask)) printk(KERN_ERR "wp status = 0x%x\n", status); return 0; @@ -2093,11 +2095,11 @@ static int onenand_do_lock_cmd(struct mtd_info *mtd, loff_t ofs, size_t len, int /* Set start block address */ this->write_word(block, this->base + ONENAND_REG_START_BLOCK_ADDRESS); - /* Write unlock command */ - this->command(mtd, ONENAND_CMD_UNLOCK, 0, 0); + /* Write lock command */ + this->command(mtd, cmd, 0, 0); /* There's no return value */ - this->wait(mtd, FL_UNLOCKING); + this->wait(mtd, FL_LOCKING); /* Sanity check */ while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS) @@ -2106,7 +2108,7 @@ static int onenand_do_lock_cmd(struct mtd_info *mtd, loff_t ofs, size_t len, int /* Check lock status */ status = this->read_word(this->base + ONENAND_REG_WP_STATUS); - if (!(status & ONENAND_WP_US)) + if (!(status & wp_status_mask)) printk(KERN_ERR "block = %d, wp status = 0x%x\n", block, status); } @@ -2226,6 +2228,59 @@ static void onenand_unlock_all(struct mtd_info *mtd) onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_UNLOCK); } +/** + * onenand_lock_tight - [OneNAND Interface] Lock-tight block(s) + * @param mtd MTD device structure + * @param ofs offset relative to mtd start + * @param len number of bytes to lock-tight + * + * Lock-tight one or more blocks + */ +static int onenand_lock_tight(struct mtd_info *mtd, loff_t ofs, size_t len) +{ + int ret; + + onenand_get_device(mtd, FL_LOCKING); + ret = onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_LOCK_TIGHT); + onenand_release_device(mtd); + return ret; +} + +/** + * onenand_block_islock - [MTD Interface] Check whether the block at the given offset is locked + * @param mtd MTD device structure + * @param ofs offset relative to mtd start + * + * Check whether the block is bad + */ +static int onenand_block_islock(struct mtd_info *mtd, loff_t ofs) +{ + struct onenand_chip *this = mtd->priv; + int block, value, status; + + /* Check for invalid offset */ + if (ofs > mtd->size) + return -EINVAL; + + onenand_get_device(mtd, FL_READING); + + block = onenand_block(this, ofs); + /* Set block address */ + value = onenand_block_address(this, block); + this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1); + /* Select DataRAM for DDP */ + value = onenand_bufferram_address(this, block); + this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2); + /* Set start block address */ + this->write_word(block, this->base + ONENAND_REG_START_BLOCK_ADDRESS); + + /* Check lock status */ + status = this->read_word(this->base + ONENAND_REG_WP_STATUS); + + onenand_release_device(mtd); + + return status; +} /** * onenand_check_features - Check and set OneNAND features @@ -2791,6 +2846,10 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) this->bbt_wait = onenand_bbt_wait; if (!this->unlock_all) this->unlock_all = onenand_unlock_all; + if (!this->lock_tight) + this->lock_tight = onenand_lock_tight; + if (!this->block_islock) + this->block_islock = onenand_block_islock; if (!this->read_bufferram) this->read_bufferram = onenand_read_bufferram; @@ -2879,9 +2938,6 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) mtd->ecclayout = this->ecclayout; - /* Unlock whole block */ - this->unlock_all(mtd); - return this->scan_bbt(mtd); } diff --git a/recovery/onenand.c b/recovery/onenand.c index e52f92e..3a6f939 100644 --- a/recovery/onenand.c +++ b/recovery/onenand.c @@ -12,17 +12,14 @@ #include +#include "recovery.h" #include "onenand.h" -#ifdef printk -#undef printk +#ifdef RECOVERY_DEBUG +#define PUTS(s) serial_puts(DEBUG_MARK"onenand: "s) +#else +#define PUTS(s) #endif -#define printk(...) do {} while (0) -#define puts(...) do {} while (0) -#ifdef printf -#undef printf -#endif -#define printf(...) do {} while (0) struct mtd_info onenand_mtd; struct onenand_chip onenand_chip; @@ -49,11 +46,14 @@ static int onenand_block_read(loff_t from, ssize_t len, while (len > 0) { thislen = min_t(ssize_t, len, blocksize); thislen = ALIGN(thislen, mtd->writesize); + if (ofs > mtd->size) { + PUTS(" range overflow\n"); + break; + } ret = mtd->block_isbad(mtd, ofs); if (ret) { - printf("Bad blocks %d at 0x%x\n", - (u32)(ofs >> this->erase_shift), (u32)ofs); + PUTS("Bad blocks\n"); ofs += blocksize; /* FIXME need to check how to handle the 'len' */ len -= blocksize; @@ -71,14 +71,15 @@ static int onenand_block_read(loff_t from, ssize_t len, ops.retlen = 0; ret = mtd->read_oob(mtd, ofs, &ops); if (ret) { - printf("Read failed 0x%x, %d\n", (u32)ofs, ret); + PUTS("read failed\n"); ofs += thislen; continue; } ofs += thislen; buf += thislen; len -= thislen; - *retlen += ops.retlen; + if (retlen != NULL) + *retlen += ops.retlen; } return 0; @@ -90,6 +91,7 @@ static int onenand_block_write(loff_t to, ssize_t len, struct onenand_chip *this = mtd->priv; int blocksize = (1 << this->erase_shift); struct mtd_oob_ops ops = { + .mode = MTD_OOB_PLACE, .retlen = 0, .oobbuf = NULL, }; @@ -109,11 +111,14 @@ static int onenand_block_write(loff_t to, ssize_t len, while (len > 0) { thislen = min_t(ssize_t, len, blocksize); thislen = ALIGN(thislen, mtd->writesize); + if (ofs > mtd->size) { + PUTS(" range overflow\n"); + break; + } ret = mtd->block_isbad(mtd, ofs); if (ret) { - printf("Bad blocks %d at 0x%x\n", - (u32)(ofs >> this->erase_shift), (u32)ofs); + PUTS("bad blocks\n"); skip_ofs += blocksize; goto next; } @@ -123,7 +128,7 @@ static int onenand_block_write(loff_t to, ssize_t len, ops.retlen = 0; ret = mtd->write_oob(mtd, ofs, &ops); if (ret) { - printf("Write failed 0x%x, %d", (u32)ofs, ret); + PUTS("write failed\n"); skip_ofs += thislen; goto next; } @@ -152,8 +157,7 @@ static int onenand_block_erase(u32 start, u32 size, int force) for (ofs = start; ofs < (start + size); ofs += blocksize) { ret = mtd->block_isbad(mtd, ofs); if (ret && !force) { - printf("Skip erase bad block %d at 0x%x\n", - (u32)(ofs >> this->erase_shift), (u32)ofs); + PUTS("skip erase bad block \n"); continue; } @@ -163,20 +167,30 @@ static int onenand_block_erase(u32 start, u32 size, int force) instr.mtd = mtd; ret = mtd->erase(mtd, &instr); if (ret) { - printf("erase failed block %d at 0x%x\n", - (u32)(ofs >> this->erase_shift), (u32)ofs); - continue; + PUTS("erase failed\n"); + return ret; } } return 0; } +static int onenand_block_lock_tight(u32 start, u32 size) +{ + struct onenand_chip *this = mtd->priv; + int ret; + + ret = this->lock_tight(mtd, start, size); + + return ret; +} + void onenand_set_interface(struct onenand_op *onenand) { onenand->read = onenand_block_read; onenand->write = onenand_block_write; onenand->erase = onenand_block_erase; + onenand->lock_tight = onenand_block_lock_tight; onenand->mtd = &onenand_mtd; onenand->this = &onenand_chip; diff --git a/recovery/onenand.h b/recovery/onenand.h index 5fe7831..6dbc720 100644 --- a/recovery/onenand.h +++ b/recovery/onenand.h @@ -10,6 +10,7 @@ struct onenand_op { int (*read)(loff_t, ssize_t, ssize_t *, u_char *, int); int (*write)(loff_t, ssize_t, ssize_t *, u_char *); int (*erase)(u32, u32, int); + int (*lock_tight)(u32, u32); struct mtd_info *mtd; struct onenand_chip *this;