diff --git a/arch/arm/include/asm/arch-tegra/tegra_mmc.h b/arch/arm/include/asm/arch-tegra/tegra_mmc.h index 75e56c4ea7..07ef4c04c8 100644 --- a/arch/arm/include/asm/arch-tegra/tegra_mmc.h +++ b/arch/arm/include/asm/arch-tegra/tegra_mmc.h @@ -9,6 +9,9 @@ #ifndef __TEGRA_MMC_H_ #define __TEGRA_MMC_H_ +#include +#include +#include #include #include @@ -134,7 +137,10 @@ struct mmc_host { int id; /* device id/number, 0-3 */ int enabled; /* 1 to enable, 0 to disable */ int width; /* Bus Width, 1, 4 or 8 */ -#ifndef CONFIG_TEGRA186 +#ifdef CONFIG_TEGRA186 + struct reset_ctl reset_ctl; + struct clk clk; +#else enum periph_id mmc_id; /* Peripheral ID: PERIPH_ID_... */ #endif struct gpio_desc cd_gpio; /* Change Detect GPIO */ diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c index 023ba3c643..f0a39a63c6 100644 --- a/drivers/mmc/tegra_mmc.c +++ b/drivers/mmc/tegra_mmc.c @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -20,6 +21,15 @@ #include #include +/* + * FIXME: TODO: This driver contains a number of ifdef CONFIG_TEGRA186 that + * should not be present. These are needed because newer Tegra SoCs support + * only the standard clock/reset APIs, whereas older Tegra SoCs support only + * a custom Tegra-specific API. ASAP the older Tegra SoCs' code should be + * fixed to implement the standard APIs, and all drivers converted to solely + * use the new standard APIs, with no ifdefs. + */ + DECLARE_GLOBAL_DATA_PTR; struct mmc_host mmc_host[CONFIG_SYS_MMC_MAX_DEVICE]; @@ -360,11 +370,14 @@ static void mmc_change_clock(struct mmc_host *host, uint clock) */ if (clock == 0) goto out; -#ifndef CONFIG_TEGRA186 +#ifdef CONFIG_TEGRA186 + { + ulong rate = clk_set_rate(&host->clk, clock); + div = (rate + clock - 1) / clock; + } +#else clock_adjust_periph_pll_div(host->mmc_id, CLOCK_ID_PERIPH, clock, &div); -#else - div = (20000000 + clock - 1) / clock; #endif debug("div = %d\n", div); @@ -539,6 +552,9 @@ static int do_mmc_init(int dev_index, bool removable) { struct mmc_host *host; struct mmc *mmc; +#ifdef CONFIG_TEGRA186 + int ret; +#endif /* DT should have been read & host config filled in */ host = &mmc_host[dev_index]; @@ -550,7 +566,21 @@ static int do_mmc_init(int dev_index, bool removable) gpio_get_number(&host->cd_gpio)); host->clock = 0; -#ifndef CONFIG_TEGRA186 + +#ifdef CONFIG_TEGRA186 + ret = reset_assert(&host->reset_ctl); + if (ret) + return ret; + ret = clk_enable(&host->clk); + if (ret) + return ret; + ret = clk_set_rate(&host->clk, 20000000); + if (IS_ERR_VALUE(ret)) + return ret; + ret = reset_deassert(&host->reset_ctl); + if (ret) + return ret; +#else clock_start_periph_pll(host->mmc_id, CLOCK_ID_PERIPH, 20000000); #endif @@ -577,11 +607,7 @@ static int do_mmc_init(int dev_index, bool removable) * (actually 52MHz) */ host->cfg.f_min = 375000; -#ifndef CONFIG_TEGRA186 host->cfg.f_max = 48000000; -#else - host->cfg.f_max = 375000; -#endif host->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; @@ -613,7 +639,27 @@ static int mmc_get_config(const void *blob, int node, struct mmc_host *host, return -FDT_ERR_NOTFOUND; } -#ifndef CONFIG_TEGRA186 +#ifdef CONFIG_TEGRA186 + { + /* + * FIXME: This variable should go away when the MMC device + * actually is a udevice. + */ + struct udevice dev; + int ret; + dev.of_offset = node; + ret = reset_get_by_name(&dev, "sdmmc", &host->reset_ctl); + if (ret) { + debug("reset_get_by_index() failed: %d\n", ret); + return ret; + } + ret = clk_get_by_name(&dev, "sdmmc", &host->clk); + if (ret) { + debug("clk_get_by_index() failed: %d\n", ret); + return ret; + } + } +#else host->mmc_id = clock_decode_periph_id(blob, node); if (host->mmc_id == PERIPH_ID_NONE) { debug("%s: could not decode periph id\n", __func__);