mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-12-01 08:59:33 +00:00
mmc: tegra: add basic Tegra186 support
Tegra186's MMC controller needs to be explicitly identified. Add another compatible value for it. Tegra186 will use an entirely different clock/reset control mechanism to existing chips, and will use standard clock/reset APIs rather than the existing Tegra-specific custom APIs. The driver support for that isn't ready yet, so simply disable all clock/reset usage if compiling for Tegra186. This must happen at compile time rather than run-time since the custom APIs won't even be compiled in on Tegra186. In the long term, the plan would be to convert the existing custom APIs to standard APIs and get rid of the ifdefs completely. The system's main eMMC will work without any clock/reset support, since the firmware will have already initialized the controller in order to load U-Boot. Hence the driver is useful even in this apparently crippled state. Signed-off-by: Stephen Warren <swarren@nvidia.com> Signed-off-by: Tom Warren <twarren@nvidia.com>
This commit is contained in:
parent
074a1fdd27
commit
39f633320c
4 changed files with 35 additions and 1 deletions
|
@ -134,7 +134,9 @@ 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
|
||||
enum periph_id mmc_id; /* Peripheral ID: PERIPH_ID_... */
|
||||
#endif
|
||||
struct gpio_desc cd_gpio; /* Change Detect GPIO */
|
||||
struct gpio_desc pwr_gpio; /* Power GPIO */
|
||||
struct gpio_desc wp_gpio; /* Write Protect GPIO */
|
||||
|
|
|
@ -11,8 +11,10 @@
|
|||
#include <common.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/io.h>
|
||||
#ifndef CONFIG_TEGRA186
|
||||
#include <asm/arch/clock.h>
|
||||
#include <asm/arch-tegra/clk_rst.h>
|
||||
#endif
|
||||
#include <asm/arch-tegra/mmc.h>
|
||||
#include <asm/arch-tegra/tegra_mmc.h>
|
||||
#include <mmc.h>
|
||||
|
@ -357,8 +359,12 @@ static void mmc_change_clock(struct mmc_host *host, uint clock)
|
|||
*/
|
||||
if (clock == 0)
|
||||
goto out;
|
||||
#ifndef CONFIG_TEGRA186
|
||||
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);
|
||||
|
||||
writew(0, &host->reg->clkcon);
|
||||
|
@ -543,7 +549,9 @@ static int do_mmc_init(int dev_index, bool removable)
|
|||
gpio_get_number(&host->cd_gpio));
|
||||
|
||||
host->clock = 0;
|
||||
#ifndef CONFIG_TEGRA186
|
||||
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);
|
||||
|
@ -568,7 +576,11 @@ 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;
|
||||
|
||||
|
@ -600,11 +612,13 @@ static int mmc_get_config(const void *blob, int node, struct mmc_host *host,
|
|||
return -FDT_ERR_NOTFOUND;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_TEGRA186
|
||||
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 +638,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,6 +688,16 @@ 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, "sdhci",
|
||||
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",
|
||||
COMPAT_NVIDIA_TEGRA210_SDMMC, node_list,
|
||||
|
|
|
@ -123,6 +123,7 @@ enum fdt_compat_id {
|
|||
COMPAT_NVIDIA_TEGRA124_SOR, /* Tegra 124 Serial Output Resource */
|
||||
COMPAT_NVIDIA_TEGRA124_PMC, /* Tegra 124 power mgmt controller */
|
||||
COMPAT_NVIDIA_TEGRA20_DC, /* Tegra 2 Display controller */
|
||||
COMPAT_NVIDIA_TEGRA186_SDMMC, /* Tegra186 SDMMC controller */
|
||||
COMPAT_NVIDIA_TEGRA210_SDMMC, /* Tegra210 SDMMC controller */
|
||||
COMPAT_NVIDIA_TEGRA124_SDMMC, /* Tegra124 SDMMC controller */
|
||||
COMPAT_NVIDIA_TEGRA30_SDMMC, /* Tegra30 SDMMC controller */
|
||||
|
|
|
@ -30,6 +30,7 @@ static const char * const compat_names[COMPAT_COUNT] = {
|
|||
COMPAT(NVIDIA_TEGRA124_SOR, "nvidia,tegra124-sor"),
|
||||
COMPAT(NVIDIA_TEGRA124_PMC, "nvidia,tegra124-pmc"),
|
||||
COMPAT(NVIDIA_TEGRA20_DC, "nvidia,tegra20-dc"),
|
||||
COMPAT(NVIDIA_TEGRA186_SDMMC, "nvidia,tegra186-sdhci"),
|
||||
COMPAT(NVIDIA_TEGRA210_SDMMC, "nvidia,tegra210-sdhci"),
|
||||
COMPAT(NVIDIA_TEGRA124_SDMMC, "nvidia,tegra124-sdhci"),
|
||||
COMPAT(NVIDIA_TEGRA30_SDMMC, "nvidia,tegra30-sdhci"),
|
||||
|
|
Loading…
Reference in a new issue