|
@@ -940,7 +940,7 @@ static int onenand_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs,
|
|
|
u_char *eccbuf, struct nand_oobinfo *oobsel)
|
|
|
{
|
|
|
struct onenand_chip *this = mtd->priv;
|
|
|
- unsigned char buffer[MAX_ONENAND_PAGESIZE], *pbuf;
|
|
|
+ unsigned char *pbuf;
|
|
|
size_t total_len, len;
|
|
|
int i, written = 0;
|
|
|
int ret = 0;
|
|
@@ -975,7 +975,7 @@ static int onenand_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs,
|
|
|
/* Loop until all keve's data has been written */
|
|
|
len = 0;
|
|
|
while (count) {
|
|
|
- pbuf = buffer;
|
|
|
+ pbuf = this->page_buf;
|
|
|
/*
|
|
|
* If the given tuple is >= pagesize then
|
|
|
* write it out from the iov
|
|
@@ -995,7 +995,7 @@ static int onenand_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs,
|
|
|
int cnt = 0, thislen;
|
|
|
while (cnt < mtd->oobblock) {
|
|
|
thislen = min_t(int, mtd->oobblock - cnt, vecs->iov_len - len);
|
|
|
- memcpy(buffer + cnt, vecs->iov_base + len, thislen);
|
|
|
+ memcpy(this->page_buf + cnt, vecs->iov_base + len, thislen);
|
|
|
cnt += thislen;
|
|
|
len += thislen;
|
|
|
|
|
@@ -1296,6 +1296,12 @@ static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
|
|
|
|
|
|
/* Block lock scheme */
|
|
|
for (block = start; 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);
|
|
|
/* Write unlock command */
|
|
@@ -1309,10 +1315,6 @@ static 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, 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))
|
|
@@ -1346,7 +1348,6 @@ static void onenand_print_device_info(int device)
|
|
|
|
|
|
static const struct onenand_manufacturers onenand_manuf_ids[] = {
|
|
|
{ONENAND_MFR_SAMSUNG, "Samsung"},
|
|
|
- {ONENAND_MFR_UNKNOWN, "Unknown"}
|
|
|
};
|
|
|
|
|
|
/**
|
|
@@ -1357,17 +1358,22 @@ 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; i < size; i++)
|
|
|
if (manuf == onenand_manuf_ids[i].id)
|
|
|
break;
|
|
|
- }
|
|
|
|
|
|
- printk(KERN_DEBUG "OneNAND Manufacturer: %s (0x%0x)\n",
|
|
|
- onenand_manuf_ids[i].name, manuf);
|
|
|
+ if (i < size)
|
|
|
+ name = onenand_manuf_ids[i].name;
|
|
|
+ else
|
|
|
+ name = "Unknown";
|
|
|
+
|
|
|
+ printk(KERN_DEBUG "OneNAND Manufacturer: %s (0x%0x)\n", name, manuf);
|
|
|
|
|
|
- return (i != ONENAND_MFR_UNKNOWN);
|
|
|
+ return (i == size);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -1513,6 +1519,18 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
|
|
|
this->read_bufferram = onenand_sync_read_bufferram;
|
|
|
}
|
|
|
|
|
|
+ /* Allocate buffers, if necessary */
|
|
|
+ if (!this->page_buf) {
|
|
|
+ size_t len;
|
|
|
+ len = mtd->oobblock + mtd->oobsize;
|
|
|
+ this->page_buf = kmalloc(len, GFP_KERNEL);
|
|
|
+ if (!this->page_buf) {
|
|
|
+ printk(KERN_ERR "onenand_scan(): Can't allocate page_buf\n");
|
|
|
+ return -ENOMEM;
|
|
|
+ }
|
|
|
+ this->options |= ONENAND_PAGEBUF_ALLOC;
|
|
|
+ }
|
|
|
+
|
|
|
this->state = FL_READY;
|
|
|
init_waitqueue_head(&this->wq);
|
|
|
spin_lock_init(&this->chip_lock);
|
|
@@ -1574,12 +1592,21 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
|
|
|
*/
|
|
|
void onenand_release(struct mtd_info *mtd)
|
|
|
{
|
|
|
+ struct onenand_chip *this = mtd->priv;
|
|
|
+
|
|
|
#ifdef CONFIG_MTD_PARTITIONS
|
|
|
/* Deregister partitions */
|
|
|
del_mtd_partitions (mtd);
|
|
|
#endif
|
|
|
/* Deregister the device */
|
|
|
del_mtd_device (mtd);
|
|
|
+
|
|
|
+ /* Free bad block table memory, if allocated */
|
|
|
+ if (this->bbm)
|
|
|
+ kfree(this->bbm);
|
|
|
+ /* Buffer allocated by onenand_scan */
|
|
|
+ if (this->options & ONENAND_PAGEBUF_ALLOC)
|
|
|
+ kfree(this->page_buf);
|
|
|
}
|
|
|
|
|
|
EXPORT_SYMBOL_GPL(onenand_scan);
|