WS cleanup: remove SPACE(s) followed by TAB
[platform/kernel/u-boot.git] / drivers / mtd / onenand / onenand_base.c
index 24e02c2..46aeef2 100644 (file)
  */
 
 #include <common.h>
-#include <linux/mtd/compat.h>
+#include <log.h>
+#include <watchdog.h>
+#include <dm/devres.h>
+#include <linux/bitops.h>
+#include <linux/compat.h>
 #include <linux/mtd/mtd.h>
+#include "linux/mtd/flashchip.h"
 #include <linux/mtd/onenand.h>
 
 #include <asm/io.h>
-#include <asm/errno.h>
+#include <linux/errno.h>
 #include <malloc.h>
 
 /* It should access 16-bit instead of 8-bit */
@@ -91,7 +96,13 @@ static struct nand_ecclayout onenand_oob_32 = {
        .oobfree        = { {2, 3}, {14, 2}, {18, 3}, {30, 2} }
 };
 
-static const unsigned char ffchars[] = {
+/*
+ * Warning! This array is used with the memcpy_16() function, thus
+ * it must be aligned to 2 bytes. GCC can make this array unaligned
+ * as the array is made of unsigned char, which memcpy16() doesn't
+ * like and will cause unaligned access.
+ */
+static const unsigned char __aligned(2) ffchars[] = {
        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 16 */
        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
@@ -367,7 +378,7 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr,
                this->write_word(value,
                                 this->base + ONENAND_REG_START_ADDRESS2);
 
-               if (ONENAND_IS_MLC(this))
+               if (ONENAND_IS_4KB_PAGE(this))
                        ONENAND_SET_BUFFERRAM0(this);
                else
                        /* Switch to the next data buffer */
@@ -395,7 +406,7 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr,
                case FLEXONENAND_CMD_RECOVER_LSB:
                case ONENAND_CMD_READ:
                case ONENAND_CMD_READOOB:
-                       if (ONENAND_IS_MLC(this))
+                       if (ONENAND_IS_4KB_PAGE(this))
                                dataram = ONENAND_SET_BUFFERRAM0(this);
                        else
                                dataram = ONENAND_SET_NEXT_BUFFERRAM(this);
@@ -460,15 +471,18 @@ static int onenand_read_ecc(struct onenand_chip *this)
 static int onenand_wait(struct mtd_info *mtd, int state)
 {
        struct onenand_chip *this = mtd->priv;
-       unsigned int flags = ONENAND_INT_MASTER;
        unsigned int interrupt = 0;
        unsigned int ctrl;
 
-       while (1) {
+       /* Wait at most 20ms ... */
+       u32 timeo = (CONFIG_SYS_HZ * 20) / 1000;
+       u32 time_start = get_timer(0);
+       do {
+               WATCHDOG_RESET();
+               if (get_timer(time_start) > timeo)
+                       return -EIO;
                interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT);
-               if (interrupt & flags)
-                       break;
-       }
+       } while ((interrupt & ONENAND_INT_MASTER) == 0);
 
        ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS);
 
@@ -632,10 +646,6 @@ static int onenand_check_bufferram(struct mtd_info *mtd, loff_t addr)
        int blockpage, found = 0;
        unsigned int i;
 
-#ifdef CONFIG_S3C64XX
-       return 0;
-#endif
-
        if (ONENAND_IS_2PLANE(this))
                blockpage = onenand_get_2x_blockpage(mtd, addr);
        else
@@ -747,7 +757,7 @@ static void onenand_release_device(struct mtd_info *mtd)
 }
 
 /**
- * onenand_transfer_auto_oob - [Internal] oob auto-placement transfer
+ * onenand_transfer_auto_oob - [INTERN] oob auto-placement transfer
  * @param mtd          MTD device structure
  * @param buf          destination address
  * @param column       oob offset to read from
@@ -765,7 +775,8 @@ static int onenand_transfer_auto_oob(struct mtd_info *mtd, uint8_t *buf,
        uint8_t *oob_buf = this->oob_buf;
 
        free = this->ecclayout->oobfree;
-       for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free->length; i++, free++) {
+       for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES_LARGE && free->length;
+            i++, free++) {
                if (readcol >= lastgap)
                        readcol += free->offset - lastgap;
                if (readend >= lastgap)
@@ -774,7 +785,8 @@ static int onenand_transfer_auto_oob(struct mtd_info *mtd, uint8_t *buf,
        }
        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++) {
+       for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES_LARGE && free->length;
+            i++, free++) {
                int free_end = free->offset + free->length;
                if (free->offset < readend && free_end > readcol) {
                        int st = max_t(int,free->offset,readcol);
@@ -811,7 +823,7 @@ static int onenand_recover_lsb(struct mtd_info *mtd, loff_t addr, int status)
                return status;
 
        /* check if we failed due to uncorrectable error */
-       if (status != -EBADMSG && status != ONENAND_BBT_READ_ECC_ERROR)
+       if (!mtd_is_eccerr(status) && status != ONENAND_BBT_READ_ECC_ERROR)
                return status;
 
        /* check if address lies in MLC region */
@@ -849,9 +861,10 @@ 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);
+       pr_debug("onenand_read_ops_nolock: from = 0x%08x, len = %i\n",
+                (unsigned int) from, (int) len);
 
-       if (ops->mode == MTD_OOB_AUTO)
+       if (ops->mode == MTD_OPS_AUTO_OOB)
                oobsize = this->ecclayout->oobavail;
        else
                oobsize = mtd->oobsize;
@@ -893,7 +906,7 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from,
        while (!ret) {
                /* If there is more to load then start next load */
                from += thislen;
-               if (!ONENAND_IS_MLC(this) && read + thislen < len) {
+               if (!ONENAND_IS_4KB_PAGE(this) && read + thislen < len) {
                        this->main_buf = buf + thislen;
                        this->command(mtd, ONENAND_CMD_READ, from, writesize);
                        /*
@@ -918,7 +931,7 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from,
                        thisooblen = oobsize - oobcolumn;
                        thisooblen = min_t(int, thisooblen, ooblen - oobread);
 
-                       if (ops->mode == MTD_OOB_AUTO)
+                       if (ops->mode == MTD_OPS_AUTO_OOB)
                                onenand_transfer_auto_oob(mtd, oobbuf, oobcolumn, thisooblen);
                        else
                                this->read_bufferram(mtd, 0, ONENAND_SPARERAM, oobbuf, oobcolumn, thisooblen);
@@ -927,13 +940,13 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from,
                        oobcolumn = 0;
                }
 
-               if (ONENAND_IS_MLC(this) && (read + thislen < len)) {
+               if (ONENAND_IS_4KB_PAGE(this) && (read + thislen < len)) {
                        this->command(mtd, ONENAND_CMD_READ, from, writesize);
                        ret = this->wait(mtd, FL_READING);
                        if (unlikely(ret))
                                ret = onenand_recover_lsb(mtd, from, ret);
                        onenand_update_bufferram(mtd, from, !ret);
-                       if (ret == -EBADMSG)
+                       if (mtd_is_eccerr(ret))
                                ret = 0;
                }
 
@@ -944,17 +957,17 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from,
                /* Set up for next read from bufferRAM */
                if (unlikely(boundary))
                        this->write_word(ONENAND_DDP_CHIP1, this->base + ONENAND_REG_START_ADDRESS2);
-               if (!ONENAND_IS_MLC(this))
+               if (!ONENAND_IS_4KB_PAGE(this))
                        ONENAND_SET_NEXT_BUFFERRAM(this);
                buf += thislen;
                thislen = min_t(int, writesize, len - read);
                column = 0;
 
-               if (!ONENAND_IS_MLC(this)) {
+               if (!ONENAND_IS_4KB_PAGE(this)) {
                        /* Now wait for load */
                        ret = this->wait(mtd, FL_READING);
                        onenand_update_bufferram(mtd, from, !ret);
-                       if (ret == -EBADMSG)
+                       if (mtd_is_eccerr(ret))
                                ret = 0;
                }
        }
@@ -973,7 +986,8 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from,
        if (mtd->ecc_stats.failed - stats.failed)
                return -EBADMSG;
 
-       return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0;
+       /* return max bitflips per ecc step; ONENANDs correct 1 bit only */
+       return mtd->ecc_stats.corrected != stats.corrected ? 1 : 0;
 }
 
 /**
@@ -991,18 +1005,19 @@ static int onenand_read_oob_nolock(struct mtd_info *mtd, loff_t from,
        struct mtd_ecc_stats stats;
        int read = 0, thislen, column, oobsize;
        size_t len = ops->ooblen;
-       mtd_oob_mode_t mode = ops->mode;
+       unsigned int mode = ops->mode;
        u_char *buf = ops->oobbuf;
        int ret = 0, readcmd;
 
        from += ops->ooboffs;
 
-       MTDDEBUG(MTD_DEBUG_LEVEL3, "onenand_read_oob_nolock: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
+       pr_debug("onenand_read_oob_nolock: from = 0x%08x, len = %i\n",
+                (unsigned int) from, (int) len);
 
        /* Initialize return length value */
        ops->oobretlen = 0;
 
-       if (mode == MTD_OOB_AUTO)
+       if (mode == MTD_OPS_AUTO_OOB)
                oobsize = this->ecclayout->oobavail;
        else
                oobsize = mtd->oobsize;
@@ -1024,7 +1039,8 @@ static int onenand_read_oob_nolock(struct mtd_info *mtd, loff_t from,
 
        stats = mtd->ecc_stats;
 
-       readcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_READ : ONENAND_CMD_READOOB;
+       readcmd = ONENAND_IS_4KB_PAGE(this) ?
+               ONENAND_CMD_READ : ONENAND_CMD_READOOB;
 
        while (read < len) {
                thislen = oobsize - column;
@@ -1044,7 +1060,7 @@ static int onenand_read_oob_nolock(struct mtd_info *mtd, loff_t from,
                        break;
                }
 
-               if (mode == MTD_OOB_AUTO)
+               if (mode == MTD_OPS_AUTO_OOB)
                        onenand_transfer_auto_oob(mtd, buf, column, thislen);
                else
                        this->read_bufferram(mtd, 0, ONENAND_SPARERAM, buf, column, thislen);
@@ -1118,10 +1134,10 @@ int onenand_read_oob(struct mtd_info *mtd, loff_t from,
        int ret;
 
        switch (ops->mode) {
-       case MTD_OOB_PLACE:
-       case MTD_OOB_AUTO:
+       case MTD_OPS_PLACE_OOB:
+       case MTD_OPS_AUTO_OOB:
                break;
-       case MTD_OOB_RAW:
+       case MTD_OPS_RAW:
                /* Not implemented yet */
        default:
                return -EINVAL;
@@ -1147,15 +1163,18 @@ int onenand_read_oob(struct mtd_info *mtd, loff_t from,
 static int onenand_bbt_wait(struct mtd_info *mtd, int state)
 {
        struct onenand_chip *this = mtd->priv;
-       unsigned int flags = ONENAND_INT_MASTER;
        unsigned int interrupt;
        unsigned int ctrl;
 
-       while (1) {
+       /* Wait at most 20ms ... */
+       u32 timeo = (CONFIG_SYS_HZ * 20) / 1000;
+       u32 time_start = get_timer(0);
+       do {
+               WATCHDOG_RESET();
+               if (get_timer(time_start) > timeo)
+                       return ONENAND_BBT_READ_FATAL_ERROR;
                interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT);
-               if (interrupt & flags)
-                       break;
-       }
+       } while ((interrupt & ONENAND_INT_MASTER) == 0);
 
        /* To get correct interrupt status in timeout case */
        interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT);
@@ -1200,9 +1219,11 @@ 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);
+       pr_debug("onenand_bbt_read_oob: from = 0x%08x, len = %zi\n",
+                (unsigned int) from, len);
 
-       readcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_READ : ONENAND_CMD_READOOB;
+       readcmd = ONENAND_IS_4KB_PAGE(this) ?
+               ONENAND_CMD_READ : ONENAND_CMD_READOOB;
 
        /* Initialize return value */
        ops->oobretlen = 0;
@@ -1271,7 +1292,8 @@ static int onenand_verify_oob(struct mtd_info *mtd, const u_char *buf, loff_t to
        u_char *oob_buf = this->oob_buf;
        int status, i, readcmd;
 
-       readcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_READ : ONENAND_CMD_READOOB;
+       readcmd = ONENAND_IS_4KB_PAGE(this) ?
+               ONENAND_CMD_READ : ONENAND_CMD_READOOB;
 
        this->command(mtd, readcmd, to, mtd->oobsize);
        onenand_update_bufferram(mtd, to, 0);
@@ -1338,7 +1360,7 @@ static int onenand_verify(struct mtd_info *mtd, const u_char *buf, loff_t addr,
 #define NOTALIGNED(x)  ((x & (this->subpagesize - 1)) != 0)
 
 /**
- * onenand_fill_auto_oob - [Internal] oob auto-placement transfer
+ * onenand_fill_auto_oob - [INTERN] oob auto-placement transfer
  * @param mtd           MTD device structure
  * @param oob_buf       oob buffer
  * @param buf           source address
@@ -1356,7 +1378,8 @@ static int onenand_fill_auto_oob(struct mtd_info *mtd, u_char *oob_buf,
        unsigned int i;
 
        free = this->ecclayout->oobfree;
-       for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free->length; i++, free++) {
+       for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES_LARGE && free->length;
+            i++, free++) {
                if (writecol >= lastgap)
                        writecol += free->offset - lastgap;
                if (writeend >= lastgap)
@@ -1364,7 +1387,8 @@ static int onenand_fill_auto_oob(struct mtd_info *mtd, u_char *oob_buf,
                lastgap = free->offset + free->length;
        }
        free = this->ecclayout->oobfree;
-       for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free->length; i++, free++) {
+       for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES_LARGE && free->length;
+            i++, free++) {
                int free_end = free->offset + free->length;
                if (free->offset < writeend && free_end > writecol) {
                        int st = max_t(int,free->offset,writecol);
@@ -1399,25 +1423,20 @@ 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);
+       pr_debug("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;
        ops->oobretlen = 0;
 
-       /* Do not allow writes past end of device */
-       if (unlikely((to + len) > mtd->size)) {
-               printk(KERN_ERR "onenand_write_ops_nolock: Attempt write to past end of device\n");
-               return -EINVAL;
-       }
-
        /* Reject writes, which are not page aligned */
        if (unlikely(NOTALIGNED(to) || NOTALIGNED(len))) {
                printk(KERN_ERR "onenand_write_ops_nolock: Attempt to write not page aligned data\n");
                return -EINVAL;
        }
 
-       if (ops->mode == MTD_OOB_AUTO)
+       if (ops->mode == MTD_OPS_AUTO_OOB)
                oobsize = this->ecclayout->oobavail;
        else
                oobsize = mtd->oobsize;
@@ -1451,7 +1470,7 @@ static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to,
                        /* We send data to spare ram with oobsize
                         *                          * to prevent byte access */
                        memset(oobbuf, 0xff, mtd->oobsize);
-                       if (ops->mode == MTD_OOB_AUTO)
+                       if (ops->mode == MTD_OPS_AUTO_OOB)
                                onenand_fill_auto_oob(mtd, oobbuf, oob, oobcolumn, thisooblen);
                        else
                                memcpy(oobbuf + oobcolumn, oob, thisooblen);
@@ -1503,7 +1522,7 @@ static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to,
 }
 
 /**
- * onenand_write_oob_nolock - [Internal] OneNAND write out-of-band
+ * onenand_write_oob_nolock - [INTERN] OneNAND write out-of-band
  * @param mtd           MTD device structure
  * @param to            offset to write to
  * @param len           number of bytes to write
@@ -1522,16 +1541,17 @@ static int onenand_write_oob_nolock(struct mtd_info *mtd, loff_t to,
        u_char *oobbuf;
        size_t len = ops->ooblen;
        const u_char *buf = ops->oobbuf;
-       mtd_oob_mode_t mode = ops->mode;
+       unsigned int mode = ops->mode;
 
        to += ops->ooboffs;
 
-       MTDDEBUG(MTD_DEBUG_LEVEL3, "onenand_write_oob_nolock: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);
+       pr_debug("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;
 
-       if (mode == MTD_OOB_AUTO)
+       if (mode == MTD_OPS_AUTO_OOB)
                oobsize = this->ecclayout->oobavail;
        else
                oobsize = mtd->oobsize;
@@ -1560,7 +1580,8 @@ static int onenand_write_oob_nolock(struct mtd_info *mtd, loff_t to,
 
        oobbuf = this->oob_buf;
 
-       oobcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_PROG : ONENAND_CMD_PROGOOB;
+       oobcmd = ONENAND_IS_4KB_PAGE(this) ?
+               ONENAND_CMD_PROG : ONENAND_CMD_PROGOOB;
 
        /* Loop until all data write */
        while (written < len) {
@@ -1571,13 +1592,13 @@ static int onenand_write_oob_nolock(struct mtd_info *mtd, loff_t to,
                /* We send data to spare ram with oobsize
                 * to prevent byte access */
                memset(oobbuf, 0xff, mtd->oobsize);
-               if (mode == MTD_OOB_AUTO)
+               if (mode == MTD_OPS_AUTO_OOB)
                        onenand_fill_auto_oob(mtd, oobbuf, buf, column, thislen);
                else
                        memcpy(oobbuf + column, buf, thislen);
                this->write_bufferram(mtd, 0, ONENAND_SPARERAM, oobbuf, 0, mtd->oobsize);
 
-               if (ONENAND_IS_MLC(this)) {
+               if (ONENAND_IS_4KB_PAGE(this)) {
                        /* Set main area of DataRAM to 0xff*/
                        memset(this->page_buf, 0xff, mtd->writesize);
                        this->write_bufferram(mtd, 0, ONENAND_DATARAM,
@@ -1661,10 +1682,10 @@ int onenand_write_oob(struct mtd_info *mtd, loff_t to,
        int ret;
 
        switch (ops->mode) {
-       case MTD_OOB_PLACE:
-       case MTD_OOB_AUTO:
+       case MTD_OPS_PLACE_OOB:
+       case MTD_OPS_AUTO_OOB:
                break;
-       case MTD_OOB_RAW:
+       case MTD_OPS_RAW:
                /* Not implemented yet */
        default:
                return -EINVAL;
@@ -1717,16 +1738,9 @@ int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
        struct mtd_erase_region_info *region = NULL;
        unsigned int region_end = 0;
 
-       MTDDEBUG(MTD_DEBUG_LEVEL3, "onenand_erase: start = 0x%08x, len = %i\n",
+       pr_debug("onenand_erase: start = 0x%08x, len = %i\n",
                        (unsigned int) addr, len);
 
-       /* Do not allow erase past end of device */
-       if (unlikely((len + addr) > mtd->size)) {
-               MTDDEBUG(MTD_DEBUG_LEVEL0, "onenand_erase:"
-                                       "Erase past end of device\n");
-               return -EINVAL;
-       }
-
        if (FLEXONENAND(this)) {
                /* Find the eraseregion of this address */
                i = flexonenand_region(mtd, addr);
@@ -1740,8 +1754,7 @@ int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
                 * Erase region's start offset is always block start address.
                 */
                if (unlikely((addr - region->offset) & (block_size - 1))) {
-                       MTDDEBUG(MTD_DEBUG_LEVEL0, "onenand_erase:"
-                               " Unaligned address\n");
+                       pr_debug("onenand_erase:" " Unaligned address\n");
                        return -EINVAL;
                }
        } else {
@@ -1749,21 +1762,17 @@ int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
 
                /* Start address must align on block boundary */
                if (unlikely(addr & (block_size - 1))) {
-                       MTDDEBUG(MTD_DEBUG_LEVEL0, "onenand_erase:"
-                                               "Unaligned address\n");
+                       pr_debug("onenand_erase:" "Unaligned address\n");
                        return -EINVAL;
                }
        }
 
        /* Length must align on block boundary */
        if (unlikely(len & (block_size - 1))) {
-               MTDDEBUG (MTD_DEBUG_LEVEL0,
-                        "onenand_erase: Length not block aligned\n");
+               pr_debug("onenand_erase: Length not block aligned\n");
                return -EINVAL;
        }
 
-       instr->fail_addr = 0xffffffff;
-
        /* Grab the lock and see if the device is available */
        onenand_get_device(mtd, FL_ERASING);
 
@@ -1789,12 +1798,12 @@ int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
                /* Check, if it is write protected */
                if (ret) {
                        if (ret == -EPERM)
-                               MTDDEBUG (MTD_DEBUG_LEVEL0, "onenand_erase: "
-                                         "Device is write protected!!!\n");
+                               pr_debug("onenand_erase: "
+                                        "Device is write protected!!!\n");
                        else
-                               MTDDEBUG (MTD_DEBUG_LEVEL0, "onenand_erase: "
-                                         "Failed erase, block %d\n",
-                                       onenand_block(this, addr));
+                               pr_debug("onenand_erase: "
+                                        "Failed erase, block %d\n",
+                                        onenand_block(this, addr));
                        instr->state = MTD_ERASE_FAILED;
                        instr->fail_addr = addr;
 
@@ -1845,7 +1854,7 @@ erase_exit:
  */
 void onenand_sync(struct mtd_info *mtd)
 {
-       MTDDEBUG (MTD_DEBUG_LEVEL3, "onenand_sync: called\n");
+       pr_debug("onenand_sync: called\n");
 
        /* Grab the lock and see if the device is available */
        onenand_get_device(mtd, FL_SYNCING);
@@ -1889,7 +1898,7 @@ static int onenand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
        struct bbm_info *bbm = this->bbm;
        u_char buf[2] = {0, 0};
        struct mtd_oob_ops ops = {
-               .mode = MTD_OOB_PLACE,
+               .mode = MTD_OPS_PLACE_OOB,
                .ooblen = 2,
                .oobbuf = buf,
                .ooboffs = 0,
@@ -1926,7 +1935,10 @@ int onenand_block_markbad(struct mtd_info *mtd, loff_t ofs)
                return ret;
        }
 
+       onenand_get_device(mtd, FL_WRITING);
        ret = this->block_markbad(mtd, ofs);
+       onenand_release_device(mtd);
+
        return ret;
 }
 
@@ -1943,16 +1955,10 @@ static int onenand_do_lock_cmd(struct mtd_info *mtd, loff_t ofs, size_t len, int
 {
        struct onenand_chip *this = mtd->priv;
        int start, end, block, value, status;
-       int wp_status_mask;
 
        start = onenand_block(this, ofs);
        end = onenand_block(this, ofs + len);
 
-       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_HAS_CONT_LOCK) {
                /* Set start block address */
@@ -2146,7 +2152,10 @@ static void onenand_check_features(struct mtd_info *mtd)
        /* Lock scheme */
        switch (density) {
        case ONENAND_DEVICE_DENSITY_4Gb:
-               this->options |= ONENAND_HAS_2PLANE;
+               if (ONENAND_IS_DDP(this))
+                       this->options |= ONENAND_HAS_2PLANE;
+               else
+                       this->options |= ONENAND_HAS_4KB_PAGE;
 
        case ONENAND_DEVICE_DENSITY_2Gb:
                /* 2Gb DDP don't have 2 plane */
@@ -2168,6 +2177,9 @@ static void onenand_check_features(struct mtd_info *mtd)
        }
 
        if (ONENAND_IS_MLC(this))
+               this->options |= ONENAND_HAS_4KB_PAGE;
+
+       if (ONENAND_IS_4KB_PAGE(this))
                this->options &= ~ONENAND_HAS_2PLANE;
 
        if (FLEXONENAND(this)) {
@@ -2181,6 +2193,9 @@ static void onenand_check_features(struct mtd_info *mtd)
                printk(KERN_DEBUG "Chip support all block unlock\n");
        if (this->options & ONENAND_HAS_2PLANE)
                printk(KERN_DEBUG "Chip has 2 plane\n");
+       if (this->options & ONENAND_HAS_4KB_PAGE)
+               printk(KERN_DEBUG "Chip has 4KiB pagesize\n");
+
 }
 
 /**
@@ -2226,19 +2241,21 @@ 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;
+#ifdef ONENAND_DEBUG
+       char *name;
+#endif
 
        for (i = 0; i < size; i++)
                if (manuf == onenand_manuf_ids[i].id)
                        break;
 
+#ifdef ONENAND_DEBUG
        if (i < size)
                name = onenand_manuf_ids[i].name;
        else
                name = "Unknown";
 
-#ifdef ONENAND_DEBUG
        printk(KERN_DEBUG "OneNAND Manufacturer: %s (0x%0x)\n", name, manuf);
 #endif
 
@@ -2255,7 +2272,7 @@ static int flexonenand_get_boundary(struct mtd_info *mtd)
 {
        struct onenand_chip *this = mtd->priv;
        unsigned int die, bdry;
-       int ret, syscfg, locked;
+       int syscfg, locked;
 
        /* Disable ECC */
        syscfg = this->read_word(this->base + ONENAND_REG_SYS_CFG1);
@@ -2266,7 +2283,7 @@ static int flexonenand_get_boundary(struct mtd_info *mtd)
                this->wait(mtd, FL_SYNCING);
 
                this->command(mtd, FLEXONENAND_CMD_READ_PI, die, 0);
-               ret = this->wait(mtd, FL_READING);
+               this->wait(mtd, FL_READING);
 
                bdry = this->read_word(this->base + ONENAND_DATARAM);
                if ((bdry >> FLEXONENAND_PI_UNLOCK_SHIFT) == 3)
@@ -2276,7 +2293,7 @@ static int flexonenand_get_boundary(struct mtd_info *mtd)
                this->boundary[die] = bdry & FLEXONENAND_PI_MASK;
 
                this->command(mtd, ONENAND_CMD_RESET, 0, 0);
-               ret = this->wait(mtd, FL_RESETING);
+               this->wait(mtd, FL_RESETING);
 
                printk(KERN_INFO "Die %d boundary: %d%s\n", die,
                       this->boundary[die], locked ? "(Locked)" : "(Unlocked)");
@@ -2289,8 +2306,8 @@ static int flexonenand_get_boundary(struct mtd_info *mtd)
 
 /**
  * flexonenand_get_size - Fill up fields in onenand_chip and mtd_info
- *                       boundary[], diesize[], mtd->size, mtd->erasesize,
- *                       mtd->eraseregions
+ *                       boundary[], diesize[], mtd->size, mtd->erasesize,
+ *                       mtd->eraseregions
  * @param mtd          - MTD device structure
  */
 static void flexonenand_get_size(struct mtd_info *mtd)
@@ -2381,7 +2398,7 @@ static int flexonenand_check_blocks_erased(struct mtd_info *mtd,
        int i, ret;
        int block;
        struct mtd_oob_ops ops = {
-               .mode = MTD_OOB_PLACE,
+               .mode = MTD_OPS_PLACE_OOB,
                .ooboffs = 0,
                .ooblen = mtd->oobsize,
                .datbuf = NULL,
@@ -2505,23 +2522,24 @@ out:
 }
 
 /**
- * onenand_probe - [OneNAND Interface] Probe the OneNAND device
+ * onenand_chip_probe - [OneNAND Interface] Probe the OneNAND chip
  * @param mtd          MTD device structure
  *
  * OneNAND detection method:
  *   Compare the the values from command with ones from register
  */
-static int onenand_probe(struct mtd_info *mtd)
+static int onenand_chip_probe(struct mtd_info *mtd)
 {
        struct onenand_chip *this = mtd->priv;
-       int bram_maf_id, bram_dev_id, maf_id, dev_id, ver_id;
-       int density;
+       int bram_maf_id, bram_dev_id, maf_id, dev_id;
        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);
+       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);
@@ -2534,7 +2552,8 @@ static int onenand_probe(struct mtd_info *mtd)
        this->write_word(ONENAND_CMD_RESET, this->base + ONENAND_BOOTRAM);
 
        /* Wait reset */
-       this->wait(mtd, FL_RESETING);
+       if (this->wait(mtd, FL_RESETING))
+               return -ENXIO;
 
        /* Restore system configuration 1 */
        this->write_word(syscfg, this->base + ONENAND_REG_SYS_CFG1);
@@ -2546,18 +2565,45 @@ static int onenand_probe(struct mtd_info *mtd)
        /* 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);
-       this->technology = this->read_word(this->base + ONENAND_REG_TECHNOLOGY);
 
        /* Check OneNAND device */
        if (maf_id != bram_maf_id || dev_id != bram_dev_id)
                return -ENXIO;
 
+       return 0;
+}
+
+/**
+ * onenand_probe - [OneNAND Interface] Probe the OneNAND device
+ * @param mtd          MTD device structure
+ *
+ * OneNAND detection method:
+ *   Compare the the values from command with ones from register
+ */
+int onenand_probe(struct mtd_info *mtd)
+{
+       struct onenand_chip *this = mtd->priv;
+       int dev_id, ver_id;
+       int density;
+       int ret;
+
+       ret = this->chip_probe(mtd);
+       if (ret)
+               return ret;
+
+       /* Read device IDs from Register */
+       dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID);
+       ver_id = this->read_word(this->base + ONENAND_REG_VERSION_ID);
+       this->technology = this->read_word(this->base + ONENAND_REG_TECHNOLOGY);
+
        /* Flash device information */
        mtd->name = onenand_print_device_info(dev_id, ver_id);
        this->device_id = dev_id;
        this->version_id = ver_id;
 
+       /* Check OneNAND features */
+       onenand_check_features(mtd);
+
        density = onenand_get_density(dev_id);
        if (FLEXONENAND(this)) {
                this->dies = ONENAND_IS_DDP(this) ? 2 : 1;
@@ -2580,7 +2626,7 @@ static int onenand_probe(struct mtd_info *mtd)
        mtd->writesize =
            this->read_word(this->base + ONENAND_REG_DATA_BUFFER_SIZE);
        /* We use the full BufferRAM */
-       if (ONENAND_IS_MLC(this))
+       if (ONENAND_IS_4KB_PAGE(this))
                mtd->writesize <<= 1;
 
        mtd->oobsize = mtd->writesize >> 5;
@@ -2611,18 +2657,15 @@ static int onenand_probe(struct mtd_info *mtd)
        else
                mtd->size = this->chipsize;
 
-       /* Check OneNAND features */
-       onenand_check_features(mtd);
-
+       mtd->type = ONENAND_IS_MLC(this) ? MTD_MLCNANDFLASH : MTD_NANDFLASH;
        mtd->flags = MTD_CAP_NANDFLASH;
-       mtd->erase = onenand_erase;
-       mtd->read = onenand_read;
-       mtd->write = onenand_write;
-       mtd->read_oob = onenand_read_oob;
-       mtd->write_oob = onenand_write_oob;
-       mtd->sync = onenand_sync;
-       mtd->block_isbad = onenand_block_isbad;
-       mtd->block_markbad = onenand_block_markbad;
+       mtd->_erase = onenand_erase;
+       mtd->_read_oob = onenand_read_oob;
+       mtd->_write_oob = onenand_write_oob;
+       mtd->_sync = onenand_sync;
+       mtd->_block_isbad = onenand_block_isbad;
+       mtd->_block_markbad = onenand_block_markbad;
+       mtd->writebufsize = mtd->writesize;
 
        return 0;
 }
@@ -2659,6 +2702,9 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
        if (!this->write_bufferram)
                this->write_bufferram = onenand_write_bufferram;
 
+       if (!this->chip_probe)
+               this->chip_probe = onenand_chip_probe;
+
        if (!this->block_markbad)
                this->block_markbad = onenand_default_block_markbad;
        if (!this->scan_bbt)
@@ -2732,7 +2778,8 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
         * the out of band area
         */
        this->ecclayout->oobavail = 0;
-       for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES &&
+
+       for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES_LARGE &&
            this->ecclayout->oobfree[i].length; i++)
                this->ecclayout->oobavail +=
                        this->ecclayout->oobfree[i].length;