mtd: nand: fix oob read pannic.
authorYonghui Yu <yonghui.yu@amlogic.com>
Thu, 8 Jun 2017 13:00:13 +0000 (21:00 +0800)
committerJianxin Pan <jianxin.pan@amlogic.com>
Fri, 16 Jun 2017 04:55:35 +0000 (21:55 -0700)
PD#145890: nand: fix oob read

When reading oob by nandread from toolbox of andriod,
the oob should be protected. so we read back the whole
page with ecc on, and copy out oob only.

Change-Id: I08f35396015316a35631727dfbfedb862567d913
Signed-off-by: Yonghui Yu <yonghui.yu@amlogic.com>
drivers/amlogic/mtd/aml_mtd.h
drivers/amlogic/mtd/aml_nand.c
drivers/amlogic/mtd/boot.c
drivers/amlogic/mtd/m3_nand.c

index 1ce7a4f..d7cc6fd 100644 (file)
@@ -848,6 +848,9 @@ int m3_nand_boot_erase_cmd(struct mtd_info *mtd, int page);
 int m3_nand_boot_read_page_hwecc(struct mtd_info *mtd,
        struct nand_chip *chip, uint8_t *buf, int oob_required, int page);
 
+int m3_nand_boot_read_oob(struct mtd_info *mtd,
+       struct nand_chip *chip, int page);
+
 int m3_nand_boot_write_page_hwecc(struct mtd_info *mtd,
        struct nand_chip *chip, const uint8_t *buf, int oob_required, int page);
 
index 162945b..cf18a35 100644 (file)
@@ -1900,365 +1900,23 @@ int aml_nand_write_page(struct mtd_info *mtd,
        return 0;
 }
 
+/* read the whole page, and cpy oob to caller */
 int aml_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip, int page)
 {
-       int32_t page_addr, user_byte_num, internal_chipnr = 1;
+       int ret = 0;
        struct aml_nand_chip *aml_chip = mtd_to_nand_chip(mtd);
-       unsigned char *nand_buffer = aml_chip->aml_nand_data_buf;
-       unsigned char *oob_buffer = chip->oob_poi;
-       int32_t pages_per_blk_shift = chip->phys_erase_shift-chip->page_shift;
-       unsigned int nand_page_size = 1 << chip->page_shift;
-       unsigned int nand_read_size = mtd->oobavail, dma_once_size;
-       unsigned int read_chip_num;
-       int ran_mode = aml_chip->ran_mode;
-       int32_t error = 0, i, stat = 0, j = 0;
-       int temp;
-       int page_temp, readretry_failed_cnt = 0;
-       int pages_per_blk =  (1 << (chip->phys_erase_shift - chip->page_shift));
-       int retry_cnt = aml_chip->new_nand_info.read_rety_info.retry_cnt;
-       struct new_tech_nand_t *new_nand_info = &aml_chip->new_nand_info;
-       struct aml_nand_dynamic_read *nand_dynamic_read;
-       struct aml_nand_read_retry *nand_read_retry;
-
-       nand_dynamic_read = &new_nand_info->dynamic_read_info;
-       nand_read_retry = &new_nand_info->read_rety_info;
-
-       if (aml_chip->support_new_nand == 1) {
-               if ((aml_chip->new_nand_info.type == HYNIX_20NM_8GB)
-               || (aml_chip->new_nand_info.type == HYNIX_20NM_4GB)
-               || (aml_chip->new_nand_info.type == HYNIX_1YNM_8GB)) {
-                       temp = aml_chip->new_nand_info.read_rety_info.retry_cnt;
-                       retry_cnt = temp * temp;
-               }
-       }
-       temp = (unsigned int)aml_chip->plane_num * nand_page_size;
-       read_chip_num = (nand_read_size + temp - 1) / temp;
-
-       if (nand_read_size >= nand_page_size)
-               temp = nand_page_size + chip->ecc.size - 1;
-       else
-               temp = nand_read_size + chip->ecc.size - 1;
-       user_byte_num = (temp / chip->ecc.size) * aml_chip->user_byte_mode;
-       page_addr = page;
-       if (aml_chip->ops_mode & AML_INTERLEAVING_MODE) {
-               internal_chipnr = aml_chip->internal_chipnr;
-               temp = read_chip_num + aml_chip->internal_chipnr - 1;
-               if (read_chip_num < internal_chipnr) {
-                       internal_chipnr = temp / aml_chip->internal_chipnr;
-                       read_chip_num = 1;
-               } else
-                       read_chip_num = temp / aml_chip->internal_chipnr;
-       }
-
-       if (chip->cmdfunc == aml_nand_command)
-               chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page_addr);
-       else {
-               aml_chip->aml_nand_select_chip(aml_chip, 0);
-               chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page_addr);
-       }
-
-       for (i = 0; i < read_chip_num; i++) {
-               if (aml_chip->valid_chip[i]) {
-                       page_addr = aml_chip->page_addr;
-                       if (i > 0) {
-                               aml_chip->aml_nand_select_chip(aml_chip, i);
-                               aml_chip->aml_nand_command(aml_chip,
-                                       NAND_CMD_READ0, 0, page_addr, i);
-                       }
-                       readretry_failed_cnt = 0;
-read_retry:
-                       page_addr = aml_chip->page_addr;
-                       for (j = 0; j < internal_chipnr; j++) {
-                               if (j > 0) {
-                                       page_addr = aml_chip->page_addr;
-                                       page_addr |=
-                               (1 << aml_chip->internal_chip_shift) * j;
-                               aml_chip->aml_nand_select_chip(aml_chip, i);
-                               aml_chip->aml_nand_command(aml_chip,
-                                       NAND_CMD_READ0, 0, page_addr, i);
-                               }
-
-                       if (!aml_chip->aml_nand_wait_devready(aml_chip, i)) {
-                               pr_info("read couldn't found c%d ready\n", i);
-                               error = -EBUSY;
-                               goto exit;
-                       }
-                       if (aml_chip->ops_mode & AML_CHIP_NONE_RB)
-                               chip->cmd_ctrl(mtd, NAND_CMD_READ0 & 0xff,
-                                       NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
-
-       if (aml_chip->plane_num == 2) {
-               dma_once_size = min(nand_read_size, nand_page_size);
-               aml_chip->aml_nand_command(aml_chip,
-                       NAND_CMD_TWOPLANE_READ1, 0x00, page_addr, i);
-dma_retry_plane0:
-               error = aml_chip->aml_nand_dma_read(aml_chip,
-                       nand_buffer, dma_once_size, aml_chip->bch_mode);
-               if (error)
-                       goto exit;
-
-               aml_chip->aml_nand_get_user_byte(aml_chip,
-                       oob_buffer, user_byte_num);
-               stat = aml_chip->aml_nand_hwecc_correct(aml_chip,
-                       nand_buffer, dma_once_size, oob_buffer);
-               if (stat < 0) {
-                       if (aml_chip->ran_mode
-                               && (aml_chip->zero_cnt < aml_chip->ecc_max)) {
-                               memset(oob_buffer, 0xff, user_byte_num);
-                               goto plane0_ff;
-                       }
-                       if (ran_mode && aml_chip->ran_mode) {
-                               aml_chip->ran_mode = 0;
-                               ndelay(300);
-                               aml_chip->aml_nand_command(aml_chip,
-                                       NAND_CMD_RNDOUT, 0, -1, i);
-                               ndelay(500);
-                               goto dma_retry_plane0;
-                       }
-                       memset(oob_buffer, 0x22, user_byte_num);
-                       mtd->ecc_stats.failed++;
-                       pr_info("rdoob pl0 failed pg%d chip%d\n", page_addr, i);
-               } else {
-                       if (aml_chip->ecc_cnt_cur > aml_chip->ecc_cnt_limit) {
-                               pr_info("%s %d uncorrect ", __func__, __LINE__);
-                               pr_info("ecnt:%d limit:%d pg:%d blk:%d c%d\n",
-                                       aml_chip->ecc_cnt_cur,
-                                       aml_chip->ecc_cnt_limit,
-                                       page_addr,
-                                       page_addr >> pages_per_blk_shift,
-                                       i);
-                               mtd->ecc_stats.corrected++;
-                       }
-                       mtd->ecc_stats.corrected += stat;
-               }
-plane0_ff:
-               aml_chip->ran_mode = ran_mode;
-               oob_buffer += user_byte_num;
-               nand_read_size -= dma_once_size;
-
-               if (nand_read_size > 0) {
-                       dma_once_size = min(nand_read_size, nand_page_size);
-                       aml_chip->aml_nand_command(aml_chip,
-                               NAND_CMD_TWOPLANE_READ2,
-                               0x00, page_addr, i);
-dma_retry_plane1:
-                       error = aml_chip->aml_nand_dma_read(aml_chip,
-                                       nand_buffer, dma_once_size,
-                                       aml_chip->bch_mode);
-                       if (error) {
-                               aml_chip->ran_mode = ran_mode;
-                               goto exit;
-                       }
-
-                       aml_chip->aml_nand_get_user_byte(aml_chip,
-                               oob_buffer, user_byte_num);
-                       stat = aml_chip->aml_nand_hwecc_correct(aml_chip,
-                               nand_buffer, dma_once_size, oob_buffer);
-                       if (stat < 0) {
-                               if (aml_chip->ran_mode
-                               && (aml_chip->zero_cnt <  aml_chip->ecc_max)) {
-                                       memset(oob_buffer, 0xff, user_byte_num);
-                                       aml_chip->ran_mode = ran_mode;
-                                       oob_buffer += user_byte_num;
-                                       nand_read_size -= dma_once_size;
-                                       continue;
-                               }
-                               if (ran_mode && aml_chip->ran_mode) {
-                                       aml_chip->ran_mode = 0;
-                                       ndelay(300);
-                                       aml_chip->aml_nand_command(aml_chip,
-                                               NAND_CMD_RNDOUT, 0, -1, i);
-                                       ndelay(500);
-                                       goto dma_retry_plane1;
-                               }
-                               memset(oob_buffer, 0xff, user_byte_num);
-                               mtd->ecc_stats.failed++;
-                               pr_info("read oob pl1 failed page %d chip%d\n",
-                                       page_addr, i);
-                       } else {
-                               temp = aml_chip->ecc_cnt_limit;
-                               if (aml_chip->ecc_cnt_cur > temp) {
-                                       pr_info("%s %d uncorrect ",
-                                               __func__, __LINE__);
-                               pr_info("ecnt:%d limit:%d pg:%d, blk:%d c%d\n",
-                                       aml_chip->ecc_cnt_cur,
-                                       aml_chip->ecc_cnt_limit,
-                                       page_addr,
-                                       page_addr >> pages_per_blk_shift, i);
-                                       mtd->ecc_stats.corrected++;
-                               }
-                               mtd->ecc_stats.corrected += stat;
-                       }
-                       aml_chip->ran_mode = ran_mode;
-                       oob_buffer += user_byte_num;
-                       nand_read_size -= dma_once_size;
-               }
-       } else if (aml_chip->plane_num == 1) {
-               dma_once_size = min(nand_read_size, nand_page_size);
-               error = aml_chip->aml_nand_dma_read(aml_chip,
-               nand_buffer, dma_once_size, aml_chip->bch_mode);
-               if (error) {
-                       aml_chip->ran_mode = ran_mode;
-                       return error;
-               }
 
-               aml_chip->aml_nand_get_user_byte(aml_chip,
-                       oob_buffer, user_byte_num);
-               stat = aml_chip->aml_nand_hwecc_correct(aml_chip,
-                       nand_buffer, dma_once_size, oob_buffer);
-               if (stat < 0) {
-                       if (aml_chip->ran_mode
-                               && (aml_chip->zero_cnt  <  aml_chip->ecc_max)) {
-                               memset(oob_buffer, 0xff, user_byte_num);
-                               oob_buffer += user_byte_num;
-                               nand_read_size -= dma_once_size;
-                               continue;
-                       }
-                       aml_chip->ran_mode = ran_mode;
-               if (aml_chip->support_new_nand == 1) {
-                       if (aml_chip->new_nand_info.type == SANDISK_19NM) {
-                               temp =
-                               pages_per_blk*(page_addr>>pages_per_blk_shift);
-                               page_temp = page_addr - temp;
-                               if (((page_temp % 2 == 0) && (page_temp != 0))
-                                       || (page_temp == (pages_per_blk - 1))) {
-                                       temp = readretry_failed_cnt;
-                                       if (temp++ < DYNAMIC_CNT_UPPER) {
-                                               pr_info("read ecc failed ");
-                               pr_info("pg:%d blk %d c%d,retrycnt:%d\n",
-                                       page_addr,
-                                       page_addr>>pages_per_blk_shift,
-                                       i, readretry_failed_cnt);
-                               nand_dynamic_read->dynamic_read_handle(mtd,
-                                       page_temp, i);
-                               aml_chip->aml_nand_command(aml_chip,
-                                       NAND_CMD_READ0, 0, page_addr, i);
-                                               goto read_retry;
-                                       }
-                               } else {
-                                       temp = readretry_failed_cnt;
-                                       if (temp++ < DYNAMIC_CNT_LOWER) {
-                                               pr_info("read ecc failed ");
-                               pr_info("pg:%d blk%d chip%d, retry_cnt:%d\n",
-                                       page_addr,
-                                       page_addr >> pages_per_blk_shift,
-                                       i, readretry_failed_cnt);
-                               nand_dynamic_read->dynamic_read_handle(mtd,
-                                       page_temp, i);
-                               aml_chip->aml_nand_command(aml_chip,
-                                       NAND_CMD_READ0, 0, page_addr, i);
-                                               goto read_retry;
-                                       }
-                               }
-                       } else if (aml_chip->new_nand_info.type) {
-                               if (readretry_failed_cnt++ < retry_cnt) {
-                                       pr_info("read ecc failed ");
-                                       pr_info("pg:%d blk %d c%d retrcnt:%d\n",
-                                               page_addr,
-                                               page_addr>>pages_per_blk_shift,
-                                               i, readretry_failed_cnt);
-                                       nand_read_retry->read_retry_handle(mtd,
-                                               i);
-                                       aml_chip->aml_nand_command(aml_chip,
-                                               NAND_CMD_READ0,
-                                               0, page_addr, i);
-                                       goto read_retry;
-                               }
-                       }
-               }
+       /* send cmd 00-addr-30 */
+       aml_chip->aml_nand_command(aml_chip, NAND_CMD_READ0,
+                               0, page, 0);
 
-                       pr_info("%s %d read oob fail at pg:%d, blk:%d c%d\n",
-                               __func__, __LINE__, page_addr,
-                               page_addr >> pages_per_blk_shift, i);
-
-                       memset(oob_buffer, 0x22, user_byte_num);
-                       mtd->ecc_stats.failed++;
-               if (aml_chip->support_new_nand == 1) {
-                       if ((aml_chip->new_nand_info.type)
-                               && (aml_chip->new_nand_info.type < 10)) {
-                               aml_chip->aml_nand_command(aml_chip,
-                                               NAND_CMD_RESET, -1, -1, i);
-                       if (!aml_chip->aml_nand_wait_devready(aml_chip, i)) {
-                               pr_info("read not found c%d ready\n",
-                                       i);
-                               error = -EBUSY;
-                               goto exit;
-                       }
-                       }
-               }
-               } else {
-                       aml_chip->ran_mode = ran_mode;
-               if (aml_chip->support_new_nand == 1) {
-                       if (aml_chip->new_nand_info.type == SANDISK_19NM) {
-                               temp = page_addr >> pages_per_blk_shift;
-                               temp = pages_per_blk * temp;
-                               page_temp = page_addr - temp;
-                               temp = readretry_failed_cnt;
-                               if (((page_temp % 2 == 0) && (page_temp != 0))
-                                       || (page_temp == (pages_per_blk - 1))) {
-                                       if (temp > DYNAMIC_CNT_UPPER - 2) {
-                                               pr_info("%s %d uncorrect ",
-                                                       __func__, __LINE__);
-               pr_info("ecccnt:%d limit:%d pg:%d blk:%d C%d rrcnt:%d\n",
-
-                       aml_chip->ecc_cnt_cur, aml_chip->ecc_cnt_limit,
-                       page_addr,
-                       page_addr >> pages_per_blk_shift,
-                       i, temp);
-                                               mtd->ecc_stats.corrected++;
-                                       }
-                               } else {
-                                       if (temp > DYNAMIC_CNT_LOWER - 2) {
-                                               pr_info("%s %d uncorrect ",
-                                                       __func__, __LINE__);
-               pr_info("ecccnt:%d limit:%d pg:%d blk:%d C%d rrcnt:%d\n",
-                       aml_chip->ecc_cnt_cur,
-                       aml_chip->ecc_cnt_limit,
-                       page_addr,
-                       page_addr >> pages_per_blk_shift,
-                       i, temp);
-                                               mtd->ecc_stats.corrected++;
-                                       }
-                               }
-                       } else if (aml_chip->new_nand_info.type) {
-                               if (readretry_failed_cnt > (retry_cnt-2)) {
-                                       pr_info("%s %d uncorrect ",
-                                               __func__, __LINE__);
-               pr_info("ecccnt:%d limit:%d page:%d blk:%d C%d rrcnt:%d\n",
-                       aml_chip->ecc_cnt_cur, aml_chip->ecc_cnt_limit,
-                       page_addr,
-                       page_addr >> pages_per_blk_shift,
-                       i, readretry_failed_cnt);
-                                       mtd->ecc_stats.corrected++;
-                               }
+       ret = aml_nand_read_page_hwecc(mtd,
+               chip, aml_chip->aml_nand_data_buf, 0, page);
 
-                       }
-               }
-                       mtd->ecc_stats.corrected += stat;
-               }
-       if (aml_chip->support_new_nand == 1) {
-               if (readretry_failed_cnt) {
-                       if ((aml_chip->new_nand_info.type == SANDISK_19NM)
-                               && (nand_dynamic_read->dynamic_read_exit))
-                               nand_dynamic_read->dynamic_read_exit(mtd, i);
-                       else if ((aml_chip->new_nand_info.type)
-                               && (nand_read_retry->read_retry_exit))
-                               nand_read_retry->read_retry_exit(mtd, i);
-               }
-       }
-               oob_buffer += user_byte_num;
-               nand_read_size -= dma_once_size;
-       } else {
-               error = -ENODEV;
-               goto exit;
-       } /*plane*/
-                       } /*for (j = 0; j < internal_chipnr; j++) { */
-               } /*if (aml_chip->valid_chip[i]) {*/
-       } /*for (i = 0; i < read_chip_num; i++) {*/
-exit:
-       return nand_read_size;
+       return ret;
 }
 
+
 int aml_nand_write_oob(struct mtd_info *mtd, struct nand_chip *chip, int page)
 {
        pr_info("our host controller`s structure couldn`t support oob write\n");
@@ -2452,100 +2110,9 @@ int aml_nand_init(struct aml_nand_chip *aml_chip)
                err = -ENXIO;
                goto exit_error;
        }
-/*#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 13)*/
-#if 0
-       if (plat->platform_nand_data.chip.ecclayout)
-               chip->ecc.layout = plat->platform_nand_data.chip.ecclayout;
-       else {
-               oobmul = mtd->oobsize / aml_chip->oob_size;
-               if (!chip->ecc.layout)
-                       chip->ecc.layout =
-                       kzalloc(sizeof(struct nand_ecclayout), GFP_KERNEL);
-               if (!chip->ecc.layout) {
-                       err = -ENOMEM;
-                       goto exit_error;
-               }
-               if (!strncmp((char *)plat->name, NAND_BOOT_NAME,
-                       strlen((const char *)NAND_BOOT_NAME)))
-                       memcpy(chip->ecc.layout,
-                       &aml_nand_uboot_oob, sizeof(struct nand_ecclayout));
-               else if (chip->ecc.mode != NAND_ECC_SOFT) {
-                       elsize = sizeof(struct nand_ecclayout);
-                       switch (aml_chip->oob_size) {
-                       case 64:
-                       memcpy(chip->ecc.layout, &aml_nand_oob_64, elsize);
-                       break;
-                       case 128:
-                       memcpy(chip->ecc.layout, &aml_nand_oob_128, elsize);
-                       break;
-                       case 218:
-                       memcpy(chip->ecc.layout, &aml_nand_oob_218, elsize);
-                       break;
-                       case 224:
-                       memcpy(chip->ecc.layout, &aml_nand_oob_224, elsize);
-                       break;
-                       case 256:
-                       memcpy(chip->ecc.layout, &aml_nand_oob_256, elsize);
-                       break;
-                       case 376:
-                       memcpy(chip->ecc.layout, &aml_nand_oob_376, elsize);
-                       break;
-                       case 436:
-                       memcpy(chip->ecc.layout, &aml_nand_oob_436, elsize);
-                       break;
-                       case 448:
-                       memcpy(chip->ecc.layout, &aml_nand_oob_448, elsize);
-                       break;
-                       case 640:
-                       memcpy(chip->ecc.layout, &aml_nand_oob_640, elsize);
-                       break;
-                       case 744:
-                       memcpy(chip->ecc.layout, &aml_nand_oob_744, elsize);
-                       break;
-                       case 1280:
-                       memcpy(chip->ecc.layout, &aml_nand_oob_1280, elsize);
-                       break;
-                       case 1664:
-                       memcpy(chip->ecc.layout, &aml_nand_oob_1664, elsize);
-                       break;
-                       default:
-                       pr_info("default,use nand base oob layout %d\n",
-                               mtd->oobsize);
-                       chip->ecc.layout->oobfree[0].length =
-               (mtd->writesize / chip->ecc.size) * aml_chip->user_byte_mode;
-                       break;
-                       }
-
-                       chip->ecc.layout->oobfree[0].length *= oobmul;
-                       chip->ecc.layout->eccbytes *= oobmul;
-                       pr_info("%s :oobmul=%d,oobfree.length=%d,oob_size=%d\n",
-                               __func__,
-                               oobmul,
-                               chip->ecc.layout->oobfree[0].length,
-                               aml_chip->oob_size);
-               }
-       }
-
-       /*
-        * The number of bytes available for a client to place data into
-        * the out of band area
-        */
-       chip->ecc.layout->oobavail = 0;
-       oobfree = chip->ecc.layout->oobfree;
-       tmp_value = ARRAY_SIZE(chip->ecc.layout->oobfree);
-       for (i = 0; oobfree[i].length && i < tmp_value; i++)
-               chip->ecc.layout->oobavail += oobfree[i].length;
-       pr_info("oob avail size %d\n", chip->ecc.layout->oobavail);
-
        mtd_set_ooblayout(mtd, &aml_ooblayout_ops);
-
-       mtd->oobavail = chip->ecc.layout->oobavail;
-       mtd->ecclayout = chip->ecc.layout;
-#else
-       mtd_set_ooblayout(mtd, &aml_ooblayout_ops);
-       mtd_ooblayout_ecc(mtd, 0, &oobregion);
+       mtd_ooblayout_free(mtd, 0, &oobregion);
        mtd->oobavail = oobregion.length;
-#endif
 
        aml_chip->virtual_page_size = mtd->writesize;
        aml_chip->virtual_block_size = mtd->erasesize;
index 8fa0d4d..4f393c0 100644 (file)
@@ -389,6 +389,23 @@ exit:
        return error;
 }
 
+/*
+ * read oob only.
+ */
+int m3_nand_boot_read_oob(struct mtd_info *mtd,
+       struct nand_chip *chip, int page)
+{
+       int ret = 0;
+       struct aml_nand_chip *aml_chip = mtd_to_nand_chip(mtd);
+       /* send cmd 00-addr-30 */
+       aml_chip->aml_nand_command(aml_chip, NAND_CMD_READ0,
+                               0, page, 0);
+       ret = m3_nand_boot_read_page_hwecc(mtd,
+               chip, aml_chip->aml_nand_data_buf, 0, page);
+
+       return ret;
+}
+
 /* mtd support interface:
  * chip->ecc.write_page
  * function:int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
index 7a10787..6e6a380 100644 (file)
@@ -690,6 +690,7 @@ static int m3_nand_dma_read(struct aml_nand_chip *aml_chip,
                0, count*PER_INFO_BYTE);
 
 #ifndef AML_NAND_UBOOT
+       WARN_ON(count == 0);
        info_buf =
 (u32 *)&(aml_chip->user_info_buf[(count-1)*info_times_int_len]);
        /*smp_wmb*/
@@ -935,6 +936,7 @@ static int m3_nand_probe(struct aml_nand_platform *plat, unsigned int dev_num)
                NAND_BOOT_NAME, strlen((const char *)NAND_BOOT_NAME))) {
                /* interface is chip->erase_cmd on 3.14*/
                chip->erase = m3_nand_boot_erase_cmd;
+               chip->ecc.read_oob  = m3_nand_boot_read_oob;
                chip->ecc.read_page = m3_nand_boot_read_page_hwecc;
                chip->ecc.write_page = m3_nand_boot_write_page_hwecc;
                chip->write_page = m3_nand_boot_write_page;