ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS);
 
        if (ctrl & ONENAND_CTRL_ERROR) {
-               /* It maybe occur at initial bad block */
                DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: controller error = 0x%04x\n", ctrl);
-               /* Clear other interrupt bits for preventing ECC error */
-               interrupt &= ONENAND_INT_MASTER;
-       }
-
-       if (ctrl & ONENAND_CTRL_LOCK) {
-               DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: it's locked error = 0x%04x\n", ctrl);
-               return -EACCES;
+               if (ctrl & ONENAND_CTRL_LOCK)
+                       DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: it's locked error.\n");
+               return ctrl;
        }
 
        if (interrupt & ONENAND_INT_READ) {
 
                        ret = this->wait(mtd, FL_READING);
                        /* First copy data and check return value for ECC handling */
-                       onenand_update_bufferram(mtd, from, 1);
+                       onenand_update_bufferram(mtd, from, !ret);
                }
 
                this->read_bufferram(mtd, ONENAND_DATARAM, buf, column, thislen);
 
-               read += thislen;
-
-               if (read == len)
-                       break;
-
                if (ret) {
                        DEBUG(MTD_DEBUG_LEVEL0, "onenand_read: read failed = %d\n", ret);
                        goto out;
                }
 
+               read += thislen;
+
+               if (read == len)
+                       break;
+
                from += thislen;
                buf += thislen;
        }
 
                this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen);
 
+               if (ret) {
+                       DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_oob: read failed = 0x%x\n", ret);
+                       goto out;
+               }
+
                read += thislen;
 
                if (read == len)
                        break;
 
-               if (ret) {
-                       DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_oob: read failed = %d\n", ret);
-                       goto out;
-               }
-
                buf += thislen;
 
                /* Read more? */
                ret = this->wait(mtd, FL_ERASING);
                /* Check, if it is write protected */
                if (ret) {
-                       if (ret == -EPERM)
-                               DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Device is write protected!!!\n");
-                       else
-                               DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Failed erase, block %d\n", (unsigned) (addr >> this->erase_shift));
+                       DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Failed erase, block %d\n", (unsigned) (addr >> this->erase_shift));
                        instr->state = MTD_ERASE_FAILED;
                        instr->fail_addr = addr;
                        goto erase_exit;
 
                        ret = onenand_do_read_oob(mtd, from + j * mtd->writesize + bd->offs,
                                                  readlen, &retlen, &buf[0]);
 
-                       if (ret)
+                       /* If it is a initial bad block, just ignore it */
+                       if (ret && !(ret & ONENAND_CTRL_LOAD))
                                return ret;
 
                        if (check_short_pattern(&buf[j * scanlen], scanlen, mtd->writesize, bd)) {