diff options
Diffstat (limited to 'drivers/mmc')
| -rw-r--r-- | drivers/mmc/core/block.c | 7 | ||||
| -rw-r--r-- | drivers/mmc/core/mmc.c | 2 | ||||
| -rw-r--r-- | drivers/mmc/core/sdio_bus.c | 12 | ||||
| -rw-r--r-- | drivers/mmc/host/dw_mmc.c | 11 | ||||
| -rw-r--r-- | drivers/mmc/host/mtk-sd.c | 4 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci-esdhc-imx.c | 1 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci-of-arasan.c | 14 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci-of-at91.c | 30 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci-pci-core.c | 4 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci.c | 10 | ||||
| -rw-r--r-- | drivers/mmc/host/ushc.c | 3 | 
11 files changed, 77 insertions, 21 deletions
diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index 1621fa08e206..ff3da960c473 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -1560,11 +1560,8 @@ static bool mmc_blk_rw_cmd_err(struct mmc_blk_data *md, struct mmc_card *card,  			       struct mmc_blk_request *brq, struct request *req,  			       bool old_req_pending)  { -	struct mmc_queue_req *mq_rq;  	bool req_pending; -	mq_rq = container_of(brq, struct mmc_queue_req, brq); -  	/*  	 * If this is an SD card and we're writing, we can first  	 * mark the known good sectors as ok. @@ -1701,7 +1698,8 @@ static void mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *new_req)  		case MMC_BLK_CMD_ERR:  			req_pending = mmc_blk_rw_cmd_err(md, card, brq, old_req, req_pending);  			if (mmc_blk_reset(md, card->host, type)) { -				mmc_blk_rw_cmd_abort(card, old_req); +				if (req_pending) +					mmc_blk_rw_cmd_abort(card, old_req);  				mmc_blk_rw_try_restart(mq, new_req);  				return;  			} @@ -1817,6 +1815,7 @@ void mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)  		mmc_blk_issue_flush(mq, req);  	} else {  		mmc_blk_issue_rw_rq(mq, req); +		card->host->context_info.is_waiting_last_req = false;  	}  out: diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 7fd722868875..b502601df228 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1730,7 +1730,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,  		err = mmc_select_hs400(card);  		if (err)  			goto free_card; -	} else { +	} else if (!mmc_card_hs400es(card)) {  		/* Select the desired bus width optionally */  		err = mmc_select_bus_width(card);  		if (err > 0 && mmc_card_hs(card)) { diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c index e992a7f8a16f..2b32b88949ba 100644 --- a/drivers/mmc/core/sdio_bus.c +++ b/drivers/mmc/core/sdio_bus.c @@ -267,7 +267,7 @@ static void sdio_release_func(struct device *dev)  	sdio_free_func_cis(func);  	kfree(func->info); - +	kfree(func->tmpbuf);  	kfree(func);  } @@ -282,6 +282,16 @@ struct sdio_func *sdio_alloc_func(struct mmc_card *card)  	if (!func)  		return ERR_PTR(-ENOMEM); +	/* +	 * allocate buffer separately to make sure it's properly aligned for +	 * DMA usage (incl. 64 bit DMA) +	 */ +	func->tmpbuf = kmalloc(4, GFP_KERNEL); +	if (!func->tmpbuf) { +		kfree(func); +		return ERR_PTR(-ENOMEM); +	} +  	func->card = card;  	device_initialize(&func->dev); diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index a9ac0b457313..8718432751c5 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -22,6 +22,7 @@  #include <linux/ioport.h>  #include <linux/module.h>  #include <linux/platform_device.h> +#include <linux/pm_runtime.h>  #include <linux/seq_file.h>  #include <linux/slab.h>  #include <linux/stat.h> @@ -1621,10 +1622,16 @@ static void dw_mci_init_card(struct mmc_host *mmc, struct mmc_card *card)  		if (card->type == MMC_TYPE_SDIO ||  		    card->type == MMC_TYPE_SD_COMBO) { -			set_bit(DW_MMC_CARD_NO_LOW_PWR, &slot->flags); +			if (!test_bit(DW_MMC_CARD_NO_LOW_PWR, &slot->flags)) { +				pm_runtime_get_noresume(mmc->parent); +				set_bit(DW_MMC_CARD_NO_LOW_PWR, &slot->flags); +			}  			clk_en_a = clk_en_a_old & ~clken_low_pwr;  		} else { -			clear_bit(DW_MMC_CARD_NO_LOW_PWR, &slot->flags); +			if (test_bit(DW_MMC_CARD_NO_LOW_PWR, &slot->flags)) { +				pm_runtime_put_noidle(mmc->parent); +				clear_bit(DW_MMC_CARD_NO_LOW_PWR, &slot->flags); +			}  			clk_en_a = clk_en_a_old | clken_low_pwr;  		} diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c index 8e32580c12b5..b235d8da0602 100644 --- a/drivers/mmc/host/mtk-sd.c +++ b/drivers/mmc/host/mtk-sd.c @@ -580,7 +580,7 @@ static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz)  		}  	}  	sdr_set_field(host->base + MSDC_CFG, MSDC_CFG_CKMOD | MSDC_CFG_CKDIV, -			(mode << 8) | (div % 0xff)); +		      (mode << 8) | div);  	sdr_set_bits(host->base + MSDC_CFG, MSDC_CFG_CKPDN);  	while (!(readl(host->base + MSDC_CFG) & MSDC_CFG_CKSTB))  		cpu_relax(); @@ -1559,7 +1559,7 @@ static int msdc_drv_probe(struct platform_device *pdev)  	host->src_clk_freq = clk_get_rate(host->src_clk);  	/* Set host parameters to mmc */  	mmc->ops = &mt_msdc_ops; -	mmc->f_min = host->src_clk_freq / (4 * 255); +	mmc->f_min = DIV_ROUND_UP(host->src_clk_freq, 4 * 255);  	mmc->caps |= MMC_CAP_ERASE | MMC_CAP_CMD23;  	/* MMC core transfer sizes tunable parameters */ diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 7123ef96ed18..445fc47dc3e7 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -830,6 +830,7 @@ static int esdhc_change_pinstate(struct sdhci_host *host,  	switch (uhs) {  	case MMC_TIMING_UHS_SDR50: +	case MMC_TIMING_UHS_DDR50:  		pinctrl = imx_data->pins_100mhz;  		break;  	case MMC_TIMING_UHS_SDR104: diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c index 410a55b1c25f..1cfd7f900339 100644 --- a/drivers/mmc/host/sdhci-of-arasan.c +++ b/drivers/mmc/host/sdhci-of-arasan.c @@ -28,13 +28,9 @@  #include "sdhci-pltfm.h"  #include <linux/of.h> -#define SDHCI_ARASAN_CLK_CTRL_OFFSET	0x2c  #define SDHCI_ARASAN_VENDOR_REGISTER	0x78  #define VENDOR_ENHANCED_STROBE		BIT(0) -#define CLK_CTRL_TIMEOUT_SHIFT		16 -#define CLK_CTRL_TIMEOUT_MASK		(0xf << CLK_CTRL_TIMEOUT_SHIFT) -#define CLK_CTRL_TIMEOUT_MIN_EXP	13  #define PHY_CLK_TOO_SLOW_HZ		400000 @@ -163,15 +159,15 @@ static int sdhci_arasan_syscon_write(struct sdhci_host *host,  static unsigned int sdhci_arasan_get_timeout_clock(struct sdhci_host *host)  { -	u32 div;  	unsigned long freq;  	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); -	div = readl(host->ioaddr + SDHCI_ARASAN_CLK_CTRL_OFFSET); -	div = (div & CLK_CTRL_TIMEOUT_MASK) >> CLK_CTRL_TIMEOUT_SHIFT; +	/* SDHCI timeout clock is in kHz */ +	freq = DIV_ROUND_UP(clk_get_rate(pltfm_host->clk), 1000); -	freq = clk_get_rate(pltfm_host->clk); -	freq /= 1 << (CLK_CTRL_TIMEOUT_MIN_EXP + div); +	/* or in MHz */ +	if (host->caps & SDHCI_TIMEOUT_CLK_UNIT) +		freq = DIV_ROUND_UP(freq, 1000);  	return freq;  } diff --git a/drivers/mmc/host/sdhci-of-at91.c b/drivers/mmc/host/sdhci-of-at91.c index 2f9ad213377a..d5430ed02a67 100644 --- a/drivers/mmc/host/sdhci-of-at91.c +++ b/drivers/mmc/host/sdhci-of-at91.c @@ -29,6 +29,8 @@  #include "sdhci-pltfm.h" +#define SDMMC_MC1R	0x204 +#define		SDMMC_MC1R_DDR		BIT(3)  #define SDMMC_CACR	0x230  #define		SDMMC_CACR_CAPWREN	BIT(0)  #define		SDMMC_CACR_KEY		(0x46 << 8) @@ -85,11 +87,37 @@ static void sdhci_at91_set_clock(struct sdhci_host *host, unsigned int clock)  	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);  } +/* + * In this specific implementation of the SDHCI controller, the power register + * needs to have a valid voltage set even when the power supply is managed by + * an external regulator. + */ +static void sdhci_at91_set_power(struct sdhci_host *host, unsigned char mode, +		     unsigned short vdd) +{ +	if (!IS_ERR(host->mmc->supply.vmmc)) { +		struct mmc_host *mmc = host->mmc; + +		spin_unlock_irq(&host->lock); +		mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd); +		spin_lock_irq(&host->lock); +	} +	sdhci_set_power_noreg(host, mode, vdd); +} + +void sdhci_at91_set_uhs_signaling(struct sdhci_host *host, unsigned int timing) +{ +	if (timing == MMC_TIMING_MMC_DDR52) +		sdhci_writeb(host, SDMMC_MC1R_DDR, SDMMC_MC1R); +	sdhci_set_uhs_signaling(host, timing); +} +  static const struct sdhci_ops sdhci_at91_sama5d2_ops = {  	.set_clock		= sdhci_at91_set_clock,  	.set_bus_width		= sdhci_set_bus_width,  	.reset			= sdhci_reset, -	.set_uhs_signaling	= sdhci_set_uhs_signaling, +	.set_uhs_signaling	= sdhci_at91_set_uhs_signaling, +	.set_power		= sdhci_at91_set_power,  };  static const struct sdhci_pltfm_data soc_data_sama5d2 = { diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c index 982b3e349426..86560d590786 100644 --- a/drivers/mmc/host/sdhci-pci-core.c +++ b/drivers/mmc/host/sdhci-pci-core.c @@ -451,6 +451,8 @@ static void sdhci_intel_set_power(struct sdhci_host *host, unsigned char mode,  	if (mode == MMC_POWER_OFF)  		return; +	spin_unlock_irq(&host->lock); +  	/*  	 * Bus power might not enable after D3 -> D0 transition due to the  	 * present state not yet having propagated. Retry for up to 2ms. @@ -463,6 +465,8 @@ static void sdhci_intel_set_power(struct sdhci_host *host, unsigned char mode,  		reg |= SDHCI_POWER_ON;  		sdhci_writeb(host, reg, SDHCI_POWER_CONTROL);  	} + +	spin_lock_irq(&host->lock);  }  static const struct sdhci_ops sdhci_intel_byt_ops = { diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 6fdd7a70f229..63bc33a54d0d 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1362,7 +1362,9 @@ void sdhci_enable_clk(struct sdhci_host *host, u16 clk)  			return;  		}  		timeout--; -		mdelay(1); +		spin_unlock_irq(&host->lock); +		usleep_range(900, 1100); +		spin_lock_irq(&host->lock);  	}  	clk |= SDHCI_CLOCK_CARD_EN; @@ -1828,6 +1830,9 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)  	struct sdhci_host *host = mmc_priv(mmc);  	unsigned long flags; +	if (enable) +		pm_runtime_get_noresume(host->mmc->parent); +  	spin_lock_irqsave(&host->lock, flags);  	if (enable)  		host->flags |= SDHCI_SDIO_IRQ_ENABLED; @@ -1836,6 +1841,9 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)  	sdhci_enable_sdio_irq_nolock(host, enable);  	spin_unlock_irqrestore(&host->lock, flags); + +	if (!enable) +		pm_runtime_put_noidle(host->mmc->parent);  }  static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc, diff --git a/drivers/mmc/host/ushc.c b/drivers/mmc/host/ushc.c index d2c386f09d69..1d843357422e 100644 --- a/drivers/mmc/host/ushc.c +++ b/drivers/mmc/host/ushc.c @@ -426,6 +426,9 @@ static int ushc_probe(struct usb_interface *intf, const struct usb_device_id *id  	struct ushc_data *ushc;  	int ret; +	if (intf->cur_altsetting->desc.bNumEndpoints < 1) +		return -ENODEV; +  	mmc = mmc_alloc_host(sizeof(struct ushc_data), &intf->dev);  	if (mmc == NULL)  		return -ENOMEM;  | 
