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");
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;