mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 20:07:46 +09:00
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 <long.yu@amlogic.com>
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user