diff options
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/Makefile | 71 | ||||
-rw-r--r-- | drivers/mmc/dw_mmc.c | 17 | ||||
-rw-r--r-- | drivers/mmc/exynos_dw_mmc.c | 5 | ||||
-rw-r--r-- | drivers/mmc/fsl_esdhc.c | 69 | ||||
-rw-r--r-- | drivers/mmc/mmc.c | 17 | ||||
-rw-r--r-- | drivers/mmc/sdhci.c | 35 |
6 files changed, 127 insertions, 87 deletions
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index 06280d1..a7ae38d 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -5,53 +5,30 @@ # SPDX-License-Identifier: GPL-2.0+ # -include $(TOPDIR)/config.mk - -LIB := $(obj)libmmc.o - - -COBJS-$(CONFIG_BFIN_SDH) += bfin_sdh.o -COBJS-$(CONFIG_DAVINCI_MMC) += davinci_mmc.o -COBJS-$(CONFIG_FSL_ESDHC) += fsl_esdhc.o -COBJS-$(CONFIG_FTSDC010) += ftsdc010_mci.o -COBJS-$(CONFIG_GENERIC_MMC) += mmc.o -COBJS-$(CONFIG_GENERIC_ATMEL_MCI) += gen_atmel_mci.o -COBJS-$(CONFIG_MMC_SPI) += mmc_spi.o -COBJS-$(CONFIG_ARM_PL180_MMCI) += arm_pl180_mmci.o -COBJS-$(CONFIG_MV_SDHCI) += mv_sdhci.o -COBJS-$(CONFIG_MXC_MMC) += mxcmmc.o -COBJS-$(CONFIG_MXS_MMC) += mxsmmc.o -COBJS-$(CONFIG_OMAP_HSMMC) += omap_hsmmc.o -COBJS-$(CONFIG_PXA_MMC_GENERIC) += pxa_mmc_gen.o -COBJS-$(CONFIG_SDHCI) += sdhci.o -COBJS-$(CONFIG_BCM2835_SDHCI) += bcm2835_sdhci.o -COBJS-$(CONFIG_S5P_SDHCI) += s5p_sdhci.o -COBJS-$(CONFIG_SH_MMCIF) += sh_mmcif.o -COBJS-$(CONFIG_SPEAR_SDHCI) += spear_sdhci.o -COBJS-$(CONFIG_TEGRA_MMC) += tegra_mmc.o -COBJS-$(CONFIG_DWMMC) += dw_mmc.o -COBJS-$(CONFIG_EXYNOS_DWMMC) += exynos_dw_mmc.o -COBJS-$(CONFIG_ZYNQ_SDHCI) += zynq_sdhci.o +obj-$(CONFIG_BFIN_SDH) += bfin_sdh.o +obj-$(CONFIG_DAVINCI_MMC) += davinci_mmc.o +obj-$(CONFIG_FSL_ESDHC) += fsl_esdhc.o +obj-$(CONFIG_FTSDC010) += ftsdc010_mci.o +obj-$(CONFIG_GENERIC_MMC) += mmc.o +obj-$(CONFIG_GENERIC_ATMEL_MCI) += gen_atmel_mci.o +obj-$(CONFIG_MMC_SPI) += mmc_spi.o +obj-$(CONFIG_ARM_PL180_MMCI) += arm_pl180_mmci.o +obj-$(CONFIG_MV_SDHCI) += mv_sdhci.o +obj-$(CONFIG_MXC_MMC) += mxcmmc.o +obj-$(CONFIG_MXS_MMC) += mxsmmc.o +obj-$(CONFIG_OMAP_HSMMC) += omap_hsmmc.o +obj-$(CONFIG_PXA_MMC_GENERIC) += pxa_mmc_gen.o +obj-$(CONFIG_SDHCI) += sdhci.o +obj-$(CONFIG_BCM2835_SDHCI) += bcm2835_sdhci.o +obj-$(CONFIG_S5P_SDHCI) += s5p_sdhci.o +obj-$(CONFIG_SH_MMCIF) += sh_mmcif.o +obj-$(CONFIG_SPEAR_SDHCI) += spear_sdhci.o +obj-$(CONFIG_TEGRA_MMC) += tegra_mmc.o +obj-$(CONFIG_DWMMC) += dw_mmc.o +obj-$(CONFIG_EXYNOS_DWMMC) += exynos_dw_mmc.o +obj-$(CONFIG_ZYNQ_SDHCI) += zynq_sdhci.o ifdef CONFIG_SPL_BUILD -COBJS-$(CONFIG_SPL_MMC_BOOT) += fsl_esdhc_spl.o +obj-$(CONFIG_SPL_MMC_BOOT) += fsl_esdhc_spl.o else -COBJS-$(CONFIG_GENERIC_MMC) += mmc_write.o +obj-$(CONFIG_GENERIC_MMC) += mmc_write.o endif - -COBJS := $(COBJS-y) -SRCS := $(COBJS:.o=.c) -OBJS := $(addprefix $(obj),$(COBJS)) - -all: $(LIB) - -$(LIB): $(obj).depend $(OBJS) - $(call cmd_link_o_target, $(OBJS)) - -######################################################################### - -# defines $(obj).depend target -include $(SRCTREE)/rules.mk - -sinclude $(obj).depend - -######################################################################### diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c index 9a803a0..1e0f72b 100644 --- a/drivers/mmc/dw_mmc.c +++ b/drivers/mmc/dw_mmc.c @@ -11,6 +11,7 @@ #include <mmc.h> #include <dwmmc.h> #include <asm-generic/errno.h> +#include <asm/arch/dwmmc.h> #define PAGE_SIZE 4096 @@ -220,12 +221,12 @@ static int dwmci_setup_bus(struct dwmci_host *host, u32 freq) if ((freq == host->clock) || (freq == 0)) return 0; /* - * If host->mmc_clk didn't define, + * If host->get_mmc_clk didn't define, * then assume that host->bus_hz is source clock value. * host->bus_hz should be set from user. */ - if (host->mmc_clk) - sclk = host->mmc_clk(host->dev_index); + if (host->get_mmc_clk) + sclk = host->get_mmc_clk(host->dev_index); else if (host->bus_hz) sclk = host->bus_hz; else { @@ -301,6 +302,16 @@ static int dwmci_init(struct mmc *mmc) struct dwmci_host *host = (struct dwmci_host *)mmc->priv; u32 fifo_size; + if (host->quirks & DWMCI_QUIRK_DISABLE_SMU) { + dwmci_writel(host, EMMCP_MPSBEGIN0, 0); + dwmci_writel(host, EMMCP_SEND0, 0); + dwmci_writel(host, EMMCP_CTRL0, + MPSCTRL_SECURE_READ_BIT | + MPSCTRL_SECURE_WRITE_BIT | + MPSCTRL_NON_SECURE_READ_BIT | + MPSCTRL_NON_SECURE_WRITE_BIT | MPSCTRL_VALID); + } + dwmci_writel(host, DWMCI_PWREN, 1); if (!dwmci_wait_reset(host, DWMCI_RESET_ALL)) { diff --git a/drivers/mmc/exynos_dw_mmc.c b/drivers/mmc/exynos_dw_mmc.c index 4ef9fec..a0f1511 100644 --- a/drivers/mmc/exynos_dw_mmc.c +++ b/drivers/mmc/exynos_dw_mmc.c @@ -62,6 +62,9 @@ int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32 clksel) host->name = "EXYNOS DWMMC"; host->ioaddr = (void *)regbase; host->buswidth = bus_width; +#ifdef CONFIG_EXYNOS5420 + host->quirks = DWMCI_QUIRK_DISABLE_SMU; +#endif if (clksel) { host->clksel_val = clksel; @@ -74,7 +77,7 @@ int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32 clksel) host->clksel = exynos_dwmci_clksel; host->dev_index = index; - host->mmc_clk = exynos_dwmci_get_clk; + host->get_mmc_clk = exynos_dwmci_get_clk; /* Add the mmc channel to be registered with mmc core */ if (add_dwmci(host, DWMMC_MAX_FREQ, DWMMC_MIN_FREQ)) { debug("dwmmc%d registration failed\n", index); diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index a7170b4..e3cd0c7 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -24,31 +24,43 @@ DECLARE_GLOBAL_DATA_PTR; struct fsl_esdhc { - uint dsaddr; - uint blkattr; - uint cmdarg; - uint xfertyp; - uint cmdrsp0; - uint cmdrsp1; - uint cmdrsp2; - uint cmdrsp3; - uint datport; - uint prsstat; - uint proctl; - uint sysctl; - uint irqstat; - uint irqstaten; - uint irqsigen; - uint autoc12err; - uint hostcapblt; - uint wml; - uint mixctrl; - char reserved1[4]; - uint fevt; - char reserved2[168]; - uint hostver; - char reserved3[780]; - uint scr; + uint dsaddr; /* SDMA system address register */ + uint blkattr; /* Block attributes register */ + uint cmdarg; /* Command argument register */ + uint xfertyp; /* Transfer type register */ + uint cmdrsp0; /* Command response 0 register */ + uint cmdrsp1; /* Command response 1 register */ + uint cmdrsp2; /* Command response 2 register */ + uint cmdrsp3; /* Command response 3 register */ + uint datport; /* Buffer data port register */ + uint prsstat; /* Present state register */ + uint proctl; /* Protocol control register */ + uint sysctl; /* System Control Register */ + uint irqstat; /* Interrupt status register */ + uint irqstaten; /* Interrupt status enable register */ + uint irqsigen; /* Interrupt signal enable register */ + uint autoc12err; /* Auto CMD error status register */ + uint hostcapblt; /* Host controller capabilities register */ + uint wml; /* Watermark level register */ + uint mixctrl; /* For USDHC */ + char reserved1[4]; /* reserved */ + uint fevt; /* Force event register */ + uint admaes; /* ADMA error status register */ + uint adsaddr; /* ADMA system address register */ + char reserved2[160]; /* reserved */ + uint hostver; /* Host controller version register */ + char reserved3[4]; /* reserved */ + uint dmaerraddr; /* DMA error address register */ + char reserved4[4]; /* reserved */ + uint dmaerrattr; /* DMA error attribute register */ + char reserved5[4]; /* reserved */ + uint hostcapblt2; /* Host controller capabilities register 2 */ + char reserved6[8]; /* reserved */ + uint tcr; /* Tuning control register */ + char reserved7[28]; /* reserved */ + uint sddirctl; /* SD direction control register */ + char reserved8[712]; /* reserved */ + uint scr; /* eSDHC control register */ }; /* Return the XFERTYP flags for a given command and data packet */ @@ -521,6 +533,7 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg) if (!mmc) return -ENOMEM; + memset(mmc, 0, sizeof(struct mmc)); sprintf(mmc->name, "FSL_SDHC"); regs = (struct fsl_esdhc *)cfg->esdhc_base; @@ -544,6 +557,12 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg) caps = caps & ~(ESDHC_HOSTCAPBLT_SRS | ESDHC_HOSTCAPBLT_VS18 | ESDHC_HOSTCAPBLT_VS30); #endif + +/* T4240 host controller capabilities register should have VS33 bit */ +#ifdef CONFIG_SYS_FSL_MMC_HAS_CAPBLT_VS33 + caps = caps | ESDHC_HOSTCAPBLT_VS33; +#endif + if (caps & ESDHC_HOSTCAPBLT_VS18) voltage_caps |= MMC_VDD_165_195; if (caps & ESDHC_HOSTCAPBLT_VS30) diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 84dae4d..e1461a9 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -960,15 +960,24 @@ static int mmc_startup(struct mmc *mmc) } /* - * Check whether GROUP_DEF is set, if yes, read out - * group size from ext_csd directly, or calculate - * the group size from the csd value. + * Host needs to enable ERASE_GRP_DEF bit if device is + * partitioned. This bit will be lost every time after a reset + * or power off. This will affect erase size. */ - if (ext_csd[EXT_CSD_ERASE_GROUP_DEF]) { + if ((ext_csd[EXT_CSD_PARTITIONING_SUPPORT] & PART_SUPPORT) && + (ext_csd[EXT_CSD_PARTITIONS_ATTRIBUTE] & PART_ENH_ATTRIB)) { + err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_ERASE_GROUP_DEF, 1); + + if (err) + return err; + + /* Read out group size from ext_csd */ mmc->erase_grp_size = ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] * MMC_MAX_BLOCK_LEN * 1024; } else { + /* Calculate the group size from the csd value. */ int erase_gsz, erase_gmul; erase_gsz = (mmc->csd[2] & 0x00007c00) >> 10; erase_gmul = (mmc->csd[2] & 0x000003e0) >> 5; diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index dfb2eee..46ae9cb 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -109,6 +109,19 @@ static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data, return 0; } +/* + * No command will be sent by driver if card is busy, so driver must wait + * for card ready state. + * Every time when card is busy after timeout then (last) timeout value will be + * increased twice but only if it doesn't exceed global defined maximum. + * Each function call will use last timeout value. Max timeout can be redefined + * in board config file. + */ +#ifndef CONFIG_SDHCI_CMD_MAX_TIMEOUT +#define CONFIG_SDHCI_CMD_MAX_TIMEOUT 3200 +#endif +#define CONFIG_SDHCI_CMD_DEFAULT_TIMEOUT 100 + int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) { @@ -117,11 +130,12 @@ int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd, int ret = 0; int trans_bytes = 0, is_aligned = 1; u32 mask, flags, mode; - unsigned int timeout, start_addr = 0; + unsigned int time = 0, start_addr = 0; unsigned int retry = 10000; + int mmc_dev = mmc->block_dev.dev; - /* Wait max 10 ms */ - timeout = 10; + /* Timeout unit - ms */ + static unsigned int cmd_timeout = CONFIG_SDHCI_CMD_DEFAULT_TIMEOUT; sdhci_writel(host, SDHCI_INT_ALL_MASK, SDHCI_INT_STATUS); mask = SDHCI_CMD_INHIBIT | SDHCI_DATA_INHIBIT; @@ -132,11 +146,18 @@ int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd, mask &= ~SDHCI_DATA_INHIBIT; while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) { - if (timeout == 0) { - printf("Controller never released inhibit bit(s).\n"); - return COMM_ERR; + if (time >= cmd_timeout) { + printf("MMC: %d busy ", mmc_dev); + if (2 * cmd_timeout <= CONFIG_SDHCI_CMD_MAX_TIMEOUT) { + cmd_timeout += cmd_timeout; + printf("timeout increasing to: %u ms.\n", + cmd_timeout); + } else { + puts("timeout.\n"); + return COMM_ERR; + } } - timeout--; + time++; udelay(1000); } |