sdemmc: update fix adj tuning method
authorYonghui Yu <yonghui.yu@amlogic.com>
Wed, 8 Aug 2018 07:51:02 +0000 (15:51 +0800)
committerYonghui Yu <yonghui.yu@amlogic.com>
Mon, 3 Sep 2018 10:09:05 +0000 (18:09 +0800)
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>
drivers/amlogic/mmc/aml_sd_emmc.c
drivers/amlogic/mmc/aml_sd_emmc_v3.c

index 146b3e0..015a120 100644 (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;
index 627b707..7e79f87 100644 (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)