diff options
Diffstat (limited to 'drivers/mmc/host')
25 files changed, 1083 insertions, 499 deletions
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index fd9a58e216a5..8a1e3498261e 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -129,6 +129,14 @@ config MMC_SDHCI_OF_ARASAN  	  If unsure, say N. +config MMC_SDHCI_OF_AT91 +	tristate "SDHCI OF support for the Atmel SDMMC controller" +	depends on MMC_SDHCI_PLTFM +	depends on OF +	select MMC_SDHCI_IO_ACCESSORS +	help +	  This selects the Atmel SDMMC driver +  config MMC_SDHCI_OF_ESDHC  	tristate "SDHCI OF support for the Freescale eSDHC controller"  	depends on MMC_SDHCI_PLTFM @@ -779,6 +787,7 @@ config MMC_TOSHIBA_PCI  config MMC_MTK  	tristate "MediaTek SD/MMC Card Interface support" +	depends on HAS_DMA  	help  	  This selects the MediaTek(R) Secure digital and Multimedia card Interface.  	  If you have a machine with a integrated SD/MMC card reader, say Y or M here. diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index e928d61c5f4b..4f3452afa6ca 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile @@ -67,6 +67,7 @@ obj-$(CONFIG_MMC_SDHCI_ESDHC_IMX)	+= sdhci-esdhc-imx.o  obj-$(CONFIG_MMC_SDHCI_DOVE)		+= sdhci-dove.o  obj-$(CONFIG_MMC_SDHCI_TEGRA)		+= sdhci-tegra.o  obj-$(CONFIG_MMC_SDHCI_OF_ARASAN)	+= sdhci-of-arasan.o +obj-$(CONFIG_MMC_SDHCI_OF_AT91)		+= sdhci-of-at91.o  obj-$(CONFIG_MMC_SDHCI_OF_ESDHC)	+= sdhci-of-esdhc.o  obj-$(CONFIG_MMC_SDHCI_OF_HLWD)		+= sdhci-of-hlwd.o  obj-$(CONFIG_MMC_SDHCI_BCM_KONA)	+= sdhci-bcm-kona.o diff --git a/drivers/mmc/host/android-goldfish.c b/drivers/mmc/host/android-goldfish.c index b1eac719a4cc..dca5518b0139 100644 --- a/drivers/mmc/host/android-goldfish.c +++ b/drivers/mmc/host/android-goldfish.c @@ -118,7 +118,7 @@ struct goldfish_mmc_host {  	struct mmc_host		*mmc;  	struct device		*dev;  	unsigned char		id; /* 16xx chips have 2 MMC blocks */ -	void __iomem		*virt_base; +	void			*virt_base;  	unsigned int		phys_base;  	int			irq;  	unsigned char		bus_mode; diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 9a39e0b7e583..bf62e429f7fc 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -29,7 +29,6 @@  #include <linux/slab.h>  #include <linux/stat.h>  #include <linux/types.h> -#include <linux/platform_data/atmel.h>  #include <linux/platform_data/mmc-atmel-mci.h>  #include <linux/mmc/host.h> diff --git a/drivers/mmc/host/dw_mmc-rockchip.c b/drivers/mmc/host/dw_mmc-rockchip.c index de15121bba7d..bc76aa22473e 100644 --- a/drivers/mmc/host/dw_mmc-rockchip.c +++ b/drivers/mmc/host/dw_mmc-rockchip.c @@ -73,6 +73,9 @@ static int dw_mci_rockchip_init(struct dw_mci *host)  	/* It is slot 8 on Rockchip SoCs */  	host->sdio_id0 = 8; +	/* It needs this quirk on all Rockchip SoCs */ +	host->pdata->quirks |= DW_MCI_QUIRK_BROKEN_DTO; +  	return 0;  } diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 40e9d8e45f25..fcbf5524fd31 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -99,6 +99,9 @@ struct idmac_desc {  	__le32		des3;	/* buffer 2 physical address */  }; + +/* Each descriptor can transfer up to 4KB of data in chained mode */ +#define DW_MCI_DESC_DATA_LENGTH	0x1000  #endif /* CONFIG_MMC_DW_IDMAC */  static bool dw_mci_reset(struct dw_mci *host); @@ -235,8 +238,8 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)  	struct dw_mci *host = slot->host;  	const struct dw_mci_drv_data *drv_data = slot->host->drv_data;  	u32 cmdr; -	cmd->error = -EINPROGRESS; +	cmd->error = -EINPROGRESS;  	cmdr = cmd->opcode;  	if (cmd->opcode == MMC_STOP_TRANSMISSION || @@ -371,7 +374,7 @@ static void dw_mci_start_command(struct dw_mci *host,  		 cmd->arg, cmd_flags);  	mci_writel(host, CMDARG, cmd->arg); -	wmb(); +	wmb(); /* drain writebuffer */  	dw_mci_wait_while_busy(host, cmd_flags);  	mci_writel(host, CMD, cmd_flags | SDMMC_CMD_START); @@ -380,6 +383,7 @@ static void dw_mci_start_command(struct dw_mci *host,  static inline void send_stop_abort(struct dw_mci *host, struct mmc_data *data)  {  	struct mmc_command *stop = data->stop ? data->stop : &host->stop_abort; +  	dw_mci_start_command(host, stop, host->stop_cmdr);  } @@ -462,69 +466,102 @@ static void dw_mci_idmac_complete_dma(struct dw_mci *host)  static void dw_mci_translate_sglist(struct dw_mci *host, struct mmc_data *data,  				    unsigned int sg_len)  { +	unsigned int desc_len;  	int i; +  	if (host->dma_64bit_address == 1) { -		struct idmac_desc_64addr *desc = host->sg_cpu; +		struct idmac_desc_64addr *desc_first, *desc_last, *desc; -		for (i = 0; i < sg_len; i++, desc++) { +		desc_first = desc_last = desc = host->sg_cpu; + +		for (i = 0; i < sg_len; i++) {  			unsigned int length = sg_dma_len(&data->sg[i]); +  			u64 mem_addr = sg_dma_address(&data->sg[i]); -			/* -			 * Set the OWN bit and disable interrupts for this -			 * descriptor -			 */ -			desc->des0 = IDMAC_DES0_OWN | IDMAC_DES0_DIC | -						IDMAC_DES0_CH; -			/* Buffer length */ -			IDMAC_64ADDR_SET_BUFFER1_SIZE(desc, length); - -			/* Physical address to DMA to/from */ -			desc->des4 = mem_addr & 0xffffffff; -			desc->des5 = mem_addr >> 32; +			for ( ; length ; desc++) { +				desc_len = (length <= DW_MCI_DESC_DATA_LENGTH) ? +					   length : DW_MCI_DESC_DATA_LENGTH; + +				length -= desc_len; + +				/* +				 * Set the OWN bit and disable interrupts +				 * for this descriptor +				 */ +				desc->des0 = IDMAC_DES0_OWN | IDMAC_DES0_DIC | +							IDMAC_DES0_CH; + +				/* Buffer length */ +				IDMAC_64ADDR_SET_BUFFER1_SIZE(desc, desc_len); + +				/* Physical address to DMA to/from */ +				desc->des4 = mem_addr & 0xffffffff; +				desc->des5 = mem_addr >> 32; + +				/* Update physical address for the next desc */ +				mem_addr += desc_len; + +				/* Save pointer to the last descriptor */ +				desc_last = desc; +			}  		}  		/* Set first descriptor */ -		desc = host->sg_cpu; -		desc->des0 |= IDMAC_DES0_FD; +		desc_first->des0 |= IDMAC_DES0_FD;  		/* Set last descriptor */ -		desc = host->sg_cpu + (i - 1) * -				sizeof(struct idmac_desc_64addr); -		desc->des0 &= ~(IDMAC_DES0_CH | IDMAC_DES0_DIC); -		desc->des0 |= IDMAC_DES0_LD; +		desc_last->des0 &= ~(IDMAC_DES0_CH | IDMAC_DES0_DIC); +		desc_last->des0 |= IDMAC_DES0_LD;  	} else { -		struct idmac_desc *desc = host->sg_cpu; +		struct idmac_desc *desc_first, *desc_last, *desc; -		for (i = 0; i < sg_len; i++, desc++) { +		desc_first = desc_last = desc = host->sg_cpu; + +		for (i = 0; i < sg_len; i++) {  			unsigned int length = sg_dma_len(&data->sg[i]); +  			u32 mem_addr = sg_dma_address(&data->sg[i]); -			/* -			 * Set the OWN bit and disable interrupts for this -			 * descriptor -			 */ -			desc->des0 = cpu_to_le32(IDMAC_DES0_OWN | -					IDMAC_DES0_DIC | IDMAC_DES0_CH); -			/* Buffer length */ -			IDMAC_SET_BUFFER1_SIZE(desc, length); +			for ( ; length ; desc++) { +				desc_len = (length <= DW_MCI_DESC_DATA_LENGTH) ? +					   length : DW_MCI_DESC_DATA_LENGTH; + +				length -= desc_len; + +				/* +				 * Set the OWN bit and disable interrupts +				 * for this descriptor +				 */ +				desc->des0 = cpu_to_le32(IDMAC_DES0_OWN | +							 IDMAC_DES0_DIC | +							 IDMAC_DES0_CH); -			/* Physical address to DMA to/from */ -			desc->des2 = cpu_to_le32(mem_addr); +				/* Buffer length */ +				IDMAC_SET_BUFFER1_SIZE(desc, desc_len); + +				/* Physical address to DMA to/from */ +				desc->des2 = cpu_to_le32(mem_addr); + +				/* Update physical address for the next desc */ +				mem_addr += desc_len; + +				/* Save pointer to the last descriptor */ +				desc_last = desc; +			}  		}  		/* Set first descriptor */ -		desc = host->sg_cpu; -		desc->des0 |= cpu_to_le32(IDMAC_DES0_FD); +		desc_first->des0 |= cpu_to_le32(IDMAC_DES0_FD);  		/* Set last descriptor */ -		desc = host->sg_cpu + (i - 1) * sizeof(struct idmac_desc); -		desc->des0 &= cpu_to_le32(~(IDMAC_DES0_CH | IDMAC_DES0_DIC)); -		desc->des0 |= cpu_to_le32(IDMAC_DES0_LD); +		desc_last->des0 &= cpu_to_le32(~(IDMAC_DES0_CH | +					       IDMAC_DES0_DIC)); +		desc_last->des0 |= cpu_to_le32(IDMAC_DES0_LD);  	} -	wmb(); +	wmb(); /* drain writebuffer */  }  static void dw_mci_idmac_start_dma(struct dw_mci *host, unsigned int sg_len) @@ -542,6 +579,7 @@ static void dw_mci_idmac_start_dma(struct dw_mci *host, unsigned int sg_len)  	temp |= SDMMC_CTRL_USE_IDMAC;  	mci_writel(host, CTRL, temp); +	/* drain writebuffer */  	wmb();  	/* Enable the IDMAC */ @@ -589,7 +627,9 @@ static int dw_mci_idmac_init(struct dw_mci *host)  		host->ring_size = PAGE_SIZE / sizeof(struct idmac_desc);  		/* Forward link the descriptor list */ -		for (i = 0, p = host->sg_cpu; i < host->ring_size - 1; i++, p++) { +		for (i = 0, p = host->sg_cpu; +		     i < host->ring_size - 1; +		     i++, p++) {  			p->des3 = cpu_to_le32(host->sg_dma +  					(sizeof(struct idmac_desc) * (i + 1)));  			p->des1 = 0; @@ -718,7 +758,7 @@ static void dw_mci_adjust_fifoth(struct dw_mci *host, struct mmc_data *data)  	u32 fifo_width = 1 << host->data_shift;  	u32 blksz_depth = blksz / fifo_width, fifoth_val;  	u32 msize = 0, rx_wmark = 1, tx_wmark, tx_wmark_invers; -	int idx = (sizeof(mszs) / sizeof(mszs[0])) - 1; +	int idx = ARRAY_SIZE(mszs) - 1;  	tx_wmark = (host->fifo_depth) / 2;  	tx_wmark_invers = host->fifo_depth - tx_wmark; @@ -843,6 +883,7 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data)  static void dw_mci_submit_data(struct dw_mci *host, struct mmc_data *data)  {  	unsigned long irqflags; +	int flags = SG_MITER_ATOMIC;  	u32 temp;  	data->error = -EINPROGRESS; @@ -859,7 +900,6 @@ static void dw_mci_submit_data(struct dw_mci *host, struct mmc_data *data)  	}  	if (dw_mci_submit_data_dma(host, data)) { -		int flags = SG_MITER_ATOMIC;  		if (host->data->flags & MMC_DATA_READ)  			flags |= SG_MITER_TO_SG;  		else @@ -906,7 +946,7 @@ static void mci_send_cmd(struct dw_mci_slot *slot, u32 cmd, u32 arg)  	unsigned int cmd_status = 0;  	mci_writel(host, CMDARG, arg); -	wmb(); +	wmb(); /* drain writebuffer */  	dw_mci_wait_while_busy(host, cmd);  	mci_writel(host, CMD, SDMMC_CMD_START | cmd); @@ -1019,7 +1059,7 @@ static void __dw_mci_start_request(struct dw_mci *host,  	if (data) {  		dw_mci_submit_data(host, data); -		wmb(); +		wmb(); /* drain writebuffer */  	}  	dw_mci_start_command(host, cmd, cmdflags); @@ -1384,14 +1424,15 @@ static int dw_mci_execute_tuning(struct mmc_host *mmc, u32 opcode)  	struct dw_mci_slot *slot = mmc_priv(mmc);  	struct dw_mci *host = slot->host;  	const struct dw_mci_drv_data *drv_data = host->drv_data; -	int err = -ENOSYS; +	int err = -EINVAL;  	if (drv_data && drv_data->execute_tuning)  		err = drv_data->execute_tuning(slot);  	return err;  } -static int dw_mci_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_ios *ios) +static int dw_mci_prepare_hs400_tuning(struct mmc_host *mmc, +				       struct mmc_ios *ios)  {  	struct dw_mci_slot *slot = mmc_priv(mmc);  	struct dw_mci *host = slot->host; @@ -1533,6 +1574,20 @@ static int dw_mci_data_complete(struct dw_mci *host, struct mmc_data *data)  	return data->error;  } +static void dw_mci_set_drto(struct dw_mci *host) +{ +	unsigned int drto_clks; +	unsigned int drto_ms; + +	drto_clks = mci_readl(host, TMOUT) >> 8; +	drto_ms = DIV_ROUND_UP(drto_clks, host->bus_hz / 1000); + +	/* add a bit spare time */ +	drto_ms += 10; + +	mod_timer(&host->dto_timer, jiffies + msecs_to_jiffies(drto_ms)); +} +  static void dw_mci_tasklet_func(unsigned long priv)  {  	struct dw_mci *host = (struct dw_mci *)priv; @@ -1610,8 +1665,16 @@ static void dw_mci_tasklet_func(unsigned long priv)  			}  			if (!test_and_clear_bit(EVENT_XFER_COMPLETE, -						&host->pending_events)) +						&host->pending_events)) { +				/* +				 * If all data-related interrupts don't come +				 * within the given time in reading data state. +				 */ +				if ((host->quirks & DW_MCI_QUIRK_BROKEN_DTO) && +				    (host->dir_status == DW_MCI_RECV_STATUS)) +					dw_mci_set_drto(host);  				break; +			}  			set_bit(EVENT_XFER_COMPLETE, &host->completed_events); @@ -1644,8 +1707,17 @@ static void dw_mci_tasklet_func(unsigned long priv)  		case STATE_DATA_BUSY:  			if (!test_and_clear_bit(EVENT_DATA_COMPLETE, -						&host->pending_events)) +						&host->pending_events)) { +				/* +				 * If data error interrupt comes but data over +				 * interrupt doesn't come within the given time. +				 * in reading data state. +				 */ +				if ((host->quirks & DW_MCI_QUIRK_BROKEN_DTO) && +				    (host->dir_status == DW_MCI_RECV_STATUS)) +					dw_mci_set_drto(host);  				break; +			}  			host->data = NULL;  			set_bit(EVENT_DATA_COMPLETE, &host->completed_events); @@ -1743,7 +1815,7 @@ static int dw_mci_push_part_bytes(struct dw_mci *host, void *buf, int cnt)  /* pull first bytes from part_buf, only use during pull */  static int dw_mci_pull_part_bytes(struct dw_mci *host, void *buf, int cnt)  { -	cnt = min(cnt, (int)host->part_buf_count); +	cnt = min_t(int, cnt, host->part_buf_count);  	if (cnt) {  		memcpy(buf, (void *)&host->part_buf + host->part_buf_start,  		       cnt); @@ -1769,6 +1841,7 @@ static void dw_mci_push_data16(struct dw_mci *host, void *buf, int cnt)  	/* try and push anything in the part_buf */  	if (unlikely(host->part_buf_count)) {  		int len = dw_mci_push_part_bytes(host, buf, cnt); +  		buf += len;  		cnt -= len;  		if (host->part_buf_count == 2) { @@ -1795,6 +1868,7 @@ static void dw_mci_push_data16(struct dw_mci *host, void *buf, int cnt)  #endif  	{  		u16 *pdata = buf; +  		for (; cnt >= 2; cnt -= 2)  			mci_fifo_writew(host->fifo_reg, *pdata++);  		buf = pdata; @@ -1819,6 +1893,7 @@ static void dw_mci_pull_data16(struct dw_mci *host, void *buf, int cnt)  			int len = min(cnt & -2, (int)sizeof(aligned_buf));  			int items = len >> 1;  			int i; +  			for (i = 0; i < items; ++i)  				aligned_buf[i] = mci_fifo_readw(host->fifo_reg);  			/* memcpy from aligned buffer into output buffer */ @@ -1830,6 +1905,7 @@ static void dw_mci_pull_data16(struct dw_mci *host, void *buf, int cnt)  #endif  	{  		u16 *pdata = buf; +  		for (; cnt >= 2; cnt -= 2)  			*pdata++ = mci_fifo_readw(host->fifo_reg);  		buf = pdata; @@ -1848,6 +1924,7 @@ static void dw_mci_push_data32(struct dw_mci *host, void *buf, int cnt)  	/* try and push anything in the part_buf */  	if (unlikely(host->part_buf_count)) {  		int len = dw_mci_push_part_bytes(host, buf, cnt); +  		buf += len;  		cnt -= len;  		if (host->part_buf_count == 4) { @@ -1874,6 +1951,7 @@ static void dw_mci_push_data32(struct dw_mci *host, void *buf, int cnt)  #endif  	{  		u32 *pdata = buf; +  		for (; cnt >= 4; cnt -= 4)  			mci_fifo_writel(host->fifo_reg, *pdata++);  		buf = pdata; @@ -1898,6 +1976,7 @@ static void dw_mci_pull_data32(struct dw_mci *host, void *buf, int cnt)  			int len = min(cnt & -4, (int)sizeof(aligned_buf));  			int items = len >> 2;  			int i; +  			for (i = 0; i < items; ++i)  				aligned_buf[i] = mci_fifo_readl(host->fifo_reg);  			/* memcpy from aligned buffer into output buffer */ @@ -1909,6 +1988,7 @@ static void dw_mci_pull_data32(struct dw_mci *host, void *buf, int cnt)  #endif  	{  		u32 *pdata = buf; +  		for (; cnt >= 4; cnt -= 4)  			*pdata++ = mci_fifo_readl(host->fifo_reg);  		buf = pdata; @@ -1927,6 +2007,7 @@ static void dw_mci_push_data64(struct dw_mci *host, void *buf, int cnt)  	/* try and push anything in the part_buf */  	if (unlikely(host->part_buf_count)) {  		int len = dw_mci_push_part_bytes(host, buf, cnt); +  		buf += len;  		cnt -= len; @@ -1954,6 +2035,7 @@ static void dw_mci_push_data64(struct dw_mci *host, void *buf, int cnt)  #endif  	{  		u64 *pdata = buf; +  		for (; cnt >= 8; cnt -= 8)  			mci_fifo_writeq(host->fifo_reg, *pdata++);  		buf = pdata; @@ -1978,6 +2060,7 @@ static void dw_mci_pull_data64(struct dw_mci *host, void *buf, int cnt)  			int len = min(cnt & -8, (int)sizeof(aligned_buf));  			int items = len >> 3;  			int i; +  			for (i = 0; i < items; ++i)  				aligned_buf[i] = mci_fifo_readq(host->fifo_reg); @@ -1990,6 +2073,7 @@ static void dw_mci_pull_data64(struct dw_mci *host, void *buf, int cnt)  #endif  	{  		u64 *pdata = buf; +  		for (; cnt >= 8; cnt -= 8)  			*pdata++ = mci_fifo_readq(host->fifo_reg);  		buf = pdata; @@ -2065,7 +2149,7 @@ static void dw_mci_read_data_pio(struct dw_mci *host, bool dto)  done:  	sg_miter_stop(sg_miter);  	host->sg = NULL; -	smp_wmb(); +	smp_wmb(); /* drain writebuffer */  	set_bit(EVENT_XFER_COMPLETE, &host->pending_events);  } @@ -2119,7 +2203,7 @@ static void dw_mci_write_data_pio(struct dw_mci *host)  done:  	sg_miter_stop(sg_miter);  	host->sg = NULL; -	smp_wmb(); +	smp_wmb(); /* drain writebuffer */  	set_bit(EVENT_XFER_COMPLETE, &host->pending_events);  } @@ -2128,7 +2212,7 @@ static void dw_mci_cmd_interrupt(struct dw_mci *host, u32 status)  	if (!host->cmd_status)  		host->cmd_status = status; -	smp_wmb(); +	smp_wmb(); /* drain writebuffer */  	set_bit(EVENT_CMD_COMPLETE, &host->pending_events);  	tasklet_schedule(&host->tasklet); @@ -2192,7 +2276,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)  		if (pending & DW_MCI_CMD_ERROR_FLAGS) {  			mci_writel(host, RINTSTS, DW_MCI_CMD_ERROR_FLAGS);  			host->cmd_status = pending; -			smp_wmb(); +			smp_wmb(); /* drain writebuffer */  			set_bit(EVENT_CMD_COMPLETE, &host->pending_events);  		} @@ -2200,16 +2284,19 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)  			/* if there is an error report DATA_ERROR */  			mci_writel(host, RINTSTS, DW_MCI_DATA_ERROR_FLAGS);  			host->data_status = pending; -			smp_wmb(); +			smp_wmb(); /* drain writebuffer */  			set_bit(EVENT_DATA_ERROR, &host->pending_events);  			tasklet_schedule(&host->tasklet);  		}  		if (pending & SDMMC_INT_DATA_OVER) { +			if (host->quirks & DW_MCI_QUIRK_BROKEN_DTO) +				del_timer(&host->dto_timer); +  			mci_writel(host, RINTSTS, SDMMC_INT_DATA_OVER);  			if (!host->data_status)  				host->data_status = pending; -			smp_wmb(); +			smp_wmb(); /* drain writebuffer */  			if (host->dir_status == DW_MCI_RECV_STATUS) {  				if (host->sg != NULL)  					dw_mci_read_data_pio(host, true); @@ -2383,27 +2470,20 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)  	if (ret)  		goto err_host_allocated; -	if (host->pdata->blk_settings) { -		mmc->max_segs = host->pdata->blk_settings->max_segs; -		mmc->max_blk_size = host->pdata->blk_settings->max_blk_size; -		mmc->max_blk_count = host->pdata->blk_settings->max_blk_count; -		mmc->max_req_size = host->pdata->blk_settings->max_req_size; -		mmc->max_seg_size = host->pdata->blk_settings->max_seg_size; -	} else { -		/* Useful defaults if platform data is unset. */ -#ifdef CONFIG_MMC_DW_IDMAC +	/* Useful defaults if platform data is unset. */ +	if (host->use_dma) {  		mmc->max_segs = host->ring_size;  		mmc->max_blk_size = 65536;  		mmc->max_seg_size = 0x1000;  		mmc->max_req_size = mmc->max_seg_size * host->ring_size;  		mmc->max_blk_count = mmc->max_req_size / 512; -#else +	} else {  		mmc->max_segs = 64;  		mmc->max_blk_size = 65536; /* BLKSIZ is 16 bits */  		mmc->max_blk_count = 512; -		mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; +		mmc->max_req_size = mmc->max_blk_size * +				    mmc->max_blk_count;  		mmc->max_seg_size = mmc->max_req_size; -#endif /* CONFIG_MMC_DW_IDMAC */  	}  	if (dw_mci_get_cd(mmc)) @@ -2473,8 +2553,8 @@ static void dw_mci_init_dma(struct dw_mci *host)  	if (host->dma_ops->init && host->dma_ops->start &&  	    host->dma_ops->stop && host->dma_ops->cleanup) {  		if (host->dma_ops->init(host)) { -			dev_err(host->dev, "%s: Unable to initialize " -				"DMA Controller.\n", __func__); +			dev_err(host->dev, "%s: Unable to initialize DMA Controller.\n", +				__func__);  			goto no_dma;  		}  	} else { @@ -2488,7 +2568,6 @@ static void dw_mci_init_dma(struct dw_mci *host)  no_dma:  	dev_info(host->dev, "Using PIO mode.\n");  	host->use_dma = 0; -	return;  }  static bool dw_mci_ctrl_reset(struct dw_mci *host, u32 reset) @@ -2542,6 +2621,7 @@ static bool dw_mci_reset(struct dw_mci *host)  		if (host->use_dma) {  			unsigned long timeout = jiffies + msecs_to_jiffies(500);  			u32 status; +  			do {  				status = mci_readl(host, STATUS);  				if (!(status & SDMMC_STATUS_DMA_REQ)) @@ -2551,8 +2631,8 @@ static bool dw_mci_reset(struct dw_mci *host)  			if (status & SDMMC_STATUS_DMA_REQ) {  				dev_err(host->dev, -					"%s: Timeout waiting for dma_req to " -					"clear during reset\n", __func__); +					"%s: Timeout waiting for dma_req to clear during reset\n", +					__func__);  				goto ciu_out;  			} @@ -2563,8 +2643,8 @@ static bool dw_mci_reset(struct dw_mci *host)  	} else {  		/* if the controller reset bit did clear, then set clock regs */  		if (!(mci_readl(host, CTRL) & SDMMC_CTRL_RESET)) { -			dev_err(host->dev, "%s: fifo/dma reset bits didn't " -				"clear but ciu was reset, doing clock update\n", +			dev_err(host->dev, +				"%s: fifo/dma reset bits didn't clear but ciu was reset, doing clock update\n",  				__func__);  			goto ciu_out;  		} @@ -2598,6 +2678,28 @@ static void dw_mci_cmd11_timer(unsigned long arg)  	tasklet_schedule(&host->tasklet);  } +static void dw_mci_dto_timer(unsigned long arg) +{ +	struct dw_mci *host = (struct dw_mci *)arg; + +	switch (host->state) { +	case STATE_SENDING_DATA: +	case STATE_DATA_BUSY: +		/* +		 * If DTO interrupt does NOT come in sending data state, +		 * we should notify the driver to terminate current transfer +		 * and report a data timeout to the core. +		 */ +		host->data_status = SDMMC_INT_DRTO; +		set_bit(EVENT_DATA_ERROR, &host->pending_events); +		set_bit(EVENT_DATA_COMPLETE, &host->pending_events); +		tasklet_schedule(&host->tasklet); +		break; +	default: +		break; +	} +} +  #ifdef CONFIG_OF  static struct dw_mci_of_quirks {  	char *quirk; @@ -2625,8 +2727,8 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)  	/* find out number of slots supported */  	if (of_property_read_u32(dev->of_node, "num-slots",  				&pdata->num_slots)) { -		dev_info(dev, "num-slots property not found, " -				"assuming 1 slot is available\n"); +		dev_info(dev, +			 "num-slots property not found, assuming 1 slot is available\n");  		pdata->num_slots = 1;  	} @@ -2636,8 +2738,8 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)  			pdata->quirks |= of_quirks[idx].id;  	if (of_property_read_u32(np, "fifo-depth", &pdata->fifo_depth)) -		dev_info(dev, "fifo-depth property not found, using " -				"value of FIFOTH register as default\n"); +		dev_info(dev, +			 "fifo-depth property not found, using value of FIFOTH register as default\n");  	of_property_read_u32(np, "card-detect-delay", &pdata->detect_delay_ms); @@ -2650,8 +2752,10 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)  			return ERR_PTR(ret);  	} -	if (of_find_property(np, "supports-highspeed", NULL)) +	if (of_find_property(np, "supports-highspeed", NULL)) { +		dev_info(dev, "supports-highspeed property is deprecated.\n");  		pdata->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; +	}  	return pdata;  } @@ -2706,7 +2810,7 @@ int dw_mci_probe(struct dw_mci *host)  		}  	} -	if (host->pdata->num_slots > 1) { +	if (host->pdata->num_slots < 1) {  		dev_err(host->dev,  			"Platform data must supply num_slots.\n");  		return -ENODEV; @@ -2774,6 +2878,10 @@ int dw_mci_probe(struct dw_mci *host)  	host->quirks = host->pdata->quirks; +	if (host->quirks & DW_MCI_QUIRK_BROKEN_DTO) +		setup_timer(&host->dto_timer, +			    dw_mci_dto_timer, (unsigned long)host); +  	spin_lock_init(&host->lock);  	spin_lock_init(&host->irq_lock);  	INIT_LIST_HEAD(&host->queue); @@ -2874,11 +2982,11 @@ int dw_mci_probe(struct dw_mci *host)  	mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER |  		   SDMMC_INT_TXDR | SDMMC_INT_RXDR |  		   DW_MCI_ERROR_FLAGS); -	mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */ +	/* Enable mci interrupt */ +	mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); -	dev_info(host->dev, "DW MMC controller at irq %d, " -		 "%d bit host data width, " -		 "%u deep fifo\n", +	dev_info(host->dev, +		 "DW MMC controller at irq %d,%d bit host data width,%u deep fifo\n",  		 host->irq, width, fifo_size);  	/* We need at least one slot to succeed */ @@ -2893,8 +3001,9 @@ int dw_mci_probe(struct dw_mci *host)  	if (init_slots) {  		dev_info(host->dev, "%d slots initialized\n", init_slots);  	} else { -		dev_dbg(host->dev, "attempted to initialize %d slots, " -					"but failed on all\n", host->num_slots); +		dev_dbg(host->dev, +			"attempted to initialize %d slots, but failed on all\n", +			host->num_slots);  		goto err_dmaunmap;  	} @@ -2992,6 +3101,7 @@ int dw_mci_resume(struct dw_mci *host)  	for (i = 0; i < host->num_slots; i++) {  		struct dw_mci_slot *slot = host->slot[i]; +  		if (!slot)  			continue;  		if (slot->mmc->pm_flags & MMC_PM_KEEP_POWER) { diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index 68dd6c79c378..b763b11ed9e1 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c @@ -948,6 +948,7 @@ mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req)  {  	struct mmc_data *data = req->data;  	int i, use_dma = 1, block_size; +	struct scatterlist *sg;  	unsigned sg_len;  	host->data = data; @@ -972,8 +973,8 @@ mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req)  	sg_len = (data->blocks == 1) ? 1 : data->sg_len;  	/* Only do DMA for entire blocks */ -	for (i = 0; i < sg_len; i++) { -		if ((data->sg[i].length % block_size) != 0) { +	for_each_sg(data->sg, sg, sg_len, i) { +		if ((sg->length % block_size) != 0) {  			use_dma = 0;  			break;  		} @@ -1419,8 +1420,10 @@ static int mmc_omap_probe(struct platform_device *pdev)  	host->reg_shift = (mmc_omap7xx() ? 1 : 2);  	host->mmc_omap_wq = alloc_workqueue("mmc_omap", 0, 0); -	if (!host->mmc_omap_wq) +	if (!host->mmc_omap_wq) { +		ret = -ENOMEM;  		goto err_plat_cleanup; +	}  	for (i = 0; i < pdata->nr_slots; i++) {  		ret = mmc_omap_new_slot(host, i); diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index b2b411da297b..781e4db31767 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -181,18 +181,9 @@ struct omap_hsmmc_host {  	struct	mmc_data	*data;  	struct	clk		*fclk;  	struct	clk		*dbclk; -	/* -	 * vcc == configured supply -	 * vcc_aux == optional -	 *   -	MMC1, supply for DAT4..DAT7 -	 *   -	MMC2/MMC2, external level shifter voltage supply, for -	 *	chip (SDIO, eMMC, etc) or transceiver (MMC2 only) -	 */ -	struct	regulator	*vcc; -	struct	regulator	*vcc_aux;  	struct	regulator	*pbias; -	bool			pbias_enabled;  	void	__iomem		*base; +	int			vqmmc_enabled;  	resource_size_t		mapbase;  	spinlock_t		irq_lock; /* Prevent races with irq handler */  	unsigned int		dma_len; @@ -213,7 +204,6 @@ struct omap_hsmmc_host {  	int			context_loss;  	int			protect_card;  	int			reqs_blocked; -	int			use_reg;  	int			req_in_progress;  	unsigned long		clk_rate;  	unsigned int		flags; @@ -254,32 +244,133 @@ static int omap_hsmmc_get_cover_state(struct device *dev)  	return mmc_gpio_get_cd(host->mmc);  } -#ifdef CONFIG_REGULATOR +static int omap_hsmmc_enable_supply(struct mmc_host *mmc) +{ +	int ret; +	struct omap_hsmmc_host *host = mmc_priv(mmc); +	struct mmc_ios *ios = &mmc->ios; + +	if (mmc->supply.vmmc) { +		ret = mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd); +		if (ret) +			return ret; +	} + +	/* Enable interface voltage rail, if needed */ +	if (mmc->supply.vqmmc && !host->vqmmc_enabled) { +		ret = regulator_enable(mmc->supply.vqmmc); +		if (ret) { +			dev_err(mmc_dev(mmc), "vmmc_aux reg enable failed\n"); +			goto err_vqmmc; +		} +		host->vqmmc_enabled = 1; +	} + +	return 0; + +err_vqmmc: +	if (mmc->supply.vmmc) +		mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); + +	return ret; +} + +static int omap_hsmmc_disable_supply(struct mmc_host *mmc) +{ +	int ret; +	int status; +	struct omap_hsmmc_host *host = mmc_priv(mmc); + +	if (mmc->supply.vqmmc && host->vqmmc_enabled) { +		ret = regulator_disable(mmc->supply.vqmmc); +		if (ret) { +			dev_err(mmc_dev(mmc), "vmmc_aux reg disable failed\n"); +			return ret; +		} +		host->vqmmc_enabled = 0; +	} + +	if (mmc->supply.vmmc) { +		ret = mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); +		if (ret) +			goto err_set_ocr; +	} + +	return 0; + +err_set_ocr: +	if (mmc->supply.vqmmc) { +		status = regulator_enable(mmc->supply.vqmmc); +		if (status) +			dev_err(mmc_dev(mmc), "vmmc_aux re-enable failed\n"); +	} + +	return ret; +} + +static int omap_hsmmc_set_pbias(struct omap_hsmmc_host *host, bool power_on, +				int vdd) +{ +	int ret; + +	if (!host->pbias) +		return 0; + +	if (power_on) { +		if (vdd <= VDD_165_195) +			ret = regulator_set_voltage(host->pbias, VDD_1V8, +						    VDD_1V8); +		else +			ret = regulator_set_voltage(host->pbias, VDD_3V0, +						    VDD_3V0); +		if (ret < 0) { +			dev_err(host->dev, "pbias set voltage fail\n"); +			return ret; +		} + +		if (!regulator_is_enabled(host->pbias)) { +			ret = regulator_enable(host->pbias); +			if (ret) { +				dev_err(host->dev, "pbias reg enable fail\n"); +				return ret; +			} +		} +	} else { +		if (regulator_is_enabled(host->pbias)) { +			ret = regulator_disable(host->pbias); +			if (ret) { +				dev_err(host->dev, "pbias reg disable fail\n"); +				return ret; +			} +		} +	} + +	return 0; +}  static int omap_hsmmc_set_power(struct device *dev, int power_on, int vdd)  {  	struct omap_hsmmc_host *host =  		platform_get_drvdata(to_platform_device(dev)); +	struct mmc_host *mmc = host->mmc;  	int ret = 0; +	if (mmc_pdata(host)->set_power) +		return mmc_pdata(host)->set_power(dev, power_on, vdd); +  	/*  	 * If we don't see a Vcc regulator, assume it's a fixed  	 * voltage always-on regulator.  	 */ -	if (!host->vcc) +	if (!mmc->supply.vmmc)  		return 0;  	if (mmc_pdata(host)->before_set_reg)  		mmc_pdata(host)->before_set_reg(dev, power_on, vdd); -	if (host->pbias) { -		if (host->pbias_enabled == 1) { -			ret = regulator_disable(host->pbias); -			if (!ret) -				host->pbias_enabled = 0; -		} -		regulator_set_voltage(host->pbias, VDD_3V0, VDD_3V0); -	} +	ret = omap_hsmmc_set_pbias(host, false, 0); +	if (ret) +		return ret;  	/*  	 * Assume Vcc regulator is used only to power the card ... OMAP @@ -295,129 +386,138 @@ static int omap_hsmmc_set_power(struct device *dev, int power_on, int vdd)  	 * chips/cards need an interface voltage rail too.  	 */  	if (power_on) { -		if (host->vcc) -			ret = mmc_regulator_set_ocr(host->mmc, host->vcc, vdd); -		/* Enable interface voltage rail, if needed */ -		if (ret == 0 && host->vcc_aux) { -			ret = regulator_enable(host->vcc_aux); -			if (ret < 0 && host->vcc) -				ret = mmc_regulator_set_ocr(host->mmc, -							host->vcc, 0); -		} -	} else { -		/* Shut down the rail */ -		if (host->vcc_aux) -			ret = regulator_disable(host->vcc_aux); -		if (host->vcc) { -			/* Then proceed to shut down the local regulator */ -			ret = mmc_regulator_set_ocr(host->mmc, -						host->vcc, 0); -		} -	} - -	if (host->pbias) { -		if (vdd <= VDD_165_195) -			ret = regulator_set_voltage(host->pbias, VDD_1V8, -								VDD_1V8); -		else -			ret = regulator_set_voltage(host->pbias, VDD_3V0, -								VDD_3V0); -		if (ret < 0) -			goto error_set_power; +		ret = omap_hsmmc_enable_supply(mmc); +		if (ret) +			return ret; -		if (host->pbias_enabled == 0) { -			ret = regulator_enable(host->pbias); -			if (!ret) -				host->pbias_enabled = 1; -		} +		ret = omap_hsmmc_set_pbias(host, true, vdd); +		if (ret) +			goto err_set_voltage; +	} else { +		ret = omap_hsmmc_disable_supply(mmc); +		if (ret) +			return ret;  	}  	if (mmc_pdata(host)->after_set_reg)  		mmc_pdata(host)->after_set_reg(dev, power_on, vdd); -error_set_power: +	return 0; + +err_set_voltage: +	omap_hsmmc_disable_supply(mmc); +  	return ret;  } -static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host) +static int omap_hsmmc_disable_boot_regulator(struct regulator *reg)  { -	struct regulator *reg; -	int ocr_value = 0; +	int ret; -	reg = devm_regulator_get(host->dev, "vmmc"); -	if (IS_ERR(reg)) { -		dev_err(host->dev, "unable to get vmmc regulator %ld\n", -			PTR_ERR(reg)); -		return PTR_ERR(reg); -	} else { -		host->vcc = reg; -		ocr_value = mmc_regulator_get_ocrmask(reg); -		if (!mmc_pdata(host)->ocr_mask) { -			mmc_pdata(host)->ocr_mask = ocr_value; -		} else { -			if (!(mmc_pdata(host)->ocr_mask & ocr_value)) { -				dev_err(host->dev, "ocrmask %x is not supported\n", -					mmc_pdata(host)->ocr_mask); -				mmc_pdata(host)->ocr_mask = 0; -				return -EINVAL; -			} -		} +	if (!reg) +		return 0; + +	if (regulator_is_enabled(reg)) { +		ret = regulator_enable(reg); +		if (ret) +			return ret; + +		ret = regulator_disable(reg); +		if (ret) +			return ret;  	} -	mmc_pdata(host)->set_power = omap_hsmmc_set_power; -	/* Allow an aux regulator */ -	reg = devm_regulator_get_optional(host->dev, "vmmc_aux"); -	host->vcc_aux = IS_ERR(reg) ? NULL : reg; +	return 0; +} -	reg = devm_regulator_get_optional(host->dev, "pbias"); -	host->pbias = IS_ERR(reg) ? NULL : reg; +static int omap_hsmmc_disable_boot_regulators(struct omap_hsmmc_host *host) +{ +	struct mmc_host *mmc = host->mmc; +	int ret; -	/* For eMMC do not power off when not in sleep state */ -	if (mmc_pdata(host)->no_regulator_off_init) -		return 0;  	/* -	 * To disable boot_on regulator, enable regulator -	 * to increase usecount and then disable it. +	 * disable regulators enabled during boot and get the usecount +	 * right so that regulators can be enabled/disabled by checking +	 * the return value of regulator_is_enabled  	 */ -	if ((host->vcc && regulator_is_enabled(host->vcc) > 0) || -	    (host->vcc_aux && regulator_is_enabled(host->vcc_aux))) { -		int vdd = ffs(mmc_pdata(host)->ocr_mask) - 1; +	ret = omap_hsmmc_disable_boot_regulator(mmc->supply.vmmc); +	if (ret) { +		dev_err(host->dev, "fail to disable boot enabled vmmc reg\n"); +		return ret; +	} + +	ret = omap_hsmmc_disable_boot_regulator(mmc->supply.vqmmc); +	if (ret) { +		dev_err(host->dev, +			"fail to disable boot enabled vmmc_aux reg\n"); +		return ret; +	} -		mmc_pdata(host)->set_power(host->dev, 1, vdd); -		mmc_pdata(host)->set_power(host->dev, 0, 0); +	ret = omap_hsmmc_disable_boot_regulator(host->pbias); +	if (ret) { +		dev_err(host->dev, +			"failed to disable boot enabled pbias reg\n"); +		return ret;  	}  	return 0;  } -static void omap_hsmmc_reg_put(struct omap_hsmmc_host *host) +static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host)  { -	mmc_pdata(host)->set_power = NULL; -} +	int ocr_value = 0; +	int ret; +	struct mmc_host *mmc = host->mmc; -static inline int omap_hsmmc_have_reg(void) -{ -	return 1; -} +	if (mmc_pdata(host)->set_power) +		return 0; -#else +	mmc->supply.vmmc = devm_regulator_get_optional(host->dev, "vmmc"); +	if (IS_ERR(mmc->supply.vmmc)) { +		ret = PTR_ERR(mmc->supply.vmmc); +		if (ret != -ENODEV) +			return ret; +		dev_dbg(host->dev, "unable to get vmmc regulator %ld\n", +			PTR_ERR(mmc->supply.vmmc)); +		mmc->supply.vmmc = NULL; +	} else { +		ocr_value = mmc_regulator_get_ocrmask(mmc->supply.vmmc); +		if (ocr_value > 0) +			mmc_pdata(host)->ocr_mask = ocr_value; +	} -static inline int omap_hsmmc_reg_get(struct omap_hsmmc_host *host) -{ -	return -EINVAL; -} +	/* Allow an aux regulator */ +	mmc->supply.vqmmc = devm_regulator_get_optional(host->dev, "vmmc_aux"); +	if (IS_ERR(mmc->supply.vqmmc)) { +		ret = PTR_ERR(mmc->supply.vqmmc); +		if (ret != -ENODEV) +			return ret; +		dev_dbg(host->dev, "unable to get vmmc_aux regulator %ld\n", +			PTR_ERR(mmc->supply.vqmmc)); +		mmc->supply.vqmmc = NULL; +	} -static inline void omap_hsmmc_reg_put(struct omap_hsmmc_host *host) -{ -} +	host->pbias = devm_regulator_get_optional(host->dev, "pbias"); +	if (IS_ERR(host->pbias)) { +		ret = PTR_ERR(host->pbias); +		if (ret != -ENODEV) +			return ret; +		dev_dbg(host->dev, "unable to get pbias regulator %ld\n", +			PTR_ERR(host->pbias)); +		host->pbias = NULL; +	} + +	/* For eMMC do not power off when not in sleep state */ +	if (mmc_pdata(host)->no_regulator_off_init) +		return 0; + +	ret = omap_hsmmc_disable_boot_regulators(host); +	if (ret) +		return ret; -static inline int omap_hsmmc_have_reg(void) -{  	return 0;  } -#endif -  static irqreturn_t omap_hsmmc_cover_irq(int irq, void *dev_id);  static int omap_hsmmc_gpio_init(struct mmc_host *mmc, @@ -1062,9 +1162,14 @@ static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status)  		if (status & (CTO_EN | CCRC_EN))  			end_cmd = 1; +		if (host->data || host->response_busy) { +			end_trans = !end_cmd; +			host->response_busy = 0; +		}  		if (status & (CTO_EN | DTO_EN))  			hsmmc_command_incomplete(host, -ETIMEDOUT, end_cmd); -		else if (status & (CCRC_EN | DCRC_EN)) +		else if (status & (CCRC_EN | DCRC_EN | DEB_EN | CEB_EN | +				   BADA_EN))  			hsmmc_command_incomplete(host, -EILSEQ, end_cmd);  		if (status & ACE_EN) { @@ -1081,10 +1186,6 @@ static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status)  			}  			dev_dbg(mmc_dev(host->mmc), "AC12 err: 0x%x\n", ac12);  		} -		if (host->data || host->response_busy) { -			end_trans = !end_cmd; -			host->response_busy = 0; -		}  	}  	OMAP_HSMMC_WRITE(host->base, STAT, status); @@ -1148,11 +1249,11 @@ static int omap_hsmmc_switch_opcond(struct omap_hsmmc_host *host, int vdd)  		clk_disable_unprepare(host->dbclk);  	/* Turn the power off */ -	ret = mmc_pdata(host)->set_power(host->dev, 0, 0); +	ret = omap_hsmmc_set_power(host->dev, 0, 0);  	/* Turn the power ON with given VDD 1.8 or 3.0v */  	if (!ret) -		ret = mmc_pdata(host)->set_power(host->dev, 1, vdd); +		ret = omap_hsmmc_set_power(host->dev, 1, vdd);  	pm_runtime_get_sync(host->dev);  	if (host->dbclk)  		clk_prepare_enable(host->dbclk); @@ -1551,10 +1652,10 @@ static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)  	if (ios->power_mode != host->power_mode) {  		switch (ios->power_mode) {  		case MMC_POWER_OFF: -			mmc_pdata(host)->set_power(host->dev, 0, 0); +			omap_hsmmc_set_power(host->dev, 0, 0);  			break;  		case MMC_POWER_UP: -			mmc_pdata(host)->set_power(host->dev, 1, ios->vdd); +			omap_hsmmc_set_power(host->dev, 1, ios->vdd);  			break;  		case MMC_POWER_ON:  			do_send_init_stream = 1; @@ -1952,7 +2053,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev)  	host->base	= base + pdata->reg_offset;  	host->power_mode = MMC_POWER_OFF;  	host->next_data.cookie = 1; -	host->pbias_enabled = 0; +	host->vqmmc_enabled = 0;  	ret = omap_hsmmc_gpio_init(mmc, host, pdata);  	if (ret) @@ -2077,12 +2178,9 @@ static int omap_hsmmc_probe(struct platform_device *pdev)  		goto err_irq;  	} -	if (omap_hsmmc_have_reg() && !mmc_pdata(host)->set_power) { -		ret = omap_hsmmc_reg_get(host); -		if (ret) -			goto err_irq; -		host->use_reg = 1; -	} +	ret = omap_hsmmc_reg_get(host); +	if (ret) +		goto err_irq;  	mmc->ocr_avail = mmc_pdata(host)->ocr_mask; @@ -2124,8 +2222,6 @@ static int omap_hsmmc_probe(struct platform_device *pdev)  err_slot_name:  	mmc_remove_host(mmc); -	if (host->use_reg) -		omap_hsmmc_reg_put(host);  err_irq:  	device_init_wakeup(&pdev->dev, false);  	if (host->tx_chan) @@ -2149,8 +2245,6 @@ static int omap_hsmmc_remove(struct platform_device *pdev)  	pm_runtime_get_sync(host->dev);  	mmc_remove_host(host->mmc); -	if (host->use_reg) -		omap_hsmmc_reg_put(host);  	if (host->tx_chan)  		dma_release_channel(host->tx_chan); diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index 1b6d0bfe35f5..1420f29628c7 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c @@ -22,7 +22,9 @@  #include <linux/platform_device.h>  #include <linux/delay.h>  #include <linux/interrupt.h> +#include <linux/dmaengine.h>  #include <linux/dma-mapping.h> +#include <linux/dma/pxa-dma.h>  #include <linux/clk.h>  #include <linux/err.h>  #include <linux/mmc/host.h> @@ -37,7 +39,6 @@  #include <asm/sizes.h>  #include <mach/hardware.h> -#include <mach/dma.h>  #include <linux/platform_data/mmc-pxamci.h>  #include "pxamci.h" @@ -58,7 +59,6 @@ struct pxamci_host {  	struct clk		*clk;  	unsigned long		clkrate;  	int			irq; -	int			dma;  	unsigned int		clkrt;  	unsigned int		cmdat;  	unsigned int		imask; @@ -69,8 +69,10 @@ struct pxamci_host {  	struct mmc_command	*cmd;  	struct mmc_data		*data; +	struct dma_chan		*dma_chan_rx; +	struct dma_chan		*dma_chan_tx; +	dma_cookie_t		dma_cookie;  	dma_addr_t		sg_dma; -	struct pxa_dma_desc	*sg_cpu;  	unsigned int		dma_len;  	unsigned int		dma_dir; @@ -173,14 +175,18 @@ static void pxamci_disable_irq(struct pxamci_host *host, unsigned int mask)  	spin_unlock_irqrestore(&host->lock, flags);  } +static void pxamci_dma_irq(void *param); +  static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data)  { +	struct dma_async_tx_descriptor *tx; +	enum dma_data_direction direction; +	struct dma_slave_config	config; +	struct dma_chan *chan;  	unsigned int nob = data->blocks;  	unsigned long long clks;  	unsigned int timeout; -	bool dalgn = 0; -	u32 dcmd; -	int i; +	int ret;  	host->data = data; @@ -195,54 +201,48 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data)  	timeout = (unsigned int)clks + (data->timeout_clks << host->clkrt);  	writel((timeout + 255) / 256, host->base + MMC_RDTO); +	memset(&config, 0, sizeof(config)); +	config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; +	config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; +	config.src_addr = host->res->start + MMC_RXFIFO; +	config.dst_addr = host->res->start + MMC_TXFIFO; +	config.src_maxburst = 32; +	config.dst_maxburst = 32; +  	if (data->flags & MMC_DATA_READ) {  		host->dma_dir = DMA_FROM_DEVICE; -		dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC; -		DRCMR(host->dma_drcmrtx) = 0; -		DRCMR(host->dma_drcmrrx) = host->dma | DRCMR_MAPVLD; +		direction = DMA_DEV_TO_MEM; +		chan = host->dma_chan_rx;  	} else {  		host->dma_dir = DMA_TO_DEVICE; -		dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG; -		DRCMR(host->dma_drcmrrx) = 0; -		DRCMR(host->dma_drcmrtx) = host->dma | DRCMR_MAPVLD; +		direction = DMA_MEM_TO_DEV; +		chan = host->dma_chan_tx;  	} -	dcmd |= DCMD_BURST32 | DCMD_WIDTH1; +	config.direction = direction; + +	ret = dmaengine_slave_config(chan, &config); +	if (ret < 0) { +		dev_err(mmc_dev(host->mmc), "dma slave config failed\n"); +		return; +	} -	host->dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, +	host->dma_len = dma_map_sg(chan->device->dev, data->sg, data->sg_len,  				   host->dma_dir); -	for (i = 0; i < host->dma_len; i++) { -		unsigned int length = sg_dma_len(&data->sg[i]); -		host->sg_cpu[i].dcmd = dcmd | length; -		if (length & 31 && !(data->flags & MMC_DATA_READ)) -			host->sg_cpu[i].dcmd |= DCMD_ENDIRQEN; -		/* Not aligned to 8-byte boundary? */ -		if (sg_dma_address(&data->sg[i]) & 0x7) -			dalgn = 1; -		if (data->flags & MMC_DATA_READ) { -			host->sg_cpu[i].dsadr = host->res->start + MMC_RXFIFO; -			host->sg_cpu[i].dtadr = sg_dma_address(&data->sg[i]); -		} else { -			host->sg_cpu[i].dsadr = sg_dma_address(&data->sg[i]); -			host->sg_cpu[i].dtadr = host->res->start + MMC_TXFIFO; -		} -		host->sg_cpu[i].ddadr = host->sg_dma + (i + 1) * -					sizeof(struct pxa_dma_desc); +	tx = dmaengine_prep_slave_sg(chan, data->sg, host->dma_len, direction, +				     DMA_PREP_INTERRUPT); +	if (!tx) { +		dev_err(mmc_dev(host->mmc), "prep_slave_sg() failed\n"); +		return;  	} -	host->sg_cpu[host->dma_len - 1].ddadr = DDADR_STOP; -	wmb(); -	/* -	 * The PXA27x DMA controller encounters overhead when working with -	 * unaligned (to 8-byte boundaries) data, so switch on byte alignment -	 * mode only if we have unaligned data. -	 */ -	if (dalgn) -		DALGN |= (1 << host->dma); -	else -		DALGN &= ~(1 << host->dma); -	DDADR(host->dma) = host->sg_dma; +	if (!(data->flags & MMC_DATA_READ)) { +		tx->callback = pxamci_dma_irq; +		tx->callback_param = host; +	} + +	host->dma_cookie = dmaengine_submit(tx);  	/*  	 * workaround for erratum #91: @@ -251,7 +251,7 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data)  	 * before starting DMA.  	 */  	if (!cpu_is_pxa27x() || data->flags & MMC_DATA_READ) -		DCSR(host->dma) = DCSR_RUN; +		dma_async_issue_pending(chan);  }  static void pxamci_start_cmd(struct pxamci_host *host, struct mmc_command *cmd, unsigned int cmdat) @@ -343,7 +343,7 @@ static int pxamci_cmd_done(struct pxamci_host *host, unsigned int stat)  		 * enable DMA late  		 */  		if (cpu_is_pxa27x() && host->data->flags & MMC_DATA_WRITE) -			DCSR(host->dma) = DCSR_RUN; +			dma_async_issue_pending(host->dma_chan_tx);  	} else {  		pxamci_finish_request(host, host->mrq);  	} @@ -354,13 +354,17 @@ static int pxamci_cmd_done(struct pxamci_host *host, unsigned int stat)  static int pxamci_data_done(struct pxamci_host *host, unsigned int stat)  {  	struct mmc_data *data = host->data; +	struct dma_chan *chan;  	if (!data)  		return 0; -	DCSR(host->dma) = 0; -	dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, -		     host->dma_dir); +	if (data->flags & MMC_DATA_READ) +		chan = host->dma_chan_rx; +	else +		chan = host->dma_chan_tx; +	dma_unmap_sg(chan->device->dev, +		     data->sg, data->sg_len, host->dma_dir);  	if (stat & STAT_READ_TIME_OUT)  		data->error = -ETIMEDOUT; @@ -552,20 +556,37 @@ static const struct mmc_host_ops pxamci_ops = {  	.enable_sdio_irq	= pxamci_enable_sdio_irq,  }; -static void pxamci_dma_irq(int dma, void *devid) +static void pxamci_dma_irq(void *param)  { -	struct pxamci_host *host = devid; -	int dcsr = DCSR(dma); -	DCSR(dma) = dcsr & ~DCSR_STOPIRQEN; +	struct pxamci_host *host = param; +	struct dma_tx_state state; +	enum dma_status status; +	struct dma_chan *chan; +	unsigned long flags; + +	spin_lock_irqsave(&host->lock, flags); + +	if (!host->data) +		goto out_unlock; -	if (dcsr & DCSR_ENDINTR) { +	if (host->data->flags & MMC_DATA_READ) +		chan = host->dma_chan_rx; +	else +		chan = host->dma_chan_tx; + +	status = dmaengine_tx_status(chan, host->dma_cookie, &state); + +	if (likely(status == DMA_COMPLETE)) {  		writel(BUF_PART_FULL, host->base + MMC_PRTBUF);  	} else { -		pr_err("%s: DMA error on channel %d (DCSR=%#x)\n", -		       mmc_hostname(host->mmc), dma, dcsr); +		pr_err("%s: DMA error on %s channel\n", mmc_hostname(host->mmc), +			host->data->flags & MMC_DATA_READ ? "rx" : "tx");  		host->data->error = -EIO;  		pxamci_data_done(host, 0);  	} + +out_unlock: +	spin_unlock_irqrestore(&host->lock, flags);  }  static irqreturn_t pxamci_detect_irq(int irq, void *devid) @@ -625,7 +646,9 @@ static int pxamci_probe(struct platform_device *pdev)  	struct mmc_host *mmc;  	struct pxamci_host *host = NULL;  	struct resource *r, *dmarx, *dmatx; +	struct pxad_param param_rx, param_tx;  	int ret, irq, gpio_cd = -1, gpio_ro = -1, gpio_power = -1; +	dma_cap_mask_t mask;  	ret = pxamci_of_init(pdev);  	if (ret) @@ -671,7 +694,6 @@ static int pxamci_probe(struct platform_device *pdev)  	host = mmc_priv(mmc);  	host->mmc = mmc; -	host->dma = -1;  	host->pdata = pdev->dev.platform_data;  	host->clkrt = CLKRT_OFF; @@ -702,12 +724,6 @@ static int pxamci_probe(struct platform_device *pdev)  				     MMC_CAP_SD_HIGHSPEED;  	} -	host->sg_cpu = dma_alloc_coherent(&pdev->dev, PAGE_SIZE, &host->sg_dma, GFP_KERNEL); -	if (!host->sg_cpu) { -		ret = -ENOMEM; -		goto out; -	} -  	spin_lock_init(&host->lock);  	host->res = r;  	host->irq = irq; @@ -728,32 +744,45 @@ static int pxamci_probe(struct platform_device *pdev)  	writel(64, host->base + MMC_RESTO);  	writel(host->imask, host->base + MMC_I_MASK); -	host->dma = pxa_request_dma(DRIVER_NAME, DMA_PRIO_LOW, -				    pxamci_dma_irq, host); -	if (host->dma < 0) { -		ret = -EBUSY; -		goto out; -	} -  	ret = request_irq(host->irq, pxamci_irq, 0, DRIVER_NAME, host);  	if (ret)  		goto out;  	platform_set_drvdata(pdev, mmc); -	dmarx = platform_get_resource(pdev, IORESOURCE_DMA, 0); -	if (!dmarx) { -		ret = -ENXIO; +	if (!pdev->dev.of_node) { +		dmarx = platform_get_resource(pdev, IORESOURCE_DMA, 0); +		dmatx = platform_get_resource(pdev, IORESOURCE_DMA, 1); +		if (!dmarx || !dmatx) { +			ret = -ENXIO; +			goto out; +		} +		param_rx.prio = PXAD_PRIO_LOWEST; +		param_rx.drcmr = dmarx->start; +		param_tx.prio = PXAD_PRIO_LOWEST; +		param_tx.drcmr = dmatx->start; +	} + +	dma_cap_zero(mask); +	dma_cap_set(DMA_SLAVE, mask); + +	host->dma_chan_rx = +		dma_request_slave_channel_compat(mask, pxad_filter_fn, +						 ¶m_rx, &pdev->dev, "rx"); +	if (host->dma_chan_rx == NULL) { +		dev_err(&pdev->dev, "unable to request rx dma channel\n"); +		ret = -ENODEV;  		goto out;  	} -	host->dma_drcmrrx = dmarx->start; -	dmatx = platform_get_resource(pdev, IORESOURCE_DMA, 1); -	if (!dmatx) { -		ret = -ENXIO; +	host->dma_chan_tx = +		dma_request_slave_channel_compat(mask, pxad_filter_fn, +						 ¶m_tx,  &pdev->dev, "tx"); +	if (host->dma_chan_tx == NULL) { +		dev_err(&pdev->dev, "unable to request tx dma channel\n"); +		ret = -ENODEV;  		goto out;  	} -	host->dma_drcmrtx = dmatx->start;  	if (host->pdata) {  		gpio_cd = host->pdata->gpio_card_detect; @@ -814,12 +843,12 @@ err_gpio_ro:  	gpio_free(gpio_power);   out:  	if (host) { -		if (host->dma >= 0) -			pxa_free_dma(host->dma); +		if (host->dma_chan_rx) +			dma_release_channel(host->dma_chan_rx); +		if (host->dma_chan_tx) +			dma_release_channel(host->dma_chan_tx);  		if (host->base)  			iounmap(host->base); -		if (host->sg_cpu) -			dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);  		if (host->clk)  			clk_put(host->clk);  	} @@ -863,13 +892,12 @@ static int pxamci_remove(struct platform_device *pdev)  		       END_CMD_RES|PRG_DONE|DATA_TRAN_DONE,  		       host->base + MMC_I_MASK); -		DRCMR(host->dma_drcmrrx) = 0; -		DRCMR(host->dma_drcmrtx) = 0; -  		free_irq(host->irq, host); -		pxa_free_dma(host->dma); +		dmaengine_terminate_all(host->dma_chan_rx); +		dmaengine_terminate_all(host->dma_chan_tx); +		dma_release_channel(host->dma_chan_rx); +		dma_release_channel(host->dma_chan_tx);  		iounmap(host->base); -		dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);  		clk_put(host->clk); diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index faf0cb910c96..886d230f41d0 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -32,6 +32,7 @@  #include "sdhci-esdhc.h"  #define	ESDHC_CTRL_D3CD			0x08 +#define ESDHC_BURST_LEN_EN_INCR		(1 << 27)  /* VENDOR SPEC register */  #define ESDHC_VENDOR_SPEC		0xc0  #define  ESDHC_VENDOR_SPEC_SDIO_QUIRK	(1 << 1) @@ -44,6 +45,7 @@  #define  ESDHC_MIX_CTRL_EXE_TUNE	(1 << 22)  #define  ESDHC_MIX_CTRL_SMPCLK_SEL	(1 << 23)  #define  ESDHC_MIX_CTRL_FBCLK_SEL	(1 << 25) +#define  ESDHC_MIX_CTRL_HS400_EN	(1 << 26)  /* Bits 3 and 6 are not SDHCI standard definitions */  #define  ESDHC_MIX_CTRL_SDHCI_MASK	0xb7  /* Tuning bits */ @@ -60,10 +62,21 @@  #define  ESDHC_TUNE_CTRL_MIN		0  #define  ESDHC_TUNE_CTRL_MAX		((1 << 7) - 1) +/* strobe dll register */ +#define ESDHC_STROBE_DLL_CTRL		0x70 +#define ESDHC_STROBE_DLL_CTRL_ENABLE	(1 << 0) +#define ESDHC_STROBE_DLL_CTRL_RESET	(1 << 1) +#define ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_SHIFT	3 + +#define ESDHC_STROBE_DLL_STATUS		0x74 +#define ESDHC_STROBE_DLL_STS_REF_LOCK	(1 << 1) +#define ESDHC_STROBE_DLL_STS_SLV_LOCK	0x1 +  #define ESDHC_TUNING_CTRL		0xcc  #define ESDHC_STD_TUNING_EN		(1 << 24)  /* NOTE: the minimum valid tuning start tap for mx6sl is 1 */  #define ESDHC_TUNING_START_TAP		0x1 +#define ESDHC_TUNING_STEP_SHIFT		16  /* pinctrl state */  #define ESDHC_PINCTRL_STATE_100MHZ	"state_100mhz" @@ -120,6 +133,11 @@  #define ESDHC_FLAG_ERR004536		BIT(7)  /* The IP supports HS200 mode */  #define ESDHC_FLAG_HS200		BIT(8) +/* The IP supports HS400 mode */ +#define ESDHC_FLAG_HS400		BIT(9) + +/* A higher clock ferquency than this rate requires strobell dll control */ +#define ESDHC_STROBE_DLL_CLK_FREQ	100000000  struct esdhc_soc_data {  	u32 flags; @@ -156,6 +174,12 @@ static struct esdhc_soc_data usdhc_imx6sx_data = {  			| ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200,  }; +static struct esdhc_soc_data usdhc_imx7d_data = { +	.flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING +			| ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200 +			| ESDHC_FLAG_HS400, +}; +  struct pltfm_imx_data {  	u32 scratchpad;  	struct pinctrl *pinctrl; @@ -199,6 +223,7 @@ static const struct of_device_id imx_esdhc_dt_ids[] = {  	{ .compatible = "fsl,imx6sx-usdhc", .data = &usdhc_imx6sx_data, },  	{ .compatible = "fsl,imx6sl-usdhc", .data = &usdhc_imx6sl_data, },  	{ .compatible = "fsl,imx6q-usdhc", .data = &usdhc_imx6q_data, }, +	{ .compatible = "fsl,imx7d-usdhc", .data = &usdhc_imx7d_data, },  	{ /* sentinel */ }  };  MODULE_DEVICE_TABLE(of, imx_esdhc_dt_ids); @@ -274,6 +299,9 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg)  				val = SDHCI_SUPPORT_DDR50 | SDHCI_SUPPORT_SDR104  					| SDHCI_SUPPORT_SDR50  					| SDHCI_USE_SDR50_TUNING; + +			if (imx_data->socdata->flags & ESDHC_FLAG_HS400) +				val |= SDHCI_SUPPORT_HS400;  		}  	} @@ -448,6 +476,7 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)  		} else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) {  			u32 v = readl(host->ioaddr + SDHCI_ACMD12_ERR);  			u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL); +			u32 tuning_ctrl;  			if (val & SDHCI_CTRL_TUNED_CLK) {  				v |= ESDHC_MIX_CTRL_SMPCLK_SEL;  			} else { @@ -458,6 +487,11 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)  			if (val & SDHCI_CTRL_EXEC_TUNING) {  				v |= ESDHC_MIX_CTRL_EXE_TUNE;  				m |= ESDHC_MIX_CTRL_FBCLK_SEL; +				tuning_ctrl = readl(host->ioaddr + ESDHC_TUNING_CTRL); +				tuning_ctrl |= ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP; +				if (imx_data->boarddata.tuning_step) +					tuning_ctrl |= imx_data->boarddata.tuning_step << ESDHC_TUNING_STEP_SHIFT; +					writel(tuning_ctrl, host->ioaddr + ESDHC_TUNING_CTRL);  			} else {  				v &= ~ESDHC_MIX_CTRL_EXE_TUNE;  			} @@ -581,13 +615,8 @@ static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg)  static unsigned int esdhc_pltfm_get_max_clock(struct sdhci_host *host)  {  	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); -	struct pltfm_imx_data *imx_data = pltfm_host->priv; -	struct esdhc_platform_data *boarddata = &imx_data->boarddata; -	if (boarddata->f_max && (boarddata->f_max < pltfm_host->clock)) -		return boarddata->f_max; -	else -		return pltfm_host->clock; +	return pltfm_host->clock;  }  static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host) @@ -779,6 +808,7 @@ static int esdhc_change_pinstate(struct sdhci_host *host,  		break;  	case MMC_TIMING_UHS_SDR104:  	case MMC_TIMING_MMC_HS200: +	case MMC_TIMING_MMC_HS400:  		pinctrl = imx_data->pins_200mhz;  		break;  	default: @@ -789,24 +819,68 @@ static int esdhc_change_pinstate(struct sdhci_host *host,  	return pinctrl_select_state(imx_data->pinctrl, pinctrl);  } +/* + * For HS400 eMMC, there is a data_strobe line, this signal is generated + * by the device and used for data output and CRC status response output + * in HS400 mode. The frequency of this signal follows the frequency of + * CLK generated by host. Host receive the data which is aligned to the + * edge of data_strobe line. Due to the time delay between CLK line and + * data_strobe line, if the delay time is larger than one clock cycle, + * then CLK and data_strobe line will misaligned, read error shows up. + * So when the CLK is higher than 100MHz, each clock cycle is short enough, + * host should config the delay target. + */ +static void esdhc_set_strobe_dll(struct sdhci_host *host) +{ +	u32 v; + +	if (host->mmc->actual_clock > ESDHC_STROBE_DLL_CLK_FREQ) { +		/* force a reset on strobe dll */ +		writel(ESDHC_STROBE_DLL_CTRL_RESET, +			host->ioaddr + ESDHC_STROBE_DLL_CTRL); +		/* +		 * enable strobe dll ctrl and adjust the delay target +		 * for the uSDHC loopback read clock +		 */ +		v = ESDHC_STROBE_DLL_CTRL_ENABLE | +			(7 << ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_SHIFT); +		writel(v, host->ioaddr + ESDHC_STROBE_DLL_CTRL); +		/* wait 1us to make sure strobe dll status register stable */ +		udelay(1); +		v = readl(host->ioaddr + ESDHC_STROBE_DLL_STATUS); +		if (!(v & ESDHC_STROBE_DLL_STS_REF_LOCK)) +			dev_warn(mmc_dev(host->mmc), +				"warning! HS400 strobe DLL status REF not lock!\n"); +		if (!(v & ESDHC_STROBE_DLL_STS_SLV_LOCK)) +			dev_warn(mmc_dev(host->mmc), +				"warning! HS400 strobe DLL status SLV not lock!\n"); +	} +} +  static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing)  { +	u32 m;  	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);  	struct pltfm_imx_data *imx_data = pltfm_host->priv;  	struct esdhc_platform_data *boarddata = &imx_data->boarddata; +	/* disable ddr mode and disable HS400 mode */ +	m = readl(host->ioaddr + ESDHC_MIX_CTRL); +	m &= ~(ESDHC_MIX_CTRL_DDREN | ESDHC_MIX_CTRL_HS400_EN); +	imx_data->is_ddr = 0; +  	switch (timing) {  	case MMC_TIMING_UHS_SDR12:  	case MMC_TIMING_UHS_SDR25:  	case MMC_TIMING_UHS_SDR50:  	case MMC_TIMING_UHS_SDR104:  	case MMC_TIMING_MMC_HS200: +		writel(m, host->ioaddr + ESDHC_MIX_CTRL);  		break;  	case MMC_TIMING_UHS_DDR50:  	case MMC_TIMING_MMC_DDR52: -		writel(readl(host->ioaddr + ESDHC_MIX_CTRL) | -				ESDHC_MIX_CTRL_DDREN, -				host->ioaddr + ESDHC_MIX_CTRL); +		m |= ESDHC_MIX_CTRL_DDREN; +		writel(m, host->ioaddr + ESDHC_MIX_CTRL);  		imx_data->is_ddr = 1;  		if (boarddata->delay_line) {  			u32 v; @@ -818,6 +892,12 @@ static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing)  			writel(v, host->ioaddr + ESDHC_DLL_CTRL);  		}  		break; +	case MMC_TIMING_MMC_HS400: +		m |= ESDHC_MIX_CTRL_DDREN | ESDHC_MIX_CTRL_HS400_EN; +		writel(m, host->ioaddr + ESDHC_MIX_CTRL); +		imx_data->is_ddr = 1; +		esdhc_set_strobe_dll(host); +		break;  	}  	esdhc_change_pinstate(host, timing); @@ -878,33 +958,20 @@ static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {  static int  sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,  			 struct sdhci_host *host, -			 struct esdhc_platform_data *boarddata) +			 struct pltfm_imx_data *imx_data)  {  	struct device_node *np = pdev->dev.of_node; - -	if (!np) -		return -ENODEV; - -	if (of_get_property(np, "non-removable", NULL)) -		boarddata->cd_type = ESDHC_CD_PERMANENT; - -	if (of_get_property(np, "fsl,cd-controller", NULL)) -		boarddata->cd_type = ESDHC_CD_CONTROLLER; +	struct esdhc_platform_data *boarddata = &imx_data->boarddata; +	int ret;  	if (of_get_property(np, "fsl,wp-controller", NULL))  		boarddata->wp_type = ESDHC_WP_CONTROLLER; -	boarddata->cd_gpio = of_get_named_gpio(np, "cd-gpios", 0); -	if (gpio_is_valid(boarddata->cd_gpio)) -		boarddata->cd_type = ESDHC_CD_GPIO; -  	boarddata->wp_gpio = of_get_named_gpio(np, "wp-gpios", 0);  	if (gpio_is_valid(boarddata->wp_gpio))  		boarddata->wp_type = ESDHC_WP_GPIO; -	of_property_read_u32(np, "bus-width", &boarddata->max_bus_width); - -	of_property_read_u32(np, "max-frequency", &boarddata->f_max); +	of_property_read_u32(np, "fsl,tuning-step", &boarddata->tuning_step);  	if (of_find_property(np, "no-1-8-v", NULL))  		boarddata->support_vsel = false; @@ -916,29 +983,119 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,  	mmc_of_parse_voltage(np, &host->ocr_mask); +	/* sdr50 and sdr104 needs work on 1.8v signal voltage */ +	if ((boarddata->support_vsel) && esdhc_is_usdhc(imx_data) && +	    !IS_ERR(imx_data->pins_default)) { +		imx_data->pins_100mhz = pinctrl_lookup_state(imx_data->pinctrl, +						ESDHC_PINCTRL_STATE_100MHZ); +		imx_data->pins_200mhz = pinctrl_lookup_state(imx_data->pinctrl, +						ESDHC_PINCTRL_STATE_200MHZ); +		if (IS_ERR(imx_data->pins_100mhz) || +				IS_ERR(imx_data->pins_200mhz)) { +			dev_warn(mmc_dev(host->mmc), +				"could not get ultra high speed state, work on normal mode\n"); +			/* +			 * fall back to not support uhs by specify no 1.8v quirk +			 */ +			host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V; +		} +	} else { +		host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V; +	} +  	/* call to generic mmc_of_parse to support additional capabilities */ -	return mmc_of_parse(host->mmc); +	ret = mmc_of_parse(host->mmc); +	if (ret) +		return ret; + +	if (!IS_ERR_VALUE(mmc_gpio_get_cd(host->mmc))) +		host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION; + +	return 0;  }  #else  static inline int  sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,  			 struct sdhci_host *host, -			 struct esdhc_platform_data *boarddata) +			 struct pltfm_imx_data *imx_data)  {  	return -ENODEV;  }  #endif +static int sdhci_esdhc_imx_probe_nondt(struct platform_device *pdev, +			 struct sdhci_host *host, +			 struct pltfm_imx_data *imx_data) +{ +	struct esdhc_platform_data *boarddata = &imx_data->boarddata; +	int err; + +	if (!host->mmc->parent->platform_data) { +		dev_err(mmc_dev(host->mmc), "no board data!\n"); +		return -EINVAL; +	} + +	imx_data->boarddata = *((struct esdhc_platform_data *) +				host->mmc->parent->platform_data); +	/* write_protect */ +	if (boarddata->wp_type == ESDHC_WP_GPIO) { +		err = mmc_gpio_request_ro(host->mmc, boarddata->wp_gpio); +		if (err) { +			dev_err(mmc_dev(host->mmc), +				"failed to request write-protect gpio!\n"); +			return err; +		} +		host->mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; +	} + +	/* card_detect */ +	switch (boarddata->cd_type) { +	case ESDHC_CD_GPIO: +		err = mmc_gpio_request_cd(host->mmc, boarddata->cd_gpio, 0); +		if (err) { +			dev_err(mmc_dev(host->mmc), +				"failed to request card-detect gpio!\n"); +			return err; +		} +		/* fall through */ + +	case ESDHC_CD_CONTROLLER: +		/* we have a working card_detect back */ +		host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION; +		break; + +	case ESDHC_CD_PERMANENT: +		host->mmc->caps |= MMC_CAP_NONREMOVABLE; +		break; + +	case ESDHC_CD_NONE: +		break; +	} + +	switch (boarddata->max_bus_width) { +	case 8: +		host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA; +		break; +	case 4: +		host->mmc->caps |= MMC_CAP_4_BIT_DATA; +		break; +	case 1: +	default: +		host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA; +		break; +	} + +	return 0; +} +  static int sdhci_esdhc_imx_probe(struct platform_device *pdev)  {  	const struct of_device_id *of_id =  			of_match_device(imx_esdhc_dt_ids, &pdev->dev);  	struct sdhci_pltfm_host *pltfm_host;  	struct sdhci_host *host; -	struct esdhc_platform_data *boarddata;  	int err;  	struct pltfm_imx_data *imx_data; -	bool dt = true;  	host = sdhci_pltfm_init(pdev, &sdhci_esdhc_imx_pdata, 0);  	if (IS_ERR(host)) @@ -1003,10 +1160,26 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)  	 * to something insane.  Change it back here.  	 */  	if (esdhc_is_usdhc(imx_data)) { -		writel(0x08100810, host->ioaddr + ESDHC_WTMK_LVL); +		writel(0x10401040, host->ioaddr + ESDHC_WTMK_LVL); +  		host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN;  		host->mmc->caps |= MMC_CAP_1_8V_DDR; +		/* +		 * ROM code will change the bit burst_length_enable setting +		 * to zero if this usdhc is choosed to boot system. Change +		 * it back here, otherwise it will impact the performance a +		 * lot. This bit is used to enable/disable the burst length +		 * for the external AHB2AXI bridge, it's usefully especially +		 * for INCR transfer because without burst length indicator, +		 * the AHB2AXI bridge does not know the burst length in +		 * advance. And without burst length indicator, AHB INCR +		 * transfer can only be converted to singles on the AXI side. +		 */ +		writel(readl(host->ioaddr + SDHCI_HOST_CONTROL) +			| ESDHC_BURST_LEN_EN_INCR, +			host->ioaddr + SDHCI_HOST_CONTROL); +  		if (!(imx_data->socdata->flags & ESDHC_FLAG_HS200))  			host->quirks2 |= SDHCI_QUIRK2_BROKEN_HS200; @@ -1030,84 +1203,15 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)  	if (imx_data->socdata->flags & ESDHC_FLAG_ERR004536)  		host->quirks |= SDHCI_QUIRK_BROKEN_ADMA; -	boarddata = &imx_data->boarddata; -	if (sdhci_esdhc_imx_probe_dt(pdev, host, boarddata) < 0) { -		if (!host->mmc->parent->platform_data) { -			dev_err(mmc_dev(host->mmc), "no board data!\n"); -			err = -EINVAL; -			goto disable_clk; -		} -		imx_data->boarddata = *((struct esdhc_platform_data *) -					host->mmc->parent->platform_data); -		dt = false; -	} -	/* write_protect */ -	if (boarddata->wp_type == ESDHC_WP_GPIO && !dt) { -		err = mmc_gpio_request_ro(host->mmc, boarddata->wp_gpio); -		if (err) { -			dev_err(mmc_dev(host->mmc), -				"failed to request write-protect gpio!\n"); -			goto disable_clk; -		} -		host->mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; -	} - -	/* card_detect */ -	switch (boarddata->cd_type) { -	case ESDHC_CD_GPIO: -		if (dt) -			break; -		err = mmc_gpio_request_cd(host->mmc, boarddata->cd_gpio, 0); -		if (err) { -			dev_err(mmc_dev(host->mmc), -				"failed to request card-detect gpio!\n"); -			goto disable_clk; -		} -		/* fall through */ - -	case ESDHC_CD_CONTROLLER: -		/* we have a working card_detect back */ -		host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION; -		break; - -	case ESDHC_CD_PERMANENT: -		host->mmc->caps |= MMC_CAP_NONREMOVABLE; -		break; +	if (imx_data->socdata->flags & ESDHC_FLAG_HS400) +		host->quirks2 |= SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400; -	case ESDHC_CD_NONE: -		break; -	} - -	switch (boarddata->max_bus_width) { -	case 8: -		host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA; -		break; -	case 4: -		host->mmc->caps |= MMC_CAP_4_BIT_DATA; -		break; -	case 1: -	default: -		host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA; -		break; -	} - -	/* sdr50 and sdr104 needs work on 1.8v signal voltage */ -	if ((boarddata->support_vsel) && esdhc_is_usdhc(imx_data) && -	    !IS_ERR(imx_data->pins_default)) { -		imx_data->pins_100mhz = pinctrl_lookup_state(imx_data->pinctrl, -						ESDHC_PINCTRL_STATE_100MHZ); -		imx_data->pins_200mhz = pinctrl_lookup_state(imx_data->pinctrl, -						ESDHC_PINCTRL_STATE_200MHZ); -		if (IS_ERR(imx_data->pins_100mhz) || -				IS_ERR(imx_data->pins_200mhz)) { -			dev_warn(mmc_dev(host->mmc), -				"could not get ultra high speed state, work on normal mode\n"); -			/* fall back to not support uhs by specify no 1.8v quirk */ -			host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V; -		} -	} else { -		host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V; -	} +	if (of_id) +		err = sdhci_esdhc_imx_probe_dt(pdev, host, imx_data); +	else +		err = sdhci_esdhc_imx_probe_nondt(pdev, host, imx_data); +	if (err) +		goto disable_clk;  	err = sdhci_add_host(host);  	if (err) diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h index 3497cfaf683c..163ac9974d91 100644 --- a/drivers/mmc/host/sdhci-esdhc.h +++ b/drivers/mmc/host/sdhci-esdhc.h @@ -21,7 +21,8 @@  #define ESDHC_DEFAULT_QUIRKS	(SDHCI_QUIRK_FORCE_BLK_SZ_2048 | \  				SDHCI_QUIRK_NO_BUSY_IRQ | \  				SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | \ -				SDHCI_QUIRK_PIO_NEEDS_DELAY) +				SDHCI_QUIRK_PIO_NEEDS_DELAY | \ +				SDHCI_QUIRK_NO_HISPD_BIT)  #define ESDHC_SYSTEM_CONTROL	0x2c  #define ESDHC_CLOCK_MASK	0x0000fff0 @@ -45,6 +46,6 @@  #define ESDHC_DMA_SYSCTL	0x40c  #define ESDHC_DMA_SNOOP		0x00000040 -#define ESDHC_HOST_CONTROL_RES	0x05 +#define ESDHC_HOST_CONTROL_RES	0x01  #endif /* _DRIVERS_MMC_SDHCI_ESDHC_H */ diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index 4a09f7608c66..4bcee033feda 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -489,6 +489,11 @@ static int sdhci_msm_probe(struct platform_device *pdev)  		goto pclk_disable;  	} +	/* Vote for maximum clock rate for maximum performance */ +	ret = clk_set_rate(msm_host->clk, INT_MAX); +	if (ret) +		dev_warn(&pdev->dev, "core clock boost failed\n"); +  	ret = clk_prepare_enable(msm_host->clk);  	if (ret)  		goto pclk_disable; diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c index 21c0c08dfe54..75379cb0fb35 100644 --- a/drivers/mmc/host/sdhci-of-arasan.c +++ b/drivers/mmc/host/sdhci-of-arasan.c @@ -63,6 +63,9 @@ static struct sdhci_ops sdhci_arasan_ops = {  static struct sdhci_pltfm_data sdhci_arasan_pdata = {  	.ops = &sdhci_arasan_ops, +	.quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, +	.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | +			SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN,  };  #ifdef CONFIG_PM_SLEEP @@ -214,6 +217,7 @@ static int sdhci_arasan_remove(struct platform_device *pdev)  static const struct of_device_id sdhci_arasan_of_match[] = {  	{ .compatible = "arasan,sdhci-8.9a" }, +	{ .compatible = "arasan,sdhci-5.1" },  	{ .compatible = "arasan,sdhci-4.9a" },  	{ }  }; diff --git a/drivers/mmc/host/sdhci-of-at91.c b/drivers/mmc/host/sdhci-of-at91.c new file mode 100644 index 000000000000..d1556643a41d --- /dev/null +++ b/drivers/mmc/host/sdhci-of-at91.c @@ -0,0 +1,191 @@ +/* + * Atmel SDMMC controller driver. + * + * Copyright (C) 2015 Atmel, + *		 2015 Ludovic Desroches <[email protected]> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + */ + +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/mmc/host.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_device.h> + +#include "sdhci-pltfm.h" + +#define SDMMC_CACR	0x230 +#define		SDMMC_CACR_CAPWREN	BIT(0) +#define		SDMMC_CACR_KEY		(0x46 << 8) + +struct sdhci_at91_priv { +	struct clk *hclock; +	struct clk *gck; +	struct clk *mainck; +}; + +static const struct sdhci_ops sdhci_at91_sama5d2_ops = { +	.set_clock		= sdhci_set_clock, +	.set_bus_width		= sdhci_set_bus_width, +	.reset			= sdhci_reset, +	.set_uhs_signaling	= sdhci_set_uhs_signaling, +}; + +static const struct sdhci_pltfm_data soc_data_sama5d2 = { +	.ops = &sdhci_at91_sama5d2_ops, +}; + +static const struct of_device_id sdhci_at91_dt_match[] = { +	{ .compatible = "atmel,sama5d2-sdhci", .data = &soc_data_sama5d2 }, +	{} +}; + +static int sdhci_at91_probe(struct platform_device *pdev) +{ +	const struct of_device_id	*match; +	const struct sdhci_pltfm_data	*soc_data; +	struct sdhci_host		*host; +	struct sdhci_pltfm_host		*pltfm_host; +	struct sdhci_at91_priv		*priv; +	unsigned int			caps0, caps1; +	unsigned int			clk_base, clk_mul; +	unsigned int			gck_rate, real_gck_rate; +	int				ret; + +	match = of_match_device(sdhci_at91_dt_match, &pdev->dev); +	if (!match) +		return -EINVAL; +	soc_data = match->data; + +	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); +	if (!priv) { +		dev_err(&pdev->dev, "unable to allocate private data\n"); +		return -ENOMEM; +	} + +	priv->mainck = devm_clk_get(&pdev->dev, "baseclk"); +	if (IS_ERR(priv->mainck)) { +		dev_err(&pdev->dev, "failed to get baseclk\n"); +		return PTR_ERR(priv->mainck); +	} + +	priv->hclock = devm_clk_get(&pdev->dev, "hclock"); +	if (IS_ERR(priv->hclock)) { +		dev_err(&pdev->dev, "failed to get hclock\n"); +		return PTR_ERR(priv->hclock); +	} + +	priv->gck = devm_clk_get(&pdev->dev, "multclk"); +	if (IS_ERR(priv->gck)) { +		dev_err(&pdev->dev, "failed to get multclk\n"); +		return PTR_ERR(priv->gck); +	} + +	host = sdhci_pltfm_init(pdev, soc_data, 0); +	if (IS_ERR(host)) +		return PTR_ERR(host); + +	/* +	 * The mult clock is provided by as a generated clock by the PMC +	 * controller. In order to set the rate of gck, we have to get the +	 * base clock rate and the clock mult from capabilities. +	 */ +	clk_prepare_enable(priv->hclock); +	caps0 = readl(host->ioaddr + SDHCI_CAPABILITIES); +	caps1 = readl(host->ioaddr + SDHCI_CAPABILITIES_1); +	clk_base = (caps0 & SDHCI_CLOCK_V3_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT; +	clk_mul = (caps1 & SDHCI_CLOCK_MUL_MASK) >> SDHCI_CLOCK_MUL_SHIFT; +	gck_rate = clk_base * 1000000 * (clk_mul + 1); +	ret = clk_set_rate(priv->gck, gck_rate); +	if (ret < 0) { +		dev_err(&pdev->dev, "failed to set gck"); +		goto hclock_disable_unprepare; +		return -EINVAL; +	} +	/* +	 * We need to check if we have the requested rate for gck because in +	 * some cases this rate could be not supported. If it happens, the rate +	 * is the closest one gck can provide. We have to update the value +	 * of clk mul. +	 */ +	real_gck_rate = clk_get_rate(priv->gck); +	if (real_gck_rate != gck_rate) { +		clk_mul = real_gck_rate / (clk_base * 1000000) - 1; +		caps1 &= (~SDHCI_CLOCK_MUL_MASK); +		caps1 |= ((clk_mul << SDHCI_CLOCK_MUL_SHIFT) & SDHCI_CLOCK_MUL_MASK); +		/* Set capabilities in r/w mode. */ +		writel(SDMMC_CACR_KEY | SDMMC_CACR_CAPWREN, host->ioaddr + SDMMC_CACR); +		writel(caps1, host->ioaddr + SDHCI_CAPABILITIES_1); +		/* Set capabilities in ro mode. */ +		writel(0, host->ioaddr + SDMMC_CACR); +		dev_info(&pdev->dev, "update clk mul to %u as gck rate is %u Hz\n", +			 clk_mul, real_gck_rate); +	} + +	clk_prepare_enable(priv->mainck); +	clk_prepare_enable(priv->gck); + +	pltfm_host = sdhci_priv(host); +	pltfm_host->priv = priv; + +	ret = mmc_of_parse(host->mmc); +	if (ret) +		goto clocks_disable_unprepare; + +	sdhci_get_of_property(pdev); + +	ret = sdhci_add_host(host); +	if (ret) +		goto clocks_disable_unprepare; + +	return 0; + +clocks_disable_unprepare: +	clk_disable_unprepare(priv->gck); +	clk_disable_unprepare(priv->mainck); +hclock_disable_unprepare: +	clk_disable_unprepare(priv->hclock); +	sdhci_pltfm_free(pdev); +	return ret; +} + +static int sdhci_at91_remove(struct platform_device *pdev) +{ +	struct sdhci_host	*host = platform_get_drvdata(pdev); +	struct sdhci_pltfm_host	*pltfm_host = sdhci_priv(host); +	struct sdhci_at91_priv	*priv = pltfm_host->priv; + +	sdhci_pltfm_unregister(pdev); + +	clk_disable_unprepare(priv->gck); +	clk_disable_unprepare(priv->hclock); +	clk_disable_unprepare(priv->mainck); + +	return 0; +} + +static struct platform_driver sdhci_at91_driver = { +	.driver		= { +		.name	= "sdhci-at91", +		.of_match_table = sdhci_at91_dt_match, +		.pm	= SDHCI_PLTFM_PMOPS, +	}, +	.probe		= sdhci_at91_probe, +	.remove		= sdhci_at91_remove, +}; + +module_platform_driver(sdhci_at91_driver); + +MODULE_DESCRIPTION("SDHCI driver for at91"); +MODULE_AUTHOR("Ludovic Desroches <[email protected]>"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index 797be7549a15..653f335bef15 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c @@ -208,6 +208,12 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)  	if (clock == 0)  		return; +	/* Workaround to start pre_div at 2 for VNN < VENDOR_V_23 */ +	temp = esdhc_readw(host, SDHCI_HOST_VERSION); +	temp = (temp & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT; +	if (temp < VENDOR_V_23) +		pre_div = 2; +  	/* Workaround to reduce the clock frequency for p1010 esdhc */  	if (of_find_compatible_node(NULL, NULL, "fsl,p1010-esdhc")) {  		if (clock > 20000000) diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index 94f54d2772e8..b3b0a3e4fca1 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c @@ -618,6 +618,7 @@ static int jmicron_resume(struct sdhci_pci_chip *chip)  static const struct sdhci_pci_fixes sdhci_o2 = {  	.probe = sdhci_pci_o2_probe,  	.quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, +	.quirks2 = SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD,  	.probe_slot = sdhci_pci_o2_probe_slot,  	.resume = sdhci_pci_o2_resume,  }; diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c index 9cd5fc62f130..946d37f94a31 100644 --- a/drivers/mmc/host/sdhci-pxav3.c +++ b/drivers/mmc/host/sdhci-pxav3.c @@ -411,6 +411,7 @@ static int sdhci_pxav3_probe(struct platform_device *pdev)  			goto err_of_parse;  		sdhci_get_of_property(pdev);  		pdata = pxav3_get_mmc_pdata(dev); +		pdev->dev.platform_data = pdata;  	} else if (pdata) {  		/* on-chip device */  		if (pdata->flags & PXA_FLAG_CARD_PERMANENT) diff --git a/drivers/mmc/host/sdhci-sirf.c b/drivers/mmc/host/sdhci-sirf.c index 0110bae25b7e..884294576356 100644 --- a/drivers/mmc/host/sdhci-sirf.c +++ b/drivers/mmc/host/sdhci-sirf.c @@ -161,8 +161,8 @@ static struct sdhci_pltfm_data sdhci_sirf_pdata = {  	.quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |  		SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |  		SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | -		SDHCI_QUIRK_INVERTED_WRITE_PROTECT | -		SDHCI_QUIRK_DELAY_AFTER_POWER, +		SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS, +	.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,  };  static int sdhci_sirf_probe(struct platform_device *pdev) diff --git a/drivers/mmc/host/sdhci-spear.c b/drivers/mmc/host/sdhci-spear.c index df088343d60f..255a896769b8 100644 --- a/drivers/mmc/host/sdhci-spear.c +++ b/drivers/mmc/host/sdhci-spear.c @@ -4,7 +4,7 @@   * Support of SDHCI platform devices for spear soc family   *   * Copyright (C) 2010 ST Microelectronics - * Viresh Kumar <[email protected]> + * Viresh Kumar <[email protected]>   *   * Inspired by sdhci-pltfm.c   * @@ -211,5 +211,5 @@ static struct platform_driver sdhci_driver = {  module_platform_driver(sdhci_driver);  MODULE_DESCRIPTION("SPEAr Secure Digital Host Controller Interface driver"); -MODULE_AUTHOR("Viresh Kumar <[email protected]>"); +MODULE_AUTHOR("Viresh Kumar <[email protected]>");  MODULE_LICENSE("GPL v2"); diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index bc1445238fb3..64b7fdbd1a9c 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -54,8 +54,7 @@ static void sdhci_finish_command(struct sdhci_host *);  static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode);  static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable);  static int sdhci_pre_dma_transfer(struct sdhci_host *host, -					struct mmc_data *data, -					struct sdhci_host_next *next); +					struct mmc_data *data);  static int sdhci_do_get_cd(struct sdhci_host *host);  #ifdef CONFIG_PM @@ -207,8 +206,7 @@ EXPORT_SYMBOL_GPL(sdhci_reset);  static void sdhci_do_reset(struct sdhci_host *host, u8 mask)  {  	if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) { -		if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & -			SDHCI_CARD_PRESENT)) +		if (!sdhci_do_get_cd(host))  			return;  	} @@ -496,7 +494,7 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,  		goto fail;  	BUG_ON(host->align_addr & host->align_mask); -	host->sg_count = sdhci_pre_dma_transfer(host, data, NULL); +	host->sg_count = sdhci_pre_dma_transfer(host, data);  	if (host->sg_count < 0)  		goto unmap_align; @@ -635,9 +633,11 @@ static void sdhci_adma_table_post(struct sdhci_host *host,  		}  	} -	if (!data->host_cookie) +	if (data->host_cookie == COOKIE_MAPPED) {  		dma_unmap_sg(mmc_dev(host->mmc), data->sg,  			data->sg_len, direction); +		data->host_cookie = COOKIE_UNMAPPED; +	}  }  static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd) @@ -833,7 +833,7 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)  		} else {  			int sg_cnt; -			sg_cnt = sdhci_pre_dma_transfer(host, data, NULL); +			sg_cnt = sdhci_pre_dma_transfer(host, data);  			if (sg_cnt <= 0) {  				/*  				 * This only happens when someone fed @@ -949,11 +949,13 @@ static void sdhci_finish_data(struct sdhci_host *host)  		if (host->flags & SDHCI_USE_ADMA)  			sdhci_adma_table_post(host, data);  		else { -			if (!data->host_cookie) +			if (data->host_cookie == COOKIE_MAPPED) {  				dma_unmap_sg(mmc_dev(host->mmc),  					data->sg, data->sg_len,  					(data->flags & MMC_DATA_READ) ?  					DMA_FROM_DEVICE : DMA_TO_DEVICE); +				data->host_cookie = COOKIE_UNMAPPED; +			}  		}  	} @@ -1132,6 +1134,7 @@ static u16 sdhci_get_preset_value(struct sdhci_host *host)  		preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR104);  		break;  	case MMC_TIMING_UHS_DDR50: +	case MMC_TIMING_MMC_DDR52:  		preset = sdhci_readw(host, SDHCI_PRESET_FOR_DDR50);  		break;  	case MMC_TIMING_MMC_HS400: @@ -1152,6 +1155,7 @@ void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)  	int real_div = div, clk_mul = 1;  	u16 clk = 0;  	unsigned long timeout; +	bool switch_base_clk = false;  	host->mmc->actual_clock = 0; @@ -1189,15 +1193,25 @@ void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)  					<= clock)  					break;  			} -			/* -			 * Set Programmable Clock Mode in the Clock -			 * Control register. -			 */ -			clk = SDHCI_PROG_CLOCK_MODE; -			real_div = div; -			clk_mul = host->clk_mul; -			div--; -		} else { +			if ((host->max_clk * host->clk_mul / div) <= clock) { +				/* +				 * Set Programmable Clock Mode in the Clock +				 * Control register. +				 */ +				clk = SDHCI_PROG_CLOCK_MODE; +				real_div = div; +				clk_mul = host->clk_mul; +				div--; +			} else { +				/* +				 * Divisor can be too small to reach clock +				 * speed requirement. Then use the base clock. +				 */ +				switch_base_clk = true; +			} +		} + +		if (!host->clk_mul || switch_base_clk) {  			/* Version 3.00 divisors must be a multiple of 2. */  			if (host->max_clk <= clock)  				div = 1; @@ -1210,6 +1224,9 @@ void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)  			}  			real_div = div;  			div >>= 1; +			if ((host->quirks2 & SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN) +				&& !div && host->max_clk <= 25000000) +				div = 1;  		}  	} else {  		/* Version 2.00 divisors must be a power of 2. */ @@ -1559,7 +1576,8 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)  				 (ios->timing == MMC_TIMING_UHS_SDR25) ||  				 (ios->timing == MMC_TIMING_UHS_SDR50) ||  				 (ios->timing == MMC_TIMING_UHS_SDR104) || -				 (ios->timing == MMC_TIMING_UHS_DDR50))) { +				 (ios->timing == MMC_TIMING_UHS_DDR50) || +				 (ios->timing == MMC_TIMING_MMC_DDR52))) {  			u16 preset;  			sdhci_enable_preset_value(host, true); @@ -1601,15 +1619,21 @@ static int sdhci_do_get_cd(struct sdhci_host *host)  	if (host->flags & SDHCI_DEVICE_DEAD)  		return 0; -	/* If polling/nonremovable, assume that the card is always present. */ -	if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) || -	    (host->mmc->caps & MMC_CAP_NONREMOVABLE)) +	/* If nonremovable, assume that the card is always present. */ +	if (host->mmc->caps & MMC_CAP_NONREMOVABLE)  		return 1; -	/* Try slot gpio detect */ +	/* +	 * Try slot gpio detect, if defined it take precedence +	 * over build in controller functionality +	 */  	if (!IS_ERR_VALUE(gpio_cd))  		return !!gpio_cd; +	/* If polling, assume that the card is always present. */ +	if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) +		return 1; +  	/* Host native card detect */  	return !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT);  } @@ -2097,49 +2121,36 @@ static void sdhci_post_req(struct mmc_host *mmc, struct mmc_request *mrq,  	struct mmc_data *data = mrq->data;  	if (host->flags & SDHCI_REQ_USE_DMA) { -		if (data->host_cookie) +		if (data->host_cookie == COOKIE_GIVEN || +				data->host_cookie == COOKIE_MAPPED)  			dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,  					 data->flags & MMC_DATA_WRITE ?  					 DMA_TO_DEVICE : DMA_FROM_DEVICE); -		mrq->data->host_cookie = 0; +		data->host_cookie = COOKIE_UNMAPPED;  	}  }  static int sdhci_pre_dma_transfer(struct sdhci_host *host, -				       struct mmc_data *data, -				       struct sdhci_host_next *next) +				       struct mmc_data *data)  {  	int sg_count; -	if (!next && data->host_cookie && -	    data->host_cookie != host->next_data.cookie) { -		pr_debug(DRIVER_NAME "[%s] invalid cookie: %d, next-cookie %d\n", -			__func__, data->host_cookie, host->next_data.cookie); -		data->host_cookie = 0; +	if (data->host_cookie == COOKIE_MAPPED) { +		data->host_cookie = COOKIE_GIVEN; +		return data->sg_count;  	} -	/* Check if next job is already prepared */ -	if (next || -	    (!next && data->host_cookie != host->next_data.cookie)) { -		sg_count = dma_map_sg(mmc_dev(host->mmc), data->sg, -				     data->sg_len, -				     data->flags & MMC_DATA_WRITE ? -				     DMA_TO_DEVICE : DMA_FROM_DEVICE); - -	} else { -		sg_count = host->next_data.sg_count; -		host->next_data.sg_count = 0; -	} +	WARN_ON(data->host_cookie == COOKIE_GIVEN); +	sg_count = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, +				data->flags & MMC_DATA_WRITE ? +				DMA_TO_DEVICE : DMA_FROM_DEVICE);  	if (sg_count == 0) -		return -EINVAL; +		return -ENOSPC; -	if (next) { -		next->sg_count = sg_count; -		data->host_cookie = ++next->cookie < 0 ? 1 : next->cookie; -	} else -		host->sg_count = sg_count; +	data->sg_count = sg_count; +	data->host_cookie = COOKIE_MAPPED;  	return sg_count;  } @@ -2149,16 +2160,10 @@ static void sdhci_pre_req(struct mmc_host *mmc, struct mmc_request *mrq,  {  	struct sdhci_host *host = mmc_priv(mmc); -	if (mrq->data->host_cookie) { -		mrq->data->host_cookie = 0; -		return; -	} +	mrq->data->host_cookie = COOKIE_UNMAPPED;  	if (host->flags & SDHCI_REQ_USE_DMA) -		if (sdhci_pre_dma_transfer(host, -					mrq->data, -					&host->next_data) < 0) -			mrq->data->host_cookie = 0; +		sdhci_pre_dma_transfer(host, mrq->data);  }  static void sdhci_card_event(struct mmc_host *mmc) @@ -2866,6 +2871,7 @@ int sdhci_add_host(struct sdhci_host *host)  	u32 max_current_caps;  	unsigned int ocr_avail;  	unsigned int override_timeout_clk; +	u32 max_clk;  	int ret;  	WARN_ON(host == NULL); @@ -2978,8 +2984,11 @@ int sdhci_add_host(struct sdhci_host *host)  						      GFP_KERNEL);  		host->align_buffer = kmalloc(host->align_buffer_sz, GFP_KERNEL);  		if (!host->adma_table || !host->align_buffer) { -			dma_free_coherent(mmc_dev(mmc), host->adma_table_sz, -					  host->adma_table, host->adma_addr); +			if (host->adma_table) +				dma_free_coherent(mmc_dev(mmc), +						  host->adma_table_sz, +						  host->adma_table, +						  host->adma_addr);  			kfree(host->align_buffer);  			pr_warn("%s: Unable to allocate ADMA buffers - falling back to standard DMA\n",  				mmc_hostname(mmc)); @@ -3026,7 +3035,6 @@ int sdhci_add_host(struct sdhci_host *host)  		host->max_clk = host->ops->get_max_clock(host);  	} -	host->next_data.cookie = 1;  	/*  	 * In case of Host Controller v3.00, find out whether clock  	 * multiplier is supported. @@ -3047,18 +3055,22 @@ int sdhci_add_host(struct sdhci_host *host)  	 * Set host parameters.  	 */  	mmc->ops = &sdhci_ops; -	mmc->f_max = host->max_clk; +	max_clk = host->max_clk; +  	if (host->ops->get_min_clock)  		mmc->f_min = host->ops->get_min_clock(host);  	else if (host->version >= SDHCI_SPEC_300) {  		if (host->clk_mul) {  			mmc->f_min = (host->max_clk * host->clk_mul) / 1024; -			mmc->f_max = host->max_clk * host->clk_mul; +			max_clk = host->max_clk * host->clk_mul;  		} else  			mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_300;  	} else  		mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200; +	if (!mmc->f_max || (mmc->f_max && (mmc->f_max > max_clk))) +		mmc->f_max = max_clk; +  	if (!(host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)) {  		host->timeout_clk = (caps[0] & SDHCI_TIMEOUT_CLK_MASK) >>  					SDHCI_TIMEOUT_CLK_SHIFT; @@ -3118,7 +3130,8 @@ int sdhci_add_host(struct sdhci_host *host)  		mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED;  	if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) && -	    !(mmc->caps & MMC_CAP_NONREMOVABLE)) +	    !(mmc->caps & MMC_CAP_NONREMOVABLE) && +	    IS_ERR_VALUE(mmc_gpio_get_cd(host->mmc)))  		mmc->caps |= MMC_CAP_NEEDS_POLL;  	/* If there are external regulators, get them */ diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 5521d29368e4..7c02ff46c8ac 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -309,9 +309,10 @@ struct sdhci_adma2_64_desc {   */  #define SDHCI_MAX_SEGS		128 -struct sdhci_host_next { -	unsigned int	sg_count; -	s32		cookie; +enum sdhci_cookie { +	COOKIE_UNMAPPED, +	COOKIE_MAPPED, +	COOKIE_GIVEN,  };  struct sdhci_host { @@ -409,6 +410,8 @@ struct sdhci_host {  #define SDHCI_QUIRK2_SUPPORT_SINGLE			(1<<13)  /* Controller broken with using ACMD23 */  #define SDHCI_QUIRK2_ACMD23_BROKEN			(1<<14) +/* Broken Clock divider zero in controller */ +#define SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN		(1<<15)  	int irq;		/* Device IRQ */  	void __iomem *ioaddr;	/* Mapped address */ @@ -503,7 +506,6 @@ struct sdhci_host {  	unsigned int		tuning_mode;	/* Re-tuning mode supported by host */  #define SDHCI_TUNING_MODE_1	0 -	struct sdhci_host_next	next_data;  	unsigned long private[0] ____cacheline_aligned;  }; diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 5a1fdd405b1a..ad9ffea7d659 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -1632,7 +1632,9 @@ static int sh_mmcif_suspend(struct device *dev)  {  	struct sh_mmcif_host *host = dev_get_drvdata(dev); +	pm_runtime_get_sync(dev);  	sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL); +	pm_runtime_put(dev);  	return 0;  } diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c index 4d3e1ffe5508..a7b7a6771598 100644 --- a/drivers/mmc/host/sunxi-mmc.c +++ b/drivers/mmc/host/sunxi-mmc.c @@ -595,7 +595,7 @@ static irqreturn_t sunxi_mmc_handle_manual_stop(int irq, void *dev_id)  static int sunxi_mmc_oclk_onoff(struct sunxi_mmc_host *host, u32 oclk_en)  { -	unsigned long expire = jiffies + msecs_to_jiffies(250); +	unsigned long expire = jiffies + msecs_to_jiffies(750);  	u32 rval;  	rval = mmc_readl(host, REG_CLKCR); diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c index e3dcf31a8bd6..a10fde40b6c3 100644 --- a/drivers/mmc/host/tmio_mmc_pio.c +++ b/drivers/mmc/host/tmio_mmc_pio.c @@ -83,6 +83,8 @@ static int tmio_mmc_next_sg(struct tmio_mmc_host *host)  	return --host->sg_len;  } +#define CMDREQ_TIMEOUT	5000 +  #ifdef CONFIG_MMC_DEBUG  #define STATUS_TO_TEXT(a, status, i) \ @@ -230,7 +232,7 @@ static void tmio_mmc_reset_work(struct work_struct *work)  	 */  	if (IS_ERR_OR_NULL(mrq)  	    || time_is_after_jiffies(host->last_req_ts + -		msecs_to_jiffies(2000))) { +		msecs_to_jiffies(CMDREQ_TIMEOUT))) {  		spin_unlock_irqrestore(&host->lock, flags);  		return;  	} @@ -818,7 +820,7 @@ static void tmio_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)  	ret = tmio_mmc_start_command(host, mrq->cmd);  	if (!ret) {  		schedule_delayed_work(&host->delayed_reset_work, -				      msecs_to_jiffies(2000)); +				      msecs_to_jiffies(CMDREQ_TIMEOUT));  		return;  	} diff --git a/drivers/mmc/host/usdhi6rol0.c b/drivers/mmc/host/usdhi6rol0.c index 54b082b1804a..4498e92116b8 100644 --- a/drivers/mmc/host/usdhi6rol0.c +++ b/drivers/mmc/host/usdhi6rol0.c @@ -1611,7 +1611,7 @@ static irqreturn_t usdhi6_cd(int irq, void *dev_id)  		return IRQ_NONE;  	/* Ack */ -	usdhi6_write(host, USDHI6_SD_INFO1, !status); +	usdhi6_write(host, USDHI6_SD_INFO1, ~status);  	if (!work_pending(&mmc->detect.work) &&  	    (((status & USDHI6_SD_INFO1_CARD_INSERT) && @@ -1634,6 +1634,7 @@ static void usdhi6_timeout_work(struct work_struct *work)  	struct usdhi6_host *host = container_of(d, struct usdhi6_host, timeout_work);  	struct mmc_request *mrq = host->mrq;  	struct mmc_data *data = mrq ? mrq->data : NULL; +	struct scatterlist *sg = host->sg ?: data->sg;  	dev_warn(mmc_dev(host->mmc),  		 "%s timeout wait %u CMD%d: IRQ 0x%08x:0x%08x, last IRQ 0x%08x\n", @@ -1669,7 +1670,7 @@ static void usdhi6_timeout_work(struct work_struct *work)  			"%c: page #%u @ +0x%zx %ux%u in SG%u. Current SG %u bytes @ %u\n",  			data->flags & MMC_DATA_READ ? 'R' : 'W', host->page_idx,  			host->offset, data->blocks, data->blksz, data->sg_len, -			sg_dma_len(host->sg), host->sg->offset); +			sg_dma_len(sg), sg->offset);  		usdhi6_sg_unmap(host, true);  		/*  		 * If USDHI6_WAIT_FOR_DATA_END times out, we have already unmapped @@ -1715,12 +1716,14 @@ static int usdhi6_probe(struct platform_device *pdev)  	if (!mmc)  		return -ENOMEM; +	ret = mmc_regulator_get_supply(mmc); +	if (ret == -EPROBE_DEFER) +		goto e_free_mmc; +  	ret = mmc_of_parse(mmc);  	if (ret < 0)  		goto e_free_mmc; -	mmc_regulator_get_supply(mmc); -  	host		= mmc_priv(mmc);  	host->mmc	= mmc;  	host->wait	= USDHI6_WAIT_FOR_REQUEST; @@ -1734,8 +1737,10 @@ static int usdhi6_probe(struct platform_device *pdev)  	}  	host->clk = devm_clk_get(dev, NULL); -	if (IS_ERR(host->clk)) +	if (IS_ERR(host->clk)) { +		ret = PTR_ERR(host->clk);  		goto e_free_mmc; +	}  	host->imclk = clk_get_rate(host->clk);  |