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 06280d1fa..a7ae38dad 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 9a803a02d..1e0f72bbe 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 4ef9fec0e..a0f1511cb 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 a7170b49d..e3cd0c777 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 84dae4d8b..e1461a98d 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 dfb2eeeb4..46ae9cb52 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);  	} |