[][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);