diff options
Diffstat (limited to 'drivers/mmc/host')
| -rw-r--r-- | drivers/mmc/host/mmci.c | 2 | ||||
| -rw-r--r-- | drivers/mmc/host/mvsdio.c | 35 | ||||
| -rw-r--r-- | drivers/mmc/host/mxcmmc.c | 47 | ||||
| -rw-r--r-- | drivers/mmc/host/omap.c | 2 | ||||
| -rw-r--r-- | drivers/mmc/host/omap_hsmmc.c | 2 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci-of.c | 9 | 
6 files changed, 81 insertions, 16 deletions
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 36875dcfa49..7d4febdab28 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -490,7 +490,7 @@ static void mmci_check_status(unsigned long data)  	mod_timer(&host->timer, jiffies + HZ);  } -static int __devinit mmci_probe(struct amba_device *dev, void *id) +static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)  {  	struct mmc_platform_data *plat = dev->dev.platform_data;  	struct mmci_host *host; diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c index c643d0fe118..b56d72ff06e 100644 --- a/drivers/mmc/host/mvsdio.c +++ b/drivers/mmc/host/mvsdio.c @@ -64,6 +64,31 @@ static int mvsd_setup_data(struct mvsd_host *host, struct mmc_data *data)  	unsigned int tmout;  	int tmout_index; +	/* +	 * Hardware weirdness.  The FIFO_EMPTY bit of the HW_STATE +	 * register is sometimes not set before a while when some +	 * "unusual" data block sizes are used (such as with the SWITCH +	 * command), even despite the fact that the XFER_DONE interrupt +	 * was raised.  And if another data transfer starts before +	 * this bit comes to good sense (which eventually happens by +	 * itself) then the new transfer simply fails with a timeout. +	 */ +	if (!(mvsd_read(MVSD_HW_STATE) & (1 << 13))) { +		unsigned long t = jiffies + HZ; +		unsigned int hw_state,  count = 0; +		do { +			if (time_after(jiffies, t)) { +				dev_warn(host->dev, "FIFO_EMPTY bit missing\n"); +				break; +			} +			hw_state = mvsd_read(MVSD_HW_STATE); +			count++; +		} while (!(hw_state & (1 << 13))); +		dev_dbg(host->dev, "*** wait for FIFO_EMPTY bit " +				   "(hw=0x%04x, count=%d, jiffies=%ld)\n", +				   hw_state, count, jiffies - (t - HZ)); +	} +  	/* If timeout=0 then maximum timeout index is used. */  	tmout = DIV_ROUND_UP(data->timeout_ns, host->ns_per_clk);  	tmout += data->timeout_clks; @@ -620,9 +645,18 @@ static void mvsd_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)  	if (ios->bus_width == MMC_BUS_WIDTH_4)  		ctrl_reg |= MVSD_HOST_CTRL_DATA_WIDTH_4_BITS; +	/* +	 * The HI_SPEED_EN bit is causing trouble with many (but not all) +	 * high speed SD, SDHC and SDIO cards.  Not enabling that bit +	 * makes all cards work.  So let's just ignore that bit for now +	 * and revisit this issue if problems for not enabling this bit +	 * are ever reported. +	 */ +#if 0  	if (ios->timing == MMC_TIMING_MMC_HS ||  	    ios->timing == MMC_TIMING_SD_HS)  		ctrl_reg |= MVSD_HOST_CTRL_HI_SPEED_EN; +#endif  	host->ctrl = ctrl_reg;  	mvsd_write(MVSD_HOST_CTRL, ctrl_reg); @@ -882,3 +916,4 @@ module_param(nodma, int, 0);  MODULE_AUTHOR("Maen Suleiman, Nicolas Pitre");  MODULE_DESCRIPTION("Marvell MMC,SD,SDIO Host Controller driver");  MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:mvsdio"); diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index b4a615c55f2..f4cbe473670 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c @@ -140,6 +140,8 @@ struct mxcmci_host {  	struct work_struct	datawork;  }; +static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios); +  static inline int mxcmci_use_dma(struct mxcmci_host *host)  {  	return host->do_dma; @@ -160,7 +162,7 @@ static void mxcmci_softreset(struct mxcmci_host *host)  	writew(0xff, host->base + MMC_REG_RES_TO);  } -static void mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data) +static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)  {  	unsigned int nob = data->blocks;  	unsigned int blksz = data->blksz; @@ -168,6 +170,7 @@ static void mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)  #ifdef HAS_DMA  	struct scatterlist *sg;  	int i; +	int ret;  #endif  	if (data->flags & MMC_DATA_STREAM)  		nob = 0xffff; @@ -183,7 +186,7 @@ static void mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)  	for_each_sg(data->sg, sg, data->sg_len, i) {  		if (sg->offset & 3 || sg->length & 3) {  			host->do_dma = 0; -			return; +			return 0;  		}  	} @@ -192,23 +195,30 @@ static void mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)  		host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg,  					     data->sg_len,  host->dma_dir); -		imx_dma_setup_sg(host->dma, data->sg, host->dma_nents, datasize, -				 host->res->start + MMC_REG_BUFFER_ACCESS, -				 DMA_MODE_READ); +		ret = imx_dma_setup_sg(host->dma, data->sg, host->dma_nents, +				datasize, +				host->res->start + MMC_REG_BUFFER_ACCESS, +				DMA_MODE_READ);  	} else {  		host->dma_dir = DMA_TO_DEVICE;  		host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg,  					     data->sg_len,  host->dma_dir); -		imx_dma_setup_sg(host->dma, data->sg, host->dma_nents, datasize, -				 host->res->start + MMC_REG_BUFFER_ACCESS, -				 DMA_MODE_WRITE); +		ret = imx_dma_setup_sg(host->dma, data->sg, host->dma_nents, +				datasize, +				host->res->start + MMC_REG_BUFFER_ACCESS, +				DMA_MODE_WRITE);  	} +	if (ret) { +		dev_err(mmc_dev(host->mmc), "failed to setup DMA : %d\n", ret); +		return ret; +	}  	wmb();  	imx_dma_enable(host->dma);  #endif /* HAS_DMA */ +	return 0;  }  static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd, @@ -345,8 +355,11 @@ static int mxcmci_poll_status(struct mxcmci_host *host, u32 mask)  		stat = readl(host->base + MMC_REG_STATUS);  		if (stat & STATUS_ERR_MASK)  			return stat; -		if (time_after(jiffies, timeout)) +		if (time_after(jiffies, timeout)) { +			mxcmci_softreset(host); +			mxcmci_set_clk_rate(host, host->clock);  			return STATUS_TIME_OUT_READ; +		}  		if (stat & mask)  			return 0;  		cpu_relax(); @@ -531,6 +544,7 @@ static void mxcmci_request(struct mmc_host *mmc, struct mmc_request *req)  {  	struct mxcmci_host *host = mmc_priv(mmc);  	unsigned int cmdat = host->cmdat; +	int error;  	WARN_ON(host->req != NULL); @@ -540,7 +554,12 @@ static void mxcmci_request(struct mmc_host *mmc, struct mmc_request *req)  	host->do_dma = 1;  #endif  	if (req->data) { -		mxcmci_setup_data(host, req->data); +		error = mxcmci_setup_data(host, req->data); +		if (error) { +			req->cmd->error = error; +			goto out; +		} +  		cmdat |= CMD_DAT_CONT_DATA_ENABLE; @@ -548,7 +567,9 @@ static void mxcmci_request(struct mmc_host *mmc, struct mmc_request *req)  			cmdat |= CMD_DAT_CONT_WRITE;  	} -	if (mxcmci_start_cmd(host, req->cmd, cmdat)) +	error = mxcmci_start_cmd(host, req->cmd, cmdat); +out: +	if (error)  		mxcmci_finish_request(host, req);  } @@ -724,7 +745,9 @@ static int mxcmci_probe(struct platform_device *pdev)  		goto out_clk_put;  	} -	mmc->f_min = clk_get_rate(host->clk) >> 7; +	mmc->f_min = clk_get_rate(host->clk) >> 16; +	if (mmc->f_min < 400000) +		mmc->f_min = 400000;  	mmc->f_max = clk_get_rate(host->clk) >> 1;  	/* recommended in data sheet */ diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index bfa25c01c87..dceb5ee3bda 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c @@ -822,7 +822,7 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)  		del_timer(&host->cmd_abort_timer);  		host->abort = 1;  		OMAP_MMC_WRITE(host, IE, 0); -		disable_irq(host->irq); +		disable_irq_nosync(host->irq);  		schedule_work(&host->cmd_abort_work);  		return IRQ_HANDLED;  	} diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index e62a22a7f00..c40cb96255a 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -680,7 +680,7 @@ static void mmc_omap_dma_cb(int lch, u16 ch_status, void *data)  	host->dma_ch = -1;  	/*  	 * DMA Callback: run in interrupt context. -	 * mutex_unlock will through a kernel warning if used. +	 * mutex_unlock will throw a kernel warning if used.  	 */  	up(&host->sem);  } diff --git a/drivers/mmc/host/sdhci-of.c b/drivers/mmc/host/sdhci-of.c index 3ff4ac3abe8..128c614d11a 100644 --- a/drivers/mmc/host/sdhci-of.c +++ b/drivers/mmc/host/sdhci-of.c @@ -55,7 +55,13 @@ static u32 esdhc_readl(struct sdhci_host *host, int reg)  static u16 esdhc_readw(struct sdhci_host *host, int reg)  { -	return in_be16(host->ioaddr + (reg ^ 0x2)); +	u16 ret; + +	if (unlikely(reg == SDHCI_HOST_VERSION)) +		ret = in_be16(host->ioaddr + reg); +	else +		ret = in_be16(host->ioaddr + (reg ^ 0x2)); +	return ret;  }  static u8 esdhc_readb(struct sdhci_host *host, int reg) @@ -277,6 +283,7 @@ static int __devexit sdhci_of_remove(struct of_device *ofdev)  static const struct of_device_id sdhci_of_match[] = {  	{ .compatible = "fsl,mpc8379-esdhc", .data = &sdhci_esdhc, },  	{ .compatible = "fsl,mpc8536-esdhc", .data = &sdhci_esdhc, }, +	{ .compatible = "fsl,esdhc", .data = &sdhci_esdhc, },  	{ .compatible = "generic-sdhci", },  	{},  };  |