Example #1
0
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);
	}
}
Example #2
0
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);
    }
}