From ef0921d6b05aeb9034158f9bef5323d6da9c925e Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Tue, 4 Nov 2008 09:24:07 +0900 Subject: Sync with 2.6.27 Sync with OneNAND kernel codes Signed-off-by: Kyungmin Park diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index 9b7bf3a..66214e8 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -78,20 +78,11 @@ static void onenand_writew(unsigned short value, void __iomem * addr) * * Setup Start Address 1 Register (F100h) */ -static int onenand_block_address(int device, int block) +static int onenand_block_address(struct onenand_chip *this, int block) { - if (device & ONENAND_DEVICE_IS_DDP) { - /* Device Flash Core select, NAND Flash Block Address */ - int dfs = 0, density, mask; - - density = device >> ONENAND_DEVICE_DENSITY_SHIFT; - mask = (1 << (density + 6)); - - if (block & mask) - dfs = 1; - - return (dfs << ONENAND_DDP_SHIFT) | (block & (mask - 1)); - } + /* Device Flash Core select, NAND Flash Block Address */ + if (block & this->density_mask) + return ONENAND_DDP_CHIP1 | (block ^ this->density_mask); return block; } @@ -104,22 +95,13 @@ static int onenand_block_address(int device, int block) * * Setup Start Address 2 Register (F101h) for DDP */ -static int onenand_bufferram_address(int device, int block) +static int onenand_bufferram_address(struct onenand_chip *this, int block) { - if (device & ONENAND_DEVICE_IS_DDP) { - /* Device BufferRAM Select */ - int dbs = 0, density, mask; - - density = device >> ONENAND_DEVICE_DENSITY_SHIFT; - mask = (1 << (density + 6)); - - if (block & mask) - dbs = 1; + /* Device BufferRAM Select */ + if (block & this->density_mask) + return ONENAND_DDP_CHIP1; - return (dbs << ONENAND_DDP_SHIFT); - } - - return 0; + return ONENAND_DDP_CHIP0; } /** @@ -169,6 +151,18 @@ static int onenand_buffer_address(int dataram1, int sectors, int count) } /** + * onenand_get_density - [DEFAULT] Get OneNAND density + * @param dev_id OneNAND device ID + * + * Get OneNAND density from device ID + */ +static inline int onenand_get_density(int dev_id) +{ + int density = dev_id >> ONENAND_DEVICE_DENSITY_SHIFT; + return (density & ONENAND_DEVICE_DENSITY_MASK); +} + +/** * onenand_command - [DEFAULT] Send command to OneNAND device * @param mtd MTD device structure * @param cmd the command to be sent @@ -192,6 +186,7 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, case ONENAND_CMD_UNLOCK: case ONENAND_CMD_LOCK: case ONENAND_CMD_LOCK_TIGHT: + case ONENAND_CMD_UNLOCK_ALL: block = -1; page = -1; break; @@ -212,7 +207,7 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, /* NOTE: The setting order of the registers is very important! */ if (cmd == ONENAND_CMD_BUFFERRAM) { /* Select DataRAM for DDP */ - value = onenand_bufferram_address(this->device_id, block); + value = onenand_bufferram_address(this, block); this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2); @@ -224,9 +219,14 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, if (block != -1) { /* Write 'DFS, FBA' of Flash */ - value = onenand_block_address(this->device_id, block); + value = onenand_block_address(this, block); this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1); + + /* Write 'DFS, FBA' of Flash */ + value = onenand_bufferram_address(this, block); + this->write_word(value, + this->base + ONENAND_REG_START_ADDRESS2); } if (page != -1) { @@ -252,15 +252,6 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, /* Write 'BSA, BSC' of DataRAM */ value = onenand_buffer_address(dataram, sectors, count); this->write_word(value, this->base + ONENAND_REG_START_BUFFER); - - if (readcmd) { - /* Select DataRAM for DDP */ - value = - onenand_bufferram_address(this->device_id, block); - this->write_word(value, - this->base + - ONENAND_REG_START_ADDRESS2); - } } /* Interrupt clear */ @@ -296,14 +287,11 @@ static int onenand_wait(struct mtd_info *mtd, int state) ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS); if (ctrl & ONENAND_CTRL_ERROR) { - MTDDEBUG (MTD_DEBUG_LEVEL0, - "onenand_wait: controller error = 0x%04x\n", ctrl); - return -EAGAIN; - } + printk("onenand_wait: controller error = 0x%04x\n", ctrl); + if (ctrl & ONENAND_CTRL_LOCK) + printk("onenand_wait: it's locked error = 0x%04x\n", + ctrl); - if (ctrl & ONENAND_CTRL_LOCK) { - MTDDEBUG (MTD_DEBUG_LEVEL0, - "onenand_wait: it's locked error = 0x%04x\n", ctrl); return -EIO; } @@ -351,7 +339,7 @@ static inline int onenand_bufferram_offset(struct mtd_info *mtd, int area) * * Read the BufferRAM area */ -static int onenand_read_bufferram(struct mtd_info *mtd, int area, +static int onenand_read_bufferram(struct mtd_info *mtd, loff_t addr, int area, unsigned char *buffer, int offset, size_t count) { @@ -376,7 +364,7 @@ static int onenand_read_bufferram(struct mtd_info *mtd, int area, * * Read the BufferRAM area with Sync. Burst Mode */ -static int onenand_sync_read_bufferram(struct mtd_info *mtd, int area, +static int onenand_sync_read_bufferram(struct mtd_info *mtd, loff_t addr, int area, unsigned char *buffer, int offset, size_t count) { @@ -405,7 +393,7 @@ static int onenand_sync_read_bufferram(struct mtd_info *mtd, int area, * * Write the BufferRAM area */ -static int onenand_write_bufferram(struct mtd_info *mtd, int area, +static int onenand_write_bufferram(struct mtd_info *mtd, loff_t addr, int area, const unsigned char *buffer, int offset, size_t count) { @@ -431,21 +419,39 @@ static int onenand_write_bufferram(struct mtd_info *mtd, int area, static int onenand_check_bufferram(struct mtd_info *mtd, loff_t addr) { struct onenand_chip *this = mtd->priv; - int block, page; - int i; + int blockpage, found = 0; + unsigned int i; - block = (int)(addr >> this->erase_shift); - page = (int)(addr >> this->page_shift); - page &= this->page_mask; +#ifdef CONFIG_S3C64XX + return 0; +#endif - i = ONENAND_CURRENT_BUFFERRAM(this); + if (ONENAND_IS_2PLANE(this)) + blockpage = onenand_get_2x_blockpage(mtd, addr); + else + blockpage = (int) (addr >> this->page_shift); /* Is there valid data? */ - if (this->bufferram[i].block == block && - this->bufferram[i].page == page && this->bufferram[i].valid) - return 1; + i = ONENAND_CURRENT_BUFFERRAM(this); + if (this->bufferram[i].blockpage == blockpage) + found = 1; + else { + /* Check another BufferRAM */ + i = ONENAND_NEXT_BUFFERRAM(this); + if (this->bufferram[i].blockpage == blockpage) { + ONENAND_SET_NEXT_BUFFERRAM(this); + found = 1; + } + } - return 0; + if (found && ONENAND_IS_DDP(this)) { + /* Select DataRAM for DDP */ + int block = (int) (addr >> this->erase_shift); + int value = onenand_bufferram_address(this, block); + this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2); + } + + return found; } /** @@ -460,25 +466,25 @@ static int onenand_update_bufferram(struct mtd_info *mtd, loff_t addr, int valid) { struct onenand_chip *this = mtd->priv; - int block, page; - int i; + int blockpage; + unsigned int i; - block = (int)(addr >> this->erase_shift); - page = (int)(addr >> this->page_shift); - page &= this->page_mask; + if (ONENAND_IS_2PLANE(this)) + blockpage = onenand_get_2x_blockpage(mtd, addr); + else + blockpage = (int)(addr >> this->page_shift); - /* Invalidate BufferRAM */ - for (i = 0; i < MAX_BUFFERRAM; i++) { - if (this->bufferram[i].block == block && - this->bufferram[i].page == page) - this->bufferram[i].valid = 0; - } + /* Invalidate another BufferRAM */ + i = ONENAND_NEXT_BUFFERRAM(this); + if (this->bufferram[i].blockpage == blockpage) + this->bufferram[i].blockpage = -1; /* Update BufferRAM */ i = ONENAND_CURRENT_BUFFERRAM(this); - this->bufferram[i].block = block; - this->bufferram[i].page = page; - this->bufferram[i].valid = valid; + if (valid) + this->bufferram[i].blockpage = blockpage; + else + this->bufferram[i].blockpage = -1; return 0; } @@ -500,10 +506,10 @@ static void onenand_invalidate_bufferram(struct mtd_info *mtd, loff_t addr, /* Invalidate BufferRAM */ for (i = 0; i < MAX_BUFFERRAM; i++) { - loff_t buf_addr = this->bufferram[i].block << this->erase_shift; + loff_t buf_addr = this->bufferram[i].blockpage << this->page_shift; if (buf_addr >= addr && buf_addr < end_addr) - this->bufferram[i].valid = 0; + this->bufferram[i].blockpage = -1; } } @@ -556,7 +562,7 @@ static int onenand_transfer_auto_oob(struct mtd_info *mtd, uint8_t *buf, readend += free->offset - lastgap; lastgap = free->offset + free->length; } - this->read_bufferram(mtd, ONENAND_SPARERAM, oob_buf, 0, mtd->oobsize); + this->read_bufferram(mtd, 0, ONENAND_SPARERAM, oob_buf, 0, mtd->oobsize); free = this->ecclayout->oobfree; for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free->length; i++, free++) { int free_end = free->offset + free->length; @@ -594,9 +600,7 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from, int ret = 0, boundary = 0; int writesize = this->writesize; - MTDDEBUG(MTD_DEBUG_LEVEL3, - "onenand_read_ops_nolock: from = 0x%08x, len = %i\n", - (unsigned int) from, (int) len); + MTDDEBUG(MTD_DEBUG_LEVEL3, "onenand_read_ops_nolock: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len); if (ops->mode == MTD_OOB_AUTO) oobsize = this->ecclayout->oobavail; @@ -620,6 +624,7 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from, /* Do first load to bufferRAM */ if (read < len) { if (!onenand_check_bufferram(mtd, from)) { + this->main_buf = buf; this->command(mtd, ONENAND_CMD_READ, from, writesize); ret = this->wait(mtd, FL_READING); onenand_update_bufferram(mtd, from, !ret); @@ -637,6 +642,7 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from, /* If there is more to load then start next load */ from += thislen; if (read + thislen < len) { + this->main_buf = buf + thislen; this->command(mtd, ONENAND_CMD_READ, from, writesize); /* * Chip boundary handling in DDP @@ -653,7 +659,7 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from, } /* While load is going, read from last bufferRAM */ - this->read_bufferram(mtd, ONENAND_DATARAM, buf, column, thislen); + this->read_bufferram(mtd, from - thislen, ONENAND_DATARAM, buf, column, thislen); /* Read oob area if needed */ if (oobbuf) { @@ -663,7 +669,7 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from, if (ops->mode == MTD_OOB_AUTO) onenand_transfer_auto_oob(mtd, oobbuf, oobcolumn, thisooblen); else - this->read_bufferram(mtd, ONENAND_SPARERAM, oobbuf, oobcolumn, thisooblen); + this->read_bufferram(mtd, 0, ONENAND_SPARERAM, oobbuf, oobcolumn, thisooblen); oobread += thisooblen; oobbuf += thisooblen; oobcolumn = 0; @@ -726,9 +732,7 @@ static int onenand_read_oob_nolock(struct mtd_info *mtd, loff_t from, from += ops->ooboffs; - MTDDEBUG(MTD_DEBUG_LEVEL3, - "onenand_read_oob_nolock: from = 0x%08x, len = %i\n", - (unsigned int) from, (int) len); + MTDDEBUG(MTD_DEBUG_LEVEL3, "onenand_read_oob_nolock: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len); /* Initialize return length value */ ops->oobretlen = 0; @@ -759,6 +763,7 @@ static int onenand_read_oob_nolock(struct mtd_info *mtd, loff_t from, thislen = oobsize - column; thislen = min_t(int, thislen, len); + this->spare_buf = buf; this->command(mtd, ONENAND_CMD_READOOB, from, mtd->oobsize); onenand_update_bufferram(mtd, from, 0); @@ -772,7 +777,7 @@ static int onenand_read_oob_nolock(struct mtd_info *mtd, loff_t from, if (mode == MTD_OOB_AUTO) onenand_transfer_auto_oob(mtd, buf, column, thislen); else - this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen); + this->read_bufferram(mtd, 0, ONENAND_SPARERAM, buf, column, thislen); read += thislen; @@ -886,12 +891,6 @@ static int onenand_bbt_wait(struct mtd_info *mtd, int state) interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT); ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS); - /* Initial bad block case: 0x2400 or 0x0400 */ - if (ctrl & ONENAND_CTRL_ERROR) { - printk(KERN_DEBUG "onenand_bbt_wait: controller error = 0x%04x\n", ctrl); - return ONENAND_BBT_READ_ERROR; - } - if (interrupt & ONENAND_INT_READ) { int ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS); if (ecc & ONENAND_ECC_2BIT_ALL) @@ -902,6 +901,12 @@ static int onenand_bbt_wait(struct mtd_info *mtd, int state) return ONENAND_BBT_READ_FATAL_ERROR; } + /* Initial bad block case: 0x2400 or 0x0400 */ + if (ctrl & ONENAND_CTRL_ERROR) { + printk(KERN_DEBUG "onenand_bbt_wait: controller error = 0x%04x\n", ctrl); + return ONENAND_BBT_READ_ERROR; + } + return 0; } @@ -922,9 +927,7 @@ int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from, size_t len = ops->ooblen; u_char *buf = ops->oobbuf; - MTDDEBUG(MTD_DEBUG_LEVEL3, - "onenand_bbt_read_oob: from = 0x%08x, len = %zi\n", - (unsigned int) from, len); + MTDDEBUG(MTD_DEBUG_LEVEL3, "onenand_bbt_read_oob: from = 0x%08x, len = %zi\n", (unsigned int) from, len); /* Initialize return value */ ops->oobretlen = 0; @@ -945,15 +948,16 @@ int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from, thislen = mtd->oobsize - column; thislen = min_t(int, thislen, len); + this->spare_buf = buf; this->command(mtd, ONENAND_CMD_READOOB, from, mtd->oobsize); onenand_update_bufferram(mtd, from, 0); - ret = onenand_bbt_wait(mtd, FL_READING); + ret = this->bbt_wait(mtd, FL_READING); if (ret) break; - this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen); + this->read_spareram(mtd, 0, ONENAND_SPARERAM, buf, column, thislen); read += thislen; if (read == len) break; @@ -995,7 +999,7 @@ static int onenand_verify_oob(struct mtd_info *mtd, const u_char *buf, loff_t to if (status) return status; - this->read_bufferram(mtd, ONENAND_SPARERAM, oob_buf, 0, mtd->oobsize); + this->read_bufferram(mtd, 0, ONENAND_SPARERAM, oob_buf, 0, mtd->oobsize); for (i = 0; i < mtd->oobsize; i++) if (buf[i] != 0xFF && buf[i] != oob_buf[i]) return -EBADMSG; @@ -1115,9 +1119,7 @@ static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to, u_char *oobbuf; int ret = 0; - MTDDEBUG(MTD_DEBUG_LEVEL3, - "onenand_write_ops_nolock: to = 0x%08x, len = %i\n", - (unsigned int) to, (int) len); + MTDDEBUG(MTD_DEBUG_LEVEL3, "onenand_write_ops_nolock: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len); /* Initialize retlen, in case of early exit */ ops->retlen = 0; @@ -1161,7 +1163,7 @@ static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to, wbuf = this->page_buf; } - this->write_bufferram(mtd, ONENAND_DATARAM, wbuf, 0, mtd->writesize); + this->write_bufferram(mtd, to, ONENAND_DATARAM, wbuf, 0, mtd->writesize); if (oob) { oobbuf = this->oob_buf; @@ -1180,7 +1182,7 @@ static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to, } else oobbuf = (u_char *) ffchars; - this->write_bufferram(mtd, ONENAND_SPARERAM, oobbuf, 0, mtd->oobsize); + this->write_bufferram(mtd, 0, ONENAND_SPARERAM, oobbuf, 0, mtd->oobsize); this->command(mtd, ONENAND_CMD_PROG, to, mtd->writesize); @@ -1244,9 +1246,7 @@ static int onenand_write_oob_nolock(struct mtd_info *mtd, loff_t to, to += ops->ooboffs; - MTDDEBUG(MTD_DEBUG_LEVEL3, - "onenand_write_oob_nolock: to = 0x%08x, len = %i\n", - (unsigned int) to, (int) len); + MTDDEBUG(MTD_DEBUG_LEVEL3, "onenand_write_oob_nolock: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len); /* Initialize retlen, in case of early exit */ ops->oobretlen = 0; @@ -1293,7 +1293,7 @@ static int onenand_write_oob_nolock(struct mtd_info *mtd, loff_t to, onenand_fill_auto_oob(mtd, oobbuf, buf, column, thislen); else memcpy(oobbuf + column, buf, thislen); - this->write_bufferram(mtd, ONENAND_SPARERAM, oobbuf, 0, mtd->oobsize); + this->write_bufferram(mtd, 0, ONENAND_SPARERAM, oobbuf, 0, mtd->oobsize); this->command(mtd, ONENAND_CMD_PROGOOB, to, mtd->oobsize); @@ -1466,7 +1466,14 @@ int onenand_erase(struct mtd_info *mtd, struct erase_info *instr) while (len) { - /* TODO Check badblock */ + /* Check if we have a bad block, we do not erase bad blocks */ + if (instr->priv == 0 && onenand_block_isbad_nolock(mtd, addr, 0)) { + printk(KERN_WARNING "onenand_erase: attempt to erase" + " a bad block at addr 0x%08x\n", + (unsigned int) addr); + instr->state = MTD_ERASE_FAILED; + goto erase_exit; + } this->command(mtd, ONENAND_CMD_ERASE, addr, block_size); @@ -1482,8 +1489,16 @@ int onenand_erase(struct mtd_info *mtd, struct erase_info *instr) MTDDEBUG (MTD_DEBUG_LEVEL0, "onenand_erase: " "Failed erase, block %d\n", (unsigned)(addr >> this->erase_shift)); + if (ret == -EPERM) + printk("onenand_erase: " + "Device is write protected!!!\n"); + else + printk("onenand_erase: " + "Failed erase, block %d\n", + (unsigned)(addr >> this->erase_shift)); instr->state = MTD_ERASE_FAILED; instr->fail_addr = addr; + goto erase_exit; } @@ -1493,7 +1508,7 @@ int onenand_erase(struct mtd_info *mtd, struct erase_info *instr) instr->state = MTD_ERASE_DONE; - erase_exit: +erase_exit: ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO; /* Do call back function */ @@ -1569,23 +1584,30 @@ int onenand_block_markbad(struct mtd_info *mtd, loff_t ofs) } /** - * onenand_unlock - [MTD Interface] Unlock block(s) - * @param mtd MTD device structure - * @param ofs offset relative to mtd start - * @param len number of bytes to unlock + * onenand_do_lock_cmd - [OneNAND Interface] Lock or unlock block(s) + * @param mtd MTD device structure + * @param ofs offset relative to mtd start + * @param len number of bytes to lock or unlock + * @param cmd lock or unlock command * - * Unlock one or more blocks + * Lock or unlock one or more blocks */ -int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) +static int onenand_do_lock_cmd(struct mtd_info *mtd, loff_t ofs, size_t len, int cmd) { struct onenand_chip *this = mtd->priv; int start, end, block, value, status; + int wp_status_mask; start = ofs >> this->erase_shift; end = len >> this->erase_shift; + if (cmd == ONENAND_CMD_LOCK) + wp_status_mask = ONENAND_WP_LS; + else + wp_status_mask = ONENAND_WP_US; + /* Continuous lock scheme */ - if (this->options & ONENAND_CONT_LOCK) { + if (this->options & ONENAND_HAS_CONT_LOCK) { /* Set start block address */ this->write_word(start, this->base + ONENAND_REG_START_BLOCK_ADDRESS); @@ -1593,7 +1615,7 @@ int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) this->write_word(end - 1, this->base + ONENAND_REG_END_BLOCK_ADDRESS); /* Write unlock command */ - this->command(mtd, ONENAND_CMD_UNLOCK, 0, 0); + this->command(mtd, cmd, 0, 0); /* There's no return value */ this->wait(mtd, FL_UNLOCKING); @@ -1612,7 +1634,14 @@ int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) } /* Block lock scheme */ - for (block = start; block < end; block++) { + for (block = start; block < start + end; block++) { + /* 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); @@ -1627,11 +1656,6 @@ int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) & ONENAND_CTRL_ONGO) continue; - /* Set block address for read block status */ - value = onenand_block_address(this->device_id, block); - this->write_word(value, - this->base + ONENAND_REG_START_ADDRESS1); - /* Check lock status */ status = this->read_word(this->base + ONENAND_REG_WP_STATUS); if (!(status & ONENAND_WP_US)) @@ -1643,31 +1667,196 @@ int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) } /** + * onenand_lock - [MTD Interface] Lock block(s) + * @param mtd MTD device structure + * @param ofs offset relative to mtd start + * @param len number of bytes to unlock + * + * Lock one or more blocks + */ +static int onenand_lock(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); + onenand_release_device(mtd); + return ret; +} + +/** + * onenand_unlock - [MTD Interface] Unlock block(s) + * @param mtd MTD device structure + * @param ofs offset relative to mtd start + * @param len number of bytes to unlock + * + * Unlock one or more blocks + */ +static int onenand_unlock(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_UNLOCK); + onenand_release_device(mtd); + return ret; +} + +/** + * onenand_check_lock_status - [OneNAND Interface] Check lock status + * @param this onenand chip data structure + * + * Check lock status + */ +static int onenand_check_lock_status(struct onenand_chip *this) +{ + unsigned int value, block, status; + unsigned int end; + + end = this->chipsize >> this->erase_shift; + for (block = 0; block < end; block++) { + /* 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); + if (!(status & ONENAND_WP_US)) { + printk(KERN_ERR "block = %d, wp status = 0x%x\n", block, status); + return 0; + } + } + + return 1; +} + +/** + * onenand_unlock_all - [OneNAND Interface] unlock all blocks + * @param mtd MTD device structure + * + * Unlock all blocks + */ +static void onenand_unlock_all(struct mtd_info *mtd) +{ + struct onenand_chip *this = mtd->priv; + loff_t ofs = 0; + size_t len = this->chipsize; + + if (this->options & ONENAND_HAS_UNLOCK_ALL) { + /* Set start block address */ + this->write_word(0, this->base + ONENAND_REG_START_BLOCK_ADDRESS); + /* Write unlock command */ + this->command(mtd, ONENAND_CMD_UNLOCK_ALL, 0, 0); + + /* There's no return value */ + this->wait(mtd, FL_LOCKING); + + /* Sanity check */ + while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS) + & ONENAND_CTRL_ONGO) + continue; + + return; + + /* Check lock status */ + if (onenand_check_lock_status(this)) + return; + + /* Workaround for all block unlock in DDP */ + if (ONENAND_IS_DDP(this)) { + /* All blocks on another chip */ + ofs = this->chipsize >> 1; + len = this->chipsize >> 1; + } + } + + onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_UNLOCK); +} + + +/** + * onenand_check_features - Check and set OneNAND features + * @param mtd MTD data structure + * + * Check and set OneNAND features + * - lock scheme + * - two plane + */ +static void onenand_check_features(struct mtd_info *mtd) +{ + struct onenand_chip *this = mtd->priv; + unsigned int density, process; + + /* Lock scheme depends on density and process */ + density = onenand_get_density(this->device_id); + process = this->version_id >> ONENAND_VERSION_PROCESS_SHIFT; + + /* Lock scheme */ + switch (density) { + case ONENAND_DEVICE_DENSITY_4Gb: + this->options |= ONENAND_HAS_2PLANE; + + case ONENAND_DEVICE_DENSITY_2Gb: + /* 2Gb DDP don't have 2 plane */ + if (!ONENAND_IS_DDP(this)) + this->options |= ONENAND_HAS_2PLANE; + this->options |= ONENAND_HAS_UNLOCK_ALL; + + case ONENAND_DEVICE_DENSITY_1Gb: + /* A-Die has all block unlock */ + if (process) + this->options |= ONENAND_HAS_UNLOCK_ALL; + break; + + default: + /* Some OneNAND has continuous lock scheme */ + if (!process) + this->options |= ONENAND_HAS_CONT_LOCK; + break; + } + + if (this->options & ONENAND_HAS_CONT_LOCK) + printk(KERN_DEBUG "Lock scheme is Continuous Lock\n"); + if (this->options & ONENAND_HAS_UNLOCK_ALL) + printk(KERN_DEBUG "Chip support all block unlock\n"); + if (this->options & ONENAND_HAS_2PLANE) + printk(KERN_DEBUG "Chip has 2 plane\n"); +} + +/** * onenand_print_device_info - Print device ID * @param device device ID * * Print device ID */ -char * onenand_print_device_info(int device) +char *onenand_print_device_info(int device, int version) { int vcc, demuxed, ddp, density; char *dev_info = malloc(80); + char *p = dev_info; vcc = device & ONENAND_DEVICE_VCC_MASK; demuxed = device & ONENAND_DEVICE_IS_DEMUX; ddp = device & ONENAND_DEVICE_IS_DDP; density = device >> ONENAND_DEVICE_DENSITY_SHIFT; - sprintf(dev_info, "%sOneNAND%s %dMB %sV 16-bit (0x%02x)", + p += sprintf(dev_info, "%sOneNAND%s %dMB %sV 16-bit (0x%02x)", demuxed ? "" : "Muxed ", ddp ? "(DDP)" : "", (16 << density), vcc ? "2.65/3.3" : "1.8", device); + sprintf(p, "\nOneNAND version = 0x%04x", version); + printk("%s\n", dev_info); + return dev_info; } static const struct onenand_manufacturers onenand_manuf_ids[] = { {ONENAND_MFR_SAMSUNG, "Samsung"}, - {ONENAND_MFR_UNKNOWN, "Unknown"} }; /** @@ -1678,19 +1867,24 @@ static const struct onenand_manufacturers onenand_manuf_ids[] = { */ static int onenand_check_maf(int manuf) { + int size = ARRAY_SIZE(onenand_manuf_ids); + char *name; int i; - for (i = 0; onenand_manuf_ids[i].id; i++) { + for (i = 0; size; i++) if (manuf == onenand_manuf_ids[i].id) break; - } + + if (i < size) + name = onenand_manuf_ids[i].name; + else + name = "Unknown"; #ifdef ONENAND_DEBUG - printk(KERN_DEBUG "OneNAND Manufacturer: %s (0x%0x)\n", - onenand_manuf_ids[i].name, manuf); + printk(KERN_DEBUG "OneNAND Manufacturer: %s (0x%0x)\n", name, manuf); #endif - return (i != ONENAND_MFR_UNKNOWN); + return i == size; } /** @@ -1703,9 +1897,14 @@ static int onenand_check_maf(int manuf) static int onenand_probe(struct mtd_info *mtd) { struct onenand_chip *this = mtd->priv; - int bram_maf_id, bram_dev_id, maf_id, dev_id; - int version_id; + int bram_maf_id, bram_dev_id, maf_id, dev_id, ver_id; int density; + int syscfg; + + /* Save system configuration 1 */ + syscfg = this->read_word(this->base + ONENAND_REG_SYS_CFG1); + /* Clear Sync. Burst Read mode to read BootRAM */ + this->write_word((syscfg & ~ONENAND_SYS_CFG1_SYNC_READ), this->base + ONENAND_REG_SYS_CFG1); /* Send the command for reading device ID from BootRAM */ this->write_word(ONENAND_CMD_READID, this->base + ONENAND_BOOTRAM); @@ -1714,19 +1913,23 @@ static int onenand_probe(struct mtd_info *mtd) bram_maf_id = this->read_word(this->base + ONENAND_BOOTRAM + 0x0); bram_dev_id = this->read_word(this->base + ONENAND_BOOTRAM + 0x2); - /* Check manufacturer ID */ - if (onenand_check_maf(bram_maf_id)) - return -ENXIO; - /* Reset OneNAND to read default register values */ this->write_word(ONENAND_CMD_RESET, this->base + ONENAND_BOOTRAM); /* Wait reset */ this->wait(mtd, FL_RESETING); + /* Restore system configuration 1 */ + this->write_word(syscfg, this->base + ONENAND_REG_SYS_CFG1); + + /* Check manufacturer ID */ + if (onenand_check_maf(bram_maf_id)) + return -ENXIO; + /* Read manufacturer and device IDs from Register */ maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID); dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID); + ver_id = this->read_word(this->base + ONENAND_REG_VERSION_ID); /* Check OneNAND device */ if (maf_id != bram_maf_id || dev_id != bram_dev_id) @@ -1739,11 +1942,16 @@ static int onenand_probe(struct mtd_info *mtd) } /* Flash device information */ - mtd->name = onenand_print_device_info(dev_id); + mtd->name = onenand_print_device_info(dev_id, ver_id); this->device_id = dev_id; - density = dev_id >> ONENAND_DEVICE_DENSITY_SHIFT; + density = onenand_get_density(dev_id); this->chipsize = (16 << density) << 20; + /* Set density mask. it is used for DDP */ + if (ONENAND_IS_DDP(this)) + this->density_mask = (1 << (density + 6)); + else + this->density_mask = 0; /* OneNAND page size & block size */ /* The data buffer size is equal to page size */ @@ -1764,18 +1972,8 @@ static int onenand_probe(struct mtd_info *mtd) mtd->size = this->chipsize; - /* Version ID */ - version_id = this->read_word(this->base + ONENAND_REG_VERSION_ID); -#ifdef ONENAND_DEBUG - printk(KERN_DEBUG "OneNAND version = 0x%04x\n", version_id); -#endif - - /* Lock scheme */ - if (density <= ONENAND_DEVICE_DENSITY_512Mb && - !(version_id >> ONENAND_VERSION_PROCESS_SHIFT)) { - printk(KERN_INFO "Lock scheme is Continues Lock\n"); - this->options |= ONENAND_CONT_LOCK; - } + /* Check OneNAND features */ + onenand_check_features(mtd); mtd->flags = MTD_CAP_NANDFLASH; mtd->erase = onenand_erase; @@ -1813,12 +2011,19 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) this->command = onenand_command; if (!this->wait) this->wait = onenand_wait; + if (!this->bbt_wait) + this->bbt_wait = onenand_bbt_wait; if (!this->read_bufferram) this->read_bufferram = onenand_read_bufferram; + if (!this->read_spareram) + this->read_spareram = onenand_read_bufferram; if (!this->write_bufferram) this->write_bufferram = onenand_write_bufferram; + if (!this->scan_bbt) + this->scan_bbt = onenand_default_bbt; + if (onenand_probe(mtd)) return -ENXIO; @@ -1850,9 +2055,10 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) this->options |= ONENAND_OOBBUF_ALLOC; } - onenand_unlock(mtd, 0, mtd->size); + /* Unlock whole block */ + onenand_unlock_all(mtd); - return onenand_default_bbt(mtd); + return this->scan_bbt(mtd); } /** diff --git a/drivers/mtd/onenand/onenand_bbt.c b/drivers/mtd/onenand/onenand_bbt.c index f6092b9..d538f95 100644 --- a/drivers/mtd/onenand/onenand_bbt.c +++ b/drivers/mtd/onenand/onenand_bbt.c @@ -3,7 +3,7 @@ * * Bad Block Table support for the OneNAND driver * - * Copyright(c) 2005-2007 Samsung Electronics + * Copyright(c) 2005-2008 Samsung Electronics * Kyungmin Park * * TODO: @@ -54,7 +54,7 @@ static int check_short_pattern(uint8_t * buf, int len, int paglen, * @param buf temporary buffer * @param bd descriptor for the good/bad block search pattern * @param chip create the table for a specific chip, -1 read all chips. - * Applies only if NAND_BBT_PERCHIP option is set + * Applies only if NAND_BBT_PERCHIP option is set * * Create a bad block table by scanning the device * for the given good/bad block identify pattern @@ -156,8 +156,8 @@ static int onenand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt) res = (bbm->bbt[block >> 3] >> (block & 0x06)) & 0x03; MTDDEBUG (MTD_DEBUG_LEVEL2, - "onenand_isbad_bbt: bbt info for offs 0x%08x: (block %d) 0x%02x\n", - (unsigned int)offs, block >> 1, res); + "onenand_isbad_bbt: bbt info for offs 0x%08x: (block %d) 0x%02x\n", + (unsigned int)offs, block >> 1, res); switch ((int)res) { case 0x00: diff --git a/drivers/mtd/onenand/onenand_uboot.c b/drivers/mtd/onenand/onenand_uboot.c index 08082f3..4541b22 100644 --- a/drivers/mtd/onenand/onenand_uboot.c +++ b/drivers/mtd/onenand/onenand_uboot.c @@ -26,9 +26,17 @@ void onenand_init(void) memset(&onenand_mtd, 0, sizeof(struct mtd_info)); memset(&onenand_chip, 0, sizeof(struct onenand_chip)); - onenand_chip.base = (void *) CONFIG_SYS_ONENAND_BASE; onenand_mtd.priv = &onenand_chip; +#ifdef CONFIG_USE_ONENAND_BOARD_INIT + /* + * It's used for some board init required + */ + onenand_board_init(&onenand_mtd); +#else + onenand_chip.base = (void *) CONFIG_SYS_ONENAND_BASE; +#endif + onenand_scan(&onenand_mtd, 1); puts("OneNAND: "); diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h index 4467c2b..7547e96 100644 --- a/include/linux/mtd/onenand.h +++ b/include/linux/mtd/onenand.h @@ -30,14 +30,10 @@ extern void onenand_release (struct mtd_info *mtd); /** * struct onenand_bufferram - OneNAND BufferRAM Data - * @param block block address in BufferRAM - * @param page page address in BufferRAM - * @param valid valid flag + * @param blockpage block & page address in BufferRAM */ struct onenand_bufferram { - int block; - int page; - int valid; + int blockpage; }; /** @@ -70,6 +66,8 @@ struct onenand_chip { void __iomem *base; unsigned int chipsize; unsigned int device_id; + unsigned int version_id; + unsigned int density_mask; unsigned int options; unsigned int erase_shift; @@ -81,26 +79,35 @@ struct onenand_chip { unsigned int bufferram_index; struct onenand_bufferram bufferram[MAX_BUFFERRAM]; - int (*command) (struct mtd_info * mtd, int cmd, loff_t address, + int (*command) (struct mtd_info *mtd, int cmd, loff_t address, size_t len); - int (*wait) (struct mtd_info * mtd, int state); - int (*read_bufferram) (struct mtd_info * mtd, int area, + int (*wait) (struct mtd_info *mtd, int state); + int (*bbt_wait) (struct mtd_info *mtd, int state); + int (*read_bufferram) (struct mtd_info *mtd, loff_t addr, int area, unsigned char *buffer, int offset, size_t count); - int (*write_bufferram) (struct mtd_info * mtd, int area, + int (*read_spareram) (struct mtd_info *mtd, loff_t addr, int area, + unsigned char *buffer, int offset, size_t count); + int (*write_bufferram) (struct mtd_info *mtd, loff_t addr, int area, const unsigned char *buffer, int offset, size_t count); - unsigned short (*read_word) (void __iomem * addr); - void (*write_word) (unsigned short value, void __iomem * addr); - void (*mmcontrol) (struct mtd_info * mtd, int sync_read); + unsigned short (*read_word) (void __iomem *addr); + void (*write_word) (unsigned short value, void __iomem *addr); + void (*mmcontrol) (struct mtd_info *mtd, int sync_read); int (*block_markbad)(struct mtd_info *mtd, loff_t ofs); int (*scan_bbt)(struct mtd_info *mtd); + unsigned char *main_buf; + unsigned char *spare_buf; +#ifdef DONT_USE_UBOOT + spinlock_t chip_lock; + wait_queue_head_t wq; +#endif int state; - unsigned char *page_buf; - unsigned char *oob_buf; + unsigned char *page_buf; + unsigned char *oob_buf; struct nand_oobinfo *autooob; - struct nand_ecclayout *ecclayout; + struct nand_ecclayout *ecclayout; void *bbm; @@ -125,7 +132,9 @@ struct onenand_chip { /* * Options bits */ -#define ONENAND_CONT_LOCK (0x0001) +#define ONENAND_HAS_CONT_LOCK (0x0001) +#define ONENAND_HAS_UNLOCK_ALL (0x0002) +#define ONENAND_HAS_2PLANE (0x0004) #define ONENAND_PAGEBUF_ALLOC (0x1000) #define ONENAND_OOBBUF_ALLOC (0x2000) @@ -133,7 +142,6 @@ struct onenand_chip { * OneNAND Flash Manufacturer ID Codes */ #define ONENAND_MFR_SAMSUNG 0xec -#define ONENAND_MFR_UNKNOWN 0x00 /** * struct nand_manufacturers - NAND Flash Manufacturer ID Structure diff --git a/include/linux/mtd/onenand_regs.h b/include/linux/mtd/onenand_regs.h index a245e14..fc63380 100644 --- a/include/linux/mtd/onenand_regs.h +++ b/include/linux/mtd/onenand_regs.h @@ -119,6 +119,7 @@ #define ONENAND_CMD_UNLOCK (0x23) #define ONENAND_CMD_LOCK (0x2A) #define ONENAND_CMD_LOCK_TIGHT (0x2C) +#define ONENAND_CMD_UNLOCK_ALL (0x27) #define ONENAND_CMD_ERASE (0x94) #define ONENAND_CMD_RESET (0xF0) #define ONENAND_CMD_READID (0x90) diff --git a/include/onenand_uboot.h b/include/onenand_uboot.h index e960257..5a4fded 100644 --- a/include/onenand_uboot.h +++ b/include/onenand_uboot.h @@ -15,25 +15,29 @@ #define __UBOOT_ONENAND_H #include -#include struct mtd_info; struct erase_info; +struct onenand_chip; extern struct mtd_info onenand_mtd; +/* board */ +extern void onenand_board_init(struct mtd_info *); + /* Functions */ extern void onenand_init(void); extern int onenand_read(struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf); -extern int onenand_read_oob(struct mtd_info *mtd, loff_t from, - struct mtd_oob_ops *ops); +extern int onenand_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops); extern int onenand_write(struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, const u_char * buf); extern int onenand_erase(struct mtd_info *mtd, struct erase_info *instr); -extern int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len); +extern char *onenand_print_device_info(int device, int version); -extern char *onenand_print_device_info(int device); +/* S3C64xx */ +extern void s3c64xx_onenand_init(struct mtd_info *); +extern void s3c64xx_set_width_regs(struct onenand_chip *); #endif /* __UBOOT_ONENAND_H */ -- cgit v0.10.2 From 1ac5744e33ee0aa6d6ddab3b99f9e70953156e69 Mon Sep 17 00:00:00 2001 From: Dave Liu Date: Tue, 4 Nov 2008 14:55:06 +0800 Subject: mpc83xx: enable eLBC NAND support for MPC8315ERDB board Signed-off-by: Dave Liu diff --git a/include/configs/MPC8315ERDB.h b/include/configs/MPC8315ERDB.h index add65f0..48043c4 100644 --- a/include/configs/MPC8315ERDB.h +++ b/include/configs/MPC8315ERDB.h @@ -166,7 +166,7 @@ #undef CONFIG_SYS_RAMBOOT #endif -#define CONFIG_SYS_MONITOR_LEN (256 * 1024) /* Reserve 256 kB for Mon */ +#define CONFIG_SYS_MONITOR_LEN (384 * 1024) /* Reserve 384 kB for Mon */ #define CONFIG_SYS_MALLOC_LEN (512 * 1024) /* Reserved for malloc */ /* @@ -223,15 +223,17 @@ */ #define CONFIG_SYS_NAND_BASE 0xE0600000 /* 0xE0600000 */ #define CONFIG_SYS_MAX_NAND_DEVICE 1 -#define NAND_MAX_CHIPS 1 -#define CONFIG_MTD_NAND_VERIFY_WRITE +#define NAND_MAX_CHIPS 1 +#define CONFIG_MTD_NAND_VERIFY_WRITE 1 +#define CONFIG_CMD_NAND 1 +#define CONFIG_NAND_FSL_ELBC 1 -#define CONFIG_SYS_BR1_PRELIM ( CONFIG_SYS_NAND_BASE \ +#define CONFIG_SYS_BR1_PRELIM ( CONFIG_SYS_NAND_BASE \ | (2< Date: Tue, 11 Nov 2008 10:28:53 +0100 Subject: OneNAND: Fix compiler warnings Signed-off-by: Stefan Roese diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index 66214e8..8d004d3 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -409,6 +409,30 @@ static int onenand_write_bufferram(struct mtd_info *mtd, loff_t addr, int area, } /** + * onenand_get_2x_blockpage - [GENERIC] Get blockpage at 2x program mode + * @param mtd MTD data structure + * @param addr address to check + * @return blockpage address + * + * Get blockpage address at 2x program mode + */ +static int onenand_get_2x_blockpage(struct mtd_info *mtd, loff_t addr) +{ + struct onenand_chip *this = mtd->priv; + int blockpage, block, page; + + /* Calculate the even block number */ + block = (int) (addr >> this->erase_shift) & ~1; + /* Is it the odd plane? */ + if (addr & this->writesize) + block++; + page = (int) (addr >> (this->page_shift + 1)) & this->page_mask; + blockpage = (block << 7) | page; + + return blockpage; +} + +/** * onenand_check_bufferram - [GENERIC] Check BufferRAM information * @param mtd MTD data structure * @param addr address to check @@ -1666,6 +1690,7 @@ static int onenand_do_lock_cmd(struct mtd_info *mtd, loff_t ofs, size_t len, int return 0; } +#ifdef ONENAND_LINUX /** * onenand_lock - [MTD Interface] Lock block(s) * @param mtd MTD device structure @@ -1701,6 +1726,7 @@ static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) onenand_release_device(mtd); return ret; } +#endif /** * onenand_check_lock_status - [OneNAND Interface] Check lock status -- cgit v0.10.2 From 8cf11f3aa78673730e9ecbbe4b75213b53f212c8 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Tue, 11 Nov 2008 10:29:09 +0100 Subject: OneNAND: Save version_id in onenand_chip struct The version (ver_id) was not stored in the onenand_chip structure and because of this the continuous locking scheme could be enabled on some chips. Signed-off-by: Stefan Roese diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index 8d004d3..f62b1aa 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -1970,6 +1970,7 @@ static int onenand_probe(struct mtd_info *mtd) /* Flash device information */ mtd->name = onenand_print_device_info(dev_id, ver_id); this->device_id = dev_id; + this->version_id = ver_id; density = onenand_get_density(dev_id); this->chipsize = (16 << density) << 20; -- cgit v0.10.2 From c438ea175d8d002c1063b7a94b0c0e26668d1ac9 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Wed, 12 Nov 2008 13:47:24 +0100 Subject: OneNAND: Bad block aware read/write command support Update OneNAND command to support bad block awareness. Also change the OneNAND command style to better match the NAND version. Signed-off-by: Stefan Roese Acked-by: Kyungmin Park diff --git a/common/cmd_onenand.c b/common/cmd_onenand.c index 8d87b78..6a2c924 100644 --- a/common/cmd_onenand.c +++ b/common/cmd_onenand.c @@ -1,7 +1,7 @@ /* * U-Boot command for OneNAND support * - * Copyright (C) 2005-2007 Samsung Electronics + * Copyright (C) 2005-2008 Samsung Electronics * Kyungmin Park * * This program is free software; you can redistribute it and/or modify @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -18,159 +19,468 @@ #include -extern struct mtd_info onenand_mtd; -extern struct onenand_chip onenand_chip; +static struct mtd_info *mtd; + +static loff_t next_ofs; +static loff_t skip_ofs; + +static inline int str2long(char *p, ulong *num) +{ + char *endptr; + + *num = simple_strtoul(p, &endptr, 16); + return (*p != '\0' && *endptr == '\0') ? 1 : 0; +} + +static int arg_off_size(int argc, char *argv[], ulong *off, size_t *size) +{ + if (argc >= 1) { + if (!(str2long(argv[0], off))) { + printf("'%s' is not a number\n", argv[0]); + return -1; + } + } else { + *off = 0; + } + + if (argc >= 2) { + if (!(str2long(argv[1], (ulong *)size))) { + printf("'%s' is not a number\n", argv[1]); + return -1; + } + } else { + *size = mtd->size - *off; + } + + if ((*off + *size) > mtd->size) { + printf("total chip size (0x%x) exceeded!\n", mtd->size); + return -1; + } + + if (*size == mtd->size) + puts("whole chip\n"); + else + printf("offset 0x%lx, size 0x%x\n", *off, *size); + + return 0; +} + +static int onenand_block_read(loff_t from, size_t len, + size_t *retlen, u_char *buf, int oob) +{ + struct onenand_chip *this = mtd->priv; + int blocks = (int) len >> this->erase_shift; + int blocksize = (1 << this->erase_shift); + loff_t ofs = from; + struct mtd_oob_ops ops = { + .retlen = 0, + }; + int ret; + + if (oob) + ops.ooblen = blocksize; + else + ops.len = blocksize; + + while (blocks) { + ret = mtd->block_isbad(mtd, ofs); + if (ret) { + printk("Bad blocks %d at 0x%x\n", + (u32)(ofs >> this->erase_shift), (u32)ofs); + ofs += blocksize; + continue; + } + + if (oob) + ops.oobbuf = buf; + else + ops.datbuf = buf; + + ops.retlen = 0; + ret = mtd->read_oob(mtd, ofs, &ops); + if (ret) { + printk("Read failed 0x%x, %d\n", (u32)ofs, ret); + ofs += blocksize; + continue; + } + ofs += blocksize; + buf += blocksize; + blocks--; + *retlen += ops.retlen; + } + + return 0; +} + +static int onenand_block_write(loff_t to, size_t len, + size_t *retlen, const u_char * buf) +{ + struct onenand_chip *this = mtd->priv; + int blocks = len >> this->erase_shift; + int blocksize = (1 << this->erase_shift); + loff_t ofs; + size_t _retlen = 0; + int ret; + + if (to == next_ofs) { + next_ofs = to + len; + to += skip_ofs; + } else { + next_ofs = to + len; + skip_ofs = 0; + } + ofs = to; + + while (blocks) { + ret = mtd->block_isbad(mtd, ofs); + if (ret) { + printk("Bad blocks %d at 0x%x\n", + (u32)(ofs >> this->erase_shift), (u32)ofs); + skip_ofs += blocksize; + goto next; + } + + ret = mtd->write(mtd, ofs, blocksize, &_retlen, buf); + if (ret) { + printk("Write failed 0x%x, %d", (u32)ofs, ret); + skip_ofs += blocksize; + goto next; + } + + buf += blocksize; + blocks--; + *retlen += _retlen; +next: + ofs += blocksize; + } + + return 0; +} + +static int onenand_block_erase(u32 start, u32 size, int force) +{ + struct onenand_chip *this = mtd->priv; + struct erase_info instr = { + .callback = NULL, + }; + loff_t ofs; + int ret; + int blocksize = 1 << this->erase_shift; + + 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); + continue; + } + + instr.addr = ofs; + instr.len = blocksize; + instr.priv = 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; + } + } + + return 0; +} + +static int onenand_block_test(u32 start, u32 size) +{ + struct onenand_chip *this = mtd->priv; + struct erase_info instr = { + .callback = NULL, + .priv = 0, + }; + + int blocks; + loff_t ofs; + int blocksize = 1 << this->erase_shift; + int start_block, end_block; + size_t retlen; + u_char *buf; + u_char *verify_buf; + int ret; + + buf = malloc(blocksize); + if (!buf) { + printf("Not enough malloc space available!\n"); + return -1; + } + + verify_buf = malloc(blocksize); + if (!verify_buf) { + printf("Not enough malloc space available!\n"); + return -1; + } + + start_block = start >> this->erase_shift; + end_block = (start + size) >> this->erase_shift; + + /* Protect boot-loader from badblock testing */ + if (start_block < 2) + start_block = 2; + + if (end_block > (mtd->size >> this->erase_shift)) + end_block = mtd->size >> this->erase_shift; + + blocks = start_block; + ofs = start; + while (blocks < end_block) { + printf("\rTesting block %d at 0x%x", (u32)(ofs >> this->erase_shift), (u32)ofs); + + ret = mtd->block_isbad(mtd, ofs); + if (ret) { + printf("Skip erase bad block %d at 0x%x\n", + (u32)(ofs >> this->erase_shift), (u32)ofs); + goto next; + } + + instr.addr = ofs; + instr.len = blocksize; + ret = mtd->erase(mtd, &instr); + if (ret) { + printk("Erase failed 0x%x, %d\n", (u32)ofs, ret); + goto next; + } + + ret = mtd->write(mtd, ofs, blocksize, &retlen, buf); + if (ret) { + printk("Write failed 0x%x, %d\n", (u32)ofs, ret); + goto next; + } + + ret = mtd->read(mtd, ofs, blocksize, &retlen, verify_buf); + if (ret) { + printk("Read failed 0x%x, %d\n", (u32)ofs, ret); + goto next; + } + + if (memcmp(buf, verify_buf, blocksize)) + printk("\nRead/Write test failed at 0x%x\n", (u32)ofs); + +next: + ofs += blocksize; + blocks++; + } + printf("...Done\n"); + + free(buf); + free(verify_buf); + + return 0; +} + +static int onenand_dump(struct mtd_info *mtd, ulong off, int only_oob) +{ + int i; + u_char *datbuf, *oobbuf, *p; + struct mtd_oob_ops ops; + loff_t addr; + + datbuf = malloc(mtd->writesize + mtd->oobsize); + oobbuf = malloc(mtd->oobsize); + if (!datbuf || !oobbuf) { + puts("No memory for page buffer\n"); + return 1; + } + off &= ~(mtd->writesize - 1); + addr = (loff_t) off; + memset(&ops, 0, sizeof(ops)); + ops.datbuf = datbuf; + ops.oobbuf = oobbuf; /* must exist, but oob data will be appended to ops.datbuf */ + ops.len = mtd->writesize; + ops.ooblen = mtd->oobsize; + ops.retlen = 0; + i = mtd->read_oob(mtd, addr, &ops); + if (i < 0) { + printf("Error (%d) reading page %08lx\n", i, off); + free(datbuf); + free(oobbuf); + return 1; + } + printf("Page %08lx dump:\n", off); + i = mtd->writesize >> 4; + p = datbuf; + + while (i--) { + if (!only_oob) + printf("\t%02x %02x %02x %02x %02x %02x %02x %02x" + " %02x %02x %02x %02x %02x %02x %02x %02x\n", + p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], + p[8], p[9], p[10], p[11], p[12], p[13], p[14], + p[15]); + p += 16; + } + puts("OOB:\n"); + i = mtd->oobsize >> 3; + while (i--) { + printf("\t%02x %02x %02x %02x %02x %02x %02x %02x\n", + p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); + p += 8; + } + free(datbuf); + free(oobbuf); + + return 0; +} int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) { - int ret = 0; + struct onenand_chip *this; + int blocksize; + ulong addr, ofs; + size_t len, retlen = 0; + int ret; + char *cmd, *s; + + mtd = &onenand_mtd; + this = mtd->priv; + blocksize = (1 << this->erase_shift); + + cmd = argv[1]; switch (argc) { case 0: case 1: - printf("Usage:\n%s\n", cmdtp->usage); - return 1; + goto usage; case 2: - if (strncmp(argv[1], "open", 4) == 0) { - onenand_init(); + if (strcmp(cmd, "info") == 0) { + printf("%s\n", mtd->name); + return 0; + } + + if (strcmp(cmd, "bad") == 0) { + /* Currently only one OneNAND device is supported */ + printf("\nDevice %d bad blocks:\n", 0); + for (ofs = 0; ofs < mtd->size; ofs += mtd->erasesize) { + if (mtd->block_isbad(mtd, ofs)) + printf(" %08x\n", (u32)ofs); + } + return 0; } - printf("%s\n", onenand_mtd.name); - return 0; default: /* At least 4 args */ - if (strncmp(argv[1], "erase", 5) == 0) { - struct erase_info instr = { - .callback = NULL, - }; - ulong start, end; - ulong block; - char *endtail; - - if (strncmp(argv[2], "block", 5) == 0) { - start = simple_strtoul(argv[3], NULL, 10); - endtail = strchr(argv[3], '-'); - end = simple_strtoul(endtail + 1, NULL, 10); - } else { - start = simple_strtoul(argv[2], NULL, 10); - end = simple_strtoul(argv[3], NULL, 10); - start >>= onenand_chip.erase_shift; - end >>= onenand_chip.erase_shift; - /* Don't include the end block */ - end--; - } + /* + * Syntax is: + * 0 1 2 3 4 + * onenand erase [force] [off size] + */ + if ((strcmp(cmd, "erase") == 0) || (strcmp(cmd, "test") == 0)) { + int force = argc > 2 && !strcmp("force", argv[2]); + int o = force ? 3 : 2; + int erase; - if (!end || end < 0) - end = start; + erase = strcmp(cmd, "erase") == 0; /* 1 = erase, 0 = test */ + printf("\nOneNAND %s: ", erase ? "erase" : "test"); - printf("Erase block from %lu to %lu\n", start, end); + /* skip first two or three arguments, look for offset and size */ + if (arg_off_size(argc - o, argv + o, &ofs, &len) != 0) + return 1; - for (block = start; block <= end; block++) { - instr.addr = block << onenand_chip.erase_shift; - instr.len = 1 << onenand_chip.erase_shift; - ret = onenand_erase(&onenand_mtd, &instr); - if (ret) { - printf("erase failed %lu\n", block); - break; - } - } + if (erase) + ret = onenand_block_erase(ofs, len, force); + else + ret = onenand_block_test(ofs, len); - return 0; + printf("%s\n", ret ? "ERROR" : "OK"); + + return ret == 0 ? 0 : 1; } - if (strncmp(argv[1], "read", 4) == 0) { - ulong addr = simple_strtoul(argv[2], NULL, 16); - ulong ofs = simple_strtoul(argv[3], NULL, 16); - size_t len = simple_strtoul(argv[4], NULL, 16); - int oob = strncmp(argv[1], "read.oob", 8) ? 0 : 1; - struct mtd_oob_ops ops; + if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) { + int read; + int oob = 0; - ops.mode = MTD_OOB_PLACE; + if (argc < 4) + goto usage; - if (oob) { - ops.len = 0; - ops.datbuf = NULL; - ops.ooblen = len; - ops.oobbuf = (u_char *) addr; - } else { - ops.len = len; - ops.datbuf = (u_char *) addr; - ops.ooblen = 0; - ops.oobbuf = NULL; - } - ops.retlen = ops.oobretlen = 0; + addr = (ulong)simple_strtoul(argv[2], NULL, 16); - onenand_mtd.read_oob(&onenand_mtd, ofs, &ops); - printf("Done\n"); + read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */ + printf("\nOneNAND %s: ", read ? "read" : "write"); + if (arg_off_size(argc - 3, argv + 3, &ofs, &len) != 0) + return 1; - return 0; - } + s = strchr(cmd, '.'); + if ((s != NULL) && (!strcmp(s, ".oob"))) + oob = 1; - if (strncmp(argv[1], "write", 5) == 0) { - ulong addr = simple_strtoul(argv[2], NULL, 16); - ulong ofs = simple_strtoul(argv[3], NULL, 16); - size_t len = simple_strtoul(argv[4], NULL, 16); - size_t retlen = 0; + if (read) { + ret = onenand_block_read(ofs, len, &retlen, + (u8 *)addr, oob); + } else { + ret = onenand_block_write(ofs, len, &retlen, + (u8 *)addr); + } - onenand_write(&onenand_mtd, ofs, len, &retlen, - (u_char *) addr); - printf("Done\n"); + printf(" %d bytes %s: %s\n", retlen, + read ? "read" : "written", ret ? "ERROR" : "OK"); - return 0; + return ret == 0 ? 0 : 1; } - if (strncmp(argv[1], "block", 5) == 0) { - ulong addr = simple_strtoul(argv[2], NULL, 16); - ulong block = simple_strtoul(argv[3], NULL, 10); - ulong page = simple_strtoul(argv[4], NULL, 10); - size_t len = simple_strtol(argv[5], NULL, 10); - ulong ofs; - int oob = strncmp(argv[1], "block.oob", 9) ? 0 : 1; - struct mtd_oob_ops ops; - - ops.mode = MTD_OOB_PLACE; + if (strcmp(cmd, "markbad") == 0) { + addr = (ulong)simple_strtoul(argv[2], NULL, 16); + int ret = mtd->block_markbad(mtd, addr); + if (ret == 0) { + printf("block 0x%08lx successfully marked as bad\n", + (ulong) addr); + return 0; + } else { + printf("block 0x%08lx NOT marked as bad! ERROR %d\n", + (ulong) addr, ret); + } + return 1; + } - ofs = block << onenand_chip.erase_shift; - if (page) - ofs += page << onenand_chip.page_shift; + if (strncmp(cmd, "dump", 4) == 0) { + if (argc < 3) + goto usage; - if (!len) { - if (oob) - ops.ooblen = 64; - else - ops.len = 512; - } + s = strchr(cmd, '.'); + ofs = (int)simple_strtoul(argv[2], NULL, 16); - if (oob) { - ops.datbuf = NULL; - ops.oobbuf = (u_char *) addr; - } else { - ops.datbuf = (u_char *) addr; - ops.oobbuf = NULL; - } - ops.retlen = ops.oobretlen = 0; + if (s != NULL && strcmp(s, ".oob") == 0) + ret = onenand_dump(mtd, ofs, 1); + else + ret = onenand_dump(mtd, ofs, 0); - onenand_read_oob(&onenand_mtd, ofs, &ops); - return 0; + return ret == 0 ? 1 : 0; } break; } return 0; + +usage: + printf("Usage:\n%s\n", cmdtp->usage); + return 1; } U_BOOT_CMD( onenand, 6, 1, do_onenand, "onenand - OneNAND sub-system\n", - "info - show available OneNAND devices\n" - "onenand read[.oob] addr ofs len - read data at ofs with len to addr\n" - "onenand write addr ofs len - write data at ofs with len from addr\n" - "onenand erase saddr eaddr - erase block start addr to end addr\n" - "onenand block[.oob] addr block [page] [len] - " - "read data with (block [, page]) to addr" + "info - show available OneNAND devices\n" + "onenand bad - show bad blocks\n" + "onenand read[.oob] addr off size\n" + "onenand write[.oob] addr off size\n" + " read/write 'size' bytes starting at offset 'off'\n" + " to/from memory address 'addr', skipping bad blocks.\n" + "onenand erase [force] [off size] - erase 'size' bytes from\n" + "onenand test [off size] - test 'size' bytes from\n" + " offset 'off' (entire device if not specified)\n" + "onenand dump[.oob] off - dump page\n" + "onenand markbad off - mark bad block at offset (UNSAFE)\n" ); -- cgit v0.10.2 From 1714f51a2009baaecf3d4f6e3bd8c4e93a8d3f23 Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Thu, 13 Nov 2008 15:14:33 +0900 Subject: Add markbad function Add missing markbad function If not, it's hang when it entered the mtd->mark_bad(). Signed-off-by: Kyungmin Park diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index f62b1aa..dcc969f 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -1584,6 +1584,37 @@ int onenand_block_isbad(struct mtd_info *mtd, loff_t ofs) } /** + * onenand_default_block_markbad - [DEFAULT] mark a block bad + * @param mtd MTD device structure + * @param ofs offset from device start + * + * This is the default implementation, which can be overridden by + * a hardware specific driver. + */ +static int onenand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) +{ + struct onenand_chip *this = mtd->priv; + struct bbm_info *bbm = this->bbm; + u_char buf[2] = {0, 0}; + struct mtd_oob_ops ops = { + .mode = MTD_OOB_PLACE, + .ooblen = 2, + .oobbuf = buf, + .ooboffs = 0, + }; + int block; + + /* Get block number */ + block = ((int) ofs) >> bbm->bbt_erase_shift; + if (bbm->bbt) + bbm->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1); + + /* We write two bytes, so we dont have to mess with 16 bit access */ + ofs += mtd->oobsize + (bbm->badblockpos & ~0x01); + return onenand_write_oob_nolock(mtd, ofs, &ops); +} + +/** * onenand_block_markbad - [MTD Interface] Mark the block at the given offset as bad * @param mtd MTD device structure * @param ofs offset relative to mtd start @@ -2048,6 +2079,8 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) if (!this->write_bufferram) this->write_bufferram = onenand_write_bufferram; + if (!this->block_markbad) + this->block_markbad = onenand_default_block_markbad; if (!this->scan_bbt) this->scan_bbt = onenand_default_bbt; -- cgit v0.10.2 From 1ae39862044ebb1e682234b51f94421e3f871d6a Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Tue, 2 Dec 2008 11:06:47 +0100 Subject: OneNAND: Additional sync with 2.6.27 - Add subpage write support - Add onenand_oob_64/32 ecclayout This has been missing and without it UBI has some incompatibilies issues with the current (>= 2.6.27) Linux kernel version. vid_hdr_offset is placed differently (2048 instead of 512) without this fix. Signed-off-by: Stefan Roese Signed-off-by: Scott Wood diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index dcc969f..d482437 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -36,6 +36,35 @@ static inline void *memcpy_16(void *dst, const void *src, unsigned int len) return ret; } +/** + * onenand_oob_64 - oob info for large (2KB) page + */ +static struct nand_ecclayout onenand_oob_64 = { + .eccbytes = 20, + .eccpos = { + 8, 9, 10, 11, 12, + 24, 25, 26, 27, 28, + 40, 41, 42, 43, 44, + 56, 57, 58, 59, 60, + }, + .oobfree = { + {2, 3}, {14, 2}, {18, 3}, {30, 2}, + {34, 3}, {46, 2}, {50, 3}, {62, 2} + } +}; + +/** + * onenand_oob_32 - oob info for middle (1KB) page + */ +static struct nand_ecclayout onenand_oob_32 = { + .eccbytes = 10, + .eccpos = { + 8, 9, 10, 11, 12, + 24, 25, 26, 27, 28, + }, + .oobfree = { {2, 3}, {14, 2}, {18, 3}, {30, 2} } +}; + static const unsigned char ffchars[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 16 */ @@ -1079,7 +1108,7 @@ static int onenand_verify(struct mtd_info *mtd, const u_char *buf, loff_t addr, #define onenand_verify_oob(...) (0) #endif -#define NOTALIGNED(x) ((x & (mtd->writesize - 1)) != 0) +#define NOTALIGNED(x) ((x & (this->subpagesize - 1)) != 0) /** * onenand_fill_auto_oob - [Internal] oob auto-placement transfer @@ -2058,6 +2087,7 @@ static int onenand_probe(struct mtd_info *mtd) */ int onenand_scan(struct mtd_info *mtd, int maxchips) { + int i; struct onenand_chip *this = mtd->priv; if (!this->read_word) @@ -2115,6 +2145,46 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) this->options |= ONENAND_OOBBUF_ALLOC; } + this->state = FL_READY; + + /* + * Allow subpage writes up to oobsize. + */ + switch (mtd->oobsize) { + case 64: + this->ecclayout = &onenand_oob_64; + mtd->subpage_sft = 2; + break; + + case 32: + this->ecclayout = &onenand_oob_32; + mtd->subpage_sft = 1; + break; + + default: + printk(KERN_WARNING "No OOB scheme defined for oobsize %d\n", + mtd->oobsize); + mtd->subpage_sft = 0; + /* To prevent kernel oops */ + this->ecclayout = &onenand_oob_32; + break; + } + + this->subpagesize = mtd->writesize >> mtd->subpage_sft; + + /* + * The number of bytes available for a client to place data into + * the out of band area + */ + this->ecclayout->oobavail = 0; + for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && + this->ecclayout->oobfree[i].length; i++) + this->ecclayout->oobavail += + this->ecclayout->oobfree[i].length; + mtd->oobavail = this->ecclayout->oobavail; + + mtd->ecclayout = this->ecclayout; + /* Unlock whole block */ onenand_unlock_all(mtd); diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h index 7547e96..2597e34 100644 --- a/include/linux/mtd/onenand.h +++ b/include/linux/mtd/onenand.h @@ -107,6 +107,7 @@ struct onenand_chip { unsigned char *oob_buf; struct nand_oobinfo *autooob; + int subpagesize; struct nand_ecclayout *ecclayout; void *bbm; -- cgit v0.10.2 From 69fb8be4fc07162fdf6edf04bdc7233b0e9a920e Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sat, 6 Dec 2008 02:40:55 -0500 Subject: NAND: move board_nand_init to nand.h Rather than putting the function prototype for board_nand_init() in the one place where it gets called, put it into nand.h so that every place that also defines it gets the prototype. Otherwise, errors can go silently unnoticed such as using the wrong return value (void rather than int) when defining the function. Signed-off-by: Mike Frysinger Signed-off-by: Scott Wood diff --git a/drivers/mtd/nand/nand.c b/drivers/mtd/nand/nand.c index eeb19ff..cf92617 100644 --- a/drivers/mtd/nand/nand.c +++ b/drivers/mtd/nand/nand.c @@ -36,8 +36,6 @@ static ulong base_address[CONFIG_SYS_MAX_NAND_DEVICE] = CONFIG_SYS_NAND_BASE_LIS static const char default_nand_name[] = "nand"; -extern int board_nand_init(struct nand_chip *nand); - static void nand_init_chip(struct mtd_info *mtd, struct nand_chip *nand, ulong base_addr) { diff --git a/include/nand.h b/include/nand.h index b4f316f..065a42c 100644 --- a/include/nand.h +++ b/include/nand.h @@ -31,6 +31,8 @@ extern void nand_init(void); #include #include +extern int board_nand_init(struct nand_chip *nand); + typedef struct mtd_info nand_info_t; extern int nand_curr_device; -- cgit v0.10.2 From 50657c273278f74378e1ac39b41d612b92fdffa0 Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Sat, 13 Dec 2008 09:43:06 -0600 Subject: NAND: Enable nand lock, unlock feature Enable nand lock, unlock and status of lock feature. Not every device and platform requires this, hence, it is under define for CONFIG_CMD_NAND_LOCK_UNLOCK Nand unlock and status operate on block boundary instead of page boundary. Details in: http://www.micron.com/products/partdetail?part=MT29C2G24MAKLAJG-6%20IT Intial solution provided by Vikram Pandita Includes preliminary suggestions from Scott Wood Signed-off-by: Nishanth Menon Signed-off-by: Scott Wood diff --git a/common/cmd_nand.c b/common/cmd_nand.c index 0a366d3..a240c37 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -164,6 +164,47 @@ out: return 0; } +#ifdef CONFIG_CMD_NAND_LOCK_UNLOCK +static void print_status(ulong start, ulong end, ulong erasesize, int status) +{ + printf("%08lx - %08lx: %08lx blocks %s%s%s\n", + start, + end - 1, + (end - start) / erasesize, + ((status & NAND_LOCK_STATUS_TIGHT) ? "TIGHT " : ""), + ((status & NAND_LOCK_STATUS_LOCK) ? "LOCK " : ""), + ((status & NAND_LOCK_STATUS_UNLOCK) ? "UNLOCK " : "")); +} + +static void do_nand_status(nand_info_t *nand) +{ + ulong block_start = 0; + ulong off; + int last_status = -1; + + struct nand_chip *nand_chip = nand->priv; + /* check the WP bit */ + nand_chip->cmdfunc(nand, NAND_CMD_STATUS, -1, -1); + printf("device is %swrite protected\n", + (nand_chip->read_byte(nand) & 0x80 ? + "NOT " : "")); + + for (off = 0; off < nand->size; off += nand->erasesize) { + int s = nand_get_lock_status(nand, off); + + /* print message only if status has changed */ + if (s != last_status && off != 0) { + print_status(block_start, off, nand->erasesize, + last_status); + block_start = off; + } + last_status = s; + } + /* Print the last block info */ + print_status(block_start, off, nand->erasesize, last_status); +} +#endif + int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) { int i, dev, ret = 0; @@ -383,8 +424,9 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) return 1; } +#ifdef CONFIG_CMD_NAND_LOCK_UNLOCK if (strcmp(cmd, "lock") == 0) { - int tight = 0; + int tight = 0; int status = 0; if (argc == 3) { if (!strcmp("tight", argv[2])) @@ -392,44 +434,8 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) if (!strcmp("status", argv[2])) status = 1; } -/* - * ! BROKEN ! - * - * TODO: must be implemented and tested by someone with HW - */ -#if 0 if (status) { - ulong block_start = 0; - ulong off; - int last_status = -1; - - struct nand_chip *nand_chip = nand->priv; - /* check the WP bit */ - nand_chip->cmdfunc (nand, NAND_CMD_STATUS, -1, -1); - printf("device is %swrite protected\n", - (nand_chip->read_byte(nand) & 0x80 ? - "NOT " : "")); - - for (off = 0; off < nand->size; off += nand->writesize) { - int s = nand_get_lock_status(nand, off); - - /* print message only if status has changed - * or at end of chip - */ - if (off == nand->size - nand->writesize - || (s != last_status && off != 0)) { - - printf("%08lx - %08lx: %8d pages %s%s%s\n", - block_start, - off-1, - (off-block_start)/nand->writesize, - ((last_status & NAND_LOCK_STATUS_TIGHT) ? "TIGHT " : ""), - ((last_status & NAND_LOCK_STATUS_LOCK) ? "LOCK " : ""), - ((last_status & NAND_LOCK_STATUS_UNLOCK) ? "UNLOCK " : "")); - } - - last_status = s; - } + do_nand_status(nand); } else { if (!nand_lock(nand, tight)) { puts("NAND flash successfully locked\n"); @@ -438,7 +444,6 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) return 1; } } -#endif return 0; } @@ -446,12 +451,6 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) if (arg_off_size(argc - 2, argv + 2, nand, &off, &size) < 0) return 1; -/* - * ! BROKEN ! - * - * TODO: must be implemented and tested by someone with HW - */ -#if 0 if (!nand_unlock(nand, off, size)) { puts("NAND flash successfully unlocked\n"); } else { @@ -459,9 +458,9 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) "write and erase will probably fail\n"); return 1; } -#endif return 0; } +#endif usage: printf("Usage:\n%s\n", cmdtp->usage); @@ -483,9 +482,12 @@ U_BOOT_CMD(nand, 5, 1, do_nand, "nand scrub - really clean NAND erasing bad blocks (UNSAFE)\n" "nand markbad off - mark bad block at offset (UNSAFE)\n" "nand biterr off - make a bit error at offset (UNSAFE)\n" +#ifdef CONFIG_CMD_NAND_LOCK_UNLOCK "nand lock [tight] [status]\n" " bring nand to lock state or display locked pages\n" - "nand unlock [offset] [size] - unlock section\n"); + "nand unlock [offset] [size] - unlock section\n" +#endif +); static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand, ulong offset, ulong addr, char *cmd) diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c index d86c987..77da53e 100644 --- a/drivers/mtd/nand/nand_util.c +++ b/drivers/mtd/nand/nand_util.c @@ -238,7 +238,8 @@ static struct nand_ecclayout autoplace_ecclayout = { #endif /* XXX U-BOOT XXX */ -#if 0 +#ifdef CONFIG_CMD_NAND_LOCK_UNLOCK + /****************************************************************************** * Support for locking / unlocking operations of some NAND devices *****************************************************************************/ @@ -253,7 +254,7 @@ static struct nand_ecclayout autoplace_ecclayout = { * nand_lock: Set all pages of NAND flash chip to the LOCK or LOCK-TIGHT * state * - * @param meminfo nand mtd instance + * @param mtd nand mtd instance * @param tight bring device in lock tight mode * * @return 0 on success, -1 in case of error @@ -270,21 +271,21 @@ static struct nand_ecclayout autoplace_ecclayout = { * calls will fail. It is only posible to leave lock-tight state by * an hardware signal (low pulse on _WP pin) or by power down. */ -int nand_lock(nand_info_t *meminfo, int tight) +int nand_lock(struct mtd_info *mtd, int tight) { int ret = 0; int status; - struct nand_chip *this = meminfo->priv; + struct nand_chip *chip = mtd->priv; /* select the NAND device */ - this->select_chip(meminfo, 0); + chip->select_chip(mtd, 0); - this->cmdfunc(meminfo, + chip->cmdfunc(mtd, (tight ? NAND_CMD_LOCK_TIGHT : NAND_CMD_LOCK), -1, -1); /* call wait ready function */ - status = this->waitfunc(meminfo, this, FL_WRITING); + status = chip->waitfunc(mtd, chip); /* see if device thinks it succeeded */ if (status & 0x01) { @@ -292,7 +293,7 @@ int nand_lock(nand_info_t *meminfo, int tight) } /* de-select the NAND device */ - this->select_chip(meminfo, -1); + chip->select_chip(mtd, -1); return ret; } @@ -300,7 +301,7 @@ int nand_lock(nand_info_t *meminfo, int tight) * nand_get_lock_status: - query current lock state from one page of NAND * flash * - * @param meminfo nand mtd instance + * @param mtd nand mtd instance * @param offset page address to query (muss be page aligned!) * * @return -1 in case of error @@ -311,19 +312,19 @@ int nand_lock(nand_info_t *meminfo, int tight) * NAND_LOCK_STATUS_UNLOCK: page unlocked * */ -int nand_get_lock_status(nand_info_t *meminfo, ulong offset) +int nand_get_lock_status(struct mtd_info *mtd, ulong offset) { int ret = 0; int chipnr; int page; - struct nand_chip *this = meminfo->priv; + struct nand_chip *chip = mtd->priv; /* select the NAND device */ - chipnr = (int)(offset >> this->chip_shift); - this->select_chip(meminfo, chipnr); + chipnr = (int)(offset >> chip->chip_shift); + chip->select_chip(mtd, chipnr); - if ((offset & (meminfo->writesize - 1)) != 0) { + if ((offset & (mtd->writesize - 1)) != 0) { printf ("nand_get_lock_status: " "Start address must be beginning of " "nand page!\n"); @@ -332,16 +333,16 @@ int nand_get_lock_status(nand_info_t *meminfo, ulong offset) } /* check the Lock Status */ - page = (int)(offset >> this->page_shift); - this->cmdfunc(meminfo, NAND_CMD_LOCK_STATUS, -1, page & this->pagemask); + page = (int)(offset >> chip->page_shift); + chip->cmdfunc(mtd, NAND_CMD_LOCK_STATUS, -1, page & chip->pagemask); - ret = this->read_byte(meminfo) & (NAND_LOCK_STATUS_TIGHT + ret = chip->read_byte(mtd) & (NAND_LOCK_STATUS_TIGHT | NAND_LOCK_STATUS_LOCK | NAND_LOCK_STATUS_UNLOCK); out: /* de-select the NAND device */ - this->select_chip(meminfo, -1); + chip->select_chip(mtd, -1); return ret; } @@ -349,59 +350,65 @@ int nand_get_lock_status(nand_info_t *meminfo, ulong offset) * nand_unlock: - Unlock area of NAND pages * only one consecutive area can be unlocked at one time! * - * @param meminfo nand mtd instance + * @param mtd nand mtd instance * @param start start byte address * @param length number of bytes to unlock (must be a multiple of * page size nand->writesize) * * @return 0 on success, -1 in case of error */ -int nand_unlock(nand_info_t *meminfo, ulong start, ulong length) +int nand_unlock(struct mtd_info *mtd, ulong start, ulong length) { int ret = 0; int chipnr; int status; int page; - struct nand_chip *this = meminfo->priv; + struct nand_chip *chip = mtd->priv; printf ("nand_unlock: start: %08x, length: %d!\n", (int)start, (int)length); /* select the NAND device */ - chipnr = (int)(start >> this->chip_shift); - this->select_chip(meminfo, chipnr); + chipnr = (int)(start >> chip->chip_shift); + chip->select_chip(mtd, chipnr); /* check the WP bit */ - this->cmdfunc(meminfo, NAND_CMD_STATUS, -1, -1); - if ((this->read_byte(meminfo) & 0x80) == 0) { + chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1); + if (!(chip->read_byte(mtd) & NAND_STATUS_WP)) { printf ("nand_unlock: Device is write protected!\n"); ret = -1; goto out; } - if ((start & (meminfo->writesize - 1)) != 0) { + if ((start & (mtd->erasesize - 1)) != 0) { printf ("nand_unlock: Start address must be beginning of " - "nand page!\n"); + "nand block!\n"); ret = -1; goto out; } - if (length == 0 || (length & (meminfo->writesize - 1)) != 0) { - printf ("nand_unlock: Length must be a multiple of nand page " - "size!\n"); + if (length == 0 || (length & (mtd->erasesize - 1)) != 0) { + printf ("nand_unlock: Length must be a multiple of nand block " + "size %08x!\n", mtd->erasesize); ret = -1; goto out; } + /* + * Set length so that the last address is set to the + * starting address of the last block + */ + length -= mtd->erasesize; + /* submit address of first page to unlock */ - page = (int)(start >> this->page_shift); - this->cmdfunc(meminfo, NAND_CMD_UNLOCK1, -1, page & this->pagemask); + page = (int)(start >> chip->page_shift); + chip->cmdfunc(mtd, NAND_CMD_UNLOCK1, -1, page & chip->pagemask); /* submit ADDRESS of LAST page to unlock */ - page += (int)(length >> this->page_shift) - 1; - this->cmdfunc(meminfo, NAND_CMD_UNLOCK2, -1, page & this->pagemask); + page += (int)(length >> chip->page_shift); + chip->cmdfunc(mtd, NAND_CMD_UNLOCK2, -1, page & chip->pagemask); /* call wait ready function */ - status = this->waitfunc(meminfo, this, FL_WRITING); + status = chip->waitfunc(mtd, chip); /* see if device thinks it succeeded */ if (status & 0x01) { /* there was an error */ @@ -411,7 +418,7 @@ int nand_unlock(nand_info_t *meminfo, ulong start, ulong length) out: /* de-select the NAND device */ - this->select_chip(meminfo, -1); + chip->select_chip(mtd, -1); return ret; } #endif -- cgit v0.10.2 From c70564e6b1bd08f3230182392238907f3531a87e Mon Sep 17 00:00:00 2001 From: Dave Liu Date: Tue, 2 Dec 2008 11:48:51 +0800 Subject: NAND: Fix cache and memory inconsistency issue We load the secondary stage u-boot image from NAND to system memory by nand_load, but we did not flush d-cache to memory, nor invalidate i-cache before we jump to RAM. When the system has cache enabled and the TLB/page attribute of system memory is cacheable, it will cause issues. - 83xx family is using the d-cache lock, so all of d-cache access is cache-inhibited. so you can't see the issue. - 85xx family is using d-cache, i-cache enable, partial cache lock. you will see the issue. This patch fixes the cache issue. Signed-off-by: Dave Liu Signed-off-by: Scott Wood diff --git a/nand_spl/board/freescale/mpc8313erdb/Makefile b/nand_spl/board/freescale/mpc8313erdb/Makefile index 3da1b1f..1a8f6ff 100644 --- a/nand_spl/board/freescale/mpc8313erdb/Makefile +++ b/nand_spl/board/freescale/mpc8313erdb/Makefile @@ -34,7 +34,8 @@ AFLAGS += -DCONFIG_NAND_SPL CFLAGS += -DCONFIG_NAND_SPL SOBJS = start.o ticks.o -COBJS = nand_boot_fsl_elbc.o $(BOARD).o sdram.o ns16550.o nand_init.o time.o +COBJS = nand_boot_fsl_elbc.o $(BOARD).o sdram.o ns16550.o nand_init.o \ + time.o cache.o SRCS := $(addprefix $(obj),$(SOBJS:.o=.S) $(COBJS:.o=.c)) OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) @@ -79,6 +80,9 @@ $(obj)ns16550.c: $(obj)nand_init.c: ln -sf $(SRCTREE)/cpu/mpc83xx/nand_init.c $(obj)nand_init.c +$(obj)cache.c: + ln -sf $(SRCTREE)/lib_ppc/cache.c $(obj)cache.c + $(obj)time.c: ln -sf $(SRCTREE)/lib_ppc/time.c $(obj)time.c diff --git a/nand_spl/nand_boot_fsl_elbc.c b/nand_spl/nand_boot_fsl_elbc.c index 4a961ea..0d0c44e 100644 --- a/nand_spl/nand_boot_fsl_elbc.c +++ b/nand_spl/nand_boot_fsl_elbc.c @@ -143,6 +143,11 @@ void nand_boot(void) * Jump to U-Boot image */ puts("transfering control\n"); + /* + * Clean d-cache and invalidate i-cache, to + * make sure that no stale data is executed. + */ + flush_cache(CONFIG_SYS_NAND_U_BOOT_DST, CONFIG_SYS_NAND_U_BOOT_SIZE); uboot = (void *)CONFIG_SYS_NAND_U_BOOT_START; uboot(); } -- cgit v0.10.2 From 6c869637fef31e66380f0ea1d49690a2e26ec0d7 Mon Sep 17 00:00:00 2001 From: Wolfgang Grandegger Date: Fri, 16 Jan 2009 18:55:54 +0100 Subject: NAND: rename NAND_MAX_CHIPS to CONFIG_SYS_NAND_MAX_CHIPS This patch renames NAND_MAX_CHIPS to CONFIG_SYS_NAND_MAX_CHIPS and changes the default from 8 to 1 for the legacy and the new MTD NAND layer. This allows to remove all NAND_MAX_CHIPS definitions in the board config files because none of the boards use multi chip support (NAND_MAX_CHIPS > 1) so far. The bamboo and the DU440 define #define NAND_MAX_CHIPS CONFIG_SYS_MAX_NAND_DEVICE but that's bogus and did not work anyhow. Signed-off-by: Wolfgang Grandegger Signed-off-by: Scott Wood diff --git a/doc/README.nand b/doc/README.nand index bf80bc0..fc62f92 100644 --- a/doc/README.nand +++ b/doc/README.nand @@ -172,7 +172,7 @@ More Definitions: #define ADDR_COLUMN_PAGE 3 #define NAND_ChipID_UNKNOWN 0x00 #define NAND_MAX_FLOORS 1 - #define NAND_MAX_CHIPS 1 + #define CONFIG_SYS_NAND_MAX_CHIPS 1 #define CONFIG_SYS_DAVINCI_BROKEN_ECC Versions of U-Boot <= 1.3.3 and Montavista Linux kernels diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 94a65d4..ef37f97 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -2144,7 +2144,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, { int page, len, status, pages_per_block, ret, chipnr; struct nand_chip *chip = mtd->priv; - int rewrite_bbt[NAND_MAX_CHIPS]={0}; + int rewrite_bbt[CONFIG_SYS_NAND_MAX_CHIPS]={0}; unsigned int bbt_masked_page = 0xffffffff; MTDDEBUG (MTD_DEBUG_LEVEL3, "nand_erase: start = 0x%08x, len = %i\n", diff --git a/drivers/mtd/nand_legacy/nand_legacy.c b/drivers/mtd/nand_legacy/nand_legacy.c index 407e901..441780a 100644 --- a/drivers/mtd/nand_legacy/nand_legacy.c +++ b/drivers/mtd/nand_legacy/nand_legacy.c @@ -457,7 +457,7 @@ static void NanD_ScanChips(struct nand_chip *nand) { int floor, chip; int numchips[NAND_MAX_FLOORS]; - int maxchips = NAND_MAX_CHIPS; + int maxchips = CONFIG_SYS_NAND_MAX_CHIPS; int ret = 1; nand->numchips = 0; diff --git a/include/configs/ASH405.h b/include/configs/ASH405.h index a694083..a11a9b8 100644 --- a/include/configs/ASH405.h +++ b/include/configs/ASH405.h @@ -150,7 +150,6 @@ *----------------------------------------------------------------------- */ #define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND_BASE } -#define NAND_MAX_CHIPS 1 #define CONFIG_SYS_MAX_NAND_DEVICE 1 /* Max number of NAND devices */ #define NAND_BIG_DELAY_US 25 diff --git a/include/configs/CATcenter.h b/include/configs/CATcenter.h index a44f3e1..1e36660 100644 --- a/include/configs/CATcenter.h +++ b/include/configs/CATcenter.h @@ -219,7 +219,6 @@ #define NAND_ChipID_UNKNOWN 0x00 #define NAND_MAX_FLOORS 1 -#define NAND_MAX_CHIPS 1 #define CONFIG_SYS_NAND0_CE (0x80000000 >> 1) /* our CE is GPIO1 */ #define CONFIG_SYS_NAND0_CLE (0x80000000 >> 2) /* our CLE is GPIO2 */ diff --git a/include/configs/CMS700.h b/include/configs/CMS700.h index d0e2464..eebce38 100644 --- a/include/configs/CMS700.h +++ b/include/configs/CMS700.h @@ -157,7 +157,6 @@ *----------------------------------------------------------------------- */ #define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND_BASE } -#define NAND_MAX_CHIPS 1 #define CONFIG_SYS_MAX_NAND_DEVICE 1 /* Max number of NAND devices */ #define NAND_BIG_DELAY_US 25 diff --git a/include/configs/DU440.h b/include/configs/DU440.h index 729153c..85c0e61 100644 --- a/include/configs/DU440.h +++ b/include/configs/DU440.h @@ -411,7 +411,6 @@ int du440_phy_addr(int devnum); * NAND FLASH */ #define CONFIG_SYS_MAX_NAND_DEVICE 2 -#define NAND_MAX_CHIPS CONFIG_SYS_MAX_NAND_DEVICE #define CONFIG_SYS_NAND_SELECT_DEVICE 1 /* nand driver supports mutipl. chips */ #define CONFIG_SYS_NAND_BASE_LIST {CONFIG_SYS_NAND0_ADDR + CONFIG_SYS_NAND0_CS, \ CONFIG_SYS_NAND1_ADDR + CONFIG_SYS_NAND1_CS} diff --git a/include/configs/G2000.h b/include/configs/G2000.h index d299044..b445fae 100644 --- a/include/configs/G2000.h +++ b/include/configs/G2000.h @@ -205,7 +205,6 @@ #define NAND_ChipID_UNKNOWN 0x00 #define NAND_MAX_FLOORS 1 -#define NAND_MAX_CHIPS 1 #define CONFIG_SYS_NAND_CE (0x80000000 >> 1) /* our CE is GPIO1 */ #define CONFIG_SYS_NAND_CLE (0x80000000 >> 2) /* our CLE is GPIO2 */ diff --git a/include/configs/HH405.h b/include/configs/HH405.h index 80e59bb..e5de8ef 100644 --- a/include/configs/HH405.h +++ b/include/configs/HH405.h @@ -209,7 +209,6 @@ *----------------------------------------------------------------------- */ #define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND_BASE } -#define NAND_MAX_CHIPS 1 #define CONFIG_SYS_MAX_NAND_DEVICE 1 /* Max number of NAND devices */ #define NAND_BIG_DELAY_US 25 diff --git a/include/configs/HUB405.h b/include/configs/HUB405.h index b3c7046..1106b0d 100644 --- a/include/configs/HUB405.h +++ b/include/configs/HUB405.h @@ -149,7 +149,6 @@ *----------------------------------------------------------------------- */ #define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND_BASE } -#define NAND_MAX_CHIPS 1 #define CONFIG_SYS_MAX_NAND_DEVICE 1 /* Max number of NAND devices */ #define NAND_BIG_DELAY_US 25 diff --git a/include/configs/IDS8247.h b/include/configs/IDS8247.h index a610ac9..fbcbddb 100644 --- a/include/configs/IDS8247.h +++ b/include/configs/IDS8247.h @@ -275,7 +275,6 @@ #define NAND_ChipID_UNKNOWN 0x00 #define NAND_MAX_FLOORS 1 -#define NAND_MAX_CHIPS 1 #define NAND_DISABLE_CE(nand) do \ { \ diff --git a/include/configs/M5329EVB.h b/include/configs/M5329EVB.h index c207947..1f1586a 100644 --- a/include/configs/M5329EVB.h +++ b/include/configs/M5329EVB.h @@ -215,7 +215,6 @@ # define CONFIG_SYS_NAND_BASE CONFIG_SYS_CS2_BASE # define CONFIG_SYS_NAND_SIZE 1 # define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND_BASE } -# define NAND_MAX_CHIPS 1 # define NAND_ALLOW_ERASE_ALL 1 # define CONFIG_JFFS2_NAND 1 # define CONFIG_JFFS2_DEV "nand0" diff --git a/include/configs/M5373EVB.h b/include/configs/M5373EVB.h index a1bc32a..1991687 100644 --- a/include/configs/M5373EVB.h +++ b/include/configs/M5373EVB.h @@ -215,7 +215,6 @@ # define CONFIG_SYS_NAND_BASE CONFIG_SYS_CS2_BASE # define CONFIG_SYS_NAND_SIZE 1 # define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND_BASE } -# define NAND_MAX_CHIPS 1 # define NAND_ALLOW_ERASE_ALL 1 # define CONFIG_JFFS2_NAND 1 # define CONFIG_JFFS2_DEV "nand0" diff --git a/include/configs/MPC8313ERDB.h b/include/configs/MPC8313ERDB.h index fc3fa13..58a26e1 100644 --- a/include/configs/MPC8313ERDB.h +++ b/include/configs/MPC8313ERDB.h @@ -232,7 +232,6 @@ #endif #define CONFIG_SYS_MAX_NAND_DEVICE 1 -#define NAND_MAX_CHIPS 1 #define CONFIG_MTD_NAND_VERIFY_WRITE #define CONFIG_CMD_NAND 1 #define CONFIG_NAND_FSL_ELBC 1 diff --git a/include/configs/MPC8315ERDB.h b/include/configs/MPC8315ERDB.h index 48043c4..e4ada65 100644 --- a/include/configs/MPC8315ERDB.h +++ b/include/configs/MPC8315ERDB.h @@ -223,7 +223,6 @@ */ #define CONFIG_SYS_NAND_BASE 0xE0600000 /* 0xE0600000 */ #define CONFIG_SYS_MAX_NAND_DEVICE 1 -#define NAND_MAX_CHIPS 1 #define CONFIG_MTD_NAND_VERIFY_WRITE 1 #define CONFIG_CMD_NAND 1 #define CONFIG_NAND_FSL_ELBC 1 diff --git a/include/configs/MPC8360ERDK.h b/include/configs/MPC8360ERDK.h index a4f2862..c20f86a 100644 --- a/include/configs/MPC8360ERDK.h +++ b/include/configs/MPC8360ERDK.h @@ -211,7 +211,6 @@ #define CONFIG_CMD_NAND 1 #define CONFIG_NAND_FSL_UPM 1 #define CONFIG_SYS_MAX_NAND_DEVICE 1 -#define NAND_MAX_CHIPS 1 #define CONFIG_MTD_NAND_VERIFY_WRITE #define CONFIG_SYS_LBLAWBAR1_PRELIM CONFIG_SYS_NAND_BASE diff --git a/include/configs/MPC837XEMDS.h b/include/configs/MPC837XEMDS.h index d49155f..dbffb71 100644 --- a/include/configs/MPC837XEMDS.h +++ b/include/configs/MPC837XEMDS.h @@ -271,7 +271,6 @@ #define CONFIG_CMD_NAND 1 #define CONFIG_MTD_NAND_VERIFY_WRITE 1 #define CONFIG_SYS_MAX_NAND_DEVICE 1 -#define NAND_MAX_CHIPS 1 #define CONFIG_NAND_FSL_ELBC 1 #define CONFIG_SYS_NAND_BASE 0xE0600000 /* 0xE0600000 */ diff --git a/include/configs/MPC8536DS.h b/include/configs/MPC8536DS.h index 532c3df..505c48b 100644 --- a/include/configs/MPC8536DS.h +++ b/include/configs/MPC8536DS.h @@ -248,7 +248,6 @@ extern unsigned long get_board_ddr_clk(unsigned long dummy); CONFIG_SYS_NAND_BASE + 0x80000, \ CONFIG_SYS_NAND_BASE + 0xC0000} #define CONFIG_SYS_MAX_NAND_DEVICE 4 -#define NAND_MAX_CHIPS 1 #define CONFIG_MTD_NAND_VERIFY_WRITE #define CONFIG_CMD_NAND 1 #define CONFIG_NAND_FSL_ELBC 1 diff --git a/include/configs/MPC8572DS.h b/include/configs/MPC8572DS.h index 6c7a364..f84cc7e 100644 --- a/include/configs/MPC8572DS.h +++ b/include/configs/MPC8572DS.h @@ -267,7 +267,6 @@ extern unsigned long get_board_ddr_clk(unsigned long dummy); CONFIG_SYS_NAND_BASE + 0x80000,\ CONFIG_SYS_NAND_BASE + 0xC0000} #define CONFIG_SYS_MAX_NAND_DEVICE 4 -#define NAND_MAX_CHIPS 1 #define CONFIG_MTD_NAND_VERIFY_WRITE #define CONFIG_CMD_NAND 1 #define CONFIG_NAND_FSL_ELBC 1 diff --git a/include/configs/NC650.h b/include/configs/NC650.h index 423ca71..0b97f0c 100644 --- a/include/configs/NC650.h +++ b/include/configs/NC650.h @@ -250,7 +250,6 @@ * NAND flash support */ #define CONFIG_SYS_MAX_NAND_DEVICE 1 -#define NAND_MAX_CHIPS 1 /*----------------------------------------------------------------------- * SYPCR - System Protection Control 11-9 diff --git a/include/configs/NETPHONE.h b/include/configs/NETPHONE.h index 34de947..2d04d89 100644 --- a/include/configs/NETPHONE.h +++ b/include/configs/NETPHONE.h @@ -514,7 +514,6 @@ #define ADDR_COLUMN_PAGE 3 #define NAND_ChipID_UNKNOWN 0x00 #define NAND_MAX_FLOORS 1 -#define NAND_MAX_CHIPS 1 /* ALE = PD17, CLE = PE18, CE = PE20, F_RY_BY = PE31 */ #define NAND_DISABLE_CE(nand) \ diff --git a/include/configs/NETTA.h b/include/configs/NETTA.h index 004b3c8..34fdba5 100644 --- a/include/configs/NETTA.h +++ b/include/configs/NETTA.h @@ -633,7 +633,6 @@ #define ADDR_COLUMN_PAGE 3 #define NAND_ChipID_UNKNOWN 0x00 #define NAND_MAX_FLOORS 1 -#define NAND_MAX_CHIPS 1 /* ALE = PD3, CLE = PD4, CE = PD5, F_RY_BY = PC13 */ #define NAND_DISABLE_CE(nand) \ diff --git a/include/configs/NETTA2.h b/include/configs/NETTA2.h index 70995fa..4a27027 100644 --- a/include/configs/NETTA2.h +++ b/include/configs/NETTA2.h @@ -515,7 +515,6 @@ #define ADDR_COLUMN_PAGE 3 #define NAND_ChipID_UNKNOWN 0x00 #define NAND_MAX_FLOORS 1 -#define NAND_MAX_CHIPS 1 /* ALE = PD17, CLE = PE18, CE = PE20, F_RY_BY = PE31 */ #define NAND_DISABLE_CE(nand) \ diff --git a/include/configs/NETVIA.h b/include/configs/NETVIA.h index 87c920f..f97bdcb 100644 --- a/include/configs/NETVIA.h +++ b/include/configs/NETVIA.h @@ -411,7 +411,6 @@ #define ADDR_COLUMN_PAGE 3 #define NAND_ChipID_UNKNOWN 0x00 #define NAND_MAX_FLOORS 1 -#define NAND_MAX_CHIPS 1 #define NAND_DISABLE_CE(nand) \ do { \ diff --git a/include/configs/PLU405.h b/include/configs/PLU405.h index 11ce008..e9f1646 100644 --- a/include/configs/PLU405.h +++ b/include/configs/PLU405.h @@ -173,7 +173,6 @@ * NAND-FLASH stuff */ #define CONFIG_SYS_NAND_BASE_LIST {CONFIG_SYS_NAND_BASE} -#define NAND_MAX_CHIPS 1 #define CONFIG_SYS_MAX_NAND_DEVICE 1 /* Max number of NAND devices */ #define NAND_BIG_DELAY_US 25 diff --git a/include/configs/PMC440.h b/include/configs/PMC440.h index f9f1002..fc48bc1 100644 --- a/include/configs/PMC440.h +++ b/include/configs/PMC440.h @@ -505,7 +505,6 @@ * NAND FLASH *----------------------------------------------------------------------*/ #define CONFIG_SYS_MAX_NAND_DEVICE 1 -#define NAND_MAX_CHIPS 1 #define CONFIG_SYS_NAND_BASE (CONFIG_SYS_NAND_ADDR + CONFIG_SYS_NAND_CS) #define CONFIG_SYS_NAND_SELECT_DEVICE 1 /* nand driver supports mutipl. chips */ #define CONFIG_SYS_NAND_QUIET_TEST 1 diff --git a/include/configs/PPChameleonEVB.h b/include/configs/PPChameleonEVB.h index 09a9641..d4322b6 100644 --- a/include/configs/PPChameleonEVB.h +++ b/include/configs/PPChameleonEVB.h @@ -224,8 +224,6 @@ #define NAND_BIG_DELAY_US 25 #define CONFIG_SYS_MAX_NAND_DEVICE 2 /* Max number of NAND devices */ -#define NAND_MAX_CHIPS 1 - #define CONFIG_SYS_NAND0_CE (0x80000000 >> 1) /* our CE is GPIO1 */ #define CONFIG_SYS_NAND0_RDY (0x80000000 >> 4) /* our RDY is GPIO4 */ #define CONFIG_SYS_NAND0_CLE (0x80000000 >> 2) /* our CLE is GPIO2 */ diff --git a/include/configs/SXNI855T.h b/include/configs/SXNI855T.h index 7fc455b..9857bf6 100644 --- a/include/configs/SXNI855T.h +++ b/include/configs/SXNI855T.h @@ -206,7 +206,6 @@ #define NAND_ChipID_UNKNOWN 0x00 #define NAND_MAX_FLOORS 1 -#define NAND_MAX_CHIPS 1 /* DFBUSY is available on Port C, bit 12; 0 if busy */ #define NAND_WAIT_READY(nand) \ diff --git a/include/configs/TQM8272.h b/include/configs/TQM8272.h index 1915a73..9cac696 100644 --- a/include/configs/TQM8272.h +++ b/include/configs/TQM8272.h @@ -424,7 +424,6 @@ #define CONFIG_SYS_NAND3_BASE (CONFIG_SYS_NAND2_BASE + CONFIG_SYS_NAND_CS_DIST) #define CONFIG_SYS_MAX_NAND_DEVICE 4 /* Max number of NAND devices */ -#define NAND_MAX_CHIPS 1 #define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND0_BASE, \ CONFIG_SYS_NAND1_BASE, \ diff --git a/include/configs/TQM85xx.h b/include/configs/TQM85xx.h index 6d205a7..f5831eb 100644 --- a/include/configs/TQM85xx.h +++ b/include/configs/TQM85xx.h @@ -363,7 +363,6 @@ #define CONFIG_SYS_NAND3_BASE (CONFIG_SYS_NAND2_BASE + CONFIG_SYS_NAND_CS_DIST) #define CONFIG_SYS_MAX_NAND_DEVICE 2 /* Max number of NAND devices */ -#define NAND_MAX_CHIPS 1 #if (CONFIG_SYS_MAX_NAND_DEVICE == 1) #define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND0_BASE } diff --git a/include/configs/VCMA9.h b/include/configs/VCMA9.h index 0bc2f68..83d0d56 100644 --- a/include/configs/VCMA9.h +++ b/include/configs/VCMA9.h @@ -264,7 +264,6 @@ #define NAND_ChipID_UNKNOWN 0x00 #define NAND_MAX_FLOORS 1 -#define NAND_MAX_CHIPS 1 #define NAND_WAIT_READY(nand) NF_WaitRB() diff --git a/include/configs/VOH405.h b/include/configs/VOH405.h index 10ef620..f173bcc 100644 --- a/include/configs/VOH405.h +++ b/include/configs/VOH405.h @@ -159,7 +159,6 @@ *----------------------------------------------------------------------- */ #define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND_BASE } -#define NAND_MAX_CHIPS 1 #define CONFIG_SYS_MAX_NAND_DEVICE 1 /* Max number of NAND devices */ #define NAND_BIG_DELAY_US 25 diff --git a/include/configs/WUH405.h b/include/configs/WUH405.h index 01cdf3a..de6e12f 100644 --- a/include/configs/WUH405.h +++ b/include/configs/WUH405.h @@ -147,7 +147,6 @@ *----------------------------------------------------------------------- */ #define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND_BASE } -#define NAND_MAX_CHIPS 1 #define CONFIG_SYS_MAX_NAND_DEVICE 1 /* Max number of NAND devices */ #define NAND_BIG_DELAY_US 25 diff --git a/include/configs/acadia.h b/include/configs/acadia.h index 52ccdb5..9ffd86b 100644 --- a/include/configs/acadia.h +++ b/include/configs/acadia.h @@ -262,7 +262,6 @@ * NAND FLASH *----------------------------------------------------------------------*/ #define CONFIG_SYS_MAX_NAND_DEVICE 1 -#define NAND_MAX_CHIPS 1 #define CONFIG_SYS_NAND_BASE (CONFIG_SYS_NAND_ADDR + CONFIG_SYS_NAND_CS) #define CONFIG_SYS_NAND_SELECT_DEVICE 1 /* nand driver supports mutipl. chips */ diff --git a/include/configs/afeb9260.h b/include/configs/afeb9260.h index d63a1a0..e996bbd 100644 --- a/include/configs/afeb9260.h +++ b/include/configs/afeb9260.h @@ -97,7 +97,6 @@ #define DATAFLASH_TCHS (0x1 << 24) /* NAND flash */ -#define NAND_MAX_CHIPS 1 #define CONFIG_SYS_MAX_NAND_DEVICE 1 #define CONFIG_SYS_NAND_BASE 0x40000000 #define CONFIG_SYS_NAND_DBW_8 1 diff --git a/include/configs/alpr.h b/include/configs/alpr.h index 7ce8205..e6248e9 100644 --- a/include/configs/alpr.h +++ b/include/configs/alpr.h @@ -335,7 +335,6 @@ * NAND-FLASH stuff *-----------------------------------------------------------------------*/ #define CONFIG_SYS_MAX_NAND_DEVICE 4 -#define NAND_MAX_CHIPS CONFIG_SYS_MAX_NAND_DEVICE #define CONFIG_SYS_NAND_BASE 0xF0000000 /* NAND FLASH Base Address */ #define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND_BASE + 0, CONFIG_SYS_NAND_BASE + 2, \ CONFIG_SYS_NAND_BASE + 4, CONFIG_SYS_NAND_BASE + 6 } diff --git a/include/configs/at91cap9adk.h b/include/configs/at91cap9adk.h index b2baf1b..f1c5526 100644 --- a/include/configs/at91cap9adk.h +++ b/include/configs/at91cap9adk.h @@ -118,7 +118,6 @@ #define CONFIG_SYS_MAX_FLASH_BANKS 1 /* NAND flash */ -#define NAND_MAX_CHIPS 1 #define CONFIG_SYS_MAX_NAND_DEVICE 1 #define CONFIG_SYS_NAND_BASE 0x40000000 #define CONFIG_SYS_NAND_DBW_8 1 diff --git a/include/configs/at91rm9200dk.h b/include/configs/at91rm9200dk.h index c7e83cc..5a980d3 100644 --- a/include/configs/at91rm9200dk.h +++ b/include/configs/at91rm9200dk.h @@ -129,7 +129,6 @@ #define NAND_ChipID_UNKNOWN 0x00 #define NAND_MAX_FLOORS 1 -#define NAND_MAX_CHIPS 1 #define AT91_SMART_MEDIA_ALE (1 << 22) /* our ALE is AD22 */ #define AT91_SMART_MEDIA_CLE (1 << 21) /* our CLE is AD21 */ diff --git a/include/configs/at91sam9260ek.h b/include/configs/at91sam9260ek.h index 1538929..4501cae 100644 --- a/include/configs/at91sam9260ek.h +++ b/include/configs/at91sam9260ek.h @@ -100,7 +100,6 @@ #define DATAFLASH_TCHS (0x1 << 24) /* NAND flash */ -#define NAND_MAX_CHIPS 1 #define CONFIG_SYS_MAX_NAND_DEVICE 1 #define CONFIG_SYS_NAND_BASE 0x40000000 #define CONFIG_SYS_NAND_DBW_8 1 diff --git a/include/configs/at91sam9261ek.h b/include/configs/at91sam9261ek.h index 0016b4f..668fe3b 100644 --- a/include/configs/at91sam9261ek.h +++ b/include/configs/at91sam9261ek.h @@ -111,7 +111,6 @@ #define DATAFLASH_TCHS (0x1 << 24) /* NAND flash */ -#define NAND_MAX_CHIPS 1 #define CONFIG_SYS_MAX_NAND_DEVICE 1 #define CONFIG_SYS_NAND_BASE 0x40000000 #define CONFIG_SYS_NAND_DBW_8 1 diff --git a/include/configs/at91sam9263ek.h b/include/configs/at91sam9263ek.h index d9ebc87..c6603ff 100644 --- a/include/configs/at91sam9263ek.h +++ b/include/configs/at91sam9263ek.h @@ -123,7 +123,6 @@ #endif /* NAND flash */ -#define NAND_MAX_CHIPS 1 #define CONFIG_SYS_MAX_NAND_DEVICE 1 #define CONFIG_SYS_NAND_BASE 0x40000000 #define CONFIG_SYS_NAND_DBW_8 1 diff --git a/include/configs/at91sam9rlek.h b/include/configs/at91sam9rlek.h index 35fefc4..5bef1fe 100644 --- a/include/configs/at91sam9rlek.h +++ b/include/configs/at91sam9rlek.h @@ -104,7 +104,6 @@ #define CONFIG_SYS_NO_FLASH 1 /* NAND flash */ -#define NAND_MAX_CHIPS 1 #define CONFIG_SYS_MAX_NAND_DEVICE 1 #define CONFIG_SYS_NAND_BASE 0x40000000 #define CONFIG_SYS_NAND_DBW_8 1 diff --git a/include/configs/bamboo.h b/include/configs/bamboo.h index f3ffe1c..8c4127d 100644 --- a/include/configs/bamboo.h +++ b/include/configs/bamboo.h @@ -197,7 +197,6 @@ * NAND FLASH *----------------------------------------------------------------------*/ #define CONFIG_SYS_MAX_NAND_DEVICE 2 -#define NAND_MAX_CHIPS CONFIG_SYS_MAX_NAND_DEVICE #define CONFIG_SYS_NAND_BASE (CONFIG_SYS_NAND_ADDR + CONFIG_SYS_NAND_CS) #define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND_BASE, CONFIG_SYS_NAND_ADDR + 2 } #define CONFIG_SYS_NAND_SELECT_DEVICE 1 /* nand driver supports mutipl. chips */ diff --git a/include/configs/bf537-stamp.h b/include/configs/bf537-stamp.h index 1b54d3b..ac5aaa5 100644 --- a/include/configs/bf537-stamp.h +++ b/include/configs/bf537-stamp.h @@ -278,7 +278,6 @@ #define ADDR_COLUMN_PAGE 3 #define NAND_ChipID_UNKNOWN 0x00 #define NAND_MAX_FLOORS 1 -#define NAND_MAX_CHIPS 1 #define BFIN_NAND_READY PF3 #define NAND_WAIT_READY(nand) \ diff --git a/include/configs/canyonlands.h b/include/configs/canyonlands.h index faf6304..d814012 100644 --- a/include/configs/canyonlands.h +++ b/include/configs/canyonlands.h @@ -234,7 +234,6 @@ * NAND-FLASH related *----------------------------------------------------------------------*/ #define CONFIG_SYS_MAX_NAND_DEVICE 1 -#define NAND_MAX_CHIPS 1 #define CONFIG_SYS_NAND_BASE (CONFIG_SYS_NAND_ADDR + CONFIG_SYS_NAND_CS) #define CONFIG_SYS_NAND_SELECT_DEVICE 1 /* nand driver supports mutipl. chips */ diff --git a/include/configs/csb637.h b/include/configs/csb637.h index 2df77cf..761c0dc 100644 --- a/include/configs/csb637.h +++ b/include/configs/csb637.h @@ -131,7 +131,6 @@ #define NAND_ChipID_UNKNOWN 0x00 #define NAND_MAX_FLOORS 1 -#define NAND_MAX_CHIPS 1 #define AT91_SMART_MEDIA_ALE (1 << 22) /* our ALE is AD22 */ #define AT91_SMART_MEDIA_CLE (1 << 21) /* our CLE is AD21 */ diff --git a/include/configs/davinci_dvevm.h b/include/configs/davinci_dvevm.h index 6885b2c..a727f56 100644 --- a/include/configs/davinci_dvevm.h +++ b/include/configs/davinci_dvevm.h @@ -127,7 +127,6 @@ #define CONFIG_SYS_NAND_BASE 0x02000000 #define CONFIG_SYS_NAND_HW_ECC #define CONFIG_SYS_MAX_NAND_DEVICE 1 /* Max number of NAND devices */ -#define NAND_MAX_CHIPS 1 #define CONFIG_ENV_OFFSET 0x0 /* Block 0--not used by bootcode */ #define DEF_BOOTM "" #elif defined(CONFIG_SYS_USE_NOR) diff --git a/include/configs/davinci_schmoogie.h b/include/configs/davinci_schmoogie.h index 8d7bcf5..22d3808 100644 --- a/include/configs/davinci_schmoogie.h +++ b/include/configs/davinci_schmoogie.h @@ -89,7 +89,6 @@ #define CONFIG_SYS_NAND_BASE 0x02000000 #define CONFIG_SYS_NAND_HW_ECC #define CONFIG_SYS_MAX_NAND_DEVICE 1 /* Max number of NAND devices */ -#define NAND_MAX_CHIPS 1 #define CONFIG_ENV_OFFSET 0x0 /* Block 0--not used by bootcode */ /*=====================*/ /* Board related stuff */ diff --git a/include/configs/davinci_sffsdr.h b/include/configs/davinci_sffsdr.h index e9cd5a6..875bab6 100644 --- a/include/configs/davinci_sffsdr.h +++ b/include/configs/davinci_sffsdr.h @@ -85,7 +85,6 @@ #define CONFIG_SYS_NAND_BASE 0x02000000 #define CONFIG_SYS_NAND_HW_ECC #define CONFIG_SYS_MAX_NAND_DEVICE 1 /* Max number of NAND devices */ -#define NAND_MAX_CHIPS 1 #define CONFIG_ENV_OFFSET 0x0 /* Block 0--not used by bootcode */ /* I2C switch definitions for PCA9543 chip */ #define CONFIG_SYS_I2C_PCA9543_ADDR 0x70 diff --git a/include/configs/davinci_sonata.h b/include/configs/davinci_sonata.h index 381eeb7..47ab27a 100644 --- a/include/configs/davinci_sonata.h +++ b/include/configs/davinci_sonata.h @@ -122,7 +122,6 @@ #define CONFIG_SYS_NAND_BASE 0x02000000 #define CONFIG_SYS_NAND_HW_ECC #define CONFIG_SYS_MAX_NAND_DEVICE 1 /* Max number of NAND devices */ -#define NAND_MAX_CHIPS 1 #define CONFIG_ENV_OFFSET 0x0 /* Block 0--not used by bootcode */ #define DEF_BOOTM "" #elif defined(CONFIG_SYS_USE_NOR) diff --git a/include/configs/delta.h b/include/configs/delta.h index 08b28ca..fd97b74 100644 --- a/include/configs/delta.h +++ b/include/configs/delta.h @@ -258,7 +258,6 @@ #define NAND_ChipID_UNKNOWN 0x00 #define NAND_MAX_FLOORS 1 -#define NAND_MAX_CHIPS 1 #define CONFIG_SYS_NO_FLASH 1 diff --git a/include/configs/kilauea.h b/include/configs/kilauea.h index b943f31..4d3ccf5 100644 --- a/include/configs/kilauea.h +++ b/include/configs/kilauea.h @@ -214,7 +214,6 @@ * NAND FLASH *----------------------------------------------------------------------*/ #define CONFIG_SYS_MAX_NAND_DEVICE 1 -#define NAND_MAX_CHIPS 1 #define CONFIG_SYS_NAND_BASE (CONFIG_SYS_NAND_ADDR + CONFIG_SYS_NAND_CS) #define CONFIG_SYS_NAND_SELECT_DEVICE 1 /* nand driver supports mutipl. chips */ diff --git a/include/configs/netstar.h b/include/configs/netstar.h index dda6597..fab22d1 100644 --- a/include/configs/netstar.h +++ b/include/configs/netstar.h @@ -120,7 +120,6 @@ * NAND flash */ #define CONFIG_SYS_MAX_NAND_DEVICE 1 -#define NAND_MAX_CHIPS 1 #define CONFIG_SYS_NAND_BASE 0x04000000 + (2 << 23) #define NAND_ALLOW_ERASE_ALL 1 diff --git a/include/configs/omap2420h4.h b/include/configs/omap2420h4.h index d11868e..92df0b4 100644 --- a/include/configs/omap2420h4.h +++ b/include/configs/omap2420h4.h @@ -163,7 +163,6 @@ #define NAND_ChipID_UNKNOWN 0x00 #define NAND_MAX_FLOORS 1 -#define NAND_MAX_CHIPS 1 #define WRITE_NAND_COMMAND(d, adr) do {*(volatile u16 *)0x6800A07C = d;} while(0) #define WRITE_NAND_ADDRESS(d, adr) do {*(volatile u16 *)0x6800A080 = d;} while(0) diff --git a/include/configs/pdnb3.h b/include/configs/pdnb3.h index 8b7890e..f8aac1a 100644 --- a/include/configs/pdnb3.h +++ b/include/configs/pdnb3.h @@ -264,7 +264,6 @@ * NAND-FLASH stuff */ #define CONFIG_SYS_MAX_NAND_DEVICE 1 -#define NAND_MAX_CHIPS 1 #define CONFIG_SYS_NAND_BASE 0x51000000 /* NAND FLASH Base Address */ #endif diff --git a/include/configs/quad100hd.h b/include/configs/quad100hd.h index 0f7fca3..3ea854b 100644 --- a/include/configs/quad100hd.h +++ b/include/configs/quad100hd.h @@ -224,7 +224,6 @@ #define CONFIG_SYS_NAND_CE 24 /* our CE is GPIO24 */ #define CONFIG_SYS_NAND_CLE 31 /* our CLE is GPIO31 */ #define CONFIG_SYS_NAND_ALE 30 /* our ALE is GPIO30 */ -#define NAND_MAX_CHIPS 1 #define CONFIG_SYS_MAX_NAND_DEVICE 1 #endif diff --git a/include/configs/sbc2410x.h b/include/configs/sbc2410x.h index d7a6ae4..bf4a14e 100644 --- a/include/configs/sbc2410x.h +++ b/include/configs/sbc2410x.h @@ -209,7 +209,6 @@ #define NAND_ChipID_UNKNOWN 0x00 #define NAND_MAX_FLOORS 1 -#define NAND_MAX_CHIPS 1 #define NAND_WAIT_READY(nand) NF_WaitRB() #define NAND_DISABLE_CE(nand) NF_SetCE(NFCE_HIGH) diff --git a/include/configs/sc3.h b/include/configs/sc3.h index d152a96..515b097 100644 --- a/include/configs/sc3.h +++ b/include/configs/sc3.h @@ -424,7 +424,6 @@ extern unsigned long offsetOfEnvironment; * NAND-FLASH stuff */ #define CONFIG_SYS_MAX_NAND_DEVICE 1 -#define NAND_MAX_CHIPS 1 #define CONFIG_SYS_NAND_BASE 0x77D00000 diff --git a/include/configs/sequoia.h b/include/configs/sequoia.h index 9321bdc..a3e2fce 100644 --- a/include/configs/sequoia.h +++ b/include/configs/sequoia.h @@ -373,7 +373,6 @@ * NAND FLASH */ #define CONFIG_SYS_MAX_NAND_DEVICE 1 -#define NAND_MAX_CHIPS 1 #define CONFIG_SYS_NAND_BASE (CONFIG_SYS_NAND_ADDR + CONFIG_SYS_NAND_CS) #define CONFIG_SYS_NAND_SELECT_DEVICE 1 /* nand driver supports mutipl. chips */ diff --git a/include/configs/smdk6400.h b/include/configs/smdk6400.h index 1784cc6..57c82d1 100644 --- a/include/configs/smdk6400.h +++ b/include/configs/smdk6400.h @@ -227,7 +227,6 @@ /* NAND configuration */ #define CONFIG_SYS_MAX_NAND_DEVICE 1 #define CONFIG_SYS_NAND_BASE 0x70200010 -#define NAND_MAX_CHIPS 1 #define CONFIG_SYS_S3C_NAND_HWECC #define CONFIG_SYS_NAND_SKIP_BAD_DOT_I 1 /* ".i" read skips bad blocks */ diff --git a/include/configs/socrates.h b/include/configs/socrates.h index cbf04e3..becd13e 100644 --- a/include/configs/socrates.h +++ b/include/configs/socrates.h @@ -186,7 +186,6 @@ #define CONFIG_SYS_NAND_BASE (CONFIG_SYS_FPGA_BASE + 0x70) #define CONFIG_SYS_MAX_NAND_DEVICE 1 -#define NAND_MAX_CHIPS 1 #define CONFIG_CMD_NAND /* LIME GDC */ diff --git a/include/configs/stxxtc.h b/include/configs/stxxtc.h index bc078cf..5a5f772 100644 --- a/include/configs/stxxtc.h +++ b/include/configs/stxxtc.h @@ -464,7 +464,6 @@ #define ADDR_COLUMN_PAGE 3 #define NAND_ChipID_UNKNOWN 0x00 #define NAND_MAX_FLOORS 1 -#define NAND_MAX_CHIPS 1 /* ALE = PC15, CLE = PB23, CE = PA7, F_RY_BY = PA6 */ #define NAND_DISABLE_CE(nand) \ diff --git a/include/configs/zylonite.h b/include/configs/zylonite.h index 53397d8..f30eca1 100644 --- a/include/configs/zylonite.h +++ b/include/configs/zylonite.h @@ -227,7 +227,6 @@ #define NAND_ChipID_UNKNOWN 0x00 #define NAND_MAX_FLOORS 1 -#define NAND_MAX_CHIPS 1 #define CONFIG_SYS_NO_FLASH 1 diff --git a/include/linux/mtd/bbm.h b/include/linux/mtd/bbm.h index abf8f1a..7db2546 100644 --- a/include/linux/mtd/bbm.h +++ b/include/linux/mtd/bbm.h @@ -18,8 +18,8 @@ #define __LINUX_MTD_BBM_H /* The maximum number of NAND chips in an array */ -#ifndef NAND_MAX_CHIPS -#define NAND_MAX_CHIPS 8 +#ifndef CONFIG_SYS_NAND_MAX_CHIPS +#define CONFIG_SYS_NAND_MAX_CHIPS 1 #endif /** @@ -48,10 +48,10 @@ */ struct nand_bbt_descr { int options; - int pages[NAND_MAX_CHIPS]; + int pages[CONFIG_SYS_NAND_MAX_CHIPS]; int offs; int veroffs; - uint8_t version[NAND_MAX_CHIPS]; + uint8_t version[CONFIG_SYS_NAND_MAX_CHIPS]; int len; int maxblocks; int reserved_block_code; diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 24ad2bd..a4ad571 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -46,11 +46,6 @@ extern void nand_release (struct mtd_info *mtd); /* Internal helper for board drivers which need to override command function */ extern void nand_wait_ready(struct mtd_info *mtd); -/* The maximum number of NAND chips in an array */ -#ifndef NAND_MAX_CHIPS -#define NAND_MAX_CHIPS 8 -#endif - /* This constant declares the max. oobsize / page, which * is supported now. If you add a chip with bigger oobsize/page * adjust this accordingly. @@ -477,10 +472,6 @@ struct nand_manufacturers { extern struct nand_flash_dev nand_flash_ids[]; extern struct nand_manufacturers nand_manuf_ids[]; -#ifndef NAND_MAX_CHIPS -#define NAND_MAX_CHIPS 8 -#endif - extern int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd); extern int nand_update_bbt(struct mtd_info *mtd, loff_t offs); extern int nand_default_bbt(struct mtd_info *mtd); diff --git a/include/linux/mtd/nand_legacy.h b/include/linux/mtd/nand_legacy.h index 99eafbb..4334448 100644 --- a/include/linux/mtd/nand_legacy.h +++ b/include/linux/mtd/nand_legacy.h @@ -40,6 +40,11 @@ #error This module is for the legacy NAND support #endif +/* The maximum number of NAND chips in an array */ +#ifndef CONFIG_SYS_NAND_MAX_CHIPS +#define CONFIG_SYS_NAND_MAX_CHIPS 1 +#endif + /* * Standard NAND flash commands */ -- cgit v0.10.2 From 389e6620e2271096df3316917528003627db4021 Mon Sep 17 00:00:00 2001 From: Schlaegl Manfred jun Date: Tue, 20 Jan 2009 16:57:55 +0100 Subject: nand read.jffs2 (nand_legacy) in common/cmd_nand.c Error with CONFIG_NAND_LEGACY in common/cmd_nand.c: With current code "nand read.jffs2s" (read and skip bad blocks) is always interpreted as "nand read.jffs2" (read and fill bad blocks with 0xff). This is because ".jffs2" is tested before ".jffs2s" and only the first two characters are compared. Correction: Test for ".jffs2s" first and compare the first 7 characters. Signed-off-by: Scott Wood diff --git a/common/cmd_nand.c b/common/cmd_nand.c index a240c37..3d434e8 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -856,13 +856,12 @@ int do_nand (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) (u_char *) addr); } return ret; - } else if (cmdtail && !strncmp (cmdtail, ".jffs2", 2)) - cmd |= NANDRW_JFFS2; /* skip bad blocks */ - else if (cmdtail && !strncmp (cmdtail, ".jffs2s", 2)) { + } else if (cmdtail && !strncmp (cmdtail, ".jffs2s", 7)) { cmd |= NANDRW_JFFS2; /* skip bad blocks (on read too) */ if (cmd & NANDRW_READ) cmd |= NANDRW_JFFS2_SKIP; /* skip bad blocks (on read too) */ - } + } else if (cmdtail && !strncmp (cmdtail, ".jffs2", 2)) + cmd |= NANDRW_JFFS2; /* skip bad blocks */ #ifdef SXNI855T /* need ".e" same as ".j" for compatibility with older units */ else if (cmdtail && !strcmp (cmdtail, ".e")) -- cgit v0.10.2 From d4bade8d77aa20e2846fa4accff0e7fa7961a134 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sun, 18 Jan 2009 19:46:06 -0500 Subject: nand: fixup printf modifiers to match types used Signed-off-by: Mike Frysinger Signed-off-by: Scott Wood diff --git a/common/cmd_nand.c b/common/cmd_nand.c index 3d434e8..aedf8a6 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -160,7 +160,7 @@ out: if (*size == nand->size) puts("whole chip\n"); else - printf("offset 0x%lx, size 0x%x\n", *off, *size); + printf("offset 0x%lx, size 0x%zx\n", *off, *size); return 0; } @@ -398,7 +398,7 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) return 1; } - printf(" %d bytes %s: %s\n", size, + printf(" %zu bytes %s: %s\n", size, read ? "read" : "written", ret ? "ERROR" : "OK"); return ret == 0 ? 0 : 1; diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c index 77da53e..6ba52b3 100644 --- a/drivers/mtd/nand/nand_util.c +++ b/drivers/mtd/nand/nand_util.c @@ -495,7 +495,7 @@ int nand_write_skip_bad(nand_info_t *nand, size_t offset, size_t *length, if (len_incl_bad == *length) { rval = nand_write (nand, offset, length, buffer); if (rval != 0) - printf ("NAND write to offset %x failed %d\n", + printf ("NAND write to offset %zx failed %d\n", offset, rval); return rval; @@ -506,7 +506,7 @@ int nand_write_skip_bad(nand_info_t *nand, size_t offset, size_t *length, size_t write_size; if (nand_block_isbad (nand, offset & ~(nand->erasesize - 1))) { - printf ("Skip bad block 0x%08x\n", + printf ("Skip bad block 0x%08zx\n", offset & ~(nand->erasesize - 1)); offset += nand->erasesize - block_offset; continue; @@ -519,7 +519,7 @@ int nand_write_skip_bad(nand_info_t *nand, size_t offset, size_t *length, rval = nand_write (nand, offset, &write_size, p_buffer); if (rval != 0) { - printf ("NAND write to offset %x failed %d\n", + printf ("NAND write to offset %zx failed %d\n", offset, rval); *length -= left_to_write; return rval; @@ -565,7 +565,7 @@ int nand_read_skip_bad(nand_info_t *nand, size_t offset, size_t *length, if (len_incl_bad == *length) { rval = nand_read (nand, offset, length, buffer); if (rval != 0) - printf ("NAND read from offset %x failed %d\n", + printf ("NAND read from offset %zx failed %d\n", offset, rval); return rval; @@ -576,7 +576,7 @@ int nand_read_skip_bad(nand_info_t *nand, size_t offset, size_t *length, size_t read_length; if (nand_block_isbad (nand, offset & ~(nand->erasesize - 1))) { - printf ("Skipping bad block 0x%08x\n", + printf ("Skipping bad block 0x%08zx\n", offset & ~(nand->erasesize - 1)); offset += nand->erasesize - block_offset; continue; @@ -589,7 +589,7 @@ int nand_read_skip_bad(nand_info_t *nand, size_t offset, size_t *length, rval = nand_read (nand, offset, &read_length, p_buffer); if (rval != 0) { - printf ("NAND read from offset %x failed %d\n", + printf ("NAND read from offset %zx failed %d\n", offset, rval); *length -= left_to_read; return rval; -- cgit v0.10.2