X-Git-Url: https://git.karo-electronics.de/?a=blobdiff_plain;f=drivers%2Fmmc%2Ftegra_mmc.c;h=08b4bd48245a3166a982ec974cf9bfa33950d4a1;hb=67748a73b14b239283bc1ace7564a124b714b75e;hp=c9d9432e5e87edc2149a264ef3b9df092032e179;hpb=2313d48445e59f063ec9a3b4940fe8252737db76;p=karo-tx-uboot.git diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c index c9d9432e5e..08b4bd4824 100644 --- a/drivers/mmc/tegra_mmc.c +++ b/drivers/mmc/tegra_mmc.c @@ -9,6 +9,8 @@ #include #include +#include +#include #include #include #ifndef CONFIG_TEGRA186 @@ -19,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]; @@ -216,14 +227,14 @@ static int mmc_send_cmd_bounced(struct mmc *mmc, struct mmc_cmd *cmd, if (i == retry) { printf("%s: waiting for status update\n", __func__); writel(mask, &host->reg->norintsts); - return TIMEOUT; + return -ETIMEDOUT; } if (mask & TEGRA_MMC_NORINTSTS_CMD_TIMEOUT) { /* Timeout Error */ debug("timeout: %08x cmd %d\n", mask, cmd->cmdidx); writel(mask, &host->reg->norintsts); - return TIMEOUT; + return -ETIMEDOUT; } else if (mask & TEGRA_MMC_NORINTSTS_ERR_INTERRUPT) { /* Error Interrupt */ debug("error: %08x cmd %d\n", mask, cmd->cmdidx); @@ -257,7 +268,7 @@ static int mmc_send_cmd_bounced(struct mmc *mmc, struct mmc_cmd *cmd, if (i == retry) { printf("%s: card is still busy\n", __func__); writel(mask, &host->reg->norintsts); - return TIMEOUT; + return -ETIMEDOUT; } cmd->response[0] = readl(&host->reg->rspreg0); @@ -359,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); @@ -538,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]; @@ -549,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 @@ -576,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; @@ -612,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, "sdhci", &host->reset_ctl); + if (ret) { + debug("reset_get_by_name() failed: %d\n", ret); + return ret; + } + ret = clk_get_by_index(&dev, 0, &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__); @@ -689,7 +736,7 @@ void tegra_mmc_init(void) debug("%s entry\n", __func__); /* See if any Tegra186 MMC controllers are present */ - count = fdtdec_find_aliases_for_id(blob, "sdhci", + count = fdtdec_find_aliases_for_id(blob, "mmc", COMPAT_NVIDIA_TEGRA186_SDMMC, node_list, CONFIG_SYS_MMC_MAX_DEVICE); debug("%s: count of Tegra186 sdhci nodes is %d\n", __func__, count); @@ -699,7 +746,7 @@ void tegra_mmc_init(void) } /* See if any Tegra210 MMC controllers are present */ - count = fdtdec_find_aliases_for_id(blob, "sdhci", + count = fdtdec_find_aliases_for_id(blob, "mmc", COMPAT_NVIDIA_TEGRA210_SDMMC, node_list, CONFIG_SYS_MMC_MAX_DEVICE); debug("%s: count of Tegra210 sdhci nodes is %d\n", __func__, count); @@ -709,7 +756,7 @@ void tegra_mmc_init(void) } /* See if any Tegra124 MMC controllers are present */ - count = fdtdec_find_aliases_for_id(blob, "sdhci", + count = fdtdec_find_aliases_for_id(blob, "mmc", COMPAT_NVIDIA_TEGRA124_SDMMC, node_list, CONFIG_SYS_MMC_MAX_DEVICE); debug("%s: count of Tegra124 sdhci nodes is %d\n", __func__, count); @@ -719,7 +766,7 @@ void tegra_mmc_init(void) } /* See if any Tegra30 MMC controllers are present */ - count = fdtdec_find_aliases_for_id(blob, "sdhci", + count = fdtdec_find_aliases_for_id(blob, "mmc", COMPAT_NVIDIA_TEGRA30_SDMMC, node_list, CONFIG_SYS_MMC_MAX_DEVICE); debug("%s: count of T30 sdhci nodes is %d\n", __func__, count); @@ -729,7 +776,7 @@ void tegra_mmc_init(void) } /* Now look for any Tegra20 MMC controllers */ - count = fdtdec_find_aliases_for_id(blob, "sdhci", + count = fdtdec_find_aliases_for_id(blob, "mmc", COMPAT_NVIDIA_TEGRA20_SDMMC, node_list, CONFIG_SYS_MMC_MAX_DEVICE); debug("%s: count of T20 sdhci nodes is %d\n", __func__, count);