diff options
Diffstat (limited to 'drivers/mmc')
| -rw-r--r-- | drivers/mmc/core/mmc_ops.c | 4 | ||||
| -rw-r--r-- | drivers/mmc/host/bcm2835.c | 3 | ||||
| -rw-r--r-- | drivers/mmc/host/dw_mmc-exynos.c | 1 | ||||
| -rw-r--r-- | drivers/mmc/host/dw_mmc-k3.c | 4 | ||||
| -rw-r--r-- | drivers/mmc/host/dw_mmc-rockchip.c | 1 | ||||
| -rw-r--r-- | drivers/mmc/host/dw_mmc-zx.c | 1 | ||||
| -rw-r--r-- | drivers/mmc/host/dw_mmc.c | 84 | ||||
| -rw-r--r-- | drivers/mmc/host/dw_mmc.h | 2 | ||||
| -rw-r--r-- | drivers/mmc/host/meson-gx-mmc.c | 19 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci-pci-core.c | 35 | 
10 files changed, 97 insertions, 57 deletions
| diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 908e4db03535..42d6aa89a48a 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -848,7 +848,6 @@ int mmc_interrupt_hpi(struct mmc_card *card)  		return 1;  	} -	mmc_claim_host(card->host);  	err = mmc_send_status(card, &status);  	if (err) {  		pr_err("%s: Get card status fail\n", mmc_hostname(card->host)); @@ -890,7 +889,6 @@ int mmc_interrupt_hpi(struct mmc_card *card)  	} while (!err);  out: -	mmc_release_host(card->host);  	return err;  } @@ -932,9 +930,7 @@ static int mmc_read_bkops_status(struct mmc_card *card)  	int err;  	u8 *ext_csd; -	mmc_claim_host(card->host);  	err = mmc_get_ext_csd(card, &ext_csd); -	mmc_release_host(card->host);  	if (err)  		return err; diff --git a/drivers/mmc/host/bcm2835.c b/drivers/mmc/host/bcm2835.c index 229dc18f0581..768972af8b85 100644 --- a/drivers/mmc/host/bcm2835.c +++ b/drivers/mmc/host/bcm2835.c @@ -1265,7 +1265,8 @@ static int bcm2835_add_host(struct bcm2835_host *host)  	char pio_limit_string[20];  	int ret; -	mmc->f_max = host->max_clk; +	if (!mmc->f_max || mmc->f_max > host->max_clk) +		mmc->f_max = host->max_clk;  	mmc->f_min = host->max_clk / SDCDIV_MAX_CDIV;  	mmc->max_busy_timeout = ~0 / (mmc->f_max / 1000); diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c index 35026795be28..fa41d9422d57 100644 --- a/drivers/mmc/host/dw_mmc-exynos.c +++ b/drivers/mmc/host/dw_mmc-exynos.c @@ -487,6 +487,7 @@ static unsigned long exynos_dwmmc_caps[4] = {  static const struct dw_mci_drv_data exynos_drv_data = {  	.caps			= exynos_dwmmc_caps, +	.num_caps		= ARRAY_SIZE(exynos_dwmmc_caps),  	.init			= dw_mci_exynos_priv_init,  	.set_ios		= dw_mci_exynos_set_ios,  	.parse_dt		= dw_mci_exynos_parse_dt, diff --git a/drivers/mmc/host/dw_mmc-k3.c b/drivers/mmc/host/dw_mmc-k3.c index 73fd75c3c824..89cdb3d533bb 100644 --- a/drivers/mmc/host/dw_mmc-k3.c +++ b/drivers/mmc/host/dw_mmc-k3.c @@ -135,6 +135,9 @@ static int dw_mci_hi6220_parse_dt(struct dw_mci *host)  	if (priv->ctrl_id < 0)  		priv->ctrl_id = 0; +	if (priv->ctrl_id >= TIMING_MODE) +		return -EINVAL; +  	host->priv = priv;  	return 0;  } @@ -207,6 +210,7 @@ static int dw_mci_hi6220_execute_tuning(struct dw_mci_slot *slot, u32 opcode)  static const struct dw_mci_drv_data hi6220_data = {  	.caps			= dw_mci_hi6220_caps, +	.num_caps		= ARRAY_SIZE(dw_mci_hi6220_caps),  	.switch_voltage		= dw_mci_hi6220_switch_voltage,  	.set_ios		= dw_mci_hi6220_set_ios,  	.parse_dt		= dw_mci_hi6220_parse_dt, diff --git a/drivers/mmc/host/dw_mmc-rockchip.c b/drivers/mmc/host/dw_mmc-rockchip.c index a3f1c2b30145..339295212935 100644 --- a/drivers/mmc/host/dw_mmc-rockchip.c +++ b/drivers/mmc/host/dw_mmc-rockchip.c @@ -319,6 +319,7 @@ static const struct dw_mci_drv_data rk2928_drv_data = {  static const struct dw_mci_drv_data rk3288_drv_data = {  	.caps			= dw_mci_rk3288_dwmmc_caps, +	.num_caps		= ARRAY_SIZE(dw_mci_rk3288_dwmmc_caps),  	.set_ios		= dw_mci_rk3288_set_ios,  	.execute_tuning		= dw_mci_rk3288_execute_tuning,  	.parse_dt		= dw_mci_rk3288_parse_dt, diff --git a/drivers/mmc/host/dw_mmc-zx.c b/drivers/mmc/host/dw_mmc-zx.c index d38e94ae2b85..c06b5393312f 100644 --- a/drivers/mmc/host/dw_mmc-zx.c +++ b/drivers/mmc/host/dw_mmc-zx.c @@ -195,6 +195,7 @@ static unsigned long zx_dwmmc_caps[3] = {  static const struct dw_mci_drv_data zx_drv_data = {  	.caps			= zx_dwmmc_caps, +	.num_caps		= ARRAY_SIZE(zx_dwmmc_caps),  	.execute_tuning		= dw_mci_zx_execute_tuning,  	.prepare_hs400_tuning	= dw_mci_zx_prepare_hs400_tuning,  	.parse_dt               = dw_mci_zx_parse_dt, diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 0aa39975f33b..d9b4acefed31 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -165,6 +165,8 @@ static int dw_mci_regs_show(struct seq_file *s, void *v)  {  	struct dw_mci *host = s->private; +	pm_runtime_get_sync(host->dev); +  	seq_printf(s, "STATUS:\t0x%08x\n", mci_readl(host, STATUS));  	seq_printf(s, "RINTSTS:\t0x%08x\n", mci_readl(host, RINTSTS));  	seq_printf(s, "CMD:\t0x%08x\n", mci_readl(host, CMD)); @@ -172,6 +174,8 @@ static int dw_mci_regs_show(struct seq_file *s, void *v)  	seq_printf(s, "INTMASK:\t0x%08x\n", mci_readl(host, INTMASK));  	seq_printf(s, "CLKENA:\t0x%08x\n", mci_readl(host, CLKENA)); +	pm_runtime_put_autosuspend(host->dev); +  	return 0;  } @@ -2778,12 +2782,57 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)  	return IRQ_HANDLED;  } +static int dw_mci_init_slot_caps(struct dw_mci_slot *slot) +{ +	struct dw_mci *host = slot->host; +	const struct dw_mci_drv_data *drv_data = host->drv_data; +	struct mmc_host *mmc = slot->mmc; +	int ctrl_id; + +	if (host->pdata->caps) +		mmc->caps = host->pdata->caps; + +	/* +	 * Support MMC_CAP_ERASE by default. +	 * It needs to use trim/discard/erase commands. +	 */ +	mmc->caps |= MMC_CAP_ERASE; + +	if (host->pdata->pm_caps) +		mmc->pm_caps = host->pdata->pm_caps; + +	if (host->dev->of_node) { +		ctrl_id = of_alias_get_id(host->dev->of_node, "mshc"); +		if (ctrl_id < 0) +			ctrl_id = 0; +	} else { +		ctrl_id = to_platform_device(host->dev)->id; +	} + +	if (drv_data && drv_data->caps) { +		if (ctrl_id >= drv_data->num_caps) { +			dev_err(host->dev, "invalid controller id %d\n", +				ctrl_id); +			return -EINVAL; +		} +		mmc->caps |= drv_data->caps[ctrl_id]; +	} + +	if (host->pdata->caps2) +		mmc->caps2 = host->pdata->caps2; + +	/* Process SDIO IRQs through the sdio_irq_work. */ +	if (mmc->caps & MMC_CAP_SDIO_IRQ) +		mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD; + +	return 0; +} +  static int dw_mci_init_slot(struct dw_mci *host)  {  	struct mmc_host *mmc;  	struct dw_mci_slot *slot; -	const struct dw_mci_drv_data *drv_data = host->drv_data; -	int ctrl_id, ret; +	int ret;  	u32 freq[2];  	mmc = mmc_alloc_host(sizeof(struct dw_mci_slot), host->dev); @@ -2817,38 +2866,13 @@ static int dw_mci_init_slot(struct dw_mci *host)  	if (!mmc->ocr_avail)  		mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; -	if (host->pdata->caps) -		mmc->caps = host->pdata->caps; - -	/* -	 * Support MMC_CAP_ERASE by default. -	 * It needs to use trim/discard/erase commands. -	 */ -	mmc->caps |= MMC_CAP_ERASE; - -	if (host->pdata->pm_caps) -		mmc->pm_caps = host->pdata->pm_caps; - -	if (host->dev->of_node) { -		ctrl_id = of_alias_get_id(host->dev->of_node, "mshc"); -		if (ctrl_id < 0) -			ctrl_id = 0; -	} else { -		ctrl_id = to_platform_device(host->dev)->id; -	} -	if (drv_data && drv_data->caps) -		mmc->caps |= drv_data->caps[ctrl_id]; - -	if (host->pdata->caps2) -		mmc->caps2 = host->pdata->caps2; -  	ret = mmc_of_parse(mmc);  	if (ret)  		goto err_host_allocated; -	/* Process SDIO IRQs through the sdio_irq_work. */ -	if (mmc->caps & MMC_CAP_SDIO_IRQ) -		mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD; +	ret = dw_mci_init_slot_caps(slot); +	if (ret) +		goto err_host_allocated;  	/* Useful defaults if platform data is unset. */  	if (host->use_dma == TRANS_MODE_IDMAC) { diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index e3124f06a47e..1424bd490dd1 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h @@ -543,6 +543,7 @@ struct dw_mci_slot {  /**   * dw_mci driver data - dw-mshc implementation specific driver data.   * @caps: mmc subsystem specified capabilities of the controller(s). + * @num_caps: number of capabilities specified by @caps.   * @init: early implementation specific initialization.   * @set_ios: handle bus specific extensions.   * @parse_dt: parse implementation specific device tree properties. @@ -554,6 +555,7 @@ struct dw_mci_slot {   */  struct dw_mci_drv_data {  	unsigned long	*caps; +	u32		num_caps;  	int		(*init)(struct dw_mci *host);  	void		(*set_ios)(struct dw_mci *host, struct mmc_ios *ios);  	int		(*parse_dt)(struct dw_mci *host); diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c index 22438ebfe4e6..4f972b879fe6 100644 --- a/drivers/mmc/host/meson-gx-mmc.c +++ b/drivers/mmc/host/meson-gx-mmc.c @@ -717,22 +717,6 @@ static int meson_mmc_clk_phase_tuning(struct mmc_host *mmc, u32 opcode,  static int meson_mmc_execute_tuning(struct mmc_host *mmc, u32 opcode)  {  	struct meson_host *host = mmc_priv(mmc); -	int ret; - -	/* -	 * If this is the initial tuning, try to get a sane Rx starting -	 * phase before doing the actual tuning. -	 */ -	if (!mmc->doing_retune) { -		ret = meson_mmc_clk_phase_tuning(mmc, opcode, host->rx_clk); - -		if (ret) -			return ret; -	} - -	ret = meson_mmc_clk_phase_tuning(mmc, opcode, host->tx_clk); -	if (ret) -		return ret;  	return meson_mmc_clk_phase_tuning(mmc, opcode, host->rx_clk);  } @@ -763,9 +747,8 @@ static void meson_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)  		if (!IS_ERR(mmc->supply.vmmc))  			mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd); -		/* Reset phases */ +		/* Reset rx phase */  		clk_set_phase(host->rx_clk, 0); -		clk_set_phase(host->tx_clk, 270);  		break; diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c index 6d1a983e6227..82c4f05f91d8 100644 --- a/drivers/mmc/host/sdhci-pci-core.c +++ b/drivers/mmc/host/sdhci-pci-core.c @@ -654,9 +654,36 @@ static void byt_read_dsm(struct sdhci_pci_slot *slot)  	slot->chip->rpm_retune = intel_host->d3_retune;  } -static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot) +static int intel_execute_tuning(struct mmc_host *mmc, u32 opcode) +{ +	int err = sdhci_execute_tuning(mmc, opcode); +	struct sdhci_host *host = mmc_priv(mmc); + +	if (err) +		return err; + +	/* +	 * Tuning can leave the IP in an active state (Buffer Read Enable bit +	 * set) which prevents the entry to low power states (i.e. S0i3). Data +	 * reset will clear it. +	 */ +	sdhci_reset(host, SDHCI_RESET_DATA); + +	return 0; +} + +static void byt_probe_slot(struct sdhci_pci_slot *slot)  { +	struct mmc_host_ops *ops = &slot->host->mmc_host_ops; +  	byt_read_dsm(slot); + +	ops->execute_tuning = intel_execute_tuning; +} + +static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot) +{ +	byt_probe_slot(slot);  	slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE |  				 MMC_CAP_HW_RESET | MMC_CAP_1_8V_DDR |  				 MMC_CAP_CMD_DURING_TFR | @@ -779,7 +806,7 @@ static int ni_byt_sdio_probe_slot(struct sdhci_pci_slot *slot)  {  	int err; -	byt_read_dsm(slot); +	byt_probe_slot(slot);  	err = ni_set_max_freq(slot);  	if (err) @@ -792,7 +819,7 @@ static int ni_byt_sdio_probe_slot(struct sdhci_pci_slot *slot)  static int byt_sdio_probe_slot(struct sdhci_pci_slot *slot)  { -	byt_read_dsm(slot); +	byt_probe_slot(slot);  	slot->host->mmc->caps |= MMC_CAP_POWER_OFF_CARD | MMC_CAP_NONREMOVABLE |  				 MMC_CAP_WAIT_WHILE_BUSY;  	return 0; @@ -800,7 +827,7 @@ static int byt_sdio_probe_slot(struct sdhci_pci_slot *slot)  static int byt_sd_probe_slot(struct sdhci_pci_slot *slot)  { -	byt_read_dsm(slot); +	byt_probe_slot(slot);  	slot->host->mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY |  				 MMC_CAP_AGGRESSIVE_PM | MMC_CAP_CD_WAKE;  	slot->cd_idx = 0; |