diff options
Diffstat (limited to 'drivers/mmc')
| -rw-r--r-- | drivers/mmc/host/alcor.c | 34 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci-omap.c | 38 | 
2 files changed, 51 insertions, 21 deletions
| diff --git a/drivers/mmc/host/alcor.c b/drivers/mmc/host/alcor.c index 82a97866e0cf..7c8f203f9a24 100644 --- a/drivers/mmc/host/alcor.c +++ b/drivers/mmc/host/alcor.c @@ -48,7 +48,6 @@ struct alcor_sdmmc_host {  	struct mmc_command *cmd;  	struct mmc_data *data;  	unsigned int dma_on:1; -	unsigned int early_data:1;  	struct mutex cmd_mutex; @@ -144,8 +143,7 @@ static void alcor_data_set_dma(struct alcor_sdmmc_host *host)  	host->sg_count--;  } -static void alcor_trigger_data_transfer(struct alcor_sdmmc_host *host, -					bool early) +static void alcor_trigger_data_transfer(struct alcor_sdmmc_host *host)  {  	struct alcor_pci_priv *priv = host->alcor_pci;  	struct mmc_data *data = host->data; @@ -155,13 +153,6 @@ static void alcor_trigger_data_transfer(struct alcor_sdmmc_host *host,  		ctrl |= AU6601_DATA_WRITE;  	if (data->host_cookie == COOKIE_MAPPED) { -		if (host->early_data) { -			host->early_data = false; -			return; -		} - -		host->early_data = early; -  		alcor_data_set_dma(host);  		ctrl |= AU6601_DATA_DMA_MODE;  		host->dma_on = 1; @@ -231,6 +222,7 @@ static void alcor_prepare_sg_miter(struct alcor_sdmmc_host *host)  static void alcor_prepare_data(struct alcor_sdmmc_host *host,  			       struct mmc_command *cmd)  { +	struct alcor_pci_priv *priv = host->alcor_pci;  	struct mmc_data *data = cmd->data;  	if (!data) @@ -248,7 +240,7 @@ static void alcor_prepare_data(struct alcor_sdmmc_host *host,  	if (data->host_cookie != COOKIE_MAPPED)  		alcor_prepare_sg_miter(host); -	alcor_trigger_data_transfer(host, true); +	alcor_write8(priv, 0, AU6601_DATA_XFER_CTRL);  }  static void alcor_send_cmd(struct alcor_sdmmc_host *host, @@ -435,7 +427,7 @@ static int alcor_cmd_irq_done(struct alcor_sdmmc_host *host, u32 intmask)  	if (!host->data)  		return false; -	alcor_trigger_data_transfer(host, false); +	alcor_trigger_data_transfer(host);  	host->cmd = NULL;  	return true;  } @@ -456,7 +448,7 @@ static void alcor_cmd_irq_thread(struct alcor_sdmmc_host *host, u32 intmask)  	if (!host->data)  		alcor_request_complete(host, 1);  	else -		alcor_trigger_data_transfer(host, false); +		alcor_trigger_data_transfer(host);  	host->cmd = NULL;  } @@ -487,15 +479,9 @@ static int alcor_data_irq_done(struct alcor_sdmmc_host *host, u32 intmask)  		break;  	case AU6601_INT_READ_BUF_RDY:  		alcor_trf_block_pio(host, true); -		if (!host->blocks) -			break; -		alcor_trigger_data_transfer(host, false);  		return 1;  	case AU6601_INT_WRITE_BUF_RDY:  		alcor_trf_block_pio(host, false); -		if (!host->blocks) -			break; -		alcor_trigger_data_transfer(host, false);  		return 1;  	case AU6601_INT_DMA_END:  		if (!host->sg_count) @@ -508,8 +494,14 @@ static int alcor_data_irq_done(struct alcor_sdmmc_host *host, u32 intmask)  		break;  	} -	if (intmask & AU6601_INT_DATA_END) -		return 0; +	if (intmask & AU6601_INT_DATA_END) { +		if (!host->dma_on && host->blocks) { +			alcor_trigger_data_transfer(host); +			return 1; +		} else { +			return 0; +		} +	}  	return 1;  } diff --git a/drivers/mmc/host/sdhci-omap.c b/drivers/mmc/host/sdhci-omap.c index 5bbed477c9b1..9f20fff9781b 100644 --- a/drivers/mmc/host/sdhci-omap.c +++ b/drivers/mmc/host/sdhci-omap.c @@ -797,6 +797,43 @@ void sdhci_omap_reset(struct sdhci_host *host, u8 mask)  	sdhci_reset(host, mask);  } +#define CMD_ERR_MASK (SDHCI_INT_CRC | SDHCI_INT_END_BIT | SDHCI_INT_INDEX |\ +		      SDHCI_INT_TIMEOUT) +#define CMD_MASK (CMD_ERR_MASK | SDHCI_INT_RESPONSE) + +static u32 sdhci_omap_irq(struct sdhci_host *host, u32 intmask) +{ +	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); +	struct sdhci_omap_host *omap_host = sdhci_pltfm_priv(pltfm_host); + +	if (omap_host->is_tuning && host->cmd && !host->data_early && +	    (intmask & CMD_ERR_MASK)) { + +		/* +		 * Since we are not resetting data lines during tuning +		 * operation, data error or data complete interrupts +		 * might still arrive. Mark this request as a failure +		 * but still wait for the data interrupt +		 */ +		if (intmask & SDHCI_INT_TIMEOUT) +			host->cmd->error = -ETIMEDOUT; +		else +			host->cmd->error = -EILSEQ; + +		host->cmd = NULL; + +		/* +		 * Sometimes command error interrupts and command complete +		 * interrupt will arrive together. Clear all command related +		 * interrupts here. +		 */ +		sdhci_writel(host, intmask & CMD_MASK, SDHCI_INT_STATUS); +		intmask &= ~CMD_MASK; +	} + +	return intmask; +} +  static struct sdhci_ops sdhci_omap_ops = {  	.set_clock = sdhci_omap_set_clock,  	.set_power = sdhci_omap_set_power, @@ -807,6 +844,7 @@ static struct sdhci_ops sdhci_omap_ops = {  	.platform_send_init_74_clocks = sdhci_omap_init_74_clocks,  	.reset = sdhci_omap_reset,  	.set_uhs_signaling = sdhci_omap_set_uhs_signaling, +	.irq = sdhci_omap_irq,  };  static int sdhci_omap_set_capabilities(struct sdhci_omap_host *omap_host) |