emmc: Optimized hs200 mode with the known latest data line
authorLong Yu <long.yu@amlogic.com>
Fri, 27 Apr 2018 09:48:15 +0000 (17:48 +0800)
committerJianxin Pan <jianxin.pan@amlogic.com>
Fri, 22 Jun 2018 07:17:38 +0000 (00:17 -0700)
PD#165333: emmc: Optimized hs200 mode with the known latest data line

Change-Id: Ic1581dbfbadda8e14879beabb4f7ae4a4a30546f
Signed-off-by: Long Yu <long.yu@amlogic.com>
drivers/amlogic/mmc/aml_sd_emmc.c
drivers/amlogic/mmc/aml_sd_emmc_v3.c
drivers/amlogic/mmc/amlsd_of.c
include/linux/amlogic/sd.h

index a117f51..25a0817 100644 (file)
@@ -3354,6 +3354,7 @@ static struct meson_mmc_data mmc_data_txlx = {
        .ds_pin_poll = 0x3c,
        .ds_pin_poll_en = 0x4a,
        .ds_pin_poll_bit = 11,
+       .latest_dat = 7,
        .sdmmc.init.core_phase = 3,
        .sdmmc.init.tx_phase = 0,
        .sdmmc.init.rx_phase = 0,
index 4cd922c..7a5772b 100644 (file)
@@ -1132,40 +1132,106 @@ tunning:
        return 0;
 }
 
-int aml_emmc_hs200_timming(struct mmc_host *mmc)
+int aml_get_data_eyetest(struct mmc_host *mmc)
 {
        struct amlsd_platform *pdata = mmc_priv(mmc);
        struct amlsd_host *host = pdata->host;
-       u32 count = 0, delay1 = 0, delay2 = 0, line_x;
+       u32 delay1 = readl(host->base + SD_EMMC_DELAY1_V3);
+       u32 delay2 = readl(host->base + SD_EMMC_DELAY2_V3);
+       int ret = 0, retry = 10, line_x;
 
        host->is_timming = 1;
-       pr_info("[%s] 2017-8-30 emmc HS200 Timming\n", __func__);
+       host->is_tunning = 1;
+       pr_info("[%s] 2018-4-18 emmc HS200 Timming\n", __func__);
        aml_sd_emmc_clktest(mmc);
-       update_all_line_eyetest(mmc);
-       for (line_x = 0; line_x < 8; line_x++) {
-               count = fbinary(pdata->align[line_x]);
-               if (count < (pdata->count / 2))
-                       count = (pdata->count / 2) - count;
-               else
-                       count = 0;
-               if (line_x < 5)
-                       delay1 |= count << (6 * line_x);
-               else
-                       delay2 |= count << (6 * (line_x - 5));
-               pr_debug("gadjust:0x%x,intf3:0x%x,count:%u,line_x:%d\n",
-                       readl(host->base + SD_EMMC_ADJUST_V3),
-                       readl(host->base + SD_EMMC_INTF3),
-                       count, line_x);
+       for (line_x = 0; line_x < 10; line_x++) {
+               if (line_x == 8)
+                       continue;
+RETRY:
+               ret = emmc_eyetest_log(mmc, line_x);
+               if (ret && retry) {
+                       pr_info("add dly [%d],retry%d...\n",
+                               line_x, retry);
+                       if (line_x < 5) {
+                               delay1 += (2<<(6*line_x));
+                               writel(delay1,
+                                       (host->base + SD_EMMC_DELAY1_V3));
+                       } else {
+                               delay2 += (2<<(6*(line_x-5)));
+                               writel(delay2,
+                                       (host->base + SD_EMMC_DELAY2_V3));
+                       }
+                       pr_debug("gdelay1: 0x%x, gdelay2: 0x%x\n",
+                               readl(host->base + SD_EMMC_DELAY1_V3),
+                               readl(host->base + SD_EMMC_DELAY2_V3));
+                       retry--;
+                       goto RETRY;
+               } else if (ret && !retry) {
+                       pr_info("retry failed,line:%d\n",
+                               line_x);
+                       return 1;
+               }
+               retry = 10;
        }
-       writel(delay1, host->base + SD_EMMC_DELAY1_V3);
-       writel(delay2, host->base + SD_EMMC_DELAY2_V3);
-       pdata->dly1 = delay1;
-       pdata->dly2 = delay2;
-       pr_debug("gdelay1: 0x%x, gdelay2: 0x%x\n",
-                       readl(host->base + SD_EMMC_DELAY1_V3),
-                       readl(host->base + SD_EMMC_DELAY2_V3));
+       pr_debug("gadjust:0x%x,intf3:0x%x\n",
+               readl(host->base + SD_EMMC_ADJUST_V3),
+               readl(host->base + SD_EMMC_INTF3));
+       pr_info("gdelay1: 0x%x, gdelay2: 0x%x\n",
+               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;
+}
+
+int aml_emmc_hs200_timming(struct mmc_host *mmc)
+{
+       struct amlsd_platform *pdata = mmc_priv(mmc);
+       struct amlsd_host *host = pdata->host;
+       u32 count = 0, delay1 = 0, delay2 = 0;
+       u32 dat = host->data->latest_dat;
+       int ret = 0;
+
+       ret = aml_get_data_eyetest(mmc);
+       if (ret) {
+               pr_info("[%s]hs200 timing err!\n",
+                               __func__);
+               return 1;
+       }
+       delay1 = readl(host->base + SD_EMMC_DELAY1_V3);
+       delay2 = readl(host->base + SD_EMMC_DELAY2_V3);
+       if (pdata->latest_dat != 0)
+               dat = pdata->latest_dat;
+       count = fbinary(pdata->align[dat]);
+       if (count <= pdata->count/3)
+               count = pdata->count/3 - count;
+       else if (count <= (pdata->count*2)/3)
+               count = 0;
+       else
+               count = pdata->count/2;
+       delay1 = (count<<0)|(count<<6)|(count<<12)
+               |(count<<18)|(count<<24);
+       writel(delay1, (host->base + SD_EMMC_DELAY1_V3));
+       delay2 = (count<<0)|(count<<6)|(count<<12);
+       writel(delay2, (host->base + SD_EMMC_DELAY2_V3));
+       pr_info("delay1: 0x%x , delay2: 0x%x\n",
+               readl(host->base + SD_EMMC_DELAY1_V3),
+               readl(host->base + SD_EMMC_DELAY2_V3));
+
+       count = fbinary(pdata->align[9]);
+       if (count <= pdata->count/4)
+               count = pdata->count/4 - count;
+       else if (count <= pdata->count*3/4)
+               count = 0;
+       else
+               count = (64 - count) + pdata->count/4;
+       delay2 += (count<<24);
+       writel(delay2, (host->base + SD_EMMC_DELAY2_V3));
+       pr_info("delay1: 0x%x , delay2: 0x%x, latest_dat:%d\n",
+           readl(host->base + SD_EMMC_DELAY1_V3),
+               readl(host->base + SD_EMMC_DELAY2_V3), dat);
+       update_all_line_eyetest(mmc);
        return 0;
 }
 
index 847860c..9e4bee0 100644 (file)
@@ -184,6 +184,8 @@ int amlsd_get_platform_data(struct platform_device *pdev,
                                prop, pdata->card_type);
                SD_PARSE_U32_PROP_DEC(child, "tx_delay",
                                                prop, pdata->tx_delay);
+               SD_PARSE_U32_PROP_DEC(child, "latest_dat",
+                                               prop, pdata->latest_dat);
                SD_PARSE_U32_PROP_DEC(child, "co_phase",
                                                prop, pdata->co_phase);
                if (aml_card_type_mmc(pdata)) {
index fe480c7..2096b72 100644 (file)
@@ -217,6 +217,7 @@ struct meson_mmc_data {
        unsigned int ds_pin_poll;
        unsigned int ds_pin_poll_en;
        unsigned int ds_pin_poll_bit;
+       unsigned int latest_dat;
        struct para_e sdmmc;
 };
 
@@ -300,6 +301,7 @@ struct amlsd_platform {
        unsigned char caling;
        unsigned char calout[20][20];
 #endif
+       unsigned int latest_dat;
        u64 align[10];
        int base_line;
        unsigned int count;