diff options
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/Makefile | 1 | ||||
-rw-r--r-- | drivers/mmc/atmel_sdhci.c | 40 | ||||
-rw-r--r-- | drivers/mmc/fsl_esdhc.c | 19 | ||||
-rw-r--r-- | drivers/mmc/gen_atmel_mci.c | 60 | ||||
-rw-r--r-- | drivers/mmc/s5p_sdhci.c | 14 | ||||
-rw-r--r-- | drivers/mmc/sdhci.c | 20 |
6 files changed, 115 insertions, 39 deletions
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index 99d02954ed..5d357056dd 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_DM_MMC) += mmc-uclass.o obj-$(CONFIG_ARM_PL180_MMCI) += arm_pl180_mmci.o +obj-$(CONFIG_ATMEL_SDHCI) += atmel_sdhci.o obj-$(CONFIG_BCM2835_SDHCI) += bcm2835_sdhci.o obj-$(CONFIG_BFIN_SDH) += bfin_sdh.o obj-$(CONFIG_DAVINCI_MMC) += davinci_mmc.o diff --git a/drivers/mmc/atmel_sdhci.c b/drivers/mmc/atmel_sdhci.c new file mode 100644 index 0000000000..24b68b640b --- /dev/null +++ b/drivers/mmc/atmel_sdhci.c @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2015 Atmel Corporation + * Wenyou.Yang <wenyou.yang@atmel.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <malloc.h> +#include <sdhci.h> +#include <asm/arch/clk.h> + +#define ATMEL_SDHC_MIN_FREQ 400000 + +int atmel_sdhci_init(void *regbase, u32 id) +{ + struct sdhci_host *host; + u32 max_clk, min_clk = ATMEL_SDHC_MIN_FREQ; + + host = (struct sdhci_host *)calloc(1, sizeof(struct sdhci_host)); + if (!host) { + printf("%s: sdhci_host calloc failed\n", __func__); + return -ENOMEM; + } + + host->name = "atmel_sdhci"; + host->ioaddr = regbase; + host->quirks = 0; + host->version = sdhci_readw(host, SDHCI_HOST_VERSION); + max_clk = at91_get_periph_generated_clk(id); + if (!max_clk) { + printf("%s: Failed to get the proper clock\n", __func__); + free(host); + return -ENODEV; + } + + add_sdhci(host, max_clk, min_clk); + + return 0; +} diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index 0b37002659..c5054d66bd 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -106,7 +106,8 @@ static uint esdhc_xfertyp(struct mmc_cmd *cmd, struct mmc_data *data) xfertyp |= XFERTYP_RSPTYP_48; #if defined(CONFIG_MX53) || defined(CONFIG_PPC_T4240) || \ - defined(CONFIG_LS102XA) || defined(CONFIG_LS2085A) + defined(CONFIG_LS102XA) || defined(CONFIG_FSL_LAYERSCAPE) || \ + defined(CONFIG_PPC_T4160) if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION) xfertyp |= XFERTYP_CMDTYP_ABORT; #endif @@ -184,7 +185,7 @@ static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data) int timeout; struct fsl_esdhc_cfg *cfg = mmc->priv; struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base; -#ifdef CONFIG_LS2085A +#ifdef CONFIG_FSL_LAYERSCAPE dma_addr_t addr; #endif uint wml_value; @@ -197,7 +198,7 @@ static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data) esdhc_clrsetbits32(®s->wml, WML_RD_WML_MASK, wml_value); #ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO -#ifdef CONFIG_LS2085A +#ifdef CONFIG_FSL_LAYERSCAPE addr = virt_to_phys((void *)(data->dest)); if (upper_32_bits(addr)) printf("Error found for upper 32 bits\n"); @@ -223,7 +224,7 @@ static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data) esdhc_clrsetbits32(®s->wml, WML_WR_WML_MASK, wml_value << 16); #ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO -#ifdef CONFIG_LS2085A +#ifdef CONFIG_FSL_LAYERSCAPE addr = virt_to_phys((void *)(data->src)); if (upper_32_bits(addr)) printf("Error found for upper 32 bits\n"); @@ -277,7 +278,7 @@ static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data) static void check_and_invalidate_dcache_range (struct mmc_cmd *cmd, struct mmc_data *data) { -#ifdef CONFIG_LS2085A +#ifdef CONFIG_FSL_LAYERSCAPE unsigned start = 0; #else unsigned start = (unsigned)data->dest ; @@ -285,7 +286,7 @@ static void check_and_invalidate_dcache_range unsigned size = roundup(ARCH_DMA_MINALIGN, data->blocks*data->blocksize); unsigned end = start+size ; -#ifdef CONFIG_LS2085A +#ifdef CONFIG_FSL_LAYERSCAPE dma_addr_t addr; addr = virt_to_phys((void *)(data->dest)); @@ -747,8 +748,14 @@ void mmc_adapter_card_type_ident(void) switch (card_id) { case QIXIS_ESDHC_ADAPTER_TYPE_EMMC45: + value = QIXIS_READ(brdcfg[5]); + value |= (QIXIS_DAT4 | QIXIS_DAT5_6_7); + QIXIS_WRITE(brdcfg[5], value); break; case QIXIS_ESDHC_ADAPTER_TYPE_SDMMC_LEGACY: + value = QIXIS_READ(pwr_ctl[1]); + value |= QIXIS_EVDD_BY_SDHC_VS; + QIXIS_WRITE(pwr_ctl[1], value); break; case QIXIS_ESDHC_ADAPTER_TYPE_EMMC44: value = QIXIS_READ(brdcfg[5]); diff --git a/drivers/mmc/gen_atmel_mci.c b/drivers/mmc/gen_atmel_mci.c index 45bcffb6b2..da870c646e 100644 --- a/drivers/mmc/gen_atmel_mci.c +++ b/drivers/mmc/gen_atmel_mci.c @@ -32,7 +32,11 @@ # define MCI_BUS 0 #endif -static int initialized = 0; +struct atmel_mci_priv { + struct mmc_config cfg; + struct atmel_mci *mci; + unsigned int initialized:1; +}; /* Read Atmel MCI IP version */ static unsigned int atmel_mci_get_version(struct atmel_mci *mci) @@ -48,14 +52,15 @@ static unsigned int atmel_mci_get_version(struct atmel_mci *mci) */ static void dump_cmd(u32 cmdr, u32 arg, u32 status, const char* msg) { - printf("gen_atmel_mci: CMDR %08x (%2u) ARGR %08x (SR: %08x) %s\n", - cmdr, cmdr&0x3F, arg, status, msg); + debug("gen_atmel_mci: CMDR %08x (%2u) ARGR %08x (SR: %08x) %s\n", + cmdr, cmdr & 0x3F, arg, status, msg); } /* Setup for MCI Clock and Block Size */ static void mci_set_mode(struct mmc *mmc, u32 hz, u32 blklen) { - atmel_mci_t *mci = mmc->priv; + struct atmel_mci_priv *priv = mmc->priv; + atmel_mci_t *mci = priv->mci; u32 bus_hz = get_mci_clk_rate(); u32 clkdiv = 255; unsigned int version = atmel_mci_get_version(mci); @@ -73,16 +78,16 @@ static void mci_set_mode(struct mmc *mmc, u32 hz, u32 blklen) clkodd = clkdiv & 1; clkdiv >>= 1; - printf("mci: setting clock %u Hz, block size %u\n", - bus_hz / (clkdiv * 2 + clkodd + 2), blklen); + debug("mci: setting clock %u Hz, block size %u\n", + bus_hz / (clkdiv * 2 + clkodd + 2), blklen); } else { /* find clkdiv yielding a rate <= than requested */ for (clkdiv = 0; clkdiv < 255; clkdiv++) { if ((bus_hz / (clkdiv + 1) / 2) <= hz) break; } - printf("mci: setting clock %u Hz, block size %u\n", - (bus_hz / (clkdiv + 1)) / 2, blklen); + debug("mci: setting clock %u Hz, block size %u\n", + (bus_hz / (clkdiv + 1)) / 2, blklen); } } @@ -113,7 +118,9 @@ static void mci_set_mode(struct mmc *mmc, u32 hz, u32 blklen) if (mmc->card_caps & mmc->cfg->host_caps & MMC_MODE_HS) writel(MMCI_BIT(HSMODE), &mci->cfg); - initialized = 1; + udelay(50); + + priv->initialized = 1; } /* Return the CMDR with flags for a given command and data packet */ @@ -196,12 +203,13 @@ io_fail: static int mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) { - atmel_mci_t *mci = mmc->priv; + struct atmel_mci_priv *priv = mmc->priv; + atmel_mci_t *mci = priv->mci; u32 cmdr; u32 error_flags = 0; u32 status; - if (!initialized) { + if (!priv->initialized) { puts ("MCI not initialized!\n"); return COMM_ERR; } @@ -321,7 +329,8 @@ mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) /* Entered into mmc structure during driver init */ static void mci_set_ios(struct mmc *mmc) { - atmel_mci_t *mci = mmc->priv; + struct atmel_mci_priv *priv = mmc->priv; + atmel_mci_t *mci = priv->mci; int bus_width = mmc->bus_width; unsigned int version = atmel_mci_get_version(mci); int busw; @@ -357,7 +366,8 @@ static void mci_set_ios(struct mmc *mmc) /* Entered into mmc structure during driver init */ static int mci_init(struct mmc *mmc) { - atmel_mci_t *mci = mmc->priv; + struct atmel_mci_priv *priv = mmc->priv; + atmel_mci_t *mci = priv->mci; /* Initialize controller */ writel(MMCI_BIT(SWRST), &mci->cr); /* soft reset */ @@ -391,22 +401,24 @@ int atmel_mci_init(void *regs) { struct mmc *mmc; struct mmc_config *cfg; - struct atmel_mci *mci; + struct atmel_mci_priv *priv; unsigned int version; - cfg = malloc(sizeof(*cfg)); - if (cfg == NULL) - return -1; - memset(cfg, 0, sizeof(*cfg)); + priv = calloc(1, sizeof(*priv)); + if (!priv) + return -ENOMEM; - mci = (struct atmel_mci *)regs; + cfg = &priv->cfg; cfg->name = "mci"; cfg->ops = &atmel_mci_ops; + priv->mci = (struct atmel_mci *)regs; + priv->initialized = 0; + /* need to be able to pass these in on a board by board basis */ cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; - version = atmel_mci_get_version(mci); + version = atmel_mci_get_version(priv->mci); if ((version & 0xf00) >= 0x300) { cfg->host_caps = MMC_MODE_8BIT; cfg->host_caps |= MMC_MODE_HS | MMC_MODE_HS_52MHz; @@ -423,13 +435,13 @@ int atmel_mci_init(void *regs) cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; - mmc = mmc_create(cfg, regs); + mmc = mmc_create(cfg, priv); if (mmc == NULL) { - free(cfg); - return -1; + free(priv); + return -ENODEV; } - /* NOTE: possibly leaking the cfg structure */ + /* NOTE: possibly leaking the priv structure */ return 0; } diff --git a/drivers/mmc/s5p_sdhci.c b/drivers/mmc/s5p_sdhci.c index 15ecfee961..44353c72f4 100644 --- a/drivers/mmc/s5p_sdhci.c +++ b/drivers/mmc/s5p_sdhci.c @@ -106,6 +106,12 @@ static int do_sdhci_init(struct sdhci_host *host) flag = host->bus_width == 8 ? PINMUX_FLAG_8BIT_MODE : PINMUX_FLAG_NONE; dev_id = host->index + PERIPH_ID_SDMMC0; + ret = exynos_pinmux_config(dev_id, flag); + if (ret) { + printf("external SD not configured\n"); + return ret; + } + if (dm_gpio_is_valid(&host->pwr_gpio)) { dm_gpio_set_value(&host->pwr_gpio, 1); ret = exynos_pinmux_config(dev_id, flag); @@ -121,12 +127,6 @@ static int do_sdhci_init(struct sdhci_host *host) debug("no SD card detected (%d)\n", ret); return -ENODEV; } - - ret = exynos_pinmux_config(dev_id, flag); - if (ret) { - printf("external SD not configured\n"); - return ret; - } } return s5p_sdhci_core_init(host); @@ -193,7 +193,7 @@ static int process_nodes(const void *blob, int node_list[], int count) } ret = do_sdhci_init(host); - if (ret) { + if (ret && ret != -ENODEV) { printf("%s: failed to initialize dev %d (%d)\n", __func__, i, ret); failed++; } diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index d89e302841..02d71b9344 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -286,9 +286,25 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd, static int sdhci_set_clock(struct mmc *mmc, unsigned int clock) { struct sdhci_host *host = mmc->priv; - unsigned int div, clk, timeout; + unsigned int div, clk, timeout, reg; - sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); + /* Wait max 20 ms */ + timeout = 200; + while (sdhci_readl(host, SDHCI_PRESENT_STATE) & + (SDHCI_CMD_INHIBIT | SDHCI_DATA_INHIBIT)) { + if (timeout == 0) { + printf("%s: Timeout to wait cmd & data inhibit\n", + __func__); + return -1; + } + + timeout--; + udelay(100); + } + + reg = sdhci_readw(host, SDHCI_CLOCK_CONTROL); + reg &= ~SDHCI_CLOCK_CARD_EN; + sdhci_writew(host, reg, SDHCI_CLOCK_CONTROL); if (clock == 0) return 0; |