From ca709001f4ec7f79296970e0d4557ee67f8326e6 Mon Sep 17 00:00:00 2001 From: Long Yu Date: Tue, 14 May 2019 15:17:30 +0800 Subject: [PATCH] emmc: report response crc error on G12B when hs400 200M busmode [1/1] PD#SWPL-8670 Problem: G12B report response crc error when hs400 200M busmode Solution: find a eyetest hole between 14-20 or 48-54, otherwise tuning tx_delay and find again and adjust CMD rx timing dynamically in HS400 mode Verify: passed on G12B Change-Id: I23e4d5118e0ca0564367a77102aea9e1085633a9 Signed-off-by: Long Yu --- drivers/amlogic/mmc/aml_sd_emmc.c | 3 +- drivers/amlogic/mmc/aml_sd_emmc_v3.c | 90 ++++++++++++++++++++---------------- include/linux/amlogic/sd.h | 3 +- 3 files changed, 53 insertions(+), 43 deletions(-) diff --git a/drivers/amlogic/mmc/aml_sd_emmc.c b/drivers/amlogic/mmc/aml_sd_emmc.c index 5b899c6..859962f 100644 --- a/drivers/amlogic/mmc/aml_sd_emmc.c +++ b/drivers/amlogic/mmc/aml_sd_emmc.c @@ -3128,7 +3128,8 @@ static int meson_mmc_probe(struct platform_device *pdev) host->pinctrl = NULL; host->status = HOST_INVALID; host->is_tunning = 0; - host->is_timming = 0; + host->find_win = 0; + host->cmd_retune = 0; if (host->ctrl_ver >= 3) ret = meson_mmc_clk_init_v3(host); diff --git a/drivers/amlogic/mmc/aml_sd_emmc_v3.c b/drivers/amlogic/mmc/aml_sd_emmc_v3.c index b1dbc72..e9c25c1 100644 --- a/drivers/amlogic/mmc/aml_sd_emmc_v3.c +++ b/drivers/amlogic/mmc/aml_sd_emmc_v3.c @@ -520,6 +520,7 @@ irqreturn_t meson_mmc_irq_thread_v3(int irq, void *dev_id) unsigned long flags; enum aml_mmc_waitfor xfer_step; u32 status, xfer_bytes = 0; + u32 delay2 = 0, tmp = 0; spin_lock_irqsave(&host->mrq_lock, flags); pdata = mmc_priv(host->mmc); @@ -595,9 +596,6 @@ irqreturn_t meson_mmc_irq_thread_v3(int irq, void *dev_id) case HOST_DAT_TIMEOUT_ERR: case HOST_RSP_CRC_ERR: case HOST_DAT_CRC_ERR: - if (host->is_tunning == 0) - pr_info("%s %d %s: cmd:%d\n", __func__, __LINE__, - mmc_hostname(host->mmc), mrq->cmd->opcode); if (mrq->cmd->data) { dma_unmap_sg(mmc_dev(host->mmc), mrq->cmd->data->sg, mrq->cmd->data->sg_len, @@ -606,14 +604,29 @@ irqreturn_t meson_mmc_irq_thread_v3(int irq, void *dev_id) } meson_mmc_read_resp(host->mmc, host->mrq->cmd); + if (((status == HOST_RSP_CRC_ERR) + || (status == HOST_RSP_TIMEOUT_ERR)) + && (host->cmd_retune == 1)) { + + if (host->error_flag == 0) + host->is_tunning = 0; + delay2 = readl(host->base + SD_EMMC_DELAY2_V3); + tmp = (((delay2 >> 24) & 0x3f) + 3) % 0x3f; + delay2 = (delay2 & ~(0x3f << 24)) | (tmp << 24); + writel(delay2, host->base + SD_EMMC_DELAY2_V3); + pr_err("retune cmd-delay:0x%x\n", delay2); + } /* set retry @ 1st error happens! */ if ((host->error_flag == 0) && (aml_card_type_mmc(pdata) || aml_card_type_non_sdio(pdata)) && (host->is_tunning == 0)) { - pr_err("%s() %d: set 1st retry!\n", + if (host->find_win == 0) + pr_err("%s() %d: set 1st retry!\n", __func__, __LINE__); + else + host->is_tunning = 1; host->error_flag |= (1<<0); spin_lock_irqsave(&host->mrq_lock, flags); mrq->cmd->retries = 3; @@ -622,7 +635,8 @@ irqreturn_t meson_mmc_irq_thread_v3(int irq, void *dev_id) if (aml_card_type_mmc(pdata) && (host->error_flag & (1<<0)) && mrq->cmd->retries) { - pr_err("retry cmd %d the %d-th time(s)\n", + if (host->find_win == 0) + pr_err("retry cmd %d the %d-th time(s)\n", mrq->cmd->opcode, mrq->cmd->retries); /* chage configs on current host */ } @@ -630,7 +644,8 @@ irqreturn_t meson_mmc_irq_thread_v3(int irq, void *dev_id) if ((aml_card_type_mmc(pdata) || aml_card_type_non_sdio(pdata)) && host->error_flag && (mrq->cmd->retries == 0)) { host->error_flag |= (1<<30); - pr_err("Command retried failed line:%d, cmd:%d\n", + if (host->find_win == 0) + pr_err("Command retried failed line:%d, cmd:%d\n", __LINE__, mrq->cmd->opcode); } /* retry need send a stop 2 emmc... */ @@ -1090,9 +1105,14 @@ static int emmc_ds_manual_sht(struct mmc_host *mmc) int best_start = -1, best_size = -1; int cur_start = -1, cur_size = 0; - host->is_tunning = 1; + if (host->data->chip_type >= MMC_CHIP_TL1) { + host->cmd_retune = 1; + host->find_win = 1; + } for (i = 0; i < 64; i++) { + host->is_tunning = 1; err = emmc_test_bus(mmc); + host->is_tunning = 0; pr_debug("intf3: 0x%x, err[%d]: %d\n", readl(host->base + SD_EMMC_INTF3), i, err); if (!err) @@ -1145,7 +1165,7 @@ static int emmc_ds_manual_sht(struct mmc_host *mmc) readl(host->base + SD_EMMC_INTF3), readl(host->base + SD_EMMC_CLOCK_V3)); pr_info("adjust:0x%x\n", readl(host->base + SD_EMMC_ADJUST_V3)); - host->is_tunning = 0; + host->find_win = 0; return 0; } #endif @@ -1534,7 +1554,6 @@ int aml_get_data_eyetest(struct mmc_host *mmc) u32 delay2 = readl(host->base + SD_EMMC_DELAY2_V3); int ret = 0, retry = 10, line_x; - host->is_timming = 1; host->is_tunning = 1; pr_info("[%s] 2018-4-18 emmc HS200 Timming\n", __func__); aml_sd_emmc_clktest(mmc); @@ -1574,7 +1593,6 @@ RETRY: readl(host->base + SD_EMMC_DELAY1_V3), readl(host->base + SD_EMMC_DELAY2_V3)); update_all_line_eyetest(mmc); - host->is_timming = 0; host->is_tunning = 0; return 0; } @@ -1591,6 +1609,7 @@ int aml_emmc_hs200_tl1(struct mmc_host *mmc) int i, j, err = 0; int retry_times = 0; + aml_sd_emmc_clktest(mmc); clk_bak = vclkc; clkc->tx_phase = para->hs4.tx_phase; clkc->core_phase = para->hs4.core_phase; @@ -1609,42 +1628,31 @@ retry: if (err) continue; count = fbinary(pdata->align[9]); - if (host->data->chip_type == MMC_CHIP_TL1) { - if (((count >= 14) && (count <= 20)) - || ((count >= 48) && (count <= 54))) { - if (retry_times != 3) { - retry_times++; - goto retry; - } else - break; - } - } else { - if (((count >= 10) && (count <= 22)) - || ((count >= 45) && (count <= 56))) + if (((count >= 14) && (count <= 20)) + || ((count >= 48) && (count <= 54))) { + if (retry_times != 3) { + retry_times++; + goto retry; + } else break; } } - if (host->data->chip_type == MMC_CHIP_TL1) { - if (delay2 == 63) { - for (j = 0; j < 6; j++) { - clkc->tx_delay++; - pr_info("modify tx delay to %d\n", - clkc->tx_delay); - writel(vclkc, host->base + SD_EMMC_CLOCK_V3); - err = emmc_eyetest_log(mmc, 9); - if (err) - continue; - count = fbinary(pdata->align[9]); - if (((count >= 14) && (count <= 20)) - || ((count >= 48) && (count <= 54))) - break; - } - pdata->tx_delay = clkc->tx_delay; + if (i == 63) { + for (j = 0; j < 6; j++) { + clkc->tx_delay++; + pr_info("modify tx delay to %d\n", + clkc->tx_delay); + writel(vclkc, host->base + SD_EMMC_CLOCK_V3); + err = emmc_eyetest_log(mmc, 9); + if (err) + continue; + count = fbinary(pdata->align[9]); + if (((count >= 14) && (count <= 20)) + || ((count >= 48) && (count <= 54))) + break; } - } else { - if (i == 63) - pr_err("[%s]no find cmd timing\n", __func__); + pdata->tx_delay = clkc->tx_delay; } pdata->cmd_c = (delay2 >> 24); diff --git a/include/linux/amlogic/sd.h b/include/linux/amlogic/sd.h index 78f731c..fbd1388 100644 --- a/include/linux/amlogic/sd.h +++ b/include/linux/amlogic/sd.h @@ -443,7 +443,8 @@ struct amlsd_host { dma_addr_t dma_gping; /* 0x400 */ dma_addr_t dma_gpong; /* 0x800 */ char is_tunning; - char is_timming; + char cmd_retune; + char find_win; char tuning_mode; unsigned int is_sduart; unsigned int irq; -- 2.7.4