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