[][mtd: mtk-snand: add read retry to cover uncorrectable ECC when HW is unstable]
[Description]
Add read retry and add sample_dly by 2 at each retry to cover
uncorrectable ECC, which may happen because of long wiring,
temperature of NAND devices or other board layout issues.
[Release-log]
N/A
Change-Id: Ibe404e3e4a4017dfa8d31681a60dd8f2c5833e67
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/4777182
diff --git a/target/linux/mediatek/files-5.4/drivers/mtd/mtk-snand/mtk-snand.c b/target/linux/mediatek/files-5.4/drivers/mtd/mtk-snand/mtk-snand.c
index 0d88053..79bfd4d 100644
--- a/target/linux/mediatek/files-5.4/drivers/mtd/mtk-snand/mtk-snand.c
+++ b/target/linux/mediatek/files-5.4/drivers/mtd/mtk-snand/mtk-snand.c
@@ -885,12 +885,14 @@
void *buf, void *oob, bool raw, bool format)
{
uint64_t die_addr;
- uint32_t page;
- int ret;
+ uint32_t page, dly_ctrl3;
+ int ret, retry_cnt = 0;
die_addr = mtk_snand_select_die_address(snf, addr);
page = die_addr >> snf->writesize_shift;
+ dly_ctrl3 = nfi_read32(snf, SNF_DLY_CTL3);
+
ret = mtk_snand_page_op(snf, page, SNAND_CMD_READ_TO_CACHE);
if (ret)
return ret;
@@ -901,10 +903,30 @@
return ret;
}
+retry:
ret = mtk_snand_read_cache(snf, page, raw);
if (ret < 0 && ret != -EBADMSG)
return ret;
+ if (ret == -EBADMSG && retry_cnt < 16) {
+ nfi_write32(snf, SNF_DLY_CTL3, retry_cnt * 2);
+ retry_cnt++;
+ goto retry;
+ }
+
+ if (retry_cnt) {
+ if(ret == -EBADMSG) {
+ nfi_write32(snf, SNF_DLY_CTL3, dly_ctrl3);
+ snand_log_chip(snf->pdev,
+ "NFI calibration failed. Original sample delay: 0x%x\n",
+ dly_ctrl3);
+ } else {
+ snand_log_chip(snf->pdev,
+ "NFI calibration passed. New sample delay: 0x%x\n",
+ nfi_read32(snf, SNF_DLY_CTL3));
+ }
+ }
+
if (raw) {
if (format) {
mtk_snand_bm_swap_raw(snf);