diff --git a/arch/arm/boot/dts/amlogic/mesontl1.dtsi b/arch/arm/boot/dts/amlogic/mesontl1.dtsi index e0f59bc4ddd0..287df2f962ad 100644 --- a/arch/arm/boot/dts/amlogic/mesontl1.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontl1.dtsi @@ -1120,8 +1120,9 @@ <&clkc CLKID_SD_EMMC_C_P0_COMP>, <&clkc CLKID_FCLK_DIV2>, <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_GP0_PLL>, <&xtal>; - clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + clock-names = "core","clkin0","clkin1","clkin2","clkin3","xtal"; bus-width = <8>; cap-sd-highspeed; diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts index f2d2b8564f98..d5741b9e6ac1 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts @@ -1318,10 +1318,9 @@ "MMC_CAP_HW_RESET", "MMC_CAP_ERASE", "MMC_CAP_CMD23"; - caps2 = "MMC_CAP2_HS200"; - /* "MMC_CAP2_HS400";*/ + caps2 = "MMC_CAP2_HS200", "MMC_CAP2_HS400"; f_min = <400000>; - f_max = <200000000>; + f_max = <198000000>; }; }; diff --git a/drivers/amlogic/clk/tl1/tl1_clk_sdemmc.c b/drivers/amlogic/clk/tl1/tl1_clk_sdemmc.c index 37c37402f025..b5479b615f49 100644 --- a/drivers/amlogic/clk/tl1/tl1_clk_sdemmc.c +++ b/drivers/amlogic/clk/tl1/tl1_clk_sdemmc.c @@ -27,7 +27,7 @@ #include "tl1.h" PNAME(sd_emmc_parent_names) = { "xtal", "fclk_div2", - "fclk_div3", "fclk_div5", "fclk_div7", "mpll2", "mpll3", "gp0" }; + "fclk_div3", "fclk_div5", "fclk_div7", "mpll2", "mpll3", "gp0_pll" }; /*sd_emmc B*/ static MUX(sd_emmc_p0_mux_B, HHI_SD_EMMC_CLK_CNTL, 0x7, 25, sd_emmc_parent_names, CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED); diff --git a/drivers/amlogic/mmc/aml_sd_emmc.c b/drivers/amlogic/mmc/aml_sd_emmc.c index 6e1e4dc749db..b9f192ca783f 100644 --- a/drivers/amlogic/mmc/aml_sd_emmc.c +++ b/drivers/amlogic/mmc/aml_sd_emmc.c @@ -2618,7 +2618,7 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id) mmc_hostname(host->mmc), vstat, virqc); host->status = HOST_RSP_CRC_ERR; - mrq->cmd->error = -EILSEQ; + mrq->cmd->error = -EBADMSG; } else if (ista->resp_timeout) { if (host->is_tunning == 0) pr_err("%s: resp_timeout,vstat:0x%x,virqc:%x\n", @@ -3327,6 +3327,16 @@ static int meson_mmc_probe(struct platform_device *pdev) #endif /* CONFIG_MESON_CPU_EMULATOR */ } pr_info("%s() : success!\n", __func__); + if (host->ctrl_ver >= 3) { + ret = device_create_file(&pdev->dev, &dev_attr_emmc_eyetest); + if (ret) + dev_warn(mmc_dev(host->mmc), + "Unable to creat sysfs attributes\n"); + ret = device_create_file(&pdev->dev, &dev_attr_emmc_clktest); + if (ret) + dev_warn(mmc_dev(host->mmc), + "Unable to creat sysfs attributes\n"); + } return 0; free_host: @@ -3581,9 +3591,11 @@ static struct meson_mmc_data mmc_data_g12b = { .sdmmc.hs.core_phase = 1, .sdmmc.ddr.core_phase = 2, .sdmmc.ddr.tx_phase = 0, - .sdmmc.hs2.core_phase = 3, + .sdmmc.hs2.core_phase = 2, .sdmmc.hs2.tx_phase = 0, - .sdmmc.hs4.tx_delay = 0, + .sdmmc.hs4.tx_phase = 0, + .sdmmc.hs4.core_phase = 0, + .sdmmc.hs4.tx_delay = 16, .sdmmc.sd_hs.core_phase = 2, .sdmmc.sdr104.core_phase = 2, .sdmmc.sdr104.tx_phase = 0, @@ -3604,8 +3616,9 @@ static struct meson_mmc_data mmc_data_tl1 = { .sdmmc.init.rx_phase = 0, .sdmmc.hs.core_phase = 1, .sdmmc.ddr.core_phase = 2, - .sdmmc.hs2.core_phase = 3, - .sdmmc.hs4.tx_delay = 0, + .sdmmc.hs2.core_phase = 2, + .sdmmc.hs4.core_phase = 0, + .sdmmc.hs4.tx_delay = 16, .sdmmc.sd_hs.core_phase = 2, .sdmmc.sdr104.core_phase = 2, }; diff --git a/drivers/amlogic/mmc/aml_sd_emmc_v3.c b/drivers/amlogic/mmc/aml_sd_emmc_v3.c index b04f7901d6a5..35cf1e87ae34 100644 --- a/drivers/amlogic/mmc/aml_sd_emmc_v3.c +++ b/drivers/amlogic/mmc/aml_sd_emmc_v3.c @@ -234,7 +234,23 @@ static int meson_mmc_clk_set_rate_v3(struct mmc_host *mmc, src0_clk = devm_clk_get(host->dev, "clkin2"); ret = clk_set_parent(host->mux_parent[0], src0_clk); if (ret) - pr_warn("set src0: div5 as comp0 parent error\n"); + pr_warn("set src0 as comp0 parent error\n"); + ret = clk_set_parent(host->mux_clk, + host->mux_parent[0]); + if (ret) + pr_warn("set comp0 as mux_clk parent error\n"); + } else if ((host->data->chip_type == MMC_CHIP_TL1) + && (clk_ios >= 166000000)) { + src0_clk = devm_clk_get(host->dev, "clkin3"); + if (ret) + pr_warn("not get GP0\n"); + ret = clk_set_rate(src0_clk, 792000000); + pr_warn("set rate gp0>>>>>>>>>clk:%lu\n", + clk_get_rate(src0_clk)); + ret = clk_set_parent(host->mux_parent[0], + src0_clk); + if (ret) + pr_warn("set src0 as comp0 parent error\n"); ret = clk_set_parent(host->mux_clk, host->mux_parent[0]); if (ret) @@ -278,7 +294,7 @@ static int meson_mmc_clk_set_rate_v3(struct mmc_host *mmc, mmc->actual_clock, readl(host->clksrc_base + (HHI_NAND_CLK_CNTL << 2))); - pr_debug("[%s] after clock: 0x%x\n", + pr_debug("[%s] after clock: 0x%x\n", __func__, readl(host->base + SD_EMMC_CLOCK_V3)); return ret; @@ -297,11 +313,21 @@ static void aml_sd_emmc_set_timing_v3(struct amlsd_platform *pdata, u8 clk_div = 0; struct para_e *para = &(host->data->sdmmc); unsigned int fixdiv = 0, ret = 0; + u32 irq_en = readl(host->base + SD_EMMC_IRQ_EN); vctrl = readl(host->base + SD_EMMC_CFG); if ((timing == MMC_TIMING_MMC_HS400) || (timing == MMC_TIMING_MMC_DDR52) || (timing == MMC_TIMING_UHS_DDR50)) { + + if (timing == MMC_TIMING_MMC_DDR52) { + if (aml_card_type_mmc(pdata)) { + clkc->core_phase = para->ddr.core_phase; + clkc->tx_phase = para->ddr.tx_phase; + } + pr_info("%s: try set sd/emmc to DDR mode\n", + mmc_hostname(host->mmc)); + } if (timing == MMC_TIMING_MMC_HS400) { /*ctrl->chk_ds = 1;*/ if (host->data->chip_type >= MMC_CHIP_TXLX) { @@ -315,6 +341,17 @@ static void aml_sd_emmc_set_timing_v3(struct amlsd_platform *pdata, */ if (pdata->tx_delay != 0) clkc->tx_delay = pdata->tx_delay; + + if ((host->data->chip_type == MMC_CHIP_TL1) + && aml_card_type_mmc(pdata)) { + clkc->core_phase = para->hs4.core_phase; + clkc->tx_phase = para->hs4.tx_phase; + + irq_en |= (1<<17); + writel(irq_en, + host->base + SD_EMMC_IRQ_EN); + /*improve CMD setup time by half SD_CLK cycle*/ + } } pr_info("%s: try set sd/emmc to HS400 mode\n", mmc_hostname(host->mmc)); @@ -324,12 +361,6 @@ static void aml_sd_emmc_set_timing_v3(struct amlsd_platform *pdata, if (clk_div & 0x01) clk_div++; clkc->div = clk_div / 2; - if (aml_card_type_mmc(pdata)) { - clkc->core_phase = para->ddr.core_phase; - clkc->tx_phase = para->ddr.tx_phase; - } - pr_info("%s: try set sd/emmc to DDR mode\n", - mmc_hostname(host->mmc)); } else if (timing == MMC_TIMING_MMC_HS) { clkc->core_phase = para->hs.core_phase; /* overide co-phase by dts */ @@ -658,7 +689,7 @@ static int emmc_send_cmd(struct mmc_host *mmc, u32 opcode, err = mmc_wait_for_cmd(mmc, &cmd, 3); if (err) { - pr_info("[%s][%d] cmd:0x%x send error\n", + pr_debug("[%s][%d] cmd:0x%x send error\n", __func__, __LINE__, cmd.opcode); return err; } @@ -746,9 +777,10 @@ RETRY: eyetest_out1 = readl(host->base + SD_EMMC_EYETEST_OUT1); gintf3->eyetest_on = 0; writel(intf3, host->base + SD_EMMC_INTF3); + writel(0, host->base + SD_EMMC_ADJUST_V3); pdata->intf3 = intf3; pdata->align[line_x] = ((tmp | eyetest_out1) << 32) | eyetest_out0; - pr_debug("d1:0x%x,d2:0x%x,u64eyet:0x%016llx,l_x:%d\n", + pr_info("d1:0x%x,d2:0x%x,u64eyet:0x%016llx,l_x:%d\n", readl(host->base + SD_EMMC_DELAY1_V3), readl(host->base + SD_EMMC_DELAY2_V3), pdata->align[line_x], line_x); @@ -873,6 +905,25 @@ static void update_all_line_eyetest(struct mmc_host *mmc) } } +static unsigned int tl1_emmc_line_timing(struct mmc_host *mmc) +{ + struct amlsd_platform *pdata = mmc_priv(mmc); + struct amlsd_host *host = pdata->host; + u32 delay1 = 0, delay2 = 0, count = 12; + + delay1 = (count<<0)|(count<<6)|(count<<12) + |(count<<18)|(count<<24); + delay2 = (count<<0)|(count<<6)|(count<<12) + |(pdata->cmd_c<<24); + writel(delay1, host->base + SD_EMMC_DELAY1_V3); + writel(delay2, host->base + SD_EMMC_DELAY2_V3); + pr_info("[%s], delay1: 0x%x, delay2: 0x%x\n", + __func__, readl(host->base + SD_EMMC_DELAY1_V3), + readl(host->base + SD_EMMC_DELAY2_V3)); + return 0; + +} + static unsigned int get_emmc_cmd_win(struct mmc_host *mmc) { struct amlsd_platform *pdata = mmc_priv(mmc); @@ -992,20 +1043,12 @@ static int emmc_ds_manual_sht(struct mmc_host *mmc) struct intf3 *gintf3 = (struct intf3 *)&(intf3); u32 blksz = 512; int i, err = 0; - int match[32]; + int match[64]; int best_start = -1, best_size = -1; int cur_start = -1, cur_size = 0; - sd_emmc_debug = 0x2000; - update_all_line_eyetest(mmc); - emmc_ds_core_align(mmc); - update_all_line_eyetest(mmc); - emmc_all_data_line_alignment(mmc); - update_all_line_eyetest(mmc); - emmc_ds_data_alignment(mmc); - update_all_line_eyetest(mmc); host->is_tunning = 1; - for (i = 0; i < 32; i++) { + for (i = 0; i < 64; i++) { gintf3->ds_sht_m += 1; writel(intf3, host->base + SD_EMMC_INTF3); pdata->intf3 = intf3; @@ -1019,7 +1062,7 @@ static int emmc_ds_manual_sht(struct mmc_host *mmc) else match[i] = -1; } - for (i = 0; i < 32; i++) { + for (i = 0; i < 64; i++) { if (match[i] == 0) { if (cur_start < 0) cur_start = i; @@ -1059,11 +1102,31 @@ static int emmc_ds_manual_sht(struct mmc_host *mmc) gintf3->ds_sht_m, best_size, 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; return 0; } #endif +static void aml_emmc_hs400_general(struct mmc_host *mmc) +{ + + update_all_line_eyetest(mmc); + emmc_ds_core_align(mmc); + update_all_line_eyetest(mmc); + emmc_all_data_line_alignment(mmc); + update_all_line_eyetest(mmc); + emmc_ds_data_alignment(mmc); + update_all_line_eyetest(mmc); + emmc_ds_manual_sht(mmc); +} + +static void aml_emmc_hs400_tl1(struct mmc_host *mmc) +{ + + tl1_emmc_line_timing(mmc); + emmc_ds_manual_sht(mmc); +} /* test clock, return delay cells for one cycle */ @@ -1382,6 +1445,47 @@ RETRY: return 0; } +int aml_emmc_hs200_tl1(struct mmc_host *mmc) +{ + struct amlsd_platform *pdata = mmc_priv(mmc); + struct amlsd_host *host = pdata->host; + u32 vclkc = readl(host->base + SD_EMMC_CLOCK_V3); + struct sd_emmc_clock_v3 *clkc = (struct sd_emmc_clock_v3 *)&vclkc; + struct para_e *para = &(host->data->sdmmc); + u32 clk_bak = 0; + u32 delay2 = 0, count = 0; + int i, err = 0; + + clk_bak = vclkc; + clkc->core_phase = para->hs4.core_phase; + clkc->tx_delay = para->hs4.tx_delay; + if (pdata->tx_delay != 0) + clkc->tx_delay = pdata->tx_delay; + writel(vclkc, host->base + SD_EMMC_CLOCK_V3); + pr_info("[%s][%d] clk config:0x%x\n", + __func__, __LINE__, readl(host->base + SD_EMMC_CLOCK_V3)); + for (i = 0; i < 63; i++) { + delay2 += (1 << 24); + writel(delay2, host->base + SD_EMMC_DELAY2_V3); + err = emmc_eyetest_log(mmc, 9); + if (err) + continue; + count = fbinary(pdata->align[9]); + if (((count >= 10) && (count <= 22)) + || ((count >= 43) && (count <= 56))) + break; + } + if (i == 63) + pr_err("[%s]no find cmd timing\n", __func__); + pdata->cmd_c = (delay2 >> 24); + writel(0, host->base + SD_EMMC_DELAY2_V3); + writel(clk_bak, host->base + SD_EMMC_CLOCK_V3); + pr_info("[%s][%d] clk config:0x%x\n", + __func__, __LINE__, readl(host->base + SD_EMMC_CLOCK_V3)); + return 0; + +} + int __attribute__((unused)) aml_emmc_hs200_timming(struct mmc_host *mmc) { struct amlsd_platform *pdata = mmc_priv(mmc); @@ -1642,6 +1746,8 @@ int aml_mmc_execute_tuning_v3(struct mmc_host *mmc, u32 opcode) intf3 |= (1<<22); writel(intf3, (host->base + SD_EMMC_INTF3)); pdata->intf3 = intf3; + if (host->data->chip_type == MMC_CHIP_TL1) + aml_emmc_hs200_tl1(mmc); err = 0; } @@ -1654,9 +1760,13 @@ int aml_mmc_execute_tuning_v3(struct mmc_host *mmc, u32 opcode) } int aml_post_hs400_timming(struct mmc_host *mmc) { - int ret = 0; + struct amlsd_platform *pdata = mmc_priv(mmc); + struct amlsd_host *host = pdata->host; aml_sd_emmc_clktest(mmc); - ret = emmc_ds_manual_sht(mmc); + if (host->data->chip_type == MMC_CHIP_TL1) + aml_emmc_hs400_tl1(mmc); + else + aml_emmc_hs400_general(mmc); return 0; } diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 691db1bcdb1c..f8d6df5076d1 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1192,15 +1192,20 @@ static int mmc_select_hs400(struct mmc_card *card) pr_info("%s: no support driver strength type 1 and 4\n", mmc_hostname(host)); } + err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_HS_TIMING, val, + card->ext_csd.generic_cmd6_time, + true, true, true); #else val = EXT_CSD_TIMING_HS400 | card->drive_strength << EXT_CSD_DRV_STR_SHIFT; -#endif err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, val, card->ext_csd.generic_cmd6_time, true, false, true); +#endif + if (err) { pr_err("%s: switch to hs400 failed, err:%d\n", mmc_hostname(host), err); @@ -1211,9 +1216,11 @@ static int mmc_select_hs400(struct mmc_card *card) mmc_set_timing(host, MMC_TIMING_MMC_HS400); mmc_set_bus_speed(card); +#ifndef CONFIG_AMLOGIC_MMC err = mmc_switch_status(card); if (err) goto out_err; +#endif return 0; diff --git a/include/linux/amlogic/sd.h b/include/linux/amlogic/sd.h index bcd815bb69b2..5fea7cc01f87 100644 --- a/include/linux/amlogic/sd.h +++ b/include/linux/amlogic/sd.h @@ -331,6 +331,7 @@ struct amlsd_platform { u64 align[10]; int base_line; unsigned int count; + unsigned int cmd_c; unsigned int delay_cell; /* int order; */ unsigned int rx_err;