sdemmc: update fix adj tuning method

PD#172367: sdemmc: update fix adj tuning method

All adj delay are avalible is not fair when
fix adj mode were used for tuning.
We had tried to add all data with rx delay
to find out the unstable adj delay point.
This method can not cover all scene.
For example:
All adj delay are available as below.
ADJ   0   1   2   3   4   0   1
Src   --__--__--__--__--__--__--
D0    __________________--------
D1    __________________--------
D2    __________________--------
D3    __________________--------
when same rx delay were added to all data line.
All adj delay are still avalible as below.
ADJ   0   1   2   3   4   0   1
Src   --__--__--__--__--__--__--
D0    ----__________________----
D1    ----__________________----
D2    ----__________________----
D3    ----__________________----

So, a new method to find out the unstable adj point
were designed for better compatibility.
Rx delay were added on only 1 data line, such as D1.

When rx delay were added on D1 only. Adj delay 1 is
not available anymore as below.
ADJ   0   1   2   3   4   0   1
Src   --__--__--__--__--__--__--
D0    __________________--------
D1    ----__________________----
D2    __________________--------
D3    __________________--------

In this way, the unsatble adj delay could be
distinguished.

Change-Id: I0488dec001a55f6b50b431ee4d691c872947f0f3
Signed-off-by: Yonghui Yu <yonghui.yu@amlogic.com>
This commit is contained in:
Yonghui Yu
2018-08-08 15:51:02 +08:00
parent 8e5a6e3870
commit 784b259a54
2 changed files with 36 additions and 23 deletions

View File

@@ -716,8 +716,11 @@ int aml_sd_emmc_execute_tuning_(struct mmc_host *mmc, u32 opcode,
u32 clock, clk_div;
u32 adj_delay_find;
int best_win_start = -1, best_win_size = 0;
u32 rxdly[4] = {0, 0x55555555, 0xAAAAAAAA, 0xFFFFFFFF};
u32 old_dly, d1_dly, dly;
old_dly = readl(host->base + SD_EMMC_DELAY);
d1_dly = (old_dly >> 4) & 0xF;
pr_info("Data 1 aligned delay is %d\n", d1_dly);
writel(0, host->base + SD_EMMC_ADJUST);
tunning:
@@ -748,17 +751,21 @@ tunning:
pr_err("%s: tuning failed, reduce freq and retuning\n",
mmc_hostname(host->mmc));
goto tunning;
/* fixme, debug code for sharping delay cell */
} else if (best_win_size == clk_div) {
if (++tuning_num > MAX_TUNING_RETRY) {
pr_err("%s: tuning failed\n",
mmc_hostname(host->mmc));
return -1;
}
pr_warn("wave is not sharp, again\n");
/* add basic data rx delay */
writel(rxdly[tuning_num-1], host->base + SD_EMMC_DELAY);
pr_warn("rxdly @ %d is %x\n", tuning_num, rxdly[tuning_num-1]);
goto tunning;
pr_debug("%s(), d1_dly %d, window start %d, size %d\n",
__func__, d1_dly, best_win_start, best_win_size);
dly = readl(host->base + SD_EMMC_DELAY);
d1_dly = (dly >> 4) & 0xF;
if (d1_dly < 16) {
d1_dly++;
dly &= ~(0xF << 4);
dly |= d1_dly << 4;
writel(dly, host->base + SD_EMMC_DELAY);
pr_info("%s(), window is not sharp\n", __func__);
goto tunning;
} else
pr_err("%s(), all adj used out!\n", __func__);
} else {
pr_info("%s: best_win_start =%d, best_win_size =%d\n",
mmc_hostname(host->mmc), best_win_start, best_win_size);
@@ -788,7 +795,8 @@ tunning:
gadjust->cali_enable = 0;
gadjust->cali_rise = 0;
writel(adjust, host->base + SD_EMMC_ADJUST);
/* restore aligned data */
writel(old_dly, host->base + SD_EMMC_DELAY);
/* fixme, yyh for retry flow. */
emmc_adj->adj_win_start = best_win_start;
emmc_adj->adj_win_len = best_win_size;

View File

@@ -960,7 +960,6 @@ static int _aml_sd_emmc_execute_tuning(struct mmc_host *mmc, u32 opcode,
struct aml_tuning_data *tuning_data,
u32 adj_win_start)
{
#if 1 /* need finish later */
struct amlsd_platform *pdata = mmc_priv(mmc);
struct amlsd_host *host = pdata->host;
u32 vclk;
@@ -980,11 +979,15 @@ static int _aml_sd_emmc_execute_tuning(struct mmc_host *mmc, u32 opcode,
int wrap_win_start, wrap_win_size;
int best_win_start, best_win_size;
int curr_win_start, curr_win_size;
u32 rxdly[3] = {0xA28A28A, 0x15500514, 0x1FF8079E};
u32 old_dly, d1_dly, dly;
if ((host->mem->start == host->data->port_b_base)
&& host->data->tdma_f)
wait_for_completion(&host->drv_completion);
old_dly = readl(host->base + SD_EMMC_DELAY1_V3);
d1_dly = (old_dly >> 0x6) & 0x3F;
pr_info("Data 1 aligned delay is %d\n", d1_dly);
writel(0, host->base + SD_EMMC_ADJUST_V3);
tunning:
@@ -1045,7 +1048,6 @@ tunning:
curr_win_size = 0;
}
}
}
/* last point is ok! */
if (curr_win_start >= 0) {
@@ -1084,7 +1086,11 @@ tunning:
mmc_hostname(host->mmc));
goto tunning;
} else if (best_win_size == clk_div) {
if (++tuning_num > MAX_TUNING_RETRY) {
dly = readl(host->base + SD_EMMC_DELAY1_V3);
d1_dly = (dly >> 0x6) & 0x3F;
pr_warn("%s() d1_dly %d, window start %d, size %d\n",
__func__, d1_dly, best_win_start, best_win_size);
if (++d1_dly > 0x3F) {
pr_err("%s: tuning failed\n",
mmc_hostname(host->mmc));
host->is_tunning = 0;
@@ -1093,11 +1099,10 @@ tunning:
complete(&host->drv_completion);
return -1;
}
pr_warn("wave is not sharp, again\n");
/* add basic data rx delay */
writel(rxdly[tuning_num-1], host->base + SD_EMMC_DELAY1_V3);
writel(rxdly[tuning_num-1], host->base + SD_EMMC_DELAY2_V3);
pr_warn("rxdly @ %x\n", rxdly[tuning_num-1]);
dly &= ~(0x3F << 6);
dly |= d1_dly << 6;
pdata->dly1 = dly;
writel(dly, host->base + SD_EMMC_DELAY1_V3);
goto tunning;
} else
pr_info("%s: best_win_start =%d, best_win_size =%d\n",
@@ -1114,6 +1119,8 @@ tunning:
gadjust->cali_rise = 0;
writel(adjust, host->base + SD_EMMC_ADJUST_V3);
pdata->adj = adjust;
pdata->dly1 = old_dly;
writel(old_dly, host->base + SD_EMMC_DELAY1_V3);
pr_info("%s: sd_emmc_regs->gclock=0x%x,sd_emmc_regs->gadjust=0x%x\n",
mmc_hostname(host->mmc),
@@ -1125,8 +1132,6 @@ tunning:
complete(&host->drv_completion);
return ret;
#endif
return 0;
}
int aml_get_data_eyetest(struct mmc_host *mmc)