static void exynos_dwmci_set_io_timing(void *data, unsigned int tuning, unsigned char timing, struct mmc_host *mmc) { struct dw_mci *host = (struct dw_mci *)data; struct dw_mci_board *pdata = host->pdata; struct dw_mci_clk *clk_tbl = pdata->clk_tbl; u32 clksel, rddqs, dline; u32 sclkin, cclkin; unsigned char timing_init = MMC_TIMING_INIT; if (timing > MMC_TIMING_MMC_HS200_DDR) { pr_err("%s: timing(%d): not suppored\n", __func__, timing); return; } sclkin = clk_tbl[timing].sclkin; cclkin = clk_tbl[timing].cclkin; if (timing == MMC_TIMING_LEGACY && pdata->misc_flag & DW_MMC_MISC_LOW_FREQ_HOOK) { if (mmc == NULL || (mmc && mmc->ios.clock <= mmc->f_init)) { sclkin = clk_tbl[timing_init].sclkin; cclkin = clk_tbl[timing_init].cclkin; } } rddqs = DWMCI_DDR200_RDDQS_EN_DEF; dline = DWMCI_DDR200_DLINE_CTRL_DEF; clksel = __raw_readl(host->regs + DWMCI_CLKSEL); if (host->bus_hz != cclkin) { host->bus_hz = cclkin; host->current_speed = 0; if (host->cclk2) clk_set_rate(host->cclk2, sclkin); clk_set_rate(host->cclk, sclkin); } if (timing == MMC_TIMING_MMC_HS200_DDR) { clksel = (pdata->ddr200_timing & 0xfffffff8) | pdata->clk_smpl; if (pdata->is_fine_tuned) clksel |= BIT(6); if (!tuning) { rddqs |= DWMCI_RDDQS_EN; if (host->pdata->delay_line) dline = DWMCI_FIFO_CLK_DELAY_CTRL(0x2) | DWMCI_RD_DQS_DELAY_CTRL(host->pdata->delay_line); else dline = DWMCI_FIFO_CLK_DELAY_CTRL(0x2) | DWMCI_RD_DQS_DELAY_CTRL(90); host->quirks &= ~DW_MCI_QUIRK_NO_DETECT_EBIT; } } else if (timing == MMC_TIMING_MMC_HS200 || timing == MMC_TIMING_UHS_SDR104) { clksel = (clksel & 0xfff8ffff) | (pdata->clk_drv << 16); } else if (timing == MMC_TIMING_UHS_SDR50) { clksel = (clksel & 0xfff8ffff) | (pdata->clk_drv << 16); } else if (timing == MMC_TIMING_UHS_DDR50) { clksel = pdata->ddr_timing; } else { clksel = pdata->sdr_timing; } __raw_writel(clksel, host->regs + DWMCI_CLKSEL); if (soc_is_exynos3250() || soc_is_exynos4415() || soc_is_exynos5420() || soc_is_exynos5260() || soc_is_exynos3470()) { __raw_writel(rddqs, host->regs + DWMCI_DDR200_RDDQS_EN + 0x70); __raw_writel(dline, host->regs + DWMCI_DDR200_DLINE_CTRL + 0x70); if (timing == MMC_TIMING_MMC_HS200_DDR) __raw_writel(0x1, host->regs + DWMCI_DDR200_ASYNC_FIFO_CTRL + 0x70); } else { __raw_writel(rddqs, host->regs + DWMCI_DDR200_RDDQS_EN); __raw_writel(dline, host->regs + DWMCI_DDR200_DLINE_CTRL); if (timing == MMC_TIMING_MMC_HS200_DDR) __raw_writel(0x1, host->regs + DWMCI_DDR200_ASYNC_FIFO_CTRL); } }
static void exynos_dwmci_set_io_timing(void *data, unsigned int tuning, unsigned char timing) { struct dw_mci *host = (struct dw_mci *)data; struct dw_mci_board *pdata = host->pdata; struct dw_mci_clk *clk_tbl = pdata->clk_tbl; u32 clksel, rddqs, dline; u32 sclkin, cclkin; unsigned char timing_org = timing; if (timing > MMC_TIMING_MMC_HS200_DDR_ES) { pr_err("%s: timing(%d): not suppored\n", __func__, timing); return; } if (timing == MMC_TIMING_MMC_HS200_DDR_ES) timing = MMC_TIMING_MMC_HS200_DDR; sclkin = clk_tbl[timing].sclkin; cclkin = clk_tbl[timing].cclkin; rddqs = DWMCI_DDR200_RDDQS_EN_DEF; dline = DWMCI_DDR200_DLINE_CTRL_DEF; clksel = __raw_readl(host->regs + DWMCI_CLKSEL); if (host->bus_hz != cclkin) { host->bus_hz = cclkin; host->current_speed = 0; clk_set_rate(host->cclk, sclkin); } if (timing == MMC_TIMING_MMC_HS200_DDR) { clksel = (pdata->ddr200_timing & 0xfffffff8) | pdata->clk_smpl; if (!tuning) { rddqs |= DWMCI_RDDQS_EN; if (timing_org == MMC_TIMING_MMC_HS200_DDR_ES) { rddqs |= DWMCI_RESP_RCLK_MODE; } #if defined(CONFIG_V1A) || defined(CONFIG_V2A) || defined(CONFIG_CHAGALL) dline = DWMCI_FIFO_CLK_DELAY_CTRL(0x2) | DWMCI_RD_DQS_DELAY_CTRL(110); #elif defined(CONFIG_N1A) || defined(CONFIG_N2A) dline = DWMCI_FIFO_CLK_DELAY_CTRL(0x2) | DWMCI_RD_DQS_DELAY_CTRL(100); #else dline = DWMCI_FIFO_CLK_DELAY_CTRL(0x2) | DWMCI_RD_DQS_DELAY_CTRL(90); #endif host->quirks &= ~DW_MCI_QUIRK_NO_DETECT_EBIT; } } else if (timing == MMC_TIMING_MMC_HS200 || timing == MMC_TIMING_UHS_SDR104) { clksel = (clksel & 0xfff8ffff) | (pdata->clk_drv << 16); } else if (timing == MMC_TIMING_UHS_SDR50) { clksel = (clksel & 0xfff8ffff) | (pdata->clk_drv << 16); } else if (timing == MMC_TIMING_UHS_DDR50) { clksel = pdata->ddr_timing; } else { clksel = pdata->sdr_timing; } __raw_writel(clksel, host->regs + DWMCI_CLKSEL); if (soc_is_exynos5420()) { __raw_writel(rddqs, host->regs + DWMCI_DDR200_RDDQS_EN + 0x70); __raw_writel(dline, host->regs + DWMCI_DDR200_DLINE_CTRL + 0x70); } else { __raw_writel(rddqs, host->regs + DWMCI_DDR200_RDDQS_EN); __raw_writel(dline, host->regs + DWMCI_DDR200_DLINE_CTRL); } }