diff options
Diffstat (limited to 'drivers/mmc/host/sdhci.c')
| -rw-r--r-- | drivers/mmc/host/sdhci.c | 837 | 
1 files changed, 418 insertions, 419 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 7a7fb4f0d5a..47055f3f01b 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -44,12 +44,13 @@  #define MAX_TUNING_LOOP 40 +#define ADMA_SIZE	((128 * 2 + 1) * 4) +  static unsigned int debug_quirks = 0;  static unsigned int debug_quirks2;  static void sdhci_finish_data(struct sdhci_host *); -static void sdhci_send_command(struct sdhci_host *, struct mmc_command *);  static void sdhci_finish_command(struct sdhci_host *);  static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode);  static void sdhci_tuning_timer(unsigned long data); @@ -132,43 +133,26 @@ static void sdhci_dumpregs(struct sdhci_host *host)   *                                                                           *  \*****************************************************************************/ -static void sdhci_clear_set_irqs(struct sdhci_host *host, u32 clear, u32 set) -{ -	u32 ier; - -	ier = sdhci_readl(host, SDHCI_INT_ENABLE); -	ier &= ~clear; -	ier |= set; -	sdhci_writel(host, ier, SDHCI_INT_ENABLE); -	sdhci_writel(host, ier, SDHCI_SIGNAL_ENABLE); -} - -static void sdhci_unmask_irqs(struct sdhci_host *host, u32 irqs) -{ -	sdhci_clear_set_irqs(host, 0, irqs); -} - -static void sdhci_mask_irqs(struct sdhci_host *host, u32 irqs) -{ -	sdhci_clear_set_irqs(host, irqs, 0); -} -  static void sdhci_set_card_detection(struct sdhci_host *host, bool enable)  { -	u32 present, irqs; +	u32 present;  	if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) ||  	    (host->mmc->caps & MMC_CAP_NONREMOVABLE))  		return; -	present = sdhci_readl(host, SDHCI_PRESENT_STATE) & -			      SDHCI_CARD_PRESENT; -	irqs = present ? SDHCI_INT_CARD_REMOVE : SDHCI_INT_CARD_INSERT; +	if (enable) { +		present = sdhci_readl(host, SDHCI_PRESENT_STATE) & +				      SDHCI_CARD_PRESENT; -	if (enable) -		sdhci_unmask_irqs(host, irqs); -	else -		sdhci_mask_irqs(host, irqs); +		host->ier |= present ? SDHCI_INT_CARD_REMOVE : +				       SDHCI_INT_CARD_INSERT; +	} else { +		host->ier &= ~(SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT); +	} + +	sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); +	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);  }  static void sdhci_enable_card_detection(struct sdhci_host *host) @@ -181,22 +165,9 @@ static void sdhci_disable_card_detection(struct sdhci_host *host)  	sdhci_set_card_detection(host, false);  } -static void sdhci_reset(struct sdhci_host *host, u8 mask) +void sdhci_reset(struct sdhci_host *host, u8 mask)  {  	unsigned long timeout; -	u32 uninitialized_var(ier); - -	if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) { -		if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & -			SDHCI_CARD_PRESENT)) -			return; -	} - -	if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET) -		ier = sdhci_readl(host, SDHCI_INT_ENABLE); - -	if (host->ops->platform_reset_enter) -		host->ops->platform_reset_enter(host, mask);  	sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET); @@ -221,16 +192,27 @@ static void sdhci_reset(struct sdhci_host *host, u8 mask)  		timeout--;  		mdelay(1);  	} +} +EXPORT_SYMBOL_GPL(sdhci_reset); -	if (host->ops->platform_reset_exit) -		host->ops->platform_reset_exit(host, mask); +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)) +			return; +	} -	if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET) -		sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, ier); +	host->ops->reset(host, mask); -	if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { -		if ((host->ops->enable_dma) && (mask & SDHCI_RESET_ALL)) -			host->ops->enable_dma(host); +	if (mask & SDHCI_RESET_ALL) { +		if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { +			if (host->ops->enable_dma) +				host->ops->enable_dma(host); +		} + +		/* Resetting the controller clears many */ +		host->preset_enabled = false;  	}  } @@ -239,15 +221,18 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios);  static void sdhci_init(struct sdhci_host *host, int soft)  {  	if (soft) -		sdhci_reset(host, SDHCI_RESET_CMD|SDHCI_RESET_DATA); +		sdhci_do_reset(host, SDHCI_RESET_CMD|SDHCI_RESET_DATA);  	else -		sdhci_reset(host, SDHCI_RESET_ALL); +		sdhci_do_reset(host, SDHCI_RESET_ALL); + +	host->ier = SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT | +		    SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | +		    SDHCI_INT_INDEX | SDHCI_INT_END_BIT | SDHCI_INT_CRC | +		    SDHCI_INT_TIMEOUT | SDHCI_INT_DATA_END | +		    SDHCI_INT_RESPONSE; -	sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, -		SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT | -		SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX | -		SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT | -		SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE); +	sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); +	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);  	if (soft) {  		/* force clock reconfiguration */ @@ -503,11 +488,6 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,  	else  		direction = DMA_TO_DEVICE; -	/* -	 * The ADMA descriptor table is mapped further down as we -	 * need to fill it with data first. -	 */ -  	host->align_addr = dma_map_single(mmc_dev(host->mmc),  		host->align_buffer, 128 * 4, direction);  	if (dma_mapping_error(mmc_dev(host->mmc), host->align_addr)) @@ -568,7 +548,7 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,  		 * If this triggers then we have a calculation bug  		 * somewhere. :/  		 */ -		WARN_ON((desc - host->adma_desc) > (128 * 2 + 1) * 4); +		WARN_ON((desc - host->adma_desc) > ADMA_SIZE);  	}  	if (host->quirks & SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC) { @@ -596,17 +576,8 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,  			host->align_addr, 128 * 4, direction);  	} -	host->adma_addr = dma_map_single(mmc_dev(host->mmc), -		host->adma_desc, (128 * 2 + 1) * 4, DMA_TO_DEVICE); -	if (dma_mapping_error(mmc_dev(host->mmc), host->adma_addr)) -		goto unmap_entries; -	BUG_ON(host->adma_addr & 0x3); -  	return 0; -unmap_entries: -	dma_unmap_sg(mmc_dev(host->mmc), data->sg, -		data->sg_len, direction);  unmap_align:  	dma_unmap_single(mmc_dev(host->mmc), host->align_addr,  		128 * 4, direction); @@ -624,19 +595,25 @@ static void sdhci_adma_table_post(struct sdhci_host *host,  	u8 *align;  	char *buffer;  	unsigned long flags; +	bool has_unaligned;  	if (data->flags & MMC_DATA_READ)  		direction = DMA_FROM_DEVICE;  	else  		direction = DMA_TO_DEVICE; -	dma_unmap_single(mmc_dev(host->mmc), host->adma_addr, -		(128 * 2 + 1) * 4, DMA_TO_DEVICE); -  	dma_unmap_single(mmc_dev(host->mmc), host->align_addr,  		128 * 4, direction); -	if (data->flags & MMC_DATA_READ) { +	/* Do a quick scan of the SG list for any unaligned mappings */ +	has_unaligned = false; +	for_each_sg(data->sg, sg, host->sg_count, i) +		if (sg_dma_address(sg) & 3) { +			has_unaligned = true; +			break; +		} + +	if (has_unaligned && data->flags & MMC_DATA_READ) {  		dma_sync_sg_for_cpu(mmc_dev(host->mmc), data->sg,  			data->sg_len, direction); @@ -676,12 +653,12 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd)  		return 0xE;  	/* Unspecified timeout, assume max */ -	if (!data && !cmd->cmd_timeout_ms) +	if (!data && !cmd->busy_timeout)  		return 0xE;  	/* timeout in us */  	if (!data) -		target_timeout = cmd->cmd_timeout_ms * 1000; +		target_timeout = cmd->busy_timeout * 1000;  	else {  		target_timeout = data->timeout_ns / 1000;  		if (host->clock) @@ -722,9 +699,12 @@ static void sdhci_set_transfer_irqs(struct sdhci_host *host)  	u32 dma_irqs = SDHCI_INT_DMA_END | SDHCI_INT_ADMA_ERROR;  	if (host->flags & SDHCI_REQ_USE_DMA) -		sdhci_clear_set_irqs(host, pio_irqs, dma_irqs); +		host->ier = (host->ier & ~pio_irqs) | dma_irqs;  	else -		sdhci_clear_set_irqs(host, dma_irqs, pio_irqs); +		host->ier = (host->ier & ~dma_irqs) | pio_irqs; + +	sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); +	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);  }  static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) @@ -899,8 +879,13 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host,  	u16 mode;  	struct mmc_data *data = cmd->data; -	if (data == NULL) +	if (data == NULL) { +		/* clear Auto CMD settings for no data CMDs */ +		mode = sdhci_readw(host, SDHCI_TRANSFER_MODE); +		sdhci_writew(host, mode & ~(SDHCI_TRNS_AUTO_CMD12 | +				SDHCI_TRNS_AUTO_CMD23), SDHCI_TRANSFER_MODE);  		return; +	}  	WARN_ON(!host->data); @@ -972,8 +957,8 @@ static void sdhci_finish_data(struct sdhci_host *host)  		 * upon error conditions.  		 */  		if (data->error) { -			sdhci_reset(host, SDHCI_RESET_CMD); -			sdhci_reset(host, SDHCI_RESET_DATA); +			sdhci_do_reset(host, SDHCI_RESET_CMD); +			sdhci_do_reset(host, SDHCI_RESET_DATA);  		}  		sdhci_send_command(host, data->stop); @@ -981,7 +966,7 @@ static void sdhci_finish_data(struct sdhci_host *host)  		tasklet_schedule(&host->finish_tasklet);  } -static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) +void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)  {  	int flags;  	u32 mask; @@ -1014,7 +999,12 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)  		mdelay(1);  	} -	mod_timer(&host->timer, jiffies + 10 * HZ); +	timeout = jiffies; +	if (!cmd->data && cmd->busy_timeout > 9000) +		timeout += DIV_ROUND_UP(cmd->busy_timeout, 1000) * HZ + HZ; +	else +		timeout += 10 * HZ; +	mod_timer(&host->timer, timeout);  	host->cmd = cmd; @@ -1053,6 +1043,7 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)  	sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND);  } +EXPORT_SYMBOL_GPL(sdhci_send_command);  static void sdhci_finish_command(struct sdhci_host *host)  { @@ -1097,24 +1088,23 @@ static void sdhci_finish_command(struct sdhci_host *host)  static u16 sdhci_get_preset_value(struct sdhci_host *host)  { -	u16 ctrl, preset = 0; - -	ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); +	u16 preset = 0; -	switch (ctrl & SDHCI_CTRL_UHS_MASK) { -	case SDHCI_CTRL_UHS_SDR12: +	switch (host->timing) { +	case MMC_TIMING_UHS_SDR12:  		preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR12);  		break; -	case SDHCI_CTRL_UHS_SDR25: +	case MMC_TIMING_UHS_SDR25:  		preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR25);  		break; -	case SDHCI_CTRL_UHS_SDR50: +	case MMC_TIMING_UHS_SDR50:  		preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR50);  		break; -	case SDHCI_CTRL_UHS_SDR104: +	case MMC_TIMING_UHS_SDR104: +	case MMC_TIMING_MMC_HS200:  		preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR104);  		break; -	case SDHCI_CTRL_UHS_DDR50: +	case MMC_TIMING_UHS_DDR50:  		preset = sdhci_readw(host, SDHCI_PRESET_FOR_DDR50);  		break;  	default: @@ -1126,32 +1116,22 @@ static u16 sdhci_get_preset_value(struct sdhci_host *host)  	return preset;  } -static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) +void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)  {  	int div = 0; /* Initialized for compiler warning */  	int real_div = div, clk_mul = 1;  	u16 clk = 0;  	unsigned long timeout; -	if (clock && clock == host->clock) -		return; -  	host->mmc->actual_clock = 0; -	if (host->ops->set_clock) { -		host->ops->set_clock(host, clock); -		if (host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK) -			return; -	} -  	sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);  	if (clock == 0) -		goto out; +		return;  	if (host->version >= SDHCI_SPEC_300) { -		if (sdhci_readw(host, SDHCI_HOST_CONTROL2) & -			SDHCI_CTRL_PRESET_VAL_ENABLE) { +		if (host->preset_enabled) {  			u16 pre_val;  			clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); @@ -1237,26 +1217,16 @@ clock_set:  	clk |= SDHCI_CLOCK_CARD_EN;  	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); - -out: -	host->clock = clock; -} - -static inline void sdhci_update_clock(struct sdhci_host *host) -{ -	unsigned int clock; - -	clock = host->clock; -	host->clock = 0; -	sdhci_set_clock(host, clock);  } +EXPORT_SYMBOL_GPL(sdhci_set_clock); -static int sdhci_set_power(struct sdhci_host *host, unsigned short power) +static void sdhci_set_power(struct sdhci_host *host, unsigned char mode, +			    unsigned short vdd)  {  	u8 pwr = 0; -	if (power != (unsigned short)-1) { -		switch (1 << power) { +	if (mode != MMC_POWER_OFF) { +		switch (1 << vdd) {  		case MMC_VDD_165_195:  			pwr = SDHCI_POWER_180;  			break; @@ -1274,7 +1244,7 @@ static int sdhci_set_power(struct sdhci_host *host, unsigned short power)  	}  	if (host->pwr == pwr) -		return -1; +		return;  	host->pwr = pwr; @@ -1282,38 +1252,43 @@ static int sdhci_set_power(struct sdhci_host *host, unsigned short power)  		sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);  		if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON)  			sdhci_runtime_pm_bus_off(host); -		return 0; -	} - -	/* -	 * Spec says that we should clear the power reg before setting -	 * a new value. Some controllers don't seem to like this though. -	 */ -	if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE)) -		sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); +		vdd = 0; +	} else { +		/* +		 * Spec says that we should clear the power reg before setting +		 * a new value. Some controllers don't seem to like this though. +		 */ +		if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE)) +			sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); -	/* -	 * At least the Marvell CaFe chip gets confused if we set the voltage -	 * and set turn on power at the same time, so set the voltage first. -	 */ -	if (host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER) -		sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); +		/* +		 * At least the Marvell CaFe chip gets confused if we set the +		 * voltage and set turn on power at the same time, so set the +		 * voltage first. +		 */ +		if (host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER) +			sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); -	pwr |= SDHCI_POWER_ON; +		pwr |= SDHCI_POWER_ON; -	sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); +		sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); -	if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON) -		sdhci_runtime_pm_bus_on(host); +		if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON) +			sdhci_runtime_pm_bus_on(host); -	/* -	 * Some controllers need an extra 10ms delay of 10ms before they -	 * can apply clock after applying power -	 */ -	if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER) -		mdelay(10); +		/* +		 * Some controllers need an extra 10ms delay of 10ms before +		 * they can apply clock after applying power +		 */ +		if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER) +			mdelay(10); +	} -	return power; +	if (host->vmmc) { +		spin_unlock_irq(&host->lock); +		mmc_regulator_set_ocr(host->mmc, host->vmmc, vdd); +		spin_lock_irq(&host->lock); +	}  }  /*****************************************************************************\ @@ -1391,6 +1366,13 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)  					mmc->card->type == MMC_TYPE_MMC ?  					MMC_SEND_TUNING_BLOCK_HS200 :  					MMC_SEND_TUNING_BLOCK; + +				/* Here we need to set the host->mrq to NULL, +				 * in case the pending finish_tasklet +				 * finishes it incorrectly. +				 */ +				host->mrq = NULL; +  				spin_unlock_irqrestore(&host->lock, flags);  				sdhci_execute_tuning(mmc, tuning_opcode);  				spin_lock_irqsave(&host->lock, flags); @@ -1410,10 +1392,53 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)  	spin_unlock_irqrestore(&host->lock, flags);  } +void sdhci_set_bus_width(struct sdhci_host *host, int width) +{ +	u8 ctrl; + +	ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); +	if (width == MMC_BUS_WIDTH_8) { +		ctrl &= ~SDHCI_CTRL_4BITBUS; +		if (host->version >= SDHCI_SPEC_300) +			ctrl |= SDHCI_CTRL_8BITBUS; +	} else { +		if (host->version >= SDHCI_SPEC_300) +			ctrl &= ~SDHCI_CTRL_8BITBUS; +		if (width == MMC_BUS_WIDTH_4) +			ctrl |= SDHCI_CTRL_4BITBUS; +		else +			ctrl &= ~SDHCI_CTRL_4BITBUS; +	} +	sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); +} +EXPORT_SYMBOL_GPL(sdhci_set_bus_width); + +void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing) +{ +	u16 ctrl_2; + +	ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); +	/* Select Bus Speed Mode for host */ +	ctrl_2 &= ~SDHCI_CTRL_UHS_MASK; +	if ((timing == MMC_TIMING_MMC_HS200) || +	    (timing == MMC_TIMING_UHS_SDR104)) +		ctrl_2 |= SDHCI_CTRL_UHS_SDR104; +	else if (timing == MMC_TIMING_UHS_SDR12) +		ctrl_2 |= SDHCI_CTRL_UHS_SDR12; +	else if (timing == MMC_TIMING_UHS_SDR25) +		ctrl_2 |= SDHCI_CTRL_UHS_SDR25; +	else if (timing == MMC_TIMING_UHS_SDR50) +		ctrl_2 |= SDHCI_CTRL_UHS_SDR50; +	else if ((timing == MMC_TIMING_UHS_DDR50) || +		 (timing == MMC_TIMING_MMC_DDR52)) +		ctrl_2 |= SDHCI_CTRL_UHS_DDR50; +	sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); +} +EXPORT_SYMBOL_GPL(sdhci_set_uhs_signaling); +  static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)  {  	unsigned long flags; -	int vdd_bit = -1;  	u8 ctrl;  	spin_lock_irqsave(&host->lock, flags); @@ -1435,48 +1460,21 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)  	}  	if (host->version >= SDHCI_SPEC_300 && -		(ios->power_mode == MMC_POWER_UP)) +		(ios->power_mode == MMC_POWER_UP) && +		!(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN))  		sdhci_enable_preset_value(host, false); -	sdhci_set_clock(host, ios->clock); - -	if (ios->power_mode == MMC_POWER_OFF) -		vdd_bit = sdhci_set_power(host, -1); -	else -		vdd_bit = sdhci_set_power(host, ios->vdd); - -	if (host->vmmc && vdd_bit != -1) { -		spin_unlock_irqrestore(&host->lock, flags); -		mmc_regulator_set_ocr(host->mmc, host->vmmc, vdd_bit); -		spin_lock_irqsave(&host->lock, flags); +	if (!ios->clock || ios->clock != host->clock) { +		host->ops->set_clock(host, ios->clock); +		host->clock = ios->clock;  	} +	sdhci_set_power(host, ios->power_mode, ios->vdd); +  	if (host->ops->platform_send_init_74_clocks)  		host->ops->platform_send_init_74_clocks(host, ios->power_mode); -	/* -	 * If your platform has 8-bit width support but is not a v3 controller, -	 * or if it requires special setup code, you should implement that in -	 * platform_bus_width(). -	 */ -	if (host->ops->platform_bus_width) { -		host->ops->platform_bus_width(host, ios->bus_width); -	} else { -		ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); -		if (ios->bus_width == MMC_BUS_WIDTH_8) { -			ctrl &= ~SDHCI_CTRL_4BITBUS; -			if (host->version >= SDHCI_SPEC_300) -				ctrl |= SDHCI_CTRL_8BITBUS; -		} else { -			if (host->version >= SDHCI_SPEC_300) -				ctrl &= ~SDHCI_CTRL_8BITBUS; -			if (ios->bus_width == MMC_BUS_WIDTH_4) -				ctrl |= SDHCI_CTRL_4BITBUS; -			else -				ctrl &= ~SDHCI_CTRL_4BITBUS; -		} -		sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); -	} +	host->ops->set_bus_width(host, ios->bus_width);  	ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); @@ -1492,19 +1490,20 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)  		/* In case of UHS-I modes, set High Speed Enable */  		if ((ios->timing == MMC_TIMING_MMC_HS200) || +		    (ios->timing == MMC_TIMING_MMC_DDR52) ||  		    (ios->timing == MMC_TIMING_UHS_SDR50) ||  		    (ios->timing == MMC_TIMING_UHS_SDR104) ||  		    (ios->timing == MMC_TIMING_UHS_DDR50) ||  		    (ios->timing == MMC_TIMING_UHS_SDR25))  			ctrl |= SDHCI_CTRL_HISPD; -		ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); -		if (!(ctrl_2 & SDHCI_CTRL_PRESET_VAL_ENABLE)) { +		if (!host->preset_enabled) {  			sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);  			/*  			 * We only need to set Driver Strength if the  			 * preset value enable is not set.  			 */ +			ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);  			ctrl_2 &= ~SDHCI_CTRL_DRV_TYPE_MASK;  			if (ios->drv_type == MMC_SET_DRIVER_TYPE_A)  				ctrl_2 |= SDHCI_CTRL_DRV_TYPE_A; @@ -1528,7 +1527,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)  			sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);  			/* Re-enable SD Clock */ -			sdhci_update_clock(host); +			host->ops->set_clock(host, host->clock);  		} @@ -1537,25 +1536,8 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)  		clk &= ~SDHCI_CLOCK_CARD_EN;  		sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); -		if (host->ops->set_uhs_signaling) -			host->ops->set_uhs_signaling(host, ios->timing); -		else { -			ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); -			/* Select Bus Speed Mode for host */ -			ctrl_2 &= ~SDHCI_CTRL_UHS_MASK; -			if ((ios->timing == MMC_TIMING_MMC_HS200) || -			    (ios->timing == MMC_TIMING_UHS_SDR104)) -				ctrl_2 |= SDHCI_CTRL_UHS_SDR104; -			else if (ios->timing == MMC_TIMING_UHS_SDR12) -				ctrl_2 |= SDHCI_CTRL_UHS_SDR12; -			else if (ios->timing == MMC_TIMING_UHS_SDR25) -				ctrl_2 |= SDHCI_CTRL_UHS_SDR25; -			else if (ios->timing == MMC_TIMING_UHS_SDR50) -				ctrl_2 |= SDHCI_CTRL_UHS_SDR50; -			else if (ios->timing == MMC_TIMING_UHS_DDR50) -				ctrl_2 |= SDHCI_CTRL_UHS_DDR50; -			sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); -		} +		host->ops->set_uhs_signaling(host, ios->timing); +		host->timing = ios->timing;  		if (!(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN) &&  				((ios->timing == MMC_TIMING_UHS_SDR12) || @@ -1572,7 +1554,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)  		}  		/* Re-enable SD Clock */ -		sdhci_update_clock(host); +		host->ops->set_clock(host, host->clock);  	} else  		sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); @@ -1582,7 +1564,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)  	 * it on each ios seems to solve the problem.  	 */  	if(host->quirks & SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS) -		sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); +		sdhci_do_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);  	mmiowb();  	spin_unlock_irqrestore(&host->lock, flags); @@ -1691,24 +1673,16 @@ static int sdhci_get_ro(struct mmc_host *mmc)  static void sdhci_enable_sdio_irq_nolock(struct sdhci_host *host, int enable)  { -	if (host->flags & SDHCI_DEVICE_DEAD) -		goto out; - -	if (enable) -		host->flags |= SDHCI_SDIO_IRQ_ENABLED; -	else -		host->flags &= ~SDHCI_SDIO_IRQ_ENABLED; - -	/* SDIO IRQ will be enabled as appropriate in runtime resume */ -	if (host->runtime_suspended) -		goto out; +	if (!(host->flags & SDHCI_DEVICE_DEAD)) { +		if (enable) +			host->ier |= SDHCI_INT_CARD_INT; +		else +			host->ier &= ~SDHCI_INT_CARD_INT; -	if (enable) -		sdhci_unmask_irqs(host, SDHCI_INT_CARD_INT); -	else -		sdhci_mask_irqs(host, SDHCI_INT_CARD_INT); -out: -	mmiowb(); +		sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); +		sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); +		mmiowb(); +	}  }  static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable) @@ -1716,9 +1690,18 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)  	struct sdhci_host *host = mmc_priv(mmc);  	unsigned long flags; +	sdhci_runtime_pm_get(host); +  	spin_lock_irqsave(&host->lock, flags); +	if (enable) +		host->flags |= SDHCI_SDIO_IRQ_ENABLED; +	else +		host->flags &= ~SDHCI_SDIO_IRQ_ENABLED; +  	sdhci_enable_sdio_irq_nolock(host, enable);  	spin_unlock_irqrestore(&host->lock, flags); + +	sdhci_runtime_pm_put(host);  }  static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host, @@ -1837,21 +1820,14 @@ static int sdhci_card_busy(struct mmc_host *mmc)  static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)  { -	struct sdhci_host *host; +	struct sdhci_host *host = mmc_priv(mmc);  	u16 ctrl; -	u32 ier;  	int tuning_loop_counter = MAX_TUNING_LOOP; -	unsigned long timeout;  	int err = 0; -	bool requires_tuning_nonuhs = false; - -	host = mmc_priv(mmc); +	unsigned long flags;  	sdhci_runtime_pm_get(host); -	disable_irq(host->irq); -	spin_lock(&host->lock); - -	ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); +	spin_lock_irqsave(&host->lock, flags);  	/*  	 * The Host Controller needs tuning only in case of SDR104 mode @@ -1860,21 +1836,32 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)  	 * If the Host Controller supports the HS200 mode then the  	 * tuning function has to be executed.  	 */ -	if (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR50) && -	    (host->flags & SDHCI_SDR50_NEEDS_TUNING || -	     host->flags & SDHCI_SDR104_NEEDS_TUNING)) -		requires_tuning_nonuhs = true; - -	if (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR104) || -	    requires_tuning_nonuhs) -		ctrl |= SDHCI_CTRL_EXEC_TUNING; -	else { -		spin_unlock(&host->lock); -		enable_irq(host->irq); +	switch (host->timing) { +	case MMC_TIMING_MMC_HS200: +	case MMC_TIMING_UHS_SDR104: +		break; + +	case MMC_TIMING_UHS_SDR50: +		if (host->flags & SDHCI_SDR50_NEEDS_TUNING || +		    host->flags & SDHCI_SDR104_NEEDS_TUNING) +			break; +		/* FALLTHROUGH */ + +	default: +		spin_unlock_irqrestore(&host->lock, flags);  		sdhci_runtime_pm_put(host);  		return 0;  	} +	if (host->ops->platform_execute_tuning) { +		spin_unlock_irqrestore(&host->lock, flags); +		err = host->ops->platform_execute_tuning(host, opcode); +		sdhci_runtime_pm_put(host); +		return err; +	} + +	ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); +	ctrl |= SDHCI_CTRL_EXEC_TUNING;  	sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);  	/* @@ -1887,21 +1874,17 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)  	 * to make sure we don't hit a controller bug, we _only_  	 * enable Buffer Read Ready interrupt here.  	 */ -	ier = sdhci_readl(host, SDHCI_INT_ENABLE); -	sdhci_clear_set_irqs(host, ier, SDHCI_INT_DATA_AVAIL); +	sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE); +	sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE);  	/*  	 * Issue CMD19 repeatedly till Execute Tuning is set to 0 or the number  	 * of loops reaches 40 times or a timeout of 150ms occurs.  	 */ -	timeout = 150;  	do {  		struct mmc_command cmd = {0};  		struct mmc_request mrq = {NULL}; -		if (!tuning_loop_counter && !timeout) -			break; -  		cmd.opcode = opcode;  		cmd.arg = 0;  		cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; @@ -1909,6 +1892,9 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)  		cmd.data = NULL;  		cmd.error = 0; +		if (tuning_loop_counter-- == 0) +			break; +  		mrq.cmd = &cmd;  		host->mrq = &mrq; @@ -1942,15 +1928,12 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)  		host->cmd = NULL;  		host->mrq = NULL; -		spin_unlock(&host->lock); -		enable_irq(host->irq); - +		spin_unlock_irqrestore(&host->lock, flags);  		/* Wait for Buffer Read Ready interrupt */  		wait_event_interruptible_timeout(host->buf_ready_int,  					(host->tuning_done == 1),  					msecs_to_jiffies(50)); -		disable_irq(host->irq); -		spin_lock(&host->lock); +		spin_lock_irqsave(&host->lock, flags);  		if (!host->tuning_done) {  			pr_info(DRIVER_NAME ": Timeout waiting for " @@ -1969,25 +1952,25 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)  		host->tuning_done = 0;  		ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); -		tuning_loop_counter--; -		timeout--; -		mdelay(1); + +		/* eMMC spec does not require a delay between tuning cycles */ +		if (opcode == MMC_SEND_TUNING_BLOCK) +			mdelay(1);  	} while (ctrl & SDHCI_CTRL_EXEC_TUNING);  	/*  	 * The Host Driver has exhausted the maximum number of loops allowed,  	 * so use fixed sampling frequency.  	 */ -	if (!tuning_loop_counter || !timeout) { +	if (tuning_loop_counter < 0) {  		ctrl &= ~SDHCI_CTRL_TUNED_CLK;  		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); -	} else { -		if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) { -			pr_info(DRIVER_NAME ": Tuning procedure" -				" failed, falling back to fixed sampling" -				" clock\n"); -			err = -EIO; -		} +	} +	if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) { +		pr_info(DRIVER_NAME ": Tuning procedure" +			" failed, falling back to fixed sampling" +			" clock\n"); +		err = -EIO;  	}  out: @@ -2004,12 +1987,11 @@ out:  			host->tuning_count * HZ);  		/* Tuning mode 1 limits the maximum data length to 4MB */  		mmc->max_blk_count = (4 * 1024 * 1024) / mmc->max_blk_size; -	} else { +	} else if (host->flags & SDHCI_USING_RETUNING_TIMER) {  		host->flags &= ~SDHCI_NEEDS_RETUNING;  		/* Reload the new initial value for timer */ -		if (host->tuning_mode == SDHCI_TUNING_MODE_1) -			mod_timer(&host->tuning_timer, jiffies + -				host->tuning_count * HZ); +		mod_timer(&host->tuning_timer, jiffies + +			  host->tuning_count * HZ);  	}  	/* @@ -2023,9 +2005,9 @@ out:  	if (err && (host->flags & SDHCI_USING_RETUNING_TIMER))  		err = 0; -	sdhci_clear_set_irqs(host, SDHCI_INT_DATA_AVAIL, ier); -	spin_unlock(&host->lock); -	enable_irq(host->irq); +	sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); +	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); +	spin_unlock_irqrestore(&host->lock, flags);  	sdhci_runtime_pm_put(host);  	return err; @@ -2034,26 +2016,30 @@ out:  static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable)  { -	u16 ctrl; -  	/* Host Controller v3.00 defines preset value registers */  	if (host->version < SDHCI_SPEC_300)  		return; -	ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); -  	/*  	 * We only enable or disable Preset Value if they are not already  	 * enabled or disabled respectively. Otherwise, we bail out.  	 */ -	if (enable && !(ctrl & SDHCI_CTRL_PRESET_VAL_ENABLE)) { -		ctrl |= SDHCI_CTRL_PRESET_VAL_ENABLE; -		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); -		host->flags |= SDHCI_PV_ENABLED; -	} else if (!enable && (ctrl & SDHCI_CTRL_PRESET_VAL_ENABLE)) { -		ctrl &= ~SDHCI_CTRL_PRESET_VAL_ENABLE; +	if (host->preset_enabled != enable) { +		u16 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); + +		if (enable) +			ctrl |= SDHCI_CTRL_PRESET_VAL_ENABLE; +		else +			ctrl &= ~SDHCI_CTRL_PRESET_VAL_ENABLE; +  		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); -		host->flags &= ~SDHCI_PV_ENABLED; + +		if (enable) +			host->flags |= SDHCI_PV_ENABLED; +		else +			host->flags &= ~SDHCI_PV_ENABLED; + +		host->preset_enabled = enable;  	}  } @@ -2075,8 +2061,8 @@ static void sdhci_card_event(struct mmc_host *mmc)  		pr_err("%s: Resetting controller.\n",  			mmc_hostname(host->mmc)); -		sdhci_reset(host, SDHCI_RESET_CMD); -		sdhci_reset(host, SDHCI_RESET_DATA); +		sdhci_do_reset(host, SDHCI_RESET_CMD); +		sdhci_do_reset(host, SDHCI_RESET_DATA);  		host->mrq->cmd->error = -ENOMEDIUM;  		tasklet_schedule(&host->finish_tasklet); @@ -2104,15 +2090,6 @@ static const struct mmc_host_ops sdhci_ops = {   *                                                                           *  \*****************************************************************************/ -static void sdhci_tasklet_card(unsigned long param) -{ -	struct sdhci_host *host = (struct sdhci_host*)param; - -	sdhci_card_event(host->mmc); - -	mmc_detect_change(host->mmc, msecs_to_jiffies(200)); -} -  static void sdhci_tasklet_finish(unsigned long param)  {  	struct sdhci_host *host; @@ -2149,12 +2126,12 @@ static void sdhci_tasklet_finish(unsigned long param)  		/* Some controllers need this kick or reset won't work here */  		if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET)  			/* This is to force an update */ -			sdhci_update_clock(host); +			host->ops->set_clock(host, host->clock);  		/* Spec says we should do both at the same time, but Ricoh  		   controllers do not like that. */ -		sdhci_reset(host, SDHCI_RESET_CMD); -		sdhci_reset(host, SDHCI_RESET_DATA); +		sdhci_do_reset(host, SDHCI_RESET_CMD); +		sdhci_do_reset(host, SDHCI_RESET_DATA);  	}  	host->mrq = NULL; @@ -2404,95 +2381,94 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)  static irqreturn_t sdhci_irq(int irq, void *dev_id)  { -	irqreturn_t result; +	irqreturn_t result = IRQ_NONE;  	struct sdhci_host *host = dev_id; -	u32 intmask, unexpected = 0; -	int cardint = 0, max_loops = 16; +	u32 intmask, mask, unexpected = 0; +	int max_loops = 16;  	spin_lock(&host->lock); -	if (host->runtime_suspended) { +	if (host->runtime_suspended && !sdhci_sdio_irq_enabled(host)) {  		spin_unlock(&host->lock); -		pr_warning("%s: got irq while runtime suspended\n", -		       mmc_hostname(host->mmc)); -		return IRQ_HANDLED; +		return IRQ_NONE;  	}  	intmask = sdhci_readl(host, SDHCI_INT_STATUS); -  	if (!intmask || intmask == 0xffffffff) {  		result = IRQ_NONE;  		goto out;  	} -again: -	DBG("*** %s got interrupt: 0x%08x\n", -		mmc_hostname(host->mmc), intmask); - -	if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) { -		u32 present = sdhci_readl(host, SDHCI_PRESENT_STATE) & -			      SDHCI_CARD_PRESENT; - -		/* -		 * There is a observation on i.mx esdhc.  INSERT bit will be -		 * immediately set again when it gets cleared, if a card is -		 * inserted.  We have to mask the irq to prevent interrupt -		 * storm which will freeze the system.  And the REMOVE gets -		 * the same situation. -		 * -		 * More testing are needed here to ensure it works for other -		 * platforms though. -		 */ -		sdhci_mask_irqs(host, present ? SDHCI_INT_CARD_INSERT : -						SDHCI_INT_CARD_REMOVE); -		sdhci_unmask_irqs(host, present ? SDHCI_INT_CARD_REMOVE : -						  SDHCI_INT_CARD_INSERT); - -		sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT | -			     SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS); -		intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE); -		tasklet_schedule(&host->card_tasklet); -	} +	do { +		/* Clear selected interrupts. */ +		mask = intmask & (SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK | +				  SDHCI_INT_BUS_POWER); +		sdhci_writel(host, mask, SDHCI_INT_STATUS); -	if (intmask & SDHCI_INT_CMD_MASK) { -		sdhci_writel(host, intmask & SDHCI_INT_CMD_MASK, -			SDHCI_INT_STATUS); -		sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK); -	} +		DBG("*** %s got interrupt: 0x%08x\n", +			mmc_hostname(host->mmc), intmask); -	if (intmask & SDHCI_INT_DATA_MASK) { -		sdhci_writel(host, intmask & SDHCI_INT_DATA_MASK, -			SDHCI_INT_STATUS); -		sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK); -	} +		if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) { +			u32 present = sdhci_readl(host, SDHCI_PRESENT_STATE) & +				      SDHCI_CARD_PRESENT; -	intmask &= ~(SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK); +			/* +			 * There is a observation on i.mx esdhc.  INSERT +			 * bit will be immediately set again when it gets +			 * cleared, if a card is inserted.  We have to mask +			 * the irq to prevent interrupt storm which will +			 * freeze the system.  And the REMOVE gets the +			 * same situation. +			 * +			 * More testing are needed here to ensure it works +			 * for other platforms though. +			 */ +			host->ier &= ~(SDHCI_INT_CARD_INSERT | +				       SDHCI_INT_CARD_REMOVE); +			host->ier |= present ? SDHCI_INT_CARD_REMOVE : +					       SDHCI_INT_CARD_INSERT; +			sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); +			sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); + +			sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT | +				     SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS); + +			host->thread_isr |= intmask & (SDHCI_INT_CARD_INSERT | +						       SDHCI_INT_CARD_REMOVE); +			result = IRQ_WAKE_THREAD; +		} -	intmask &= ~SDHCI_INT_ERROR; +		if (intmask & SDHCI_INT_CMD_MASK) +			sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK); -	if (intmask & SDHCI_INT_BUS_POWER) { -		pr_err("%s: Card is consuming too much power!\n", -			mmc_hostname(host->mmc)); -		sdhci_writel(host, SDHCI_INT_BUS_POWER, SDHCI_INT_STATUS); -	} +		if (intmask & SDHCI_INT_DATA_MASK) +			sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK); -	intmask &= ~SDHCI_INT_BUS_POWER; +		if (intmask & SDHCI_INT_BUS_POWER) +			pr_err("%s: Card is consuming too much power!\n", +				mmc_hostname(host->mmc)); -	if (intmask & SDHCI_INT_CARD_INT) -		cardint = 1; +		if (intmask & SDHCI_INT_CARD_INT) { +			sdhci_enable_sdio_irq_nolock(host, false); +			host->thread_isr |= SDHCI_INT_CARD_INT; +			result = IRQ_WAKE_THREAD; +		} -	intmask &= ~SDHCI_INT_CARD_INT; +		intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE | +			     SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK | +			     SDHCI_INT_ERROR | SDHCI_INT_BUS_POWER | +			     SDHCI_INT_CARD_INT); -	if (intmask) { -		unexpected |= intmask; -		sdhci_writel(host, intmask, SDHCI_INT_STATUS); -	} +		if (intmask) { +			unexpected |= intmask; +			sdhci_writel(host, intmask, SDHCI_INT_STATUS); +		} -	result = IRQ_HANDLED; +		if (result == IRQ_NONE) +			result = IRQ_HANDLED; -	intmask = sdhci_readl(host, SDHCI_INT_STATUS); -	if (intmask && --max_loops) -		goto again; +		intmask = sdhci_readl(host, SDHCI_INT_STATUS); +	} while (intmask && --max_loops);  out:  	spin_unlock(&host->lock); @@ -2501,15 +2477,38 @@ out:  			   mmc_hostname(host->mmc), unexpected);  		sdhci_dumpregs(host);  	} -	/* -	 * We have to delay this as it calls back into the driver. -	 */ -	if (cardint) -		mmc_signal_sdio_irq(host->mmc);  	return result;  } +static irqreturn_t sdhci_thread_irq(int irq, void *dev_id) +{ +	struct sdhci_host *host = dev_id; +	unsigned long flags; +	u32 isr; + +	spin_lock_irqsave(&host->lock, flags); +	isr = host->thread_isr; +	host->thread_isr = 0; +	spin_unlock_irqrestore(&host->lock, flags); + +	if (isr & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) { +		sdhci_card_event(host->mmc); +		mmc_detect_change(host->mmc, msecs_to_jiffies(200)); +	} + +	if (isr & SDHCI_INT_CARD_INT) { +		sdio_run_irqs(host->mmc); + +		spin_lock_irqsave(&host->lock, flags); +		if (host->flags & SDHCI_SDIO_IRQ_ENABLED) +			sdhci_enable_sdio_irq_nolock(host, true); +		spin_unlock_irqrestore(&host->lock, flags); +	} + +	return isr ? IRQ_HANDLED : IRQ_NONE; +} +  /*****************************************************************************\   *                                                                           *   * Suspend/resume                                                            * @@ -2546,11 +2545,6 @@ EXPORT_SYMBOL_GPL(sdhci_disable_irq_wakeups);  int sdhci_suspend_host(struct sdhci_host *host)  { -	int ret; - -	if (host->ops->platform_suspend) -		host->ops->platform_suspend(host); -  	sdhci_disable_card_detection(host);  	/* Disable tuning since we are suspending */ @@ -2559,34 +2553,23 @@ int sdhci_suspend_host(struct sdhci_host *host)  		host->flags &= ~SDHCI_NEEDS_RETUNING;  	} -	ret = mmc_suspend_host(host->mmc); -	if (ret) { -		if (host->flags & SDHCI_USING_RETUNING_TIMER) { -			host->flags |= SDHCI_NEEDS_RETUNING; -			mod_timer(&host->tuning_timer, jiffies + -					host->tuning_count * HZ); -		} - -		sdhci_enable_card_detection(host); - -		return ret; -	} -  	if (!device_may_wakeup(mmc_dev(host->mmc))) { -		sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK); +		host->ier = 0; +		sdhci_writel(host, 0, SDHCI_INT_ENABLE); +		sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);  		free_irq(host->irq, host);  	} else {  		sdhci_enable_irq_wakeups(host);  		enable_irq_wake(host->irq);  	} -	return ret; +	return 0;  }  EXPORT_SYMBOL_GPL(sdhci_suspend_host);  int sdhci_resume_host(struct sdhci_host *host)  { -	int ret; +	int ret = 0;  	if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {  		if (host->ops->enable_dma) @@ -2594,8 +2577,9 @@ int sdhci_resume_host(struct sdhci_host *host)  	}  	if (!device_may_wakeup(mmc_dev(host->mmc))) { -		ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED, -				  mmc_hostname(host->mmc), host); +		ret = request_threaded_irq(host->irq, sdhci_irq, +					   sdhci_thread_irq, IRQF_SHARED, +					   mmc_hostname(host->mmc), host);  		if (ret)  			return ret;  	} else { @@ -2615,12 +2599,8 @@ int sdhci_resume_host(struct sdhci_host *host)  		mmiowb();  	} -	ret = mmc_resume_host(host->mmc);  	sdhci_enable_card_detection(host); -	if (host->ops->platform_resume) -		host->ops->platform_resume(host); -  	/* Set the re-tuning expiration flag */  	if (host->flags & SDHCI_USING_RETUNING_TIMER)  		host->flags |= SDHCI_NEEDS_RETUNING; @@ -2672,10 +2652,12 @@ int sdhci_runtime_suspend_host(struct sdhci_host *host)  	}  	spin_lock_irqsave(&host->lock, flags); -	sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK); +	host->ier &= SDHCI_INT_CARD_INT; +	sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); +	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);  	spin_unlock_irqrestore(&host->lock, flags); -	synchronize_irq(host->irq); +	synchronize_hardirq(host->irq);  	spin_lock_irqsave(&host->lock, flags);  	host->runtime_suspended = true; @@ -2719,7 +2701,7 @@ int sdhci_runtime_resume_host(struct sdhci_host *host)  	host->runtime_suspended = false;  	/* Enable SDIO IRQ */ -	if ((host->flags & SDHCI_SDIO_IRQ_ENABLED)) +	if (host->flags & SDHCI_SDIO_IRQ_ENABLED)  		sdhci_enable_sdio_irq_nolock(host, true);  	/* Enable Card Detection */ @@ -2778,7 +2760,7 @@ int sdhci_add_host(struct sdhci_host *host)  	if (debug_quirks2)  		host->quirks2 = debug_quirks2; -	sdhci_reset(host, SDHCI_RESET_ALL); +	sdhci_do_reset(host, SDHCI_RESET_ALL);  	host->version = sdhci_readw(host, SDHCI_HOST_VERSION);  	host->version = (host->version & SDHCI_SPEC_VER_MASK) @@ -2838,15 +2820,29 @@ int sdhci_add_host(struct sdhci_host *host)  		 * (128) and potentially one alignment transfer for  		 * each of those entries.  		 */ -		host->adma_desc = kmalloc((128 * 2 + 1) * 4, GFP_KERNEL); +		host->adma_desc = dma_alloc_coherent(mmc_dev(host->mmc), +						     ADMA_SIZE, &host->adma_addr, +						     GFP_KERNEL);  		host->align_buffer = kmalloc(128 * 4, GFP_KERNEL);  		if (!host->adma_desc || !host->align_buffer) { -			kfree(host->adma_desc); +			dma_free_coherent(mmc_dev(host->mmc), ADMA_SIZE, +					  host->adma_desc, host->adma_addr);  			kfree(host->align_buffer);  			pr_warning("%s: Unable to allocate ADMA "  				"buffers. Falling back to standard DMA.\n",  				mmc_hostname(mmc));  			host->flags &= ~SDHCI_USE_ADMA; +			host->adma_desc = NULL; +			host->align_buffer = NULL; +		} else if (host->adma_addr & 3) { +			pr_warning("%s: unable to allocate aligned ADMA descriptor\n", +				   mmc_hostname(mmc)); +			host->flags &= ~SDHCI_USE_ADMA; +			dma_free_coherent(mmc_dev(host->mmc), ADMA_SIZE, +					  host->adma_desc, host->adma_addr); +			kfree(host->align_buffer); +			host->adma_desc = NULL; +			host->align_buffer = NULL;  		}  	} @@ -2928,9 +2924,10 @@ int sdhci_add_host(struct sdhci_host *host)  	if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)  		host->timeout_clk = mmc->f_max / 1000; -	mmc->max_discard_to = (1 << 27) / host->timeout_clk; +	mmc->max_busy_timeout = (1 << 27) / host->timeout_clk;  	mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23; +	mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD;  	if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12)  		host->flags |= SDHCI_AUTO_CMD12; @@ -3002,11 +2999,13 @@ int sdhci_add_host(struct sdhci_host *host)  		/* SD3.0: SDR104 is supported so (for eMMC) the caps2  		 * field can be promoted to support HS200.  		 */ -		mmc->caps2 |= MMC_CAP2_HS200; +		if (!(host->quirks2 & SDHCI_QUIRK2_BROKEN_HS200)) +			mmc->caps2 |= MMC_CAP2_HS200;  	} else if (caps[1] & SDHCI_SUPPORT_SDR50)  		mmc->caps |= MMC_CAP_UHS_SDR50; -	if (caps[1] & SDHCI_SUPPORT_DDR50) +	if ((caps[1] & SDHCI_SUPPORT_DDR50) && +		!(host->quirks2 & SDHCI_QUIRK2_BROKEN_DDR50))  		mmc->caps |= MMC_CAP_UHS_DDR50;  	/* Does the host need tuning for SDR50? */ @@ -3200,8 +3199,6 @@ int sdhci_add_host(struct sdhci_host *host)  	/*  	 * Init tasklets.  	 */ -	tasklet_init(&host->card_tasklet, -		sdhci_tasklet_card, (unsigned long)host);  	tasklet_init(&host->finish_tasklet,  		sdhci_tasklet_finish, (unsigned long)host); @@ -3218,8 +3215,8 @@ int sdhci_add_host(struct sdhci_host *host)  	sdhci_init(host, 0); -	ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED, -		mmc_hostname(mmc), host); +	ret = request_threaded_irq(host->irq, sdhci_irq, sdhci_thread_irq, +				   IRQF_SHARED,	mmc_hostname(mmc), host);  	if (ret) {  		pr_err("%s: Failed to request IRQ %d: %d\n",  		       mmc_hostname(mmc), host->irq, ret); @@ -3261,12 +3258,12 @@ int sdhci_add_host(struct sdhci_host *host)  #ifdef SDHCI_USE_LEDS_CLASS  reset: -	sdhci_reset(host, SDHCI_RESET_ALL); -	sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK); +	sdhci_do_reset(host, SDHCI_RESET_ALL); +	sdhci_writel(host, 0, SDHCI_INT_ENABLE); +	sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);  	free_irq(host->irq, host);  #endif  untasklet: -	tasklet_kill(&host->card_tasklet);  	tasklet_kill(&host->finish_tasklet);  	return ret; @@ -3303,14 +3300,14 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)  #endif  	if (!dead) -		sdhci_reset(host, SDHCI_RESET_ALL); +		sdhci_do_reset(host, SDHCI_RESET_ALL); -	sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK); +	sdhci_writel(host, 0, SDHCI_INT_ENABLE); +	sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);  	free_irq(host->irq, host);  	del_timer_sync(&host->timer); -	tasklet_kill(&host->card_tasklet);  	tasklet_kill(&host->finish_tasklet);  	if (host->vmmc) { @@ -3323,7 +3320,9 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)  		regulator_put(host->vqmmc);  	} -	kfree(host->adma_desc); +	if (host->adma_desc) +		dma_free_coherent(mmc_dev(host->mmc), ADMA_SIZE, +				  host->adma_desc, host->adma_addr);  	kfree(host->align_buffer);  	host->adma_desc = NULL;  | 
