X-Git-Url: https://git.karo-electronics.de/?a=blobdiff_plain;f=drivers%2Fmmc%2Ftegra_mmc.c;h=08b4bd48245a3166a982ec974cf9bfa33950d4a1;hb=67748a73b14b239283bc1ace7564a124b714b75e;hp=573819a01e21a69d83aa3a6fc63f4240c78a46d3;hpb=cf432dd5953e9ddf06759565c80fed470882da6d;p=karo-tx-uboot.git diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c index 573819a01e..08b4bd4824 100644 --- a/drivers/mmc/tegra_mmc.c +++ b/drivers/mmc/tegra_mmc.c @@ -9,14 +9,27 @@ #include #include +#include +#include #include #include +#ifndef CONFIG_TEGRA186 #include #include +#endif #include #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]; @@ -214,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); @@ -255,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); @@ -357,8 +370,15 @@ static void mmc_change_clock(struct mmc_host *host, uint clock) */ if (clock == 0) goto out; +#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); +#endif debug("div = %d\n", div); writew(0, &host->reg->clkcon); @@ -532,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]; @@ -543,7 +566,23 @@ static int do_mmc_init(int dev_index, bool removable) gpio_get_number(&host->cd_gpio)); host->clock = 0; + +#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 if (dm_gpio_is_valid(&host->pwr_gpio)) dm_gpio_set_value(&host->pwr_gpio, 1); @@ -600,11 +639,33 @@ static int mmc_get_config(const void *blob, int node, struct mmc_host *host, return -FDT_ERR_NOTFOUND; } +#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__); return -FDT_ERR_NOTFOUND; } +#endif /* * NOTE: mmc->bus_width is determined by mmc.c dynamically. @@ -624,7 +685,13 @@ static int mmc_get_config(const void *blob, int node, struct mmc_host *host, *removablep = !fdtdec_get_bool(blob, node, "non-removable"); debug("%s: found controller at %p, width = %d, periph_id = %d\n", - __func__, host->reg, host->width, host->mmc_id); + __func__, host->reg, host->width, +#ifndef CONFIG_TEGRA186 + host->mmc_id +#else + -1 +#endif + ); return 0; } @@ -668,8 +735,18 @@ void tegra_mmc_init(void) const void *blob = gd->fdt_blob; debug("%s entry\n", __func__); + /* See if any Tegra186 MMC controllers are present */ + 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); + if (process_nodes(blob, node_list, count)) { + printf("%s: Error processing T186 mmc node(s)!\n", __func__); + return; + } + /* 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); @@ -679,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); @@ -689,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); @@ -699,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);