diff options
Diffstat (limited to 'drivers/mmc')
53 files changed, 1330 insertions, 540 deletions
diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index 95b41c0891d0..663d87924e5e 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -1107,7 +1107,7 @@ static void mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req)  					 card->erase_arg == MMC_TRIM_ARG ?  					 INAND_CMD38_ARG_TRIM :  					 INAND_CMD38_ARG_ERASE, -					 0); +					 card->ext_csd.generic_cmd6_time);  		}  		if (!err)  			err = mmc_erase(card, from, nr, card->erase_arg); @@ -1149,7 +1149,7 @@ retry:  				 arg == MMC_SECURE_TRIM1_ARG ?  				 INAND_CMD38_ARG_SECTRIM1 :  				 INAND_CMD38_ARG_SECERASE, -				 0); +				 card->ext_csd.generic_cmd6_time);  		if (err)  			goto out_retry;  	} @@ -1167,7 +1167,7 @@ retry:  			err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,  					 INAND_CMD38_ARG_EXT_CSD,  					 INAND_CMD38_ARG_SECTRIM2, -					 0); +					 card->ext_csd.generic_cmd6_time);  			if (err)  				goto out_retry;  		} diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index abf8f5eb0a1c..aa54d359dab7 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -2330,7 +2330,13 @@ void mmc_rescan(struct work_struct *work)  	}  	for (i = 0; i < ARRAY_SIZE(freqs); i++) { -		if (!mmc_rescan_try_freq(host, max(freqs[i], host->f_min))) +		unsigned int freq = freqs[i]; +		if (freq > host->f_max) { +			if (i + 1 < ARRAY_SIZE(freqs)) +				continue; +			freq = host->f_max; +		} +		if (!mmc_rescan_try_freq(host, max(freq, host->f_min)))  			break;  		if (freqs[i] <= host->f_min)  			break; @@ -2344,7 +2350,7 @@ void mmc_rescan(struct work_struct *work)  void mmc_start_host(struct mmc_host *host)  { -	host->f_init = max(freqs[0], host->f_min); +	host->f_init = max(min(freqs[0], host->f_max), host->f_min);  	host->rescan_disable = 0;  	host->ios.power_mode = MMC_POWER_UNDEFINED; diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index 105b7a7c0251..c8768726d925 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -175,8 +175,6 @@ int mmc_of_parse(struct mmc_host *host)  	struct device *dev = host->parent;  	u32 bus_width, drv_type, cd_debounce_delay_ms;  	int ret; -	bool cd_cap_invert, cd_gpio_invert = false; -	bool ro_cap_invert, ro_gpio_invert = false;  	if (!dev || !dev_fwnode(dev))  		return 0; @@ -219,10 +217,12 @@ int mmc_of_parse(struct mmc_host *host)  	 */  	/* Parse Card Detection */ +  	if (device_property_read_bool(dev, "non-removable")) {  		host->caps |= MMC_CAP_NONREMOVABLE;  	} else { -		cd_cap_invert = device_property_read_bool(dev, "cd-inverted"); +		if (device_property_read_bool(dev, "cd-inverted")) +			host->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;  		if (device_property_read_u32(dev, "cd-debounce-delay-ms",  					     &cd_debounce_delay_ms)) @@ -232,32 +232,19 @@ int mmc_of_parse(struct mmc_host *host)  			host->caps |= MMC_CAP_NEEDS_POLL;  		ret = mmc_gpiod_request_cd(host, "cd", 0, false, -					   cd_debounce_delay_ms * 1000, -					   &cd_gpio_invert); +					   cd_debounce_delay_ms * 1000);  		if (!ret)  			dev_info(host->parent, "Got CD GPIO\n");  		else if (ret != -ENOENT && ret != -ENOSYS)  			return ret; - -		/* -		 * There are two ways to flag that the CD line is inverted: -		 * through the cd-inverted flag and by the GPIO line itself -		 * being inverted from the GPIO subsystem. This is a leftover -		 * from the times when the GPIO subsystem did not make it -		 * possible to flag a line as inverted. -		 * -		 * If the capability on the host AND the GPIO line are -		 * both inverted, the end result is that the CD line is -		 * not inverted. -		 */ -		if (cd_cap_invert ^ cd_gpio_invert) -			host->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;  	}  	/* Parse Write Protection */ -	ro_cap_invert = device_property_read_bool(dev, "wp-inverted"); -	ret = mmc_gpiod_request_ro(host, "wp", 0, 0, &ro_gpio_invert); +	if (device_property_read_bool(dev, "wp-inverted")) +		host->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; + +	ret = mmc_gpiod_request_ro(host, "wp", 0, 0);  	if (!ret)  		dev_info(host->parent, "Got WP GPIO\n");  	else if (ret != -ENOENT && ret != -ENOSYS) @@ -266,10 +253,6 @@ int mmc_of_parse(struct mmc_host *host)  	if (device_property_read_bool(dev, "disable-wp"))  		host->caps2 |= MMC_CAP2_NO_WRITE_PROTECT; -	/* See the comment on CD inversion above */ -	if (ro_cap_invert ^ ro_gpio_invert) -		host->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; -  	if (device_property_read_bool(dev, "cap-sd-highspeed"))  		host->caps |= MMC_CAP_SD_HIGHSPEED;  	if (device_property_read_bool(dev, "cap-mmc-highspeed")) diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 09113b9ad679..da425ee2d9bf 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -19,7 +19,9 @@  #include "host.h"  #include "mmc_ops.h" -#define MMC_OPS_TIMEOUT_MS	(10 * 60 * 1000) /* 10 minute timeout */ +#define MMC_OPS_TIMEOUT_MS		(10 * 60 * 1000) /* 10min*/ +#define MMC_BKOPS_TIMEOUT_MS		(120 * 1000) /* 120s */ +#define MMC_CACHE_FLUSH_TIMEOUT_MS	(30 * 1000) /* 30s */  static const u8 tuning_blk_pattern_4bit[] = {  	0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc, @@ -458,10 +460,6 @@ static int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms,  	bool expired = false;  	bool busy = false; -	/* We have an unspecified cmd timeout, use the fallback value. */ -	if (!timeout_ms) -		timeout_ms = MMC_OPS_TIMEOUT_MS; -  	/*  	 * In cases when not allowed to poll by using CMD13 or because we aren't  	 * capable of polling by using ->card_busy(), then rely on waiting the @@ -534,14 +532,19 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,  	mmc_retune_hold(host); +	if (!timeout_ms) { +		pr_warn("%s: unspecified timeout for CMD6 - use generic\n", +			mmc_hostname(host)); +		timeout_ms = card->ext_csd.generic_cmd6_time; +	} +  	/* -	 * If the cmd timeout and the max_busy_timeout of the host are both -	 * specified, let's validate them. A failure means we need to prevent -	 * the host from doing hw busy detection, which is done by converting -	 * to a R1 response instead of a R1B. +	 * If the max_busy_timeout of the host is specified, make sure it's +	 * enough to fit the used timeout_ms. In case it's not, let's instruct +	 * the host to avoid HW busy detection, by converting to a R1 response +	 * instead of a R1B.  	 */ -	if (timeout_ms && host->max_busy_timeout && -		(timeout_ms > host->max_busy_timeout)) +	if (host->max_busy_timeout && (timeout_ms > host->max_busy_timeout))  		use_r1b_resp = false;  	cmd.opcode = MMC_SWITCH; @@ -552,10 +555,6 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,  	cmd.flags = MMC_CMD_AC;  	if (use_r1b_resp) {  		cmd.flags |= MMC_RSP_SPI_R1B | MMC_RSP_R1B; -		/* -		 * A busy_timeout of zero means the host can decide to use -		 * whatever value it finds suitable. -		 */  		cmd.busy_timeout = timeout_ms;  	} else {  		cmd.flags |= MMC_RSP_SPI_R1 | MMC_RSP_R1; @@ -941,7 +940,7 @@ void mmc_run_bkops(struct mmc_card *card)  	 * urgent levels by using an asynchronous background task, when idle.  	 */  	err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, -			EXT_CSD_BKOPS_START, 1, MMC_OPS_TIMEOUT_MS); +			 EXT_CSD_BKOPS_START, 1, MMC_BKOPS_TIMEOUT_MS);  	if (err)  		pr_warn("%s: Error %d starting bkops\n",  			mmc_hostname(card->host), err); @@ -961,7 +960,8 @@ int mmc_flush_cache(struct mmc_card *card)  			(card->ext_csd.cache_size > 0) &&  			(card->ext_csd.cache_ctrl & 1)) {  		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, -				EXT_CSD_FLUSH_CACHE, 1, 0); +				 EXT_CSD_FLUSH_CACHE, 1, +				 MMC_CACHE_FLUSH_TIMEOUT_MS);  		if (err)  			pr_err("%s: cache flush error %d\n",  					mmc_hostname(card->host), err); diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c index da2596c5fa28..05e907451df9 100644 --- a/drivers/mmc/core/slot-gpio.c +++ b/drivers/mmc/core/slot-gpio.c @@ -19,7 +19,6 @@  struct mmc_gpio {  	struct gpio_desc *ro_gpio;  	struct gpio_desc *cd_gpio; -	bool override_cd_active_level;  	irqreturn_t (*cd_gpio_isr)(int irq, void *dev_id);  	char *ro_label;  	char *cd_label; @@ -80,13 +79,6 @@ int mmc_gpio_get_cd(struct mmc_host *host)  		return -ENOSYS;  	cansleep = gpiod_cansleep(ctx->cd_gpio); -	if (ctx->override_cd_active_level) { -		int value = cansleep ? -				gpiod_get_raw_value_cansleep(ctx->cd_gpio) : -				gpiod_get_raw_value(ctx->cd_gpio); -		return !value ^ !!(host->caps2 & MMC_CAP2_CD_ACTIVE_HIGH); -	} -  	return cansleep ?  		gpiod_get_value_cansleep(ctx->cd_gpio) :  		gpiod_get_value(ctx->cd_gpio); @@ -168,8 +160,6 @@ EXPORT_SYMBOL(mmc_gpio_set_cd_isr);   * @idx: index of the GPIO to obtain in the consumer   * @override_active_level: ignore %GPIO_ACTIVE_LOW flag   * @debounce: debounce time in microseconds - * @gpio_invert: will return whether the GPIO line is inverted or not, set - * to NULL to ignore   *   * Note that this must be called prior to mmc_add_host()   * otherwise the caller must also call mmc_gpiod_request_cd_irq(). @@ -178,7 +168,7 @@ EXPORT_SYMBOL(mmc_gpio_set_cd_isr);   */  int mmc_gpiod_request_cd(struct mmc_host *host, const char *con_id,  			 unsigned int idx, bool override_active_level, -			 unsigned int debounce, bool *gpio_invert) +			 unsigned int debounce)  {  	struct mmc_gpio *ctx = host->slot.handler_priv;  	struct gpio_desc *desc; @@ -194,10 +184,14 @@ int mmc_gpiod_request_cd(struct mmc_host *host, const char *con_id,  			ctx->cd_debounce_delay_ms = debounce / 1000;  	} -	if (gpio_invert) -		*gpio_invert = !gpiod_is_active_low(desc); +	/* override forces default (active-low) polarity ... */ +	if (override_active_level && !gpiod_is_active_low(desc)) +		gpiod_toggle_active_low(desc); + +	/* ... or active-high */ +	if (host->caps2 & MMC_CAP2_CD_ACTIVE_HIGH) +		gpiod_toggle_active_low(desc); -	ctx->override_cd_active_level = override_active_level;  	ctx->cd_gpio = desc;  	return 0; @@ -218,14 +212,11 @@ EXPORT_SYMBOL(mmc_can_gpio_cd);   * @con_id: function within the GPIO consumer   * @idx: index of the GPIO to obtain in the consumer   * @debounce: debounce time in microseconds - * @gpio_invert: will return whether the GPIO line is inverted or not, - * set to NULL to ignore   *   * Returns zero on success, else an error.   */  int mmc_gpiod_request_ro(struct mmc_host *host, const char *con_id, -			 unsigned int idx, -			 unsigned int debounce, bool *gpio_invert) +			 unsigned int idx, unsigned int debounce)  {  	struct mmc_gpio *ctx = host->slot.handler_priv;  	struct gpio_desc *desc; @@ -241,8 +232,8 @@ int mmc_gpiod_request_ro(struct mmc_host *host, const char *con_id,  			return ret;  	} -	if (gpio_invert) -		*gpio_invert = !gpiod_is_active_low(desc); +	if (host->caps2 & MMC_CAP2_RO_ACTIVE_HIGH) +		gpiod_toggle_active_low(desc);  	ctx->ro_gpio = desc; diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index d06b2dfe3c95..3a5089f0332c 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -501,6 +501,7 @@ config MMC_SDHCI_MSM  	depends on ARCH_QCOM || (ARM && COMPILE_TEST)  	depends on MMC_SDHCI_PLTFM  	select MMC_SDHCI_IO_ACCESSORS +	select MMC_CQHCI  	help  	  This selects the Secure Digital Host Controller Interface (SDHCI)  	  support present in Qualcomm SOCs. The controller supports @@ -990,6 +991,7 @@ config MMC_SDHCI_BRCMSTB  	tristate "Broadcom SDIO/SD/MMC support"  	depends on ARCH_BRCMSTB || BMIPS_GENERIC  	depends on MMC_SDHCI_PLTFM +	select MMC_CQHCI  	default y  	help  	  This selects support for the SDIO/SD/MMC Host Controller on @@ -1010,6 +1012,7 @@ config MMC_SDHCI_OMAP  	depends on MMC_SDHCI_PLTFM && OF  	select THERMAL  	imply TI_SOC_THERMAL +	select MMC_SDHCI_EXTERNAL_DMA if DMA_ENGINE  	help  	  This selects the Secure Digital Host Controller Interface (SDHCI)  	  support present in TI's DRA7 SOCs. The controller supports @@ -1040,3 +1043,6 @@ config MMC_OWL  	help  	  This selects support for the SD/MMC Host Controller on  	  Actions Semi Owl SoCs. + +config MMC_SDHCI_EXTERNAL_DMA +	bool diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 6f065bb5c55a..aeaaa5314924 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -2645,7 +2645,7 @@ static int atmci_runtime_resume(struct device *dev)  {  	struct atmel_mci *host = dev_get_drvdata(dev); -	pinctrl_pm_select_default_state(dev); +	pinctrl_select_default_state(dev);  	return clk_prepare_enable(host->mck);  } diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c index bc8aeb47a7b4..8823680ca42c 100644 --- a/drivers/mmc/host/au1xmmc.c +++ b/drivers/mmc/host/au1xmmc.c @@ -984,12 +984,9 @@ static int au1xmmc_probe(struct platform_device *pdev)  		goto out2;  	} -	r = platform_get_resource(pdev, IORESOURCE_IRQ, 0); -	if (!r) { -		dev_err(&pdev->dev, "no IRQ defined\n"); +	host->irq = platform_get_irq(pdev, 0); +	if (host->irq < 0)  		goto out3; -	} -	host->irq = r->start;  	mmc->ops = &au1xmmc_ops; diff --git a/drivers/mmc/host/bcm2835.c b/drivers/mmc/host/bcm2835.c index 99f61fd2a658..c3d949847cbd 100644 --- a/drivers/mmc/host/bcm2835.c +++ b/drivers/mmc/host/bcm2835.c @@ -1393,7 +1393,17 @@ static int bcm2835_probe(struct platform_device *pdev)  	host->dma_chan = NULL;  	host->dma_desc = NULL; -	host->dma_chan_rxtx = dma_request_slave_channel(dev, "rx-tx"); +	host->dma_chan_rxtx = dma_request_chan(dev, "rx-tx"); +	if (IS_ERR(host->dma_chan_rxtx)) { +		ret = PTR_ERR(host->dma_chan_rxtx); +		host->dma_chan_rxtx = NULL; + +		if (ret == -EPROBE_DEFER) +			goto err; + +		/* Ignore errors to fall back to PIO mode */ +	} +  	clk = devm_clk_get(dev, NULL);  	if (IS_ERR(clk)) { diff --git a/drivers/mmc/host/cavium-thunderx.c b/drivers/mmc/host/cavium-thunderx.c index eee08d81b242..76013bbbcff3 100644 --- a/drivers/mmc/host/cavium-thunderx.c +++ b/drivers/mmc/host/cavium-thunderx.c @@ -76,8 +76,10 @@ static int thunder_mmc_probe(struct pci_dev *pdev,  		return ret;  	host->base = pcim_iomap(pdev, 0, pci_resource_len(pdev, 0)); -	if (!host->base) -		return -EINVAL; +	if (!host->base) { +		ret = -EINVAL; +		goto error; +	}  	/* On ThunderX these are identical */  	host->dma_base = host->base; @@ -86,12 +88,14 @@ static int thunder_mmc_probe(struct pci_dev *pdev,  	host->reg_off_dma = 0x160;  	host->clk = devm_clk_get(dev, NULL); -	if (IS_ERR(host->clk)) -		return PTR_ERR(host->clk); +	if (IS_ERR(host->clk)) { +		ret = PTR_ERR(host->clk); +		goto error; +	}  	ret = clk_prepare_enable(host->clk);  	if (ret) -		return ret; +		goto error;  	host->sys_freq = clk_get_rate(host->clk);  	spin_lock_init(&host->irq_handler_lock); @@ -157,6 +161,7 @@ error:  		}  	}  	clk_disable_unprepare(host->clk); +	pci_release_regions(pdev);  	return ret;  } @@ -175,6 +180,7 @@ static void thunder_mmc_remove(struct pci_dev *pdev)  	writeq(dma_cfg, host->dma_base + MIO_EMM_DMA_CFG(host));  	clk_disable_unprepare(host->clk); +	pci_release_regions(pdev);  }  static const struct pci_device_id thunder_mmc_id_table[] = { diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c index ebfaeb33bc8c..f01fecd75833 100644 --- a/drivers/mmc/host/davinci_mmc.c +++ b/drivers/mmc/host/davinci_mmc.c @@ -1174,13 +1174,13 @@ static int mmc_davinci_parse_pdata(struct mmc_host *mmc)  		mmc->caps |= pdata->caps;  	/* Register a cd gpio, if there is not one, enable polling */ -	ret = mmc_gpiod_request_cd(mmc, "cd", 0, false, 0, NULL); +	ret = mmc_gpiod_request_cd(mmc, "cd", 0, false, 0);  	if (ret == -EPROBE_DEFER)  		return ret;  	else if (ret)  		mmc->caps |= MMC_CAP_NEEDS_POLL; -	ret = mmc_gpiod_request_ro(mmc, "wp", 0, 0, NULL); +	ret = mmc_gpiod_request_ro(mmc, "wp", 0, 0);  	if (ret == -EPROBE_DEFER)  		return ret; diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index fc9d4d000f97..bc5278ab5707 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -833,12 +833,14 @@ static int dw_mci_edmac_init(struct dw_mci *host)  	if (!host->dms)  		return -ENOMEM; -	host->dms->ch = dma_request_slave_channel(host->dev, "rx-tx"); -	if (!host->dms->ch) { +	host->dms->ch = dma_request_chan(host->dev, "rx-tx"); +	if (IS_ERR(host->dms->ch)) { +		int ret = PTR_ERR(host->dms->ch); +  		dev_err(host->dev, "Failed to get external DMA channel.\n");  		kfree(host->dms);  		host->dms = NULL; -		return -ENXIO; +		return ret;  	}  	return 0; diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c index 78383f60a3dc..fbae87d1f017 100644 --- a/drivers/mmc/host/jz4740_mmc.c +++ b/drivers/mmc/host/jz4740_mmc.c @@ -1108,7 +1108,7 @@ static int jz4740_mmc_suspend(struct device *dev)  static int jz4740_mmc_resume(struct device *dev)  { -	return pinctrl_pm_select_default_state(dev); +	return pinctrl_select_default_state(dev);  }  static SIMPLE_DEV_PM_OPS(jz4740_mmc_pm_ops, jz4740_mmc_suspend, diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c index e712315c7e8d..35400cf2a2e4 100644 --- a/drivers/mmc/host/meson-gx-mmc.c +++ b/drivers/mmc/host/meson-gx-mmc.c @@ -161,7 +161,6 @@ struct meson_host {  	bool dram_access_quirk;  	struct pinctrl *pinctrl; -	struct pinctrl_state *pins_default;  	struct pinctrl_state *pins_clk_gate;  	unsigned int bounce_buf_size; @@ -327,7 +326,7 @@ static void meson_mmc_clk_ungate(struct meson_host *host)  	u32 cfg;  	if (host->pins_clk_gate) -		pinctrl_select_state(host->pinctrl, host->pins_default); +		pinctrl_select_default_state(host->dev);  	/* Make sure the clock is not stopped in the controller */  	cfg = readl(host->regs + SD_EMMC_CFG); @@ -1101,13 +1100,6 @@ static int meson_mmc_probe(struct platform_device *pdev)  		goto free_host;  	} -	host->pins_default = pinctrl_lookup_state(host->pinctrl, -						  PINCTRL_STATE_DEFAULT); -	if (IS_ERR(host->pins_default)) { -		ret = PTR_ERR(host->pins_default); -		goto free_host; -	} -  	host->pins_clk_gate = pinctrl_lookup_state(host->pinctrl,  						   "clk-gate");  	if (IS_ERR(host->pins_clk_gate)) { diff --git a/drivers/mmc/host/meson-mx-sdio.c b/drivers/mmc/host/meson-mx-sdio.c index ba9a63db73da..8b038e7b2cd3 100644 --- a/drivers/mmc/host/meson-mx-sdio.c +++ b/drivers/mmc/host/meson-mx-sdio.c @@ -638,7 +638,6 @@ static int meson_mx_mmc_probe(struct platform_device *pdev)  	struct platform_device *slot_pdev;  	struct mmc_host *mmc;  	struct meson_mx_mmc_host *host; -	struct resource *res;  	int ret, irq;  	u32 conf; @@ -663,8 +662,7 @@ static int meson_mx_mmc_probe(struct platform_device *pdev)  	platform_set_drvdata(pdev, host); -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	host->base = devm_ioremap_resource(host->controller_dev, res); +	host->base = devm_platform_ioremap_resource(pdev, 0);  	if (IS_ERR(host->base)) {  		ret = PTR_ERR(host->base);  		goto error_free_mmc; diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c index 74c6cfbf9172..951f76dc1ddd 100644 --- a/drivers/mmc/host/mmc_spi.c +++ b/drivers/mmc/host/mmc_spi.c @@ -1134,17 +1134,22 @@ static void mmc_spi_initsequence(struct mmc_spi_host *host)  	 * SPI protocol.  Another is that when chipselect is released while  	 * the card returns BUSY status, the clock must issue several cycles  	 * with chipselect high before the card will stop driving its output. +	 * +	 * SPI_CS_HIGH means "asserted" here. In some cases like when using +	 * GPIOs for chip select, SPI_CS_HIGH is set but this will be logically +	 * inverted by gpiolib, so if we want to ascertain to drive it high +	 * we should toggle the default with an XOR as we do here.  	 */ -	host->spi->mode |= SPI_CS_HIGH; +	host->spi->mode ^= SPI_CS_HIGH;  	if (spi_setup(host->spi) != 0) {  		/* Just warn; most cards work without it. */  		dev_warn(&host->spi->dev,  				"can't change chip-select polarity\n"); -		host->spi->mode &= ~SPI_CS_HIGH; +		host->spi->mode ^= SPI_CS_HIGH;  	} else {  		mmc_spi_readbytes(host, 18); -		host->spi->mode &= ~SPI_CS_HIGH; +		host->spi->mode ^= SPI_CS_HIGH;  		if (spi_setup(host->spi) != 0) {  			/* Wot, we can't get the same setup we had before? */  			dev_err(&host->spi->dev, @@ -1421,7 +1426,7 @@ static int mmc_spi_probe(struct spi_device *spi)  	 * Index 0 is card detect  	 * Old boardfiles were specifying 1 ms as debounce  	 */ -	status = mmc_gpiod_request_cd(mmc, NULL, 0, false, 1000, NULL); +	status = mmc_gpiod_request_cd(mmc, NULL, 0, false, 1000);  	if (status == -EPROBE_DEFER)  		goto fail_add_host;  	if (!status) { @@ -1436,7 +1441,7 @@ static int mmc_spi_probe(struct spi_device *spi)  	mmc_detect_change(mmc, 0);  	/* Index 1 is write protect/read only */ -	status = mmc_gpiod_request_ro(mmc, NULL, 1, 0, NULL); +	status = mmc_gpiod_request_ro(mmc, NULL, 1, 0);  	if (status == -EPROBE_DEFER)  		goto fail_add_host;  	if (!status) diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 40e72c30ea84..e9ffce8d41ea 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -169,6 +169,8 @@ static struct variant_data variant_ux500 = {  	.cmdreg_srsp		= MCI_CPSM_RESPONSE,  	.datalength_bits	= 24,  	.datactrl_blocksz	= 11, +	.datactrl_any_blocksz	= true, +	.dma_power_of_2		= true,  	.datactrl_mask_sdio	= MCI_DPSM_ST_SDIOEN,  	.st_sdio		= true,  	.st_clkdiv		= true, @@ -202,6 +204,8 @@ static struct variant_data variant_ux500v2 = {  	.datactrl_mask_ddrmode	= MCI_DPSM_ST_DDRMODE,  	.datalength_bits	= 24,  	.datactrl_blocksz	= 11, +	.datactrl_any_blocksz	= true, +	.dma_power_of_2		= true,  	.datactrl_mask_sdio	= MCI_DPSM_ST_SDIOEN,  	.st_sdio		= true,  	.st_clkdiv		= true, @@ -261,6 +265,7 @@ static struct variant_data variant_stm32_sdmmc = {  	.datacnt_useless	= true,  	.datalength_bits	= 25,  	.datactrl_blocksz	= 14, +	.datactrl_any_blocksz	= true,  	.stm32_idmabsize_mask	= GENMASK(12, 5),  	.busy_timeout		= true,  	.busy_detect		= true, @@ -284,6 +289,7 @@ static struct variant_data variant_qcom = {  	.data_cmd_enable	= MCI_CPSM_QCOM_DATCMD,  	.datalength_bits	= 24,  	.datactrl_blocksz	= 11, +	.datactrl_any_blocksz	= true,  	.pwrreg_powerup		= MCI_PWR_UP,  	.f_max			= 208000000,  	.explicit_mclk_control	= true, @@ -452,10 +458,11 @@ static void mmci_dma_setup(struct mmci_host *host)  static int mmci_validate_data(struct mmci_host *host,  			      struct mmc_data *data)  { +	struct variant_data *variant = host->variant; +  	if (!data)  		return 0; - -	if (!is_power_of_2(data->blksz)) { +	if (!is_power_of_2(data->blksz) && !variant->datactrl_any_blocksz) {  		dev_err(mmc_dev(host->mmc),  			"unsupported block size (%d bytes)\n", data->blksz);  		return -EINVAL; @@ -520,7 +527,9 @@ static int mmci_dma_start(struct mmci_host *host, unsigned int datactrl)  		 "Submit MMCI DMA job, sglen %d blksz %04x blks %04x flags %08x\n",  		 data->sg_len, data->blksz, data->blocks, data->flags); -	host->ops->dma_start(host, &datactrl); +	ret = host->ops->dma_start(host, &datactrl); +	if (ret) +		return ret;  	/* Trigger the DMA transfer */  	mmci_write_datactrlreg(host, datactrl); @@ -706,10 +715,20 @@ int mmci_dmae_setup(struct mmci_host *host)  	host->dma_priv = dmae; -	dmae->rx_channel = dma_request_slave_channel(mmc_dev(host->mmc), -						     "rx"); -	dmae->tx_channel = dma_request_slave_channel(mmc_dev(host->mmc), -						     "tx"); +	dmae->rx_channel = dma_request_chan(mmc_dev(host->mmc), "rx"); +	if (IS_ERR(dmae->rx_channel)) { +		int ret = PTR_ERR(dmae->rx_channel); +		dmae->rx_channel = NULL; +		return ret; +	} + +	dmae->tx_channel = dma_request_chan(mmc_dev(host->mmc), "tx"); +	if (IS_ERR(dmae->tx_channel)) { +		if (PTR_ERR(dmae->tx_channel) == -EPROBE_DEFER) +			dev_warn(mmc_dev(host->mmc), +				 "Deferred probe for TX channel ignored\n"); +		dmae->tx_channel = NULL; +	}  	/*  	 * If only an RX channel is specified, the driver will @@ -888,6 +907,18 @@ static int _mmci_dmae_prep_data(struct mmci_host *host, struct mmc_data *data,  	if (data->blksz * data->blocks <= variant->fifosize)  		return -EINVAL; +	/* +	 * This is necessary to get SDIO working on the Ux500. We do not yet +	 * know if this is a bug in: +	 * - The Ux500 DMA controller (DMA40) +	 * - The MMCI DMA interface on the Ux500 +	 * some power of two blocks (such as 64 bytes) are sent regularly +	 * during SDIO traffic and those work fine so for these we enable DMA +	 * transfers. +	 */ +	if (host->variant->dma_power_of_2 && !is_power_of_2(data->blksz)) +		return -EINVAL; +  	device = chan->device;  	nr_sg = dma_map_sg(device->dev, data->sg, data->sg_len,  			   mmc_get_dma_dir(data)); @@ -938,9 +969,14 @@ int mmci_dmae_prep_data(struct mmci_host *host,  int mmci_dmae_start(struct mmci_host *host, unsigned int *datactrl)  {  	struct mmci_dmae_priv *dmae = host->dma_priv; +	int ret;  	host->dma_in_progress = true; -	dmaengine_submit(dmae->desc_current); +	ret = dma_submit_error(dmaengine_submit(dmae->desc_current)); +	if (ret < 0) { +		host->dma_in_progress = false; +		return ret; +	}  	dma_async_issue_pending(dmae->cur);  	*datactrl |= MCI_DPSM_DMAENABLE; @@ -1321,6 +1357,7 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,  	} else if (host->variant->busy_timeout && busy_resp &&  		   status & MCI_DATATIMEOUT) {  		cmd->error = -ETIMEDOUT; +		host->irq_action = IRQ_WAKE_THREAD;  	} else {  		cmd->resp[0] = readl(base + MMCIRESPONSE0);  		cmd->resp[1] = readl(base + MMCIRESPONSE1); @@ -1339,7 +1376,10 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,  				return;  			}  		} -		mmci_request_end(host, host->mrq); + +		if (host->irq_action != IRQ_WAKE_THREAD) +			mmci_request_end(host, host->mrq); +  	} else if (sbc) {  		mmci_start_command(host, host->mrq->cmd, 0);  	} else if (!host->variant->datactrl_first && @@ -1532,9 +1572,9 @@ static irqreturn_t mmci_irq(int irq, void *dev_id)  {  	struct mmci_host *host = dev_id;  	u32 status; -	int ret = 0;  	spin_lock(&host->lock); +	host->irq_action = IRQ_HANDLED;  	do {  		status = readl(host->base + MMCISTATUS); @@ -1574,12 +1614,41 @@ static irqreturn_t mmci_irq(int irq, void *dev_id)  		if (host->variant->busy_detect_flag)  			status &= ~host->variant->busy_detect_flag; -		ret = 1;  	} while (status);  	spin_unlock(&host->lock); -	return IRQ_RETVAL(ret); +	return host->irq_action; +} + +/* + * mmci_irq_thread() - A threaded IRQ handler that manages a reset of the HW. + * + * A reset is needed for some variants, where a datatimeout for a R1B request + * causes the DPSM to stay busy (non-functional). + */ +static irqreturn_t mmci_irq_thread(int irq, void *dev_id) +{ +	struct mmci_host *host = dev_id; +	unsigned long flags; + +	if (host->rst) { +		reset_control_assert(host->rst); +		udelay(2); +		reset_control_deassert(host->rst); +	} + +	spin_lock_irqsave(&host->lock, flags); +	writel(host->clk_reg, host->base + MMCICLOCK); +	writel(host->pwr_reg, host->base + MMCIPOWER); +	writel(MCI_IRQENABLE | host->variant->start_err, +	       host->base + MMCIMASK0); + +	host->irq_action = IRQ_HANDLED; +	mmci_request_end(host, host->mrq); +	spin_unlock_irqrestore(&host->lock, flags); + +	return host->irq_action;  }  static void mmci_request(struct mmc_host *mmc, struct mmc_request *mrq) @@ -1704,7 +1773,7 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)  		if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)  			pinctrl_select_state(host->pinctrl, host->pins_opendrain);  		else -			pinctrl_select_state(host->pinctrl, host->pins_default); +			pinctrl_select_default_state(mmc_dev(mmc));  	}  	/* @@ -1877,14 +1946,6 @@ static int mmci_probe(struct amba_device *dev,  			goto host_free;  		} -		host->pins_default = pinctrl_lookup_state(host->pinctrl, -							  PINCTRL_STATE_DEFAULT); -		if (IS_ERR(host->pins_default)) { -			dev_err(mmc_dev(mmc), "Can't select default pins\n"); -			ret = PTR_ERR(host->pins_default); -			goto host_free; -		} -  		host->pins_opendrain = pinctrl_lookup_state(host->pinctrl,  							    MMCI_PINCTRL_STATE_OPENDRAIN);  		if (IS_ERR(host->pins_opendrain)) { @@ -2062,17 +2123,18 @@ static int mmci_probe(struct amba_device *dev,  	 * silently of these do not exist  	 */  	if (!np) { -		ret = mmc_gpiod_request_cd(mmc, "cd", 0, false, 0, NULL); +		ret = mmc_gpiod_request_cd(mmc, "cd", 0, false, 0);  		if (ret == -EPROBE_DEFER)  			goto clk_disable; -		ret = mmc_gpiod_request_ro(mmc, "wp", 0, 0, NULL); +		ret = mmc_gpiod_request_ro(mmc, "wp", 0, 0);  		if (ret == -EPROBE_DEFER)  			goto clk_disable;  	} -	ret = devm_request_irq(&dev->dev, dev->irq[0], mmci_irq, IRQF_SHARED, -			DRIVER_NAME " (cmd)", host); +	ret = devm_request_threaded_irq(&dev->dev, dev->irq[0], mmci_irq, +					mmci_irq_thread, IRQF_SHARED, +					DRIVER_NAME " (cmd)", host);  	if (ret)  		goto clk_disable; @@ -2203,7 +2265,7 @@ static int mmci_runtime_resume(struct device *dev)  		struct mmci_host *host = mmc_priv(mmc);  		clk_prepare_enable(host->clk);  		mmci_restore(host); -		pinctrl_pm_select_default_state(dev); +		pinctrl_select_default_state(dev);  	}  	return 0; diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h index 158e1231aa23..ea6a0b5779d4 100644 --- a/drivers/mmc/host/mmci.h +++ b/drivers/mmc/host/mmci.h @@ -279,7 +279,11 @@ struct mmci_host;   * @stm32_clkdiv: true if using a STM32-specific clock divider algorithm   * @datactrl_mask_ddrmode: ddr mode mask in datactrl register.   * @datactrl_mask_sdio: SDIO enable mask in datactrl register - * @datactrl_blksz: block size in power of two + * @datactrl_blocksz: block size in power of two + * @datactrl_any_blocksz: true if block any block sizes are accepted by + *		  hardware, such as with some SDIO traffic that send + *		  odd packets. + * @dma_power_of_2: DMA only works with blocks that are a power of 2.   * @datactrl_first: true if data must be setup before send command   * @datacnt_useless: true if you could not use datacnt register to read   *		     remaining data @@ -326,6 +330,8 @@ struct variant_data {  	unsigned int		datactrl_mask_ddrmode;  	unsigned int		datactrl_mask_sdio;  	unsigned int		datactrl_blocksz; +	u8			datactrl_any_blocksz:1; +	u8			dma_power_of_2:1;  	u8			datactrl_first:1;  	u8			datacnt_useless:1;  	u8			st_sdio:1; @@ -404,7 +410,6 @@ struct mmci_host {  	struct mmci_host_ops	*ops;  	struct variant_data	*variant;  	struct pinctrl		*pinctrl; -	struct pinctrl_state	*pins_default;  	struct pinctrl_state	*pins_opendrain;  	u8			hw_designer; @@ -412,6 +417,7 @@ struct mmci_host {  	struct timer_list	timer;  	unsigned int		oldstat; +	u32			irq_action;  	/* pio stuff */  	struct sg_mapping_iter	sg_miter; diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c index 010fe29a4888..7726dcf48f2c 100644 --- a/drivers/mmc/host/mtk-sd.c +++ b/drivers/mmc/host/mtk-sd.c @@ -2194,8 +2194,7 @@ static int msdc_drv_probe(struct platform_device *pdev)  	if (ret)  		goto host_free; -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	host->base = devm_ioremap_resource(&pdev->dev, res); +	host->base = devm_platform_ioremap_resource(pdev, 0);  	if (IS_ERR(host->base)) {  		ret = PTR_ERR(host->base);  		goto host_free; diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c index 74a0a7fbbf7f..203b61712601 100644 --- a/drivers/mmc/host/mvsdio.c +++ b/drivers/mmc/host/mvsdio.c @@ -696,16 +696,14 @@ static int mvsd_probe(struct platform_device *pdev)  	struct mmc_host *mmc = NULL;  	struct mvsd_host *host = NULL;  	const struct mbus_dram_target_info *dram; -	struct resource *r;  	int ret, irq;  	if (!np) {  		dev_err(&pdev->dev, "no DT node\n");  		return -ENODEV;  	} -	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	irq = platform_get_irq(pdev, 0); -	if (!r || irq < 0) +	if (irq < 0)  		return -ENXIO;  	mmc = mmc_alloc_host(sizeof(struct mvsd_host), &pdev->dev); @@ -758,7 +756,7 @@ static int mvsd_probe(struct platform_device *pdev)  	spin_lock_init(&host->lock); -	host->base = devm_ioremap_resource(&pdev->dev, r); +	host->base = devm_platform_ioremap_resource(pdev, 0);  	if (IS_ERR(host->base)) {  		ret = PTR_ERR(host->base);  		goto out; diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index 011b59a3602e..b3d654c688e5 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c @@ -1121,7 +1121,16 @@ static int mxcmci_probe(struct platform_device *pdev)  	mxcmci_writel(host, host->default_irq_mask, MMC_REG_INT_CNTR);  	if (!host->pdata) { -		host->dma = dma_request_slave_channel(&pdev->dev, "rx-tx"); +		host->dma = dma_request_chan(&pdev->dev, "rx-tx"); +		if (IS_ERR(host->dma)) { +			if (PTR_ERR(host->dma) == -EPROBE_DEFER) { +				ret = -EPROBE_DEFER; +				goto out_clk_put; +			} + +			/* Ignore errors to fall back to PIO mode */ +			host->dma = NULL; +		}  	} else {  		res = platform_get_resource(pdev, IORESOURCE_DMA, 0);  		if (res) { diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c index 4031217d21c3..d82674aed447 100644 --- a/drivers/mmc/host/mxs-mmc.c +++ b/drivers/mmc/host/mxs-mmc.c @@ -623,11 +623,11 @@ static int mxs_mmc_probe(struct platform_device *pdev)  		goto out_clk_disable;  	} -	ssp->dmach = dma_request_slave_channel(&pdev->dev, "rx-tx"); -	if (!ssp->dmach) { +	ssp->dmach = dma_request_chan(&pdev->dev, "rx-tx"); +	if (IS_ERR(ssp->dmach)) {  		dev_err(mmc_dev(host->mmc),  			"%s: failed to request dma\n", __func__); -		ret = -ENODEV; +		ret = PTR_ERR(ssp->dmach);  		goto out_clk_disable;  	} diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 767e964ca5a2..a379c45b985c 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -1605,12 +1605,6 @@ static int omap_hsmmc_configure_wake_irq(struct omap_hsmmc_host *host)  			ret = PTR_ERR(p);  			goto err_free_irq;  		} -		if (IS_ERR(pinctrl_lookup_state(p, PINCTRL_STATE_DEFAULT))) { -			dev_info(host->dev, "missing default pinctrl state\n"); -			devm_pinctrl_put(p); -			ret = -EINVAL; -			goto err_free_irq; -		}  		if (IS_ERR(pinctrl_lookup_state(p, PINCTRL_STATE_IDLE))) {  			dev_info(host->dev, "missing idle pinctrl state\n"); @@ -2153,14 +2147,14 @@ static int omap_hsmmc_runtime_resume(struct device *dev)  	if ((host->mmc->caps & MMC_CAP_SDIO_IRQ) &&  	    (host->flags & HSMMC_SDIO_IRQ_ENABLED)) { -		pinctrl_pm_select_default_state(host->dev); +		pinctrl_select_default_state(host->dev);  		/* irq lost, if pinmux incorrect */  		OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);  		OMAP_HSMMC_WRITE(host->base, ISE, CIRQ_EN);  		OMAP_HSMMC_WRITE(host->base, IE, CIRQ_EN);  	} else { -		pinctrl_pm_select_default_state(host->dev); +		pinctrl_select_default_state(host->dev);  	}  	spin_unlock_irqrestore(&host->irq_lock, flags);  	return 0; diff --git a/drivers/mmc/host/owl-mmc.c b/drivers/mmc/host/owl-mmc.c index 771e3d00f1bb..01ffe51f413d 100644 --- a/drivers/mmc/host/owl-mmc.c +++ b/drivers/mmc/host/owl-mmc.c @@ -616,10 +616,10 @@ static int owl_mmc_probe(struct platform_device *pdev)  	pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);  	pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask; -	owl_host->dma = dma_request_slave_channel(&pdev->dev, "mmc"); -	if (!owl_host->dma) { +	owl_host->dma = dma_request_chan(&pdev->dev, "mmc"); +	if (IS_ERR(owl_host->dma)) {  		dev_err(owl_host->dev, "Failed to get external DMA channel.\n"); -		ret = -ENXIO; +		ret = PTR_ERR(owl_host->dma);  		goto err_free_host;  	} diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index 024acc1b0a2e..3a9333475a2b 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c @@ -710,17 +710,19 @@ static int pxamci_probe(struct platform_device *pdev)  	platform_set_drvdata(pdev, mmc); -	host->dma_chan_rx = dma_request_slave_channel(dev, "rx"); -	if (host->dma_chan_rx == NULL) { +	host->dma_chan_rx = dma_request_chan(dev, "rx"); +	if (IS_ERR(host->dma_chan_rx)) {  		dev_err(dev, "unable to request rx dma channel\n"); -		ret = -ENODEV; +		ret = PTR_ERR(host->dma_chan_rx); +		host->dma_chan_rx = NULL;  		goto out;  	} -	host->dma_chan_tx = dma_request_slave_channel(dev, "tx"); -	if (host->dma_chan_tx == NULL) { +	host->dma_chan_tx = dma_request_chan(dev, "tx"); +	if (IS_ERR(host->dma_chan_tx)) {  		dev_err(dev, "unable to request tx dma channel\n"); -		ret = -ENODEV; +		ret = PTR_ERR(host->dma_chan_tx); +		host->dma_chan_tx = NULL;  		goto out;  	} @@ -734,22 +736,22 @@ static int pxamci_probe(struct platform_device *pdev)  		}  		/* FIXME: should we pass detection delay to debounce? */ -		ret = mmc_gpiod_request_cd(mmc, "cd", 0, false, 0, NULL); +		ret = mmc_gpiod_request_cd(mmc, "cd", 0, false, 0);  		if (ret && ret != -ENOENT) {  			dev_err(dev, "Failed requesting gpio_cd\n");  			goto out;  		} -		ret = mmc_gpiod_request_ro(mmc, "wp", 0, 0, NULL); +		if (!host->pdata->gpio_card_ro_invert) +			mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; + +		ret = mmc_gpiod_request_ro(mmc, "wp", 0, 0);  		if (ret && ret != -ENOENT) {  			dev_err(dev, "Failed requesting gpio_ro\n");  			goto out;  		} -		if (!ret) { +		if (!ret)  			host->use_ro_gpio = true; -			mmc->caps2 |= host->pdata->gpio_card_ro_invert ? -				0 : MMC_CAP2_RO_ACTIVE_HIGH; -		}  		if (host->pdata->init)  			host->pdata->init(dev, pxamci_detect_irq, mmc); diff --git a/drivers/mmc/host/renesas_sdhi.h b/drivers/mmc/host/renesas_sdhi.h index c0504aa90857..f524251d5113 100644 --- a/drivers/mmc/host/renesas_sdhi.h +++ b/drivers/mmc/host/renesas_sdhi.h @@ -14,8 +14,8 @@  struct renesas_sdhi_scc {  	unsigned long clk_rate;	/* clock rate for SDR104 */ -	u32 tap;		/* sampling clock position for SDR104 */ -	u32 tap_hs400;		/* sampling clock position for HS400 */ +	u32 tap;		/* sampling clock position for SDR104/HS400 (8 TAP) */ +	u32 tap_hs400_4tap;	/* sampling clock position for HS400 (4 TAP) */  };  struct renesas_sdhi_of_data { @@ -33,6 +33,11 @@ struct renesas_sdhi_of_data {  	unsigned short max_segs;  }; +struct renesas_sdhi_quirks { +	bool hs400_disabled; +	bool hs400_4taps; +}; +  struct tmio_mmc_dma {  	enum dma_slave_buswidth dma_buswidth;  	bool (*filter)(struct dma_chan *chan, void *arg); @@ -46,6 +51,7 @@ struct renesas_sdhi {  	struct clk *clk_cd;  	struct tmio_mmc_data mmc_data;  	struct tmio_mmc_dma dma_priv; +	const struct renesas_sdhi_quirks *quirks;  	struct pinctrl *pinctrl;  	struct pinctrl_state *pins_default, *pins_uhs;  	void __iomem *scc_ctl; diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index 234551a68739..35cb24cd45b4 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -46,11 +46,6 @@  #define SDHI_VER_GEN3_SD	0xcc10  #define SDHI_VER_GEN3_SDMMC	0xcd10 -struct renesas_sdhi_quirks { -	bool hs400_disabled; -	bool hs400_4taps; -}; -  static void renesas_sdhi_sdbuf_width(struct tmio_mmc_host *host, int width)  {  	u32 val; @@ -355,7 +350,7 @@ static void renesas_sdhi_hs400_complete(struct tmio_mmc_host *host)  		       0x4 << SH_MOBILE_SDHI_SCC_DTCNTL_TAPNUM_SHIFT); -	if (host->pdata->flags & TMIO_MMC_HAVE_4TAP_HS400) +	if (priv->quirks && priv->quirks->hs400_4taps)  		sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TAPSET,  			       host->tap_set / 2); @@ -493,7 +488,7 @@ static int renesas_sdhi_select_tuning(struct tmio_mmc_host *host)  static bool renesas_sdhi_check_scc_error(struct tmio_mmc_host *host)  {  	struct renesas_sdhi *priv = host_to_priv(host); -	bool use_4tap = host->pdata->flags & TMIO_MMC_HAVE_4TAP_HS400; +	bool use_4tap = priv->quirks && priv->quirks->hs400_4taps;  	/*  	 * Skip checking SCC errors when running on 4 taps in HS400 mode as @@ -627,10 +622,10 @@ static const struct renesas_sdhi_quirks sdhi_quirks_nohs400 = {  };  static const struct soc_device_attribute sdhi_quirks_match[]  = { +	{ .soc_id = "r8a774a1", .revision = "ES1.[012]", .data = &sdhi_quirks_4tap_nohs400 },  	{ .soc_id = "r8a7795", .revision = "ES1.*", .data = &sdhi_quirks_4tap_nohs400 },  	{ .soc_id = "r8a7795", .revision = "ES2.0", .data = &sdhi_quirks_4tap },  	{ .soc_id = "r8a7796", .revision = "ES1.[012]", .data = &sdhi_quirks_4tap_nohs400 }, -	{ .soc_id = "r8a774a1", .revision = "ES1.[012]", .data = &sdhi_quirks_4tap_nohs400 },  	{ .soc_id = "r8a77980", .data = &sdhi_quirks_nohs400 },  	{ /* Sentinel. */ },  }; @@ -665,6 +660,7 @@ int renesas_sdhi_probe(struct platform_device *pdev,  	if (!priv)  		return -ENOMEM; +	priv->quirks = quirks;  	mmc_data = &priv->mmc_data;  	dma_priv = &priv->dma_priv; @@ -724,9 +720,6 @@ int renesas_sdhi_probe(struct platform_device *pdev,  	if (quirks && quirks->hs400_disabled)  		host->mmc->caps2 &= ~(MMC_CAP2_HS400 | MMC_CAP2_HS400_ES); -	if (quirks && quirks->hs400_4taps) -		mmc_data->flags |= TMIO_MMC_HAVE_4TAP_HS400; -  	/* For some SoC, we disable internal WP. GPIO may override this */  	if (mmc_can_gpio_ro(host->mmc))  		mmc_data->capabilities2 &= ~MMC_CAP2_NO_WRITE_PROTECT; @@ -800,20 +793,23 @@ int renesas_sdhi_probe(struct platform_device *pdev,  	     host->mmc->caps2 & (MMC_CAP2_HS200_1_8V_SDR |  				 MMC_CAP2_HS400_1_8V))) {  		const struct renesas_sdhi_scc *taps = of_data->taps; +		bool use_4tap = priv->quirks && priv->quirks->hs400_4taps;  		bool hit = false;  		for (i = 0; i < of_data->taps_num; i++) {  			if (taps[i].clk_rate == 0 ||  			    taps[i].clk_rate == host->mmc->f_max) {  				priv->scc_tappos = taps->tap; -				priv->scc_tappos_hs400 = taps->tap_hs400; +				priv->scc_tappos_hs400 = use_4tap ? +							 taps->tap_hs400_4tap : +							 taps->tap;  				hit = true;  				break;  			}  		}  		if (!hit) -			dev_warn(&host->pdev->dev, "Unknown clock rate for SDR104\n"); +			dev_warn(&host->pdev->dev, "Unknown clock rate for tuning\n");  		host->init_tuning = renesas_sdhi_init_tuning;  		host->prepare_tuning = renesas_sdhi_prepare_tuning; diff --git a/drivers/mmc/host/renesas_sdhi_internal_dmac.c b/drivers/mmc/host/renesas_sdhi_internal_dmac.c index 18839a10594c..47ac53e91241 100644 --- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c +++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c @@ -82,7 +82,7 @@ static struct renesas_sdhi_scc rcar_gen3_scc_taps[] = {  	{  		.clk_rate = 0,  		.tap = 0x00000300, -		.tap_hs400 = 0x00000704, +		.tap_hs400_4tap = 0x00000100,  	},  }; @@ -298,38 +298,23 @@ static const struct tmio_mmc_dma_ops renesas_sdhi_internal_dmac_dma_ops = {   * Whitelist of specific R-Car Gen3 SoC ES versions to use this DMAC   * implementation as others may use a different implementation.   */ -static const struct soc_device_attribute soc_whitelist[] = { -	/* specific ones */ +static const struct soc_device_attribute soc_dma_quirks[] = {  	{ .soc_id = "r7s9210",  	  .data = (void *)BIT(SDHI_INTERNAL_DMAC_ADDR_MODE_FIXED_ONLY) },  	{ .soc_id = "r8a7795", .revision = "ES1.*",  	  .data = (void *)BIT(SDHI_INTERNAL_DMAC_ONE_RX_ONLY) },  	{ .soc_id = "r8a7796", .revision = "ES1.0",  	  .data = (void *)BIT(SDHI_INTERNAL_DMAC_ONE_RX_ONLY) }, -	/* generic ones */ -	{ .soc_id = "r8a774a1" }, -	{ .soc_id = "r8a774b1" }, -	{ .soc_id = "r8a774c0" }, -	{ .soc_id = "r8a77470" }, -	{ .soc_id = "r8a7795" }, -	{ .soc_id = "r8a7796" }, -	{ .soc_id = "r8a77965" }, -	{ .soc_id = "r8a77970" }, -	{ .soc_id = "r8a77980" }, -	{ .soc_id = "r8a77990" }, -	{ .soc_id = "r8a77995" },  	{ /* sentinel */ }  };  static int renesas_sdhi_internal_dmac_probe(struct platform_device *pdev)  { -	const struct soc_device_attribute *soc = soc_device_match(soc_whitelist); +	const struct soc_device_attribute *soc = soc_device_match(soc_dma_quirks);  	struct device *dev = &pdev->dev; -	if (!soc) -		return -ENODEV; - -	global_flags |= (unsigned long)soc->data; +	if (soc) +		global_flags |= (unsigned long)soc->data;  	dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms), GFP_KERNEL);  	if (!dev->dma_parms) diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c index bce9c33bc4b5..1e616ae56b13 100644 --- a/drivers/mmc/host/s3cmci.c +++ b/drivers/mmc/host/s3cmci.c @@ -1505,14 +1505,14 @@ static int s3cmci_probe_pdata(struct s3cmci_host *host)  		mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH;  	/* If we get -ENOENT we have no card detect GPIO line */ -	ret = mmc_gpiod_request_cd(mmc, "cd", 0, false, 0, NULL); +	ret = mmc_gpiod_request_cd(mmc, "cd", 0, false, 0);  	if (ret != -ENOENT) {  		dev_err(&pdev->dev, "error requesting GPIO for CD %d\n",  			ret);  		return ret;  	} -	ret = mmc_gpiod_request_ro(host->mmc, "wp", 0, 0, NULL); +	ret = mmc_gpiod_request_ro(host->mmc, "wp", 0, 0);  	if (ret != -ENOENT) {  		dev_err(&pdev->dev, "error requesting GPIO for WP %d\n",  			ret); diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c index 105e73d4a3b9..9651dca6863e 100644 --- a/drivers/mmc/host/sdhci-acpi.c +++ b/drivers/mmc/host/sdhci-acpi.c @@ -719,7 +719,7 @@ static int sdhci_acpi_probe(struct platform_device *pdev)  		goto err_free;  	} -	host->ioaddr = devm_ioremap_nocache(dev, iomem->start, +	host->ioaddr = devm_ioremap(dev, iomem->start,  					    resource_size(iomem));  	if (host->ioaddr == NULL) {  		err = -ENOMEM; @@ -752,7 +752,7 @@ static int sdhci_acpi_probe(struct platform_device *pdev)  	if (sdhci_acpi_flag(c, SDHCI_ACPI_SD_CD)) {  		bool v = sdhci_acpi_flag(c, SDHCI_ACPI_SD_CD_OVERRIDE_LEVEL); -		err = mmc_gpiod_request_cd(host->mmc, NULL, 0, v, 0, NULL); +		err = mmc_gpiod_request_cd(host->mmc, NULL, 0, v, 0);  		if (err) {  			if (err == -EPROBE_DEFER)  				goto err_free; diff --git a/drivers/mmc/host/sdhci-brcmstb.c b/drivers/mmc/host/sdhci-brcmstb.c index 73bb440aaf93..ad01f6451a95 100644 --- a/drivers/mmc/host/sdhci-brcmstb.c +++ b/drivers/mmc/host/sdhci-brcmstb.c @@ -9,29 +9,236 @@  #include <linux/mmc/host.h>  #include <linux/module.h>  #include <linux/of.h> +#include <linux/bitops.h> +#include <linux/delay.h>  #include "sdhci-pltfm.h" +#include "cqhci.h" -static const struct sdhci_ops sdhci_brcmstb_ops = { +#define SDHCI_VENDOR 0x78 +#define  SDHCI_VENDOR_ENHANCED_STRB 0x1 + +#define BRCMSTB_PRIV_FLAGS_NO_64BIT		BIT(0) +#define BRCMSTB_PRIV_FLAGS_BROKEN_TIMEOUT	BIT(1) + +#define SDHCI_ARASAN_CQE_BASE_ADDR		0x200 + +struct sdhci_brcmstb_priv { +	void __iomem *cfg_regs; +	bool has_cqe; +}; + +struct brcmstb_match_priv { +	void (*hs400es)(struct mmc_host *mmc, struct mmc_ios *ios); +	struct sdhci_ops *ops; +	unsigned int flags; +}; + +static void sdhci_brcmstb_hs400es(struct mmc_host *mmc, struct mmc_ios *ios) +{ +	struct sdhci_host *host = mmc_priv(mmc); + +	u32 reg; + +	dev_dbg(mmc_dev(mmc), "%s(): Setting HS400-Enhanced-Strobe mode\n", +		__func__); +	reg = readl(host->ioaddr + SDHCI_VENDOR); +	if (ios->enhanced_strobe) +		reg |= SDHCI_VENDOR_ENHANCED_STRB; +	else +		reg &= ~SDHCI_VENDOR_ENHANCED_STRB; +	writel(reg, host->ioaddr + SDHCI_VENDOR); +} + +static void sdhci_brcmstb_set_clock(struct sdhci_host *host, unsigned int clock) +{ +	u16 clk; + +	host->mmc->actual_clock = 0; + +	clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock); +	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); + +	if (clock == 0) +		return; + +	sdhci_enable_clk(host, clk); +} + +static void sdhci_brcmstb_set_uhs_signaling(struct sdhci_host *host, +					    unsigned int timing) +{ +	u16 ctrl_2; + +	dev_dbg(mmc_dev(host->mmc), "%s: Setting UHS signaling for %d timing\n", +		__func__, timing); +	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_SD_HS || +		 timing == MMC_TIMING_MMC_HS || +		 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; +	else if (timing == MMC_TIMING_MMC_HS400) +		ctrl_2 |= SDHCI_CTRL_HS400; /* Non-standard */ +	sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); +} + +static void sdhci_brcmstb_dumpregs(struct mmc_host *mmc) +{ +	sdhci_dumpregs(mmc_priv(mmc)); +} + +static void sdhci_brcmstb_cqe_enable(struct mmc_host *mmc) +{ +	struct sdhci_host *host = mmc_priv(mmc); +	u32 reg; + +	reg = sdhci_readl(host, SDHCI_PRESENT_STATE); +	while (reg & SDHCI_DATA_AVAILABLE) { +		sdhci_readl(host, SDHCI_BUFFER); +		reg = sdhci_readl(host, SDHCI_PRESENT_STATE); +	} + +	sdhci_cqe_enable(mmc); +} + +static const struct cqhci_host_ops sdhci_brcmstb_cqhci_ops = { +	.enable         = sdhci_brcmstb_cqe_enable, +	.disable        = sdhci_cqe_disable, +	.dumpregs       = sdhci_brcmstb_dumpregs, +}; + +static struct sdhci_ops sdhci_brcmstb_ops = {  	.set_clock = sdhci_set_clock,  	.set_bus_width = sdhci_set_bus_width,  	.reset = sdhci_reset,  	.set_uhs_signaling = sdhci_set_uhs_signaling,  }; -static const struct sdhci_pltfm_data sdhci_brcmstb_pdata = { +static struct sdhci_ops sdhci_brcmstb_ops_7216 = { +	.set_clock = sdhci_brcmstb_set_clock, +	.set_bus_width = sdhci_set_bus_width, +	.reset = sdhci_reset, +	.set_uhs_signaling = sdhci_brcmstb_set_uhs_signaling, +}; + +static struct brcmstb_match_priv match_priv_7425 = { +	.flags = BRCMSTB_PRIV_FLAGS_NO_64BIT | +	BRCMSTB_PRIV_FLAGS_BROKEN_TIMEOUT,  	.ops = &sdhci_brcmstb_ops,  }; +static struct brcmstb_match_priv match_priv_7445 = { +	.flags = BRCMSTB_PRIV_FLAGS_BROKEN_TIMEOUT, +	.ops = &sdhci_brcmstb_ops, +}; + +static const struct brcmstb_match_priv match_priv_7216 = { +	.hs400es = sdhci_brcmstb_hs400es, +	.ops = &sdhci_brcmstb_ops_7216, +}; + +static const struct of_device_id sdhci_brcm_of_match[] = { +	{ .compatible = "brcm,bcm7425-sdhci", .data = &match_priv_7425 }, +	{ .compatible = "brcm,bcm7445-sdhci", .data = &match_priv_7445 }, +	{ .compatible = "brcm,bcm7216-sdhci", .data = &match_priv_7216 }, +	{}, +}; + +static u32 sdhci_brcmstb_cqhci_irq(struct sdhci_host *host, u32 intmask) +{ +	int cmd_error = 0; +	int data_error = 0; + +	if (!sdhci_cqe_irq(host, intmask, &cmd_error, &data_error)) +		return intmask; + +	cqhci_irq(host->mmc, intmask, cmd_error, data_error); + +	return 0; +} + +static int sdhci_brcmstb_add_host(struct sdhci_host *host, +				  struct sdhci_brcmstb_priv *priv) +{ +	struct cqhci_host *cq_host; +	bool dma64; +	int ret; + +	if (!priv->has_cqe) +		return sdhci_add_host(host); + +	dev_dbg(mmc_dev(host->mmc), "CQE is enabled\n"); +	host->mmc->caps2 |= MMC_CAP2_CQE | MMC_CAP2_CQE_DCMD; +	ret = sdhci_setup_host(host); +	if (ret) +		return ret; + +	cq_host = devm_kzalloc(mmc_dev(host->mmc), +			       sizeof(*cq_host), GFP_KERNEL); +	if (!cq_host) { +		ret = -ENOMEM; +		goto cleanup; +	} + +	cq_host->mmio = host->ioaddr + SDHCI_ARASAN_CQE_BASE_ADDR; +	cq_host->ops = &sdhci_brcmstb_cqhci_ops; + +	dma64 = host->flags & SDHCI_USE_64_BIT_DMA; +	if (dma64) { +		dev_dbg(mmc_dev(host->mmc), "Using 64 bit DMA\n"); +		cq_host->caps |= CQHCI_TASK_DESC_SZ_128; +		cq_host->quirks |= CQHCI_QUIRK_SHORT_TXFR_DESC_SZ; +	} + +	ret = cqhci_init(cq_host, host->mmc, dma64); +	if (ret) +		goto cleanup; + +	ret = __sdhci_add_host(host); +	if (ret) +		goto cleanup; + +	return 0; + +cleanup: +	sdhci_cleanup_host(host); +	return ret; +} +  static int sdhci_brcmstb_probe(struct platform_device *pdev)  { -	struct sdhci_host *host; +	const struct brcmstb_match_priv *match_priv; +	struct sdhci_pltfm_data brcmstb_pdata;  	struct sdhci_pltfm_host *pltfm_host; +	const struct of_device_id *match; +	struct sdhci_brcmstb_priv *priv; +	struct sdhci_host *host; +	struct resource *iomem; +	bool has_cqe = false;  	struct clk *clk;  	int res; +	match = of_match_node(sdhci_brcm_of_match, pdev->dev.of_node); +	match_priv = match->data; + +	dev_dbg(&pdev->dev, "Probe found match for %s\n",  match->compatible); +  	clk = devm_clk_get(&pdev->dev, NULL);  	if (IS_ERR(clk)) { +		if (PTR_ERR(clk) == -EPROBE_DEFER) +			return -EPROBE_DEFER;  		dev_err(&pdev->dev, "Clock not found in Device Tree\n");  		clk = NULL;  	} @@ -39,36 +246,64 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)  	if (res)  		return res; -	host = sdhci_pltfm_init(pdev, &sdhci_brcmstb_pdata, 0); +	memset(&brcmstb_pdata, 0, sizeof(brcmstb_pdata)); +	if (device_property_read_bool(&pdev->dev, "supports-cqe")) { +		has_cqe = true; +		match_priv->ops->irq = sdhci_brcmstb_cqhci_irq; +	} +	brcmstb_pdata.ops = match_priv->ops; +	host = sdhci_pltfm_init(pdev, &brcmstb_pdata, +				sizeof(struct sdhci_brcmstb_priv));  	if (IS_ERR(host)) {  		res = PTR_ERR(host);  		goto err_clk;  	} +	pltfm_host = sdhci_priv(host); +	priv = sdhci_pltfm_priv(pltfm_host); +	priv->has_cqe = has_cqe; + +	/* Map in the non-standard CFG registers */ +	iomem = platform_get_resource(pdev, IORESOURCE_MEM, 1); +	priv->cfg_regs = devm_ioremap_resource(&pdev->dev, iomem); +	if (IS_ERR(priv->cfg_regs)) { +		res = PTR_ERR(priv->cfg_regs); +		goto err; +	} +  	sdhci_get_of_property(pdev);  	res = mmc_of_parse(host->mmc);  	if (res)  		goto err;  	/* +	 * If the chip has enhanced strobe and it's enabled, add +	 * callback +	 */ +	if (match_priv->hs400es && +	    (host->mmc->caps2 & MMC_CAP2_HS400_ES)) +		host->mmc_host_ops.hs400_enhanced_strobe = match_priv->hs400es; + +	/*  	 * Supply the existing CAPS, but clear the UHS modes. This  	 * will allow these modes to be specified by device tree  	 * properties through mmc_of_parse().  	 */  	host->caps = sdhci_readl(host, SDHCI_CAPABILITIES); -	if (of_device_is_compatible(pdev->dev.of_node, "brcm,bcm7425-sdhci")) +	if (match_priv->flags & BRCMSTB_PRIV_FLAGS_NO_64BIT)  		host->caps &= ~SDHCI_CAN_64BIT;  	host->caps1 = sdhci_readl(host, SDHCI_CAPABILITIES_1);  	host->caps1 &= ~(SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_SDR104 | -			SDHCI_SUPPORT_DDR50); -	host->quirks |= SDHCI_QUIRK_MISSING_CAPS | -		SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; +			 SDHCI_SUPPORT_DDR50); +	host->quirks |= SDHCI_QUIRK_MISSING_CAPS; + +	if (match_priv->flags & BRCMSTB_PRIV_FLAGS_BROKEN_TIMEOUT) +		host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; -	res = sdhci_add_host(host); +	res = sdhci_brcmstb_add_host(host, priv);  	if (res)  		goto err; -	pltfm_host = sdhci_priv(host);  	pltfm_host->clk = clk;  	return res; @@ -79,11 +314,15 @@ err_clk:  	return res;  } -static const struct of_device_id sdhci_brcm_of_match[] = { -	{ .compatible = "brcm,bcm7425-sdhci" }, -	{ .compatible = "brcm,bcm7445-sdhci" }, -	{}, -}; +static void sdhci_brcmstb_shutdown(struct platform_device *pdev) +{ +	int ret; + +	ret = sdhci_pltfm_unregister(pdev); +	if (ret) +		dev_err(&pdev->dev, "failed to shutdown\n"); +} +  MODULE_DEVICE_TABLE(of, sdhci_brcm_of_match);  static struct platform_driver sdhci_brcmstb_driver = { @@ -94,6 +333,7 @@ static struct platform_driver sdhci_brcmstb_driver = {  	},  	.probe		= sdhci_brcmstb_probe,  	.remove		= sdhci_pltfm_unregister, +	.shutdown	= sdhci_brcmstb_shutdown,  };  module_platform_driver(sdhci_brcmstb_driver); diff --git a/drivers/mmc/host/sdhci-cadence.c b/drivers/mmc/host/sdhci-cadence.c index ae0ec27dd7cc..5827d3751b81 100644 --- a/drivers/mmc/host/sdhci-cadence.c +++ b/drivers/mmc/host/sdhci-cadence.c @@ -158,7 +158,7 @@ static int sdhci_cdns_phy_init(struct sdhci_cdns_priv *priv)  	return 0;  } -static inline void *sdhci_cdns_priv(struct sdhci_host *host) +static void *sdhci_cdns_priv(struct sdhci_host *host)  {  	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 1c988d6a2433..382f25b2fa45 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -224,7 +224,6 @@ static struct esdhc_soc_data usdhc_imx8qxp_data = {  struct pltfm_imx_data {  	u32 scratchpad;  	struct pinctrl *pinctrl; -	struct pinctrl_state *pins_default;  	struct pinctrl_state *pins_100mhz;  	struct pinctrl_state *pins_200mhz;  	const struct esdhc_soc_data *socdata; @@ -951,7 +950,6 @@ static int esdhc_change_pinstate(struct sdhci_host *host,  	dev_dbg(mmc_dev(host->mmc), "change pinctrl state for uhs %d\n", uhs);  	if (IS_ERR(imx_data->pinctrl) || -		IS_ERR(imx_data->pins_default) ||  		IS_ERR(imx_data->pins_100mhz) ||  		IS_ERR(imx_data->pins_200mhz))  		return -EINVAL; @@ -968,7 +966,7 @@ static int esdhc_change_pinstate(struct sdhci_host *host,  		break;  	default:  		/* back to default state for other legacy timing */ -		pinctrl = imx_data->pins_default; +		return pinctrl_select_default_state(mmc_dev(host->mmc));  	}  	return pinctrl_select_state(imx_data->pinctrl, pinctrl); @@ -1338,7 +1336,7 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,  	mmc_of_parse_voltage(np, &host->ocr_mask); -	if (esdhc_is_usdhc(imx_data) && !IS_ERR(imx_data->pins_default)) { +	if (esdhc_is_usdhc(imx_data)) {  		imx_data->pins_100mhz = pinctrl_lookup_state(imx_data->pinctrl,  						ESDHC_PINCTRL_STATE_100MHZ);  		imx_data->pins_200mhz = pinctrl_lookup_state(imx_data->pinctrl, @@ -1381,19 +1379,20 @@ static int sdhci_esdhc_imx_probe_nondt(struct platform_device *pdev,  				host->mmc->parent->platform_data);  	/* write_protect */  	if (boarddata->wp_type == ESDHC_WP_GPIO) { -		err = mmc_gpiod_request_ro(host->mmc, "wp", 0, 0, NULL); +		host->mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; + +		err = mmc_gpiod_request_ro(host->mmc, "wp", 0, 0);  		if (err) {  			dev_err(mmc_dev(host->mmc),  				"failed to request write-protect gpio!\n");  			return err;  		} -		host->mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH;  	}  	/* card_detect */  	switch (boarddata->cd_type) {  	case ESDHC_CD_GPIO: -		err = mmc_gpiod_request_cd(host->mmc, "cd", 0, false, 0, NULL); +		err = mmc_gpiod_request_cd(host->mmc, "cd", 0, false, 0);  		if (err) {  			dev_err(mmc_dev(host->mmc),  				"failed to request card-detect gpio!\n"); @@ -1492,11 +1491,6 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)  		goto disable_ahb_clk;  	} -	imx_data->pins_default = pinctrl_lookup_state(imx_data->pinctrl, -						PINCTRL_STATE_DEFAULT); -	if (IS_ERR(imx_data->pins_default)) -		dev_warn(mmc_dev(host->mmc), "could not get default state\n"); -  	if (esdhc_is_usdhc(imx_data)) {  		host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN;  		host->mmc->caps |= MMC_CAP_1_8V_DDR | MMC_CAP_3_3V_DDR; diff --git a/drivers/mmc/host/sdhci-milbeaut.c b/drivers/mmc/host/sdhci-milbeaut.c index a1aa21b9ae1c..92f30a1db435 100644 --- a/drivers/mmc/host/sdhci-milbeaut.c +++ b/drivers/mmc/host/sdhci-milbeaut.c @@ -242,15 +242,12 @@ static int sdhci_milbeaut_probe(struct platform_device *pdev)  {  	struct sdhci_host *host;  	struct device *dev = &pdev->dev; -	struct resource *res;  	int irq, ret = 0;  	struct f_sdhost_priv *priv;  	irq = platform_get_irq(pdev, 0); -	if (irq < 0) { -		dev_err(dev, "%s: no irq specified\n", __func__); +	if (irq < 0)  		return irq; -	}  	host = sdhci_alloc_host(dev, sizeof(struct f_sdhost_priv));  	if (IS_ERR(host)) @@ -280,8 +277,7 @@ static int sdhci_milbeaut_probe(struct platform_device *pdev)  	host->ops = &sdhci_milbeaut_ops;  	host->irq = irq; -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	host->ioaddr = devm_ioremap_resource(&pdev->dev, res); +	host->ioaddr = devm_platform_ioremap_resource(pdev, 0);  	if (IS_ERR(host->ioaddr)) {  		ret = PTR_ERR(host->ioaddr);  		goto err; diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index 3d0bb5e2e09b..c3a160c18047 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -15,6 +15,7 @@  #include <linux/regulator/consumer.h>  #include "sdhci-pltfm.h" +#include "cqhci.h"  #define CORE_MCI_VERSION		0x50  #define CORE_VERSION_MAJOR_SHIFT	28 @@ -122,6 +123,10 @@  #define msm_host_writel(msm_host, val, host, offset) \  	msm_host->var_ops->msm_writel_relaxed(val, host, offset) +/* CQHCI vendor specific registers */ +#define CQHCI_VENDOR_CFG1	0xA00 +#define CQHCI_VENDOR_DIS_RST_ON_CQ_EN	(0x3 << 13) +  struct sdhci_msm_offset {  	u32 core_hc_mode;  	u32 core_mci_data_cnt; @@ -1567,6 +1572,127 @@ out:  	__sdhci_msm_set_clock(host, clock);  } +/*****************************************************************************\ + *                                                                           * + * MSM Command Queue Engine (CQE)                                            * + *                                                                           * +\*****************************************************************************/ + +static u32 sdhci_msm_cqe_irq(struct sdhci_host *host, u32 intmask) +{ +	int cmd_error = 0; +	int data_error = 0; + +	if (!sdhci_cqe_irq(host, intmask, &cmd_error, &data_error)) +		return intmask; + +	cqhci_irq(host->mmc, intmask, cmd_error, data_error); +	return 0; +} + +void sdhci_msm_cqe_disable(struct mmc_host *mmc, bool recovery) +{ +	struct sdhci_host *host = mmc_priv(mmc); +	unsigned long flags; +	u32 ctrl; + +	/* +	 * When CQE is halted, the legacy SDHCI path operates only +	 * on 16-byte descriptors in 64bit mode. +	 */ +	if (host->flags & SDHCI_USE_64_BIT_DMA) +		host->desc_sz = 16; + +	spin_lock_irqsave(&host->lock, flags); + +	/* +	 * During CQE command transfers, command complete bit gets latched. +	 * So s/w should clear command complete interrupt status when CQE is +	 * either halted or disabled. Otherwise unexpected SDCHI legacy +	 * interrupt gets triggered when CQE is halted/disabled. +	 */ +	ctrl = sdhci_readl(host, SDHCI_INT_ENABLE); +	ctrl |= SDHCI_INT_RESPONSE; +	sdhci_writel(host,  ctrl, SDHCI_INT_ENABLE); +	sdhci_writel(host, SDHCI_INT_RESPONSE, SDHCI_INT_STATUS); + +	spin_unlock_irqrestore(&host->lock, flags); + +	sdhci_cqe_disable(mmc, recovery); +} + +static const struct cqhci_host_ops sdhci_msm_cqhci_ops = { +	.enable		= sdhci_cqe_enable, +	.disable	= sdhci_msm_cqe_disable, +}; + +static int sdhci_msm_cqe_add_host(struct sdhci_host *host, +				struct platform_device *pdev) +{ +	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); +	struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host); +	struct cqhci_host *cq_host; +	bool dma64; +	u32 cqcfg; +	int ret; + +	/* +	 * When CQE is halted, SDHC operates only on 16byte ADMA descriptors. +	 * So ensure ADMA table is allocated for 16byte descriptors. +	 */ +	if (host->caps & SDHCI_CAN_64BIT) +		host->alloc_desc_sz = 16; + +	ret = sdhci_setup_host(host); +	if (ret) +		return ret; + +	cq_host = cqhci_pltfm_init(pdev); +	if (IS_ERR(cq_host)) { +		ret = PTR_ERR(cq_host); +		dev_err(&pdev->dev, "cqhci-pltfm init: failed: %d\n", ret); +		goto cleanup; +	} + +	msm_host->mmc->caps2 |= MMC_CAP2_CQE | MMC_CAP2_CQE_DCMD; +	cq_host->ops = &sdhci_msm_cqhci_ops; + +	dma64 = host->flags & SDHCI_USE_64_BIT_DMA; + +	ret = cqhci_init(cq_host, host->mmc, dma64); +	if (ret) { +		dev_err(&pdev->dev, "%s: CQE init: failed (%d)\n", +				mmc_hostname(host->mmc), ret); +		goto cleanup; +	} + +	/* Disable cqe reset due to cqe enable signal */ +	cqcfg = cqhci_readl(cq_host, CQHCI_VENDOR_CFG1); +	cqcfg |= CQHCI_VENDOR_DIS_RST_ON_CQ_EN; +	cqhci_writel(cq_host, cqcfg, CQHCI_VENDOR_CFG1); + +	/* +	 * SDHC expects 12byte ADMA descriptors till CQE is enabled. +	 * So limit desc_sz to 12 so that the data commands that are sent +	 * during card initialization (before CQE gets enabled) would +	 * get executed without any issues. +	 */ +	if (host->flags & SDHCI_USE_64_BIT_DMA) +		host->desc_sz = 12; + +	ret = __sdhci_add_host(host); +	if (ret) +		goto cleanup; + +	dev_info(&pdev->dev, "%s: CQE init: success\n", +			mmc_hostname(host->mmc)); +	return ret; + +cleanup: +	sdhci_cleanup_host(host); +	return ret; +} +  /*   * Platform specific register write functions. This is so that, if any   * register write needs to be followed up by platform specific actions, @@ -1731,6 +1857,7 @@ static const struct sdhci_ops sdhci_msm_ops = {  	.set_uhs_signaling = sdhci_msm_set_uhs_signaling,  	.write_w = sdhci_msm_writew,  	.write_b = sdhci_msm_writeb, +	.irq	= sdhci_msm_cqe_irq,  };  static const struct sdhci_pltfm_data sdhci_msm_pdata = { @@ -1746,7 +1873,6 @@ static int sdhci_msm_probe(struct platform_device *pdev)  	struct sdhci_host *host;  	struct sdhci_pltfm_host *pltfm_host;  	struct sdhci_msm_host *msm_host; -	struct resource *core_memres;  	struct clk *clk;  	int ret;  	u16 host_version, core_minor; @@ -1754,6 +1880,7 @@ static int sdhci_msm_probe(struct platform_device *pdev)  	u8 core_major;  	const struct sdhci_msm_offset *msm_offset;  	const struct sdhci_msm_variant_info *var_info; +	struct device_node *node = pdev->dev.of_node;  	host = sdhci_pltfm_init(pdev, &sdhci_msm_pdata, sizeof(*msm_host));  	if (IS_ERR(host)) @@ -1847,10 +1974,7 @@ static int sdhci_msm_probe(struct platform_device *pdev)  	}  	if (!msm_host->mci_removed) { -		core_memres = platform_get_resource(pdev, IORESOURCE_MEM, 1); -		msm_host->core_mem = devm_ioremap_resource(&pdev->dev, -				core_memres); - +		msm_host->core_mem = devm_platform_ioremap_resource(pdev, 1);  		if (IS_ERR(msm_host->core_mem)) {  			ret = PTR_ERR(msm_host->core_mem);  			goto clk_disable; @@ -1952,7 +2076,10 @@ static int sdhci_msm_probe(struct platform_device *pdev)  	pm_runtime_use_autosuspend(&pdev->dev);  	host->mmc_host_ops.execute_tuning = sdhci_msm_execute_tuning; -	ret = sdhci_add_host(host); +	if (of_property_read_bool(node, "supports-cqe")) +		ret = sdhci_msm_cqe_add_host(host, pdev); +	else +		ret = sdhci_add_host(host);  	if (ret)  		goto pm_runtime_disable;  	sdhci_msm_set_regulator_caps(msm_host); diff --git a/drivers/mmc/host/sdhci-of-at91.c b/drivers/mmc/host/sdhci-of-at91.c index 5959e394b416..ab2bd314a390 100644 --- a/drivers/mmc/host/sdhci-of-at91.c +++ b/drivers/mmc/host/sdhci-of-at91.c @@ -33,7 +33,14 @@  #define SDHCI_AT91_PRESET_COMMON_CONF	0x400 /* drv type B, programmable clock mode */ +struct sdhci_at91_soc_data { +	const struct sdhci_pltfm_data *pdata; +	bool baseclk_is_generated_internally; +	unsigned int divider_for_baseclk; +}; +  struct sdhci_at91_priv { +	const struct sdhci_at91_soc_data *soc_data;  	struct clk *hclock;  	struct clk *gck;  	struct clk *mainck; @@ -141,12 +148,24 @@ static const struct sdhci_ops sdhci_at91_sama5d2_ops = {  	.set_power		= sdhci_at91_set_power,  }; -static const struct sdhci_pltfm_data soc_data_sama5d2 = { +static const struct sdhci_pltfm_data sdhci_sama5d2_pdata = {  	.ops = &sdhci_at91_sama5d2_ops,  }; +static const struct sdhci_at91_soc_data soc_data_sama5d2 = { +	.pdata = &sdhci_sama5d2_pdata, +	.baseclk_is_generated_internally = false, +}; + +static const struct sdhci_at91_soc_data soc_data_sam9x60 = { +	.pdata = &sdhci_sama5d2_pdata, +	.baseclk_is_generated_internally = true, +	.divider_for_baseclk = 2, +}; +  static const struct of_device_id sdhci_at91_dt_match[] = {  	{ .compatible = "atmel,sama5d2-sdhci", .data = &soc_data_sama5d2 }, +	{ .compatible = "microchip,sam9x60-sdhci", .data = &soc_data_sam9x60 },  	{}  };  MODULE_DEVICE_TABLE(of, sdhci_at91_dt_match); @@ -156,50 +175,37 @@ static int sdhci_at91_set_clks_presets(struct device *dev)  	struct sdhci_host *host = dev_get_drvdata(dev);  	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);  	struct sdhci_at91_priv *priv = sdhci_pltfm_priv(pltfm_host); -	int ret;  	unsigned int			caps0, caps1;  	unsigned int			clk_base, clk_mul; -	unsigned int			gck_rate, real_gck_rate; +	unsigned int			gck_rate, clk_base_rate;  	unsigned int			preset_div; -	/* -	 * The mult clock is provided by as a generated clock by the PMC -	 * controller. In order to set the rate of gck, we have to get the -	 * base clock rate and the clock mult from capabilities. -	 */  	clk_prepare_enable(priv->hclock);  	caps0 = readl(host->ioaddr + SDHCI_CAPABILITIES);  	caps1 = readl(host->ioaddr + SDHCI_CAPABILITIES_1); -	clk_base = (caps0 & SDHCI_CLOCK_V3_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT; -	clk_mul = (caps1 & SDHCI_CLOCK_MUL_MASK) >> SDHCI_CLOCK_MUL_SHIFT; -	gck_rate = clk_base * 1000000 * (clk_mul + 1); -	ret = clk_set_rate(priv->gck, gck_rate); -	if (ret < 0) { -		dev_err(dev, "failed to set gck"); -		clk_disable_unprepare(priv->hclock); -		return ret; -	} -	/* -	 * We need to check if we have the requested rate for gck because in -	 * some cases this rate could be not supported. If it happens, the rate -	 * is the closest one gck can provide. We have to update the value -	 * of clk mul. -	 */ -	real_gck_rate = clk_get_rate(priv->gck); -	if (real_gck_rate != gck_rate) { -		clk_mul = real_gck_rate / (clk_base * 1000000) - 1; -		caps1 &= (~SDHCI_CLOCK_MUL_MASK); -		caps1 |= ((clk_mul << SDHCI_CLOCK_MUL_SHIFT) & -			  SDHCI_CLOCK_MUL_MASK); -		/* Set capabilities in r/w mode. */ -		writel(SDMMC_CACR_KEY | SDMMC_CACR_CAPWREN, -		       host->ioaddr + SDMMC_CACR); -		writel(caps1, host->ioaddr + SDHCI_CAPABILITIES_1); -		/* Set capabilities in ro mode. */ -		writel(0, host->ioaddr + SDMMC_CACR); -		dev_info(dev, "update clk mul to %u as gck rate is %u Hz\n", -			 clk_mul, real_gck_rate); -	} + +	gck_rate = clk_get_rate(priv->gck); +	if (priv->soc_data->baseclk_is_generated_internally) +		clk_base_rate = gck_rate / priv->soc_data->divider_for_baseclk; +	else +		clk_base_rate = clk_get_rate(priv->mainck); + +	clk_base = clk_base_rate / 1000000; +	clk_mul = gck_rate / clk_base_rate - 1; + +	caps0 &= ~SDHCI_CLOCK_V3_BASE_MASK; +	caps0 |= (clk_base << SDHCI_CLOCK_BASE_SHIFT) & SDHCI_CLOCK_V3_BASE_MASK; +	caps1 &= ~SDHCI_CLOCK_MUL_MASK; +	caps1 |= (clk_mul << SDHCI_CLOCK_MUL_SHIFT) & SDHCI_CLOCK_MUL_MASK; +	/* Set capabilities in r/w mode. */ +	writel(SDMMC_CACR_KEY | SDMMC_CACR_CAPWREN, host->ioaddr + SDMMC_CACR); +	writel(caps0, host->ioaddr + SDHCI_CAPABILITIES); +	writel(caps1, host->ioaddr + SDHCI_CAPABILITIES_1); +	/* Set capabilities in ro mode. */ +	writel(0, host->ioaddr + SDMMC_CACR); + +	dev_info(dev, "update clk mul to %u as gck rate is %u Hz and clk base is %u Hz\n", +		 clk_mul, gck_rate, clk_base_rate);  	/*  	 * We have to set preset values because it depends on the clk_mul @@ -207,19 +213,19 @@ static int sdhci_at91_set_clks_presets(struct device *dev)  	 * maximum sd clock value is 120 MHz instead of 208 MHz. For that  	 * reason, we need to use presets to support SDR104.  	 */ -	preset_div = DIV_ROUND_UP(real_gck_rate, 24000000) - 1; +	preset_div = DIV_ROUND_UP(gck_rate, 24000000) - 1;  	writew(SDHCI_AT91_PRESET_COMMON_CONF | preset_div,  	       host->ioaddr + SDHCI_PRESET_FOR_SDR12); -	preset_div = DIV_ROUND_UP(real_gck_rate, 50000000) - 1; +	preset_div = DIV_ROUND_UP(gck_rate, 50000000) - 1;  	writew(SDHCI_AT91_PRESET_COMMON_CONF | preset_div,  	       host->ioaddr + SDHCI_PRESET_FOR_SDR25); -	preset_div = DIV_ROUND_UP(real_gck_rate, 100000000) - 1; +	preset_div = DIV_ROUND_UP(gck_rate, 100000000) - 1;  	writew(SDHCI_AT91_PRESET_COMMON_CONF | preset_div,  	       host->ioaddr + SDHCI_PRESET_FOR_SDR50); -	preset_div = DIV_ROUND_UP(real_gck_rate, 120000000) - 1; +	preset_div = DIV_ROUND_UP(gck_rate, 120000000) - 1;  	writew(SDHCI_AT91_PRESET_COMMON_CONF | preset_div,  	       host->ioaddr + SDHCI_PRESET_FOR_SDR104); -	preset_div = DIV_ROUND_UP(real_gck_rate, 50000000) - 1; +	preset_div = DIV_ROUND_UP(gck_rate, 50000000) - 1;  	writew(SDHCI_AT91_PRESET_COMMON_CONF | preset_div,  	       host->ioaddr + SDHCI_PRESET_FOR_DDR50); @@ -314,7 +320,7 @@ static const struct dev_pm_ops sdhci_at91_dev_pm_ops = {  static int sdhci_at91_probe(struct platform_device *pdev)  {  	const struct of_device_id	*match; -	const struct sdhci_pltfm_data	*soc_data; +	const struct sdhci_at91_soc_data	*soc_data;  	struct sdhci_host		*host;  	struct sdhci_pltfm_host		*pltfm_host;  	struct sdhci_at91_priv		*priv; @@ -325,29 +331,37 @@ static int sdhci_at91_probe(struct platform_device *pdev)  		return -EINVAL;  	soc_data = match->data; -	host = sdhci_pltfm_init(pdev, soc_data, sizeof(*priv)); +	host = sdhci_pltfm_init(pdev, soc_data->pdata, sizeof(*priv));  	if (IS_ERR(host))  		return PTR_ERR(host);  	pltfm_host = sdhci_priv(host);  	priv = sdhci_pltfm_priv(pltfm_host); +	priv->soc_data = soc_data;  	priv->mainck = devm_clk_get(&pdev->dev, "baseclk");  	if (IS_ERR(priv->mainck)) { -		dev_err(&pdev->dev, "failed to get baseclk\n"); -		return PTR_ERR(priv->mainck); +		if (soc_data->baseclk_is_generated_internally) { +			priv->mainck = NULL; +		} else { +			dev_err(&pdev->dev, "failed to get baseclk\n"); +			ret = PTR_ERR(priv->mainck); +			goto sdhci_pltfm_free; +		}  	}  	priv->hclock = devm_clk_get(&pdev->dev, "hclock");  	if (IS_ERR(priv->hclock)) {  		dev_err(&pdev->dev, "failed to get hclock\n"); -		return PTR_ERR(priv->hclock); +		ret = PTR_ERR(priv->hclock); +		goto sdhci_pltfm_free;  	}  	priv->gck = devm_clk_get(&pdev->dev, "multclk");  	if (IS_ERR(priv->gck)) {  		dev_err(&pdev->dev, "failed to get multclk\n"); -		return PTR_ERR(priv->gck); +		ret = PTR_ERR(priv->gck); +		goto sdhci_pltfm_free;  	}  	ret = sdhci_at91_set_clks_presets(&pdev->dev); diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index 500f70a6ee42..5d8dd870bd44 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c @@ -173,6 +173,9 @@ static u16 esdhc_readw_fixup(struct sdhci_host *host,  	u16 ret;  	int shift = (spec_reg & 0x2) * 8; +	if (spec_reg == SDHCI_TRANSFER_MODE) +		return pltfm_host->xfer_mode_shadow; +  	if (spec_reg == SDHCI_HOST_VERSION)  		ret = value & 0xffff;  	else @@ -562,32 +565,46 @@ static unsigned int esdhc_of_get_min_clock(struct sdhci_host *host)  static void esdhc_clock_enable(struct sdhci_host *host, bool enable)  { -	u32 val; +	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); +	struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host);  	ktime_t timeout; +	u32 val, clk_en; + +	clk_en = ESDHC_CLOCK_SDCLKEN; + +	/* +	 * IPGEN/HCKEN/PEREN bits exist on eSDHC whose vendor version +	 * is 2.2 or lower. +	 */ +	if (esdhc->vendor_ver <= VENDOR_V_22) +		clk_en |= (ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | +			   ESDHC_CLOCK_PEREN);  	val = sdhci_readl(host, ESDHC_SYSTEM_CONTROL);  	if (enable) -		val |= ESDHC_CLOCK_SDCLKEN; +		val |= clk_en;  	else -		val &= ~ESDHC_CLOCK_SDCLKEN; +		val &= ~clk_en;  	sdhci_writel(host, val, ESDHC_SYSTEM_CONTROL); -	/* Wait max 20 ms */ +	/* +	 * Wait max 20 ms. If vendor version is 2.2 or lower, do not +	 * wait clock stable bit which does not exist. +	 */  	timeout = ktime_add_ms(ktime_get(), 20); -	val = ESDHC_CLOCK_STABLE; -	while  (1) { +	while (esdhc->vendor_ver > VENDOR_V_22) {  		bool timedout = ktime_after(ktime_get(), timeout); -		if (sdhci_readl(host, ESDHC_PRSSTAT) & val) +		if (sdhci_readl(host, ESDHC_PRSSTAT) & ESDHC_CLOCK_STABLE)  			break;  		if (timedout) {  			pr_err("%s: Internal clock never stabilised.\n",  				mmc_hostname(host->mmc));  			break;  		} -		udelay(10); +		usleep_range(10, 20);  	}  } @@ -621,77 +638,97 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)  {  	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);  	struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); -	int pre_div = 1; -	int div = 1; -	int division; +	unsigned int pre_div = 1, div = 1; +	unsigned int clock_fixup = 0;  	ktime_t timeout; -	long fixup = 0;  	u32 temp; -	host->mmc->actual_clock = 0; -  	if (clock == 0) { +		host->mmc->actual_clock = 0;  		esdhc_clock_enable(host, false);  		return;  	} -	/* Workaround to start pre_div at 2 for VNN < VENDOR_V_23 */ +	/* Start pre_div at 2 for vendor version < 2.3. */  	if (esdhc->vendor_ver < VENDOR_V_23)  		pre_div = 2; +	/* Fix clock value. */  	if (host->mmc->card && mmc_card_sd(host->mmc->card) && -		esdhc->clk_fixup && host->mmc->ios.timing == MMC_TIMING_LEGACY) -		fixup = esdhc->clk_fixup->sd_dflt_max_clk; +	    esdhc->clk_fixup && host->mmc->ios.timing == MMC_TIMING_LEGACY) +		clock_fixup = esdhc->clk_fixup->sd_dflt_max_clk;  	else if (esdhc->clk_fixup) -		fixup = esdhc->clk_fixup->max_clk[host->mmc->ios.timing]; - -	if (fixup && clock > fixup) -		clock = fixup; +		clock_fixup = esdhc->clk_fixup->max_clk[host->mmc->ios.timing]; -	temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); -	temp &= ~(ESDHC_CLOCK_SDCLKEN | ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | -		  ESDHC_CLOCK_PEREN | ESDHC_CLOCK_MASK); -	sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); +	if (clock_fixup == 0 || clock < clock_fixup) +		clock_fixup = clock; -	while (host->max_clk / pre_div / 16 > clock && pre_div < 256) +	/* Calculate pre_div and div. */ +	while (host->max_clk / pre_div / 16 > clock_fixup && pre_div < 256)  		pre_div *= 2; -	while (host->max_clk / pre_div / div > clock && div < 16) +	while (host->max_clk / pre_div / div > clock_fixup && div < 16)  		div++; +	esdhc->div_ratio = pre_div * div; + +	/* Limit clock division for HS400 200MHz clock for quirk. */  	if (esdhc->quirk_limited_clk_division &&  	    clock == MMC_HS200_MAX_DTR &&  	    (host->mmc->ios.timing == MMC_TIMING_MMC_HS400 ||  	     host->flags & SDHCI_HS400_TUNING)) { -		division = pre_div * div; -		if (division <= 4) { +		if (esdhc->div_ratio <= 4) {  			pre_div = 4;  			div = 1; -		} else if (division <= 8) { +		} else if (esdhc->div_ratio <= 8) {  			pre_div = 4;  			div = 2; -		} else if (division <= 12) { +		} else if (esdhc->div_ratio <= 12) {  			pre_div = 4;  			div = 3;  		} else {  			pr_warn("%s: using unsupported clock division.\n",  				mmc_hostname(host->mmc));  		} +		esdhc->div_ratio = pre_div * div;  	} +	host->mmc->actual_clock = host->max_clk / esdhc->div_ratio; +  	dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n", -		clock, host->max_clk / pre_div / div); -	host->mmc->actual_clock = host->max_clk / pre_div / div; -	esdhc->div_ratio = pre_div * div; +		clock, host->mmc->actual_clock); + +	/* Set clock division into register. */  	pre_div >>= 1;  	div--; +	esdhc_clock_enable(host, false); +  	temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); -	temp |= (ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN -		| (div << ESDHC_DIVIDER_SHIFT) -		| (pre_div << ESDHC_PREDIV_SHIFT)); +	temp &= ~ESDHC_CLOCK_MASK; +	temp |= ((div << ESDHC_DIVIDER_SHIFT) | +		(pre_div << ESDHC_PREDIV_SHIFT));  	sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); +	/* +	 * Wait max 20 ms. If vendor version is 2.2 or lower, do not +	 * wait clock stable bit which does not exist. +	 */ +	timeout = ktime_add_ms(ktime_get(), 20); +	while (esdhc->vendor_ver > VENDOR_V_22) { +		bool timedout = ktime_after(ktime_get(), timeout); + +		if (sdhci_readl(host, ESDHC_PRSSTAT) & ESDHC_CLOCK_STABLE) +			break; +		if (timedout) { +			pr_err("%s: Internal clock never stabilised.\n", +				mmc_hostname(host->mmc)); +			break; +		} +		usleep_range(10, 20); +	} + +	/* Additional setting for HS400. */  	if (host->mmc->ios.timing == MMC_TIMING_MMC_HS400 &&  	    clock == MMC_HS200_MAX_DTR) {  		temp = sdhci_readl(host, ESDHC_TBCTL); @@ -711,25 +748,7 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)  		esdhc_clock_enable(host, false);  		esdhc_flush_async_fifo(host);  	} - -	/* Wait max 20 ms */ -	timeout = ktime_add_ms(ktime_get(), 20); -	while (1) { -		bool timedout = ktime_after(ktime_get(), timeout); - -		if (sdhci_readl(host, ESDHC_PRSSTAT) & ESDHC_CLOCK_STABLE) -			break; -		if (timedout) { -			pr_err("%s: Internal clock never stabilised.\n", -				mmc_hostname(host->mmc)); -			return; -		} -		udelay(10); -	} - -	temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); -	temp |= ESDHC_CLOCK_SDCLKEN; -	sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); +	esdhc_clock_enable(host, true);  }  static void esdhc_pltfm_set_bus_width(struct sdhci_host *host, int width) @@ -758,23 +777,58 @@ static void esdhc_reset(struct sdhci_host *host, u8 mask)  {  	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);  	struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); -	u32 val; +	u32 val, bus_width = 0; +	/* +	 * Add delay to make sure all the DMA transfers are finished +	 * for quirk. +	 */  	if (esdhc->quirk_delay_before_data_reset &&  	    (mask & SDHCI_RESET_DATA) &&  	    (host->flags & SDHCI_REQ_USE_DMA))  		mdelay(5); +	/* +	 * Save bus-width for eSDHC whose vendor version is 2.2 +	 * or lower for data reset. +	 */ +	if ((mask & SDHCI_RESET_DATA) && +	    (esdhc->vendor_ver <= VENDOR_V_22)) { +		val = sdhci_readl(host, ESDHC_PROCTL); +		bus_width = val & ESDHC_CTRL_BUSWIDTH_MASK; +	} +  	sdhci_reset(host, mask); -	sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); -	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); +	/* +	 * Restore bus-width setting and interrupt registers for eSDHC +	 * whose vendor version is 2.2 or lower for data reset. +	 */ +	if ((mask & SDHCI_RESET_DATA) && +	    (esdhc->vendor_ver <= VENDOR_V_22)) { +		val = sdhci_readl(host, ESDHC_PROCTL); +		val &= ~ESDHC_CTRL_BUSWIDTH_MASK; +		val |= bus_width; +		sdhci_writel(host, val, ESDHC_PROCTL); -	if (mask & SDHCI_RESET_ALL) { +		sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); +		sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); +	} + +	/* +	 * Some bits have to be cleaned manually for eSDHC whose spec +	 * version is higher than 3.0 for all reset. +	 */ +	if ((mask & SDHCI_RESET_ALL) && +	    (esdhc->spec_ver >= SDHCI_SPEC_300)) {  		val = sdhci_readl(host, ESDHC_TBCTL);  		val &= ~ESDHC_TB_EN;  		sdhci_writel(host, val, ESDHC_TBCTL); +		/* +		 * Initialize eSDHC_DLLCFG1[DLL_PD_PULSE_STRETCH_SEL] to +		 * 0 for quirk. +		 */  		if (esdhc->quirk_unreliable_pulse_detection) {  			val = sdhci_readl(host, ESDHC_DLLCFG1);  			val &= ~ESDHC_DLL_PD_PULSE_STRETCH_SEL; @@ -854,20 +908,20 @@ static int esdhc_signal_voltage_switch(struct mmc_host *mmc,  }  static struct soc_device_attribute soc_tuning_erratum_type1[] = { -	{ .family = "QorIQ T1023", .revision = "1.0", }, -	{ .family = "QorIQ T1040", .revision = "1.0", }, -	{ .family = "QorIQ T2080", .revision = "1.0", }, -	{ .family = "QorIQ LS1021A", .revision = "1.0", }, +	{ .family = "QorIQ T1023", }, +	{ .family = "QorIQ T1040", }, +	{ .family = "QorIQ T2080", }, +	{ .family = "QorIQ LS1021A", },  	{ },  };  static struct soc_device_attribute soc_tuning_erratum_type2[] = { -	{ .family = "QorIQ LS1012A", .revision = "1.0", }, -	{ .family = "QorIQ LS1043A", .revision = "1.*", }, -	{ .family = "QorIQ LS1046A", .revision = "1.0", }, -	{ .family = "QorIQ LS1080A", .revision = "1.0", }, -	{ .family = "QorIQ LS2080A", .revision = "1.0", }, -	{ .family = "QorIQ LA1575A", .revision = "1.0", }, +	{ .family = "QorIQ LS1012A", }, +	{ .family = "QorIQ LS1043A", }, +	{ .family = "QorIQ LS1046A", }, +	{ .family = "QorIQ LS1080A", }, +	{ .family = "QorIQ LS2080A", }, +	{ .family = "QorIQ LA1575A", },  	{ },  }; @@ -888,20 +942,11 @@ static void esdhc_tuning_block_enable(struct sdhci_host *host, bool enable)  	esdhc_clock_enable(host, true);  } -static void esdhc_prepare_sw_tuning(struct sdhci_host *host, u8 *window_start, +static void esdhc_tuning_window_ptr(struct sdhci_host *host, u8 *window_start,  				    u8 *window_end)  { -	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); -	struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); -	u8 tbstat_15_8, tbstat_7_0;  	u32 val; -	if (esdhc->quirk_tuning_erratum_type1) { -		*window_start = 5 * esdhc->div_ratio; -		*window_end = 3 * esdhc->div_ratio; -		return; -	} -  	/* Write TBCTL[11:8]=4'h8 */  	val = sdhci_readl(host, ESDHC_TBCTL);  	val &= ~(0xf << 8); @@ -920,20 +965,37 @@ static void esdhc_prepare_sw_tuning(struct sdhci_host *host, u8 *window_start,  	val = sdhci_readl(host, ESDHC_TBSTAT);  	val = sdhci_readl(host, ESDHC_TBSTAT); +	*window_end = val & 0xff; +	*window_start = (val >> 8) & 0xff; +} + +static void esdhc_prepare_sw_tuning(struct sdhci_host *host, u8 *window_start, +				    u8 *window_end) +{ +	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); +	struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); +	u8 start_ptr, end_ptr; + +	if (esdhc->quirk_tuning_erratum_type1) { +		*window_start = 5 * esdhc->div_ratio; +		*window_end = 3 * esdhc->div_ratio; +		return; +	} + +	esdhc_tuning_window_ptr(host, &start_ptr, &end_ptr); +  	/* Reset data lines by setting ESDHCCTL[RSTD] */  	sdhci_reset(host, SDHCI_RESET_DATA);  	/* Write 32'hFFFF_FFFF to IRQSTAT register */  	sdhci_writel(host, 0xFFFFFFFF, SDHCI_INT_STATUS); -	/* If TBSTAT[15:8]-TBSTAT[7:0] > 4 * div_ratio -	 * or TBSTAT[7:0]-TBSTAT[15:8] > 4 * div_ratio, +	/* If TBSTAT[15:8]-TBSTAT[7:0] > (4 * div_ratio) + 2 +	 * or TBSTAT[7:0]-TBSTAT[15:8] > (4 * div_ratio) + 2,  	 * then program TBPTR[TB_WNDW_END_PTR] = 4 * div_ratio  	 * and program TBPTR[TB_WNDW_START_PTR] = 8 * div_ratio.  	 */ -	tbstat_7_0 = val & 0xff; -	tbstat_15_8 = (val >> 8) & 0xff; -	if (abs(tbstat_15_8 - tbstat_7_0) > (4 * esdhc->div_ratio)) { +	if (abs(start_ptr - end_ptr) > (4 * esdhc->div_ratio + 2)) {  		*window_start = 8 * esdhc->div_ratio;  		*window_end = 4 * esdhc->div_ratio;  	} else { @@ -1006,6 +1068,19 @@ static int esdhc_execute_tuning(struct mmc_host *mmc, u32 opcode)  		if (ret)  			break; +		/* For type2 affected platforms of the tuning erratum, +		 * tuning may succeed although eSDHC might not have +		 * tuned properly. Need to check tuning window. +		 */ +		if (esdhc->quirk_tuning_erratum_type2 && +		    !host->tuning_err) { +			esdhc_tuning_window_ptr(host, &window_start, +						&window_end); +			if (abs(window_start - window_end) > +			    (4 * esdhc->div_ratio + 2)) +				host->tuning_err = -EAGAIN; +		} +  		/* If HW tuning fails and triggers erratum,  		 * try workaround.  		 */ @@ -1238,7 +1313,8 @@ static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host)  		 * 1/2 peripheral clock.  		 */  		if (of_device_is_compatible(np, "fsl,ls1046a-esdhc") || -		    of_device_is_compatible(np, "fsl,ls1028a-esdhc")) +		    of_device_is_compatible(np, "fsl,ls1028a-esdhc") || +		    of_device_is_compatible(np, "fsl,ls1088a-esdhc"))  			esdhc->peripheral_clock = clk_get_rate(clk) / 2;  		else  			esdhc->peripheral_clock = clk_get_rate(clk); diff --git a/drivers/mmc/host/sdhci-omap.c b/drivers/mmc/host/sdhci-omap.c index 083e7e053c95..882053151a47 100644 --- a/drivers/mmc/host/sdhci-omap.c +++ b/drivers/mmc/host/sdhci-omap.c @@ -7,6 +7,7 @@   */  #include <linux/delay.h> +#include <linux/mmc/mmc.h>  #include <linux/mmc/slot-gpio.h>  #include <linux/module.h>  #include <linux/of.h> @@ -85,6 +86,7 @@  /* sdhci-omap controller flags */  #define SDHCI_OMAP_REQUIRE_IODELAY	BIT(0) +#define SDHCI_OMAP_SPECIAL_RESET	BIT(1)  struct sdhci_omap_data {  	u32 offset; @@ -685,7 +687,11 @@ static int sdhci_omap_enable_dma(struct sdhci_host *host)  	struct sdhci_omap_host *omap_host = sdhci_pltfm_priv(pltfm_host);  	reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CON); -	reg |= CON_DMA_MASTER; +	reg &= ~CON_DMA_MASTER; +	/* Switch to DMA slave mode when using external DMA */ +	if (!host->use_external_dma) +		reg |= CON_DMA_MASTER; +  	sdhci_omap_writel(omap_host, SDHCI_OMAP_CON, reg);  	return 0; @@ -774,15 +780,35 @@ static void sdhci_omap_set_uhs_signaling(struct sdhci_host *host,  	sdhci_omap_start_clock(omap_host);  } +#define MMC_TIMEOUT_US		20000		/* 20000 micro Sec */  static void sdhci_omap_reset(struct sdhci_host *host, u8 mask)  {  	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);  	struct sdhci_omap_host *omap_host = sdhci_pltfm_priv(pltfm_host); +	unsigned long limit = MMC_TIMEOUT_US; +	unsigned long i = 0;  	/* Don't reset data lines during tuning operation */  	if (omap_host->is_tuning)  		mask &= ~SDHCI_RESET_DATA; +	if (omap_host->flags & SDHCI_OMAP_SPECIAL_RESET) { +		sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET); +		while ((!(sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask)) && +		       (i++ < limit)) +			udelay(1); +		i = 0; +		while ((sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask) && +		       (i++ < limit)) +			udelay(1); + +		if (sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask) +			dev_err(mmc_dev(host->mmc), +				"Timeout waiting on controller reset in %s\n", +				__func__); +		return; +	} +  	sdhci_reset(host, mask);  } @@ -823,6 +849,15 @@ static u32 sdhci_omap_irq(struct sdhci_host *host, u32 intmask)  	return intmask;  } +static void sdhci_omap_set_timeout(struct sdhci_host *host, +				   struct mmc_command *cmd) +{ +	if (cmd->opcode == MMC_ERASE) +		sdhci_set_data_timeout_irq(host, false); + +	__sdhci_set_timeout(host, cmd); +} +  static struct sdhci_ops sdhci_omap_ops = {  	.set_clock = sdhci_omap_set_clock,  	.set_power = sdhci_omap_set_power, @@ -834,6 +869,7 @@ static struct sdhci_ops sdhci_omap_ops = {  	.reset = sdhci_omap_reset,  	.set_uhs_signaling = sdhci_omap_set_uhs_signaling,  	.irq = sdhci_omap_irq, +	.set_timeout = sdhci_omap_set_timeout,  };  static int sdhci_omap_set_capabilities(struct sdhci_omap_host *omap_host) @@ -883,6 +919,16 @@ static const struct sdhci_omap_data k2g_data = {  	.offset = 0x200,  }; +static const struct sdhci_omap_data am335_data = { +	.offset = 0x200, +	.flags = SDHCI_OMAP_SPECIAL_RESET, +}; + +static const struct sdhci_omap_data am437_data = { +	.offset = 0x200, +	.flags = SDHCI_OMAP_SPECIAL_RESET, +}; +  static const struct sdhci_omap_data dra7_data = {  	.offset = 0x200,  	.flags	= SDHCI_OMAP_REQUIRE_IODELAY, @@ -891,6 +937,8 @@ static const struct sdhci_omap_data dra7_data = {  static const struct of_device_id omap_sdhci_match[] = {  	{ .compatible = "ti,dra7-sdhci", .data = &dra7_data },  	{ .compatible = "ti,k2g-sdhci", .data = &k2g_data }, +	{ .compatible = "ti,am335-sdhci", .data = &am335_data }, +	{ .compatible = "ti,am437-sdhci", .data = &am437_data },  	{},  };  MODULE_DEVICE_TABLE(of, omap_sdhci_match); @@ -1037,6 +1085,7 @@ static int sdhci_omap_probe(struct platform_device *pdev)  	const struct of_device_id *match;  	struct sdhci_omap_data *data;  	const struct soc_device_attribute *soc; +	struct resource *regs;  	match = of_match_device(omap_sdhci_match, dev);  	if (!match) @@ -1049,6 +1098,10 @@ static int sdhci_omap_probe(struct platform_device *pdev)  	}  	offset = data->offset; +	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); +	if (!regs) +		return -ENXIO; +  	host = sdhci_pltfm_init(pdev, &sdhci_omap_pdata,  				sizeof(*omap_host));  	if (IS_ERR(host)) { @@ -1065,6 +1118,7 @@ static int sdhci_omap_probe(struct platform_device *pdev)  	omap_host->timing = MMC_TIMING_LEGACY;  	omap_host->flags = data->flags;  	host->ioaddr += offset; +	host->mapbase = regs->start + offset;  	mmc = host->mmc;  	sdhci_get_of_property(pdev); @@ -1134,6 +1188,10 @@ static int sdhci_omap_probe(struct platform_device *pdev)  	host->mmc_host_ops.execute_tuning = sdhci_omap_execute_tuning;  	host->mmc_host_ops.enable_sdio_irq = sdhci_omap_enable_sdio_irq; +	/* Switch to external DMA only if there is the "dmas" property */ +	if (of_find_property(dev->of_node, "dmas", NULL)) +		sdhci_switch_external_dma(host, true); +  	ret = sdhci_setup_host(host);  	if (ret)  		goto err_put_sync; diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c index 5091e2c1c0e5..525de2454a4d 100644 --- a/drivers/mmc/host/sdhci-pci-core.c +++ b/drivers/mmc/host/sdhci-pci-core.c @@ -1991,12 +1991,12 @@ static struct sdhci_pci_slot *sdhci_pci_probe_slot(  	if (slot->cd_idx >= 0) {  		ret = mmc_gpiod_request_cd(host->mmc, "cd", slot->cd_idx, -					   slot->cd_override_level, 0, NULL); +					   slot->cd_override_level, 0);  		if (ret && ret != -EPROBE_DEFER)  			ret = mmc_gpiod_request_cd(host->mmc, NULL,  						   slot->cd_idx,  						   slot->cd_override_level, -						   0, NULL); +						   0);  		if (ret == -EPROBE_DEFER)  			goto remove; diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index 51e096f27388..64200c78e90d 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c @@ -117,7 +117,6 @@ struct sdhci_s3c {  	struct s3c_sdhci_platdata *pdata;  	int			cur_clk;  	int			ext_cd_irq; -	int			ext_cd_gpio;  	struct clk		*clk_io;  	struct clk		*clk_bus[MAX_BUS_CLK]; @@ -481,7 +480,6 @@ static int sdhci_s3c_probe(struct platform_device *pdev)  	struct device *dev = &pdev->dev;  	struct sdhci_host *host;  	struct sdhci_s3c *sc; -	struct resource *res;  	int ret, irq, ptr, clks;  	if (!pdev->dev.platform_data && !pdev->dev.of_node) { @@ -512,7 +510,6 @@ static int sdhci_s3c_probe(struct platform_device *pdev)  			goto err_pdata_io_clk;  	} else {  		memcpy(pdata, pdev->dev.platform_data, sizeof(*pdata)); -		sc->ext_cd_gpio = -1; /* invalid gpio number */  	}  	drv_data = sdhci_s3c_get_driver_data(pdev); @@ -555,8 +552,7 @@ static int sdhci_s3c_probe(struct platform_device *pdev)  		goto err_no_busclks;  	} -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	host->ioaddr = devm_ioremap_resource(&pdev->dev, res); +	host->ioaddr = devm_platform_ioremap_resource(pdev, 0);  	if (IS_ERR(host->ioaddr)) {  		ret = PTR_ERR(host->ioaddr);  		goto err_req_regs; diff --git a/drivers/mmc/host/sdhci-sirf.c b/drivers/mmc/host/sdhci-sirf.c index e43143223320..f4b05dd6c20a 100644 --- a/drivers/mmc/host/sdhci-sirf.c +++ b/drivers/mmc/host/sdhci-sirf.c @@ -194,7 +194,7 @@ static int sdhci_sirf_probe(struct platform_device *pdev)  	 * We must request the IRQ after sdhci_add_host(), as the tasklet only  	 * gets setup in sdhci_add_host() and we oops.  	 */ -	ret = mmc_gpiod_request_cd(host->mmc, "cd", 0, false, 0, NULL); +	ret = mmc_gpiod_request_cd(host->mmc, "cd", 0, false, 0);  	if (ret == -EPROBE_DEFER)  		goto err_request_cd;  	if (!ret) diff --git a/drivers/mmc/host/sdhci-spear.c b/drivers/mmc/host/sdhci-spear.c index 916b5b09c3d1..b4b63089a4e2 100644 --- a/drivers/mmc/host/sdhci-spear.c +++ b/drivers/mmc/host/sdhci-spear.c @@ -43,7 +43,6 @@ static const struct sdhci_ops sdhci_pltfm_ops = {  static int sdhci_probe(struct platform_device *pdev)  {  	struct sdhci_host *host; -	struct resource *iomem;  	struct spear_sdhci *sdhci;  	struct device *dev;  	int ret; @@ -56,8 +55,7 @@ static int sdhci_probe(struct platform_device *pdev)  		goto err;  	} -	iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	host->ioaddr = devm_ioremap_resource(&pdev->dev, iomem); +	host->ioaddr = devm_platform_ioremap_resource(pdev, 0);  	if (IS_ERR(host->ioaddr)) {  		ret = PTR_ERR(host->ioaddr);  		dev_dbg(&pdev->dev, "unable to map iomem: %d\n", ret); @@ -98,7 +96,7 @@ static int sdhci_probe(struct platform_device *pdev)  	 * It is optional to use GPIOs for sdhci card detection. If we  	 * find a descriptor using slot GPIO, we use it.  	 */ -	ret = mmc_gpiod_request_cd(host->mmc, "cd", 0, false, 0, NULL); +	ret = mmc_gpiod_request_cd(host->mmc, "cd", 0, false, 0);  	if (ret == -EPROBE_DEFER)  		goto disable_clk; diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index 7bc950520fd9..403ac44a7378 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c @@ -386,7 +386,7 @@ static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask)  			misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_DDR50;  		if (soc_data->nvquirks & NVQUIRK_ENABLE_SDR104)  			misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_SDR104; -		if (soc_data->nvquirks & SDHCI_MISC_CTRL_ENABLE_SDR50) +		if (soc_data->nvquirks & NVQUIRK_ENABLE_SDR50)  			clk_ctrl |= SDHCI_CLOCK_CTRL_SDR50_TUNING_OVERRIDE;  	} diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 1b1c26da3fe0..63db84481dff 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -10,6 +10,7 @@   */  #include <linux/delay.h> +#include <linux/dmaengine.h>  #include <linux/ktime.h>  #include <linux/highmem.h>  #include <linux/io.h> @@ -992,7 +993,7 @@ static void sdhci_set_transfer_irqs(struct sdhci_host *host)  	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);  } -static void sdhci_set_data_timeout_irq(struct sdhci_host *host, bool enable) +void sdhci_set_data_timeout_irq(struct sdhci_host *host, bool enable)  {  	if (enable)  		host->ier |= SDHCI_INT_DATA_TIMEOUT; @@ -1001,42 +1002,36 @@ static void sdhci_set_data_timeout_irq(struct sdhci_host *host, bool enable)  	sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);  	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);  } +EXPORT_SYMBOL_GPL(sdhci_set_data_timeout_irq); -static void sdhci_set_timeout(struct sdhci_host *host, struct mmc_command *cmd) +void __sdhci_set_timeout(struct sdhci_host *host, struct mmc_command *cmd)  { -	u8 count; - -	if (host->ops->set_timeout) { -		host->ops->set_timeout(host, cmd); -	} else { -		bool too_big = false; - -		count = sdhci_calc_timeout(host, cmd, &too_big); - -		if (too_big && -		    host->quirks2 & SDHCI_QUIRK2_DISABLE_HW_TIMEOUT) { -			sdhci_calc_sw_timeout(host, cmd); -			sdhci_set_data_timeout_irq(host, false); -		} else if (!(host->ier & SDHCI_INT_DATA_TIMEOUT)) { -			sdhci_set_data_timeout_irq(host, true); -		} - -		sdhci_writeb(host, count, SDHCI_TIMEOUT_CONTROL); +	bool too_big = false; +	u8 count = sdhci_calc_timeout(host, cmd, &too_big); + +	if (too_big && +	    host->quirks2 & SDHCI_QUIRK2_DISABLE_HW_TIMEOUT) { +		sdhci_calc_sw_timeout(host, cmd); +		sdhci_set_data_timeout_irq(host, false); +	} else if (!(host->ier & SDHCI_INT_DATA_TIMEOUT)) { +		sdhci_set_data_timeout_irq(host, true);  	} + +	sdhci_writeb(host, count, SDHCI_TIMEOUT_CONTROL);  } +EXPORT_SYMBOL_GPL(__sdhci_set_timeout); -static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) +static void sdhci_set_timeout(struct sdhci_host *host, struct mmc_command *cmd)  { -	struct mmc_data *data = cmd->data; - -	host->data_timeout = 0; - -	if (sdhci_data_line_cmd(cmd)) -		sdhci_set_timeout(host, cmd); - -	if (!data) -		return; +	if (host->ops->set_timeout) +		host->ops->set_timeout(host, cmd); +	else +		__sdhci_set_timeout(host, cmd); +} +static void sdhci_initialize_data(struct sdhci_host *host, +				  struct mmc_data *data) +{  	WARN_ON(host->data);  	/* Sanity checks */ @@ -1047,6 +1042,34 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)  	host->data = data;  	host->data_early = 0;  	host->data->bytes_xfered = 0; +} + +static inline void sdhci_set_block_info(struct sdhci_host *host, +					struct mmc_data *data) +{ +	/* Set the DMA boundary value and block size */ +	sdhci_writew(host, +		     SDHCI_MAKE_BLKSZ(host->sdma_boundary, data->blksz), +		     SDHCI_BLOCK_SIZE); +	/* +	 * For Version 4.10 onwards, if v4 mode is enabled, 32-bit Block Count +	 * can be supported, in that case 16-bit block count register must be 0. +	 */ +	if (host->version >= SDHCI_SPEC_410 && host->v4_mode && +	    (host->quirks2 & SDHCI_QUIRK2_USE_32BIT_BLK_CNT)) { +		if (sdhci_readw(host, SDHCI_BLOCK_COUNT)) +			sdhci_writew(host, 0, SDHCI_BLOCK_COUNT); +		sdhci_writew(host, data->blocks, SDHCI_32BIT_BLK_CNT); +	} else { +		sdhci_writew(host, data->blocks, SDHCI_BLOCK_COUNT); +	} +} + +static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) +{ +	struct mmc_data *data = cmd->data; + +	sdhci_initialize_data(host, data);  	if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {  		struct scatterlist *sg; @@ -1133,24 +1156,192 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)  	sdhci_set_transfer_irqs(host); -	/* Set the DMA boundary value and block size */ -	sdhci_writew(host, SDHCI_MAKE_BLKSZ(host->sdma_boundary, data->blksz), -		     SDHCI_BLOCK_SIZE); +	sdhci_set_block_info(host, data); +} -	/* -	 * For Version 4.10 onwards, if v4 mode is enabled, 32-bit Block Count -	 * can be supported, in that case 16-bit block count register must be 0. -	 */ -	if (host->version >= SDHCI_SPEC_410 && host->v4_mode && -	    (host->quirks2 & SDHCI_QUIRK2_USE_32BIT_BLK_CNT)) { -		if (sdhci_readw(host, SDHCI_BLOCK_COUNT)) -			sdhci_writew(host, 0, SDHCI_BLOCK_COUNT); -		sdhci_writew(host, data->blocks, SDHCI_32BIT_BLK_CNT); +#if IS_ENABLED(CONFIG_MMC_SDHCI_EXTERNAL_DMA) + +static int sdhci_external_dma_init(struct sdhci_host *host) +{ +	int ret = 0; +	struct mmc_host *mmc = host->mmc; + +	host->tx_chan = dma_request_chan(mmc->parent, "tx"); +	if (IS_ERR(host->tx_chan)) { +		ret = PTR_ERR(host->tx_chan); +		if (ret != -EPROBE_DEFER) +			pr_warn("Failed to request TX DMA channel.\n"); +		host->tx_chan = NULL; +		return ret; +	} + +	host->rx_chan = dma_request_chan(mmc->parent, "rx"); +	if (IS_ERR(host->rx_chan)) { +		if (host->tx_chan) { +			dma_release_channel(host->tx_chan); +			host->tx_chan = NULL; +		} + +		ret = PTR_ERR(host->rx_chan); +		if (ret != -EPROBE_DEFER) +			pr_warn("Failed to request RX DMA channel.\n"); +		host->rx_chan = NULL; +	} + +	return ret; +} + +static struct dma_chan *sdhci_external_dma_channel(struct sdhci_host *host, +						   struct mmc_data *data) +{ +	return data->flags & MMC_DATA_WRITE ? host->tx_chan : host->rx_chan; +} + +static int sdhci_external_dma_setup(struct sdhci_host *host, +				    struct mmc_command *cmd) +{ +	int ret, i; +	enum dma_transfer_direction dir; +	struct dma_async_tx_descriptor *desc; +	struct mmc_data *data = cmd->data; +	struct dma_chan *chan; +	struct dma_slave_config cfg; +	dma_cookie_t cookie; +	int sg_cnt; + +	if (!host->mapbase) +		return -EINVAL; + +	cfg.src_addr = host->mapbase + SDHCI_BUFFER; +	cfg.dst_addr = host->mapbase + SDHCI_BUFFER; +	cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; +	cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; +	cfg.src_maxburst = data->blksz / 4; +	cfg.dst_maxburst = data->blksz / 4; + +	/* Sanity check: all the SG entries must be aligned by block size. */ +	for (i = 0; i < data->sg_len; i++) { +		if ((data->sg + i)->length % data->blksz) +			return -EINVAL; +	} + +	chan = sdhci_external_dma_channel(host, data); + +	ret = dmaengine_slave_config(chan, &cfg); +	if (ret) +		return ret; + +	sg_cnt = sdhci_pre_dma_transfer(host, data, COOKIE_MAPPED); +	if (sg_cnt <= 0) +		return -EINVAL; + +	dir = data->flags & MMC_DATA_WRITE ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; +	desc = dmaengine_prep_slave_sg(chan, data->sg, data->sg_len, dir, +				       DMA_PREP_INTERRUPT | DMA_CTRL_ACK); +	if (!desc) +		return -EINVAL; + +	desc->callback = NULL; +	desc->callback_param = NULL; + +	cookie = dmaengine_submit(desc); +	if (dma_submit_error(cookie)) +		ret = cookie; + +	return ret; +} + +static void sdhci_external_dma_release(struct sdhci_host *host) +{ +	if (host->tx_chan) { +		dma_release_channel(host->tx_chan); +		host->tx_chan = NULL; +	} + +	if (host->rx_chan) { +		dma_release_channel(host->rx_chan); +		host->rx_chan = NULL; +	} + +	sdhci_switch_external_dma(host, false); +} + +static void __sdhci_external_dma_prepare_data(struct sdhci_host *host, +					      struct mmc_command *cmd) +{ +	struct mmc_data *data = cmd->data; + +	sdhci_initialize_data(host, data); + +	host->flags |= SDHCI_REQ_USE_DMA; +	sdhci_set_transfer_irqs(host); + +	sdhci_set_block_info(host, data); +} + +static void sdhci_external_dma_prepare_data(struct sdhci_host *host, +					    struct mmc_command *cmd) +{ +	if (!sdhci_external_dma_setup(host, cmd)) { +		__sdhci_external_dma_prepare_data(host, cmd);  	} else { -		sdhci_writew(host, data->blocks, SDHCI_BLOCK_COUNT); +		sdhci_external_dma_release(host); +		pr_err("%s: Cannot use external DMA, switch to the DMA/PIO which standard SDHCI provides.\n", +		       mmc_hostname(host->mmc)); +		sdhci_prepare_data(host, cmd);  	}  } +static void sdhci_external_dma_pre_transfer(struct sdhci_host *host, +					    struct mmc_command *cmd) +{ +	struct dma_chan *chan; + +	if (!cmd->data) +		return; + +	chan = sdhci_external_dma_channel(host, cmd->data); +	if (chan) +		dma_async_issue_pending(chan); +} + +#else + +static inline int sdhci_external_dma_init(struct sdhci_host *host) +{ +	return -EOPNOTSUPP; +} + +static inline void sdhci_external_dma_release(struct sdhci_host *host) +{ +} + +static inline void sdhci_external_dma_prepare_data(struct sdhci_host *host, +						   struct mmc_command *cmd) +{ +	/* This should never happen */ +	WARN_ON_ONCE(1); +} + +static inline void sdhci_external_dma_pre_transfer(struct sdhci_host *host, +						   struct mmc_command *cmd) +{ +} + +static inline struct dma_chan *sdhci_external_dma_channel(struct sdhci_host *host, +							  struct mmc_data *data) +{ +	return NULL; +} + +#endif + +void sdhci_switch_external_dma(struct sdhci_host *host, bool en) +{ +	host->use_external_dma = en; +} +EXPORT_SYMBOL_GPL(sdhci_switch_external_dma); +  static inline bool sdhci_auto_cmd12(struct sdhci_host *host,  				    struct mmc_request *mrq)  { @@ -1245,22 +1436,10 @@ static bool sdhci_needs_reset(struct sdhci_host *host, struct mmc_request *mrq)  		 (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST)));  } -static void __sdhci_finish_mrq(struct sdhci_host *host, struct mmc_request *mrq) +static void sdhci_set_mrq_done(struct sdhci_host *host, struct mmc_request *mrq)  {  	int i; -	if (host->cmd && host->cmd->mrq == mrq) -		host->cmd = NULL; - -	if (host->data_cmd && host->data_cmd->mrq == mrq) -		host->data_cmd = NULL; - -	if (host->data && host->data->mrq == mrq) -		host->data = NULL; - -	if (sdhci_needs_reset(host, mrq)) -		host->pending_reset = true; -  	for (i = 0; i < SDHCI_MAX_MRQS; i++) {  		if (host->mrqs_done[i] == mrq) {  			WARN_ON(1); @@ -1276,6 +1455,23 @@ static void __sdhci_finish_mrq(struct sdhci_host *host, struct mmc_request *mrq)  	}  	WARN_ON(i >= SDHCI_MAX_MRQS); +} + +static void __sdhci_finish_mrq(struct sdhci_host *host, struct mmc_request *mrq) +{ +	if (host->cmd && host->cmd->mrq == mrq) +		host->cmd = NULL; + +	if (host->data_cmd && host->data_cmd->mrq == mrq) +		host->data_cmd = NULL; + +	if (host->data && host->data->mrq == mrq) +		host->data = NULL; + +	if (sdhci_needs_reset(host, mrq)) +		host->pending_reset = true; + +	sdhci_set_mrq_done(host, mrq);  	sdhci_del_timer(host, mrq); @@ -1326,12 +1522,12 @@ static void sdhci_finish_data(struct sdhci_host *host)  	/*  	 * Need to send CMD12 if - -	 * a) open-ended multiblock transfer (no CMD23) +	 * a) open-ended multiblock transfer not using auto CMD12 (no CMD23)  	 * b) error in multiblock transfer  	 */  	if (data->stop && -	    (data->error || -	     !data->mrq->sbc)) { +	    ((!data->mrq->sbc && !sdhci_auto_cmd12(host, data->mrq)) || +	     data->error)) {  		/*  		 * 'cap_cmd_during_tfr' request must not use the command line  		 * after mmc_command_done() has been called. It is upper layer's @@ -1390,12 +1586,19 @@ void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)  	}  	host->cmd = cmd; +	host->data_timeout = 0;  	if (sdhci_data_line_cmd(cmd)) {  		WARN_ON(host->data_cmd);  		host->data_cmd = cmd; +		sdhci_set_timeout(host, cmd);  	} -	sdhci_prepare_data(host, cmd); +	if (cmd->data) { +		if (host->use_external_dma) +			sdhci_external_dma_prepare_data(host, cmd); +		else +			sdhci_prepare_data(host, cmd); +	}  	sdhci_writel(host, cmd->arg, SDHCI_ARGUMENT); @@ -1437,6 +1640,9 @@ void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)  		timeout += 10 * HZ;  	sdhci_mod_timer(host, cmd->mrq, timeout); +	if (host->use_external_dma) +		sdhci_external_dma_pre_transfer(host, cmd); +  	sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND);  }  EXPORT_SYMBOL_GPL(sdhci_send_command); @@ -1825,17 +2031,6 @@ void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)  	sdhci_led_activate(host); -	/* -	 * Ensure we don't send the STOP for non-SET_BLOCK_COUNTED -	 * requests if Auto-CMD12 is enabled. -	 */ -	if (sdhci_auto_cmd12(host, mrq)) { -		if (mrq->stop) { -			mrq->data->stop = NULL; -			mrq->stop = NULL; -		} -	} -  	if (!present || host->flags & SDHCI_DEVICE_DEAD) {  		mrq->cmd->error = -ENOMEDIUM;  		sdhci_finish_mrq(host, mrq); @@ -2661,6 +2856,17 @@ static bool sdhci_request_done(struct sdhci_host *host)  	if (host->flags & SDHCI_REQ_USE_DMA) {  		struct mmc_data *data = mrq->data; +		if (host->use_external_dma && data && +		    (mrq->cmd->error || data->error)) { +			struct dma_chan *chan = sdhci_external_dma_channel(host, data); + +			host->mrqs_done[i] = NULL; +			spin_unlock_irqrestore(&host->lock, flags); +			dmaengine_terminate_sync(chan); +			spin_lock_irqsave(&host->lock, flags); +			sdhci_set_mrq_done(host, mrq); +		} +  		if (data && data->host_cookie == COOKIE_MAPPED) {  			if (host->bounce_buffer) {  				/* @@ -3796,6 +4002,21 @@ int sdhci_setup_host(struct sdhci_host *host)  	if (sdhci_can_64bit_dma(host))  		host->flags |= SDHCI_USE_64_BIT_DMA; +	if (host->use_external_dma) { +		ret = sdhci_external_dma_init(host); +		if (ret == -EPROBE_DEFER) +			goto unreg; +		/* +		 * Fall back to use the DMA/PIO integrated in standard SDHCI +		 * instead of external DMA devices. +		 */ +		else if (ret) +			sdhci_switch_external_dma(host, false); +		/* Disable internal DMA sources */ +		else +			host->flags &= ~(SDHCI_USE_SDMA | SDHCI_USE_ADMA); +	} +  	if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {  		if (host->ops->set_dma_mask)  			ret = host->ops->set_dma_mask(host); @@ -3822,15 +4043,13 @@ int sdhci_setup_host(struct sdhci_host *host)  		dma_addr_t dma;  		void *buf; -		if (host->flags & SDHCI_USE_64_BIT_DMA) { -			host->adma_table_sz = host->adma_table_cnt * -					      SDHCI_ADMA2_64_DESC_SZ(host); -			host->desc_sz = SDHCI_ADMA2_64_DESC_SZ(host); -		} else { -			host->adma_table_sz = host->adma_table_cnt * -					      SDHCI_ADMA2_32_DESC_SZ; -			host->desc_sz = SDHCI_ADMA2_32_DESC_SZ; -		} +		if (!(host->flags & SDHCI_USE_64_BIT_DMA)) +			host->alloc_desc_sz = SDHCI_ADMA2_32_DESC_SZ; +		else if (!host->alloc_desc_sz) +			host->alloc_desc_sz = SDHCI_ADMA2_64_DESC_SZ(host); + +		host->desc_sz = host->alloc_desc_sz; +		host->adma_table_sz = host->adma_table_cnt * host->desc_sz;  		host->align_buffer_sz = SDHCI_MAX_SEGS * SDHCI_ADMA2_ALIGN;  		/* @@ -3913,11 +4132,13 @@ int sdhci_setup_host(struct sdhci_host *host)  	if (host->ops->get_min_clock)  		mmc->f_min = host->ops->get_min_clock(host);  	else if (host->version >= SDHCI_SPEC_300) { -		if (host->clk_mul) { -			mmc->f_min = (host->max_clk * host->clk_mul) / 1024; +		if (host->clk_mul)  			max_clk = host->max_clk * host->clk_mul; -		} else -			mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_300; +		/* +		 * Divided Clock Mode minimum clock rate is always less than +		 * Programmable Clock Mode minimum clock rate. +		 */ +		mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_300;  	} else  		mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200; @@ -4276,6 +4497,10 @@ void sdhci_cleanup_host(struct sdhci_host *host)  		dma_free_coherent(mmc_dev(mmc), host->align_buffer_sz +  				  host->adma_table_sz, host->align_buffer,  				  host->align_addr); + +	if (host->use_external_dma) +		sdhci_external_dma_release(host); +  	host->adma_table = NULL;  	host->align_buffer = NULL;  } @@ -4321,6 +4546,7 @@ int __sdhci_add_host(struct sdhci_host *host)  	pr_info("%s: SDHCI controller on %s [%s] using %s\n",  		mmc_hostname(mmc), host->hw_name, dev_name(mmc_dev(mmc)), +		host->use_external_dma ? "External DMA" :  		(host->flags & SDHCI_USE_ADMA) ?  		(host->flags & SDHCI_USE_64_BIT_DMA) ? "ADMA 64-bit" : "ADMA" :  		(host->flags & SDHCI_USE_SDMA) ? "DMA" : "PIO"); @@ -4409,6 +4635,9 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)  				  host->adma_table_sz, host->align_buffer,  				  host->align_addr); +	if (host->use_external_dma) +		sdhci_external_dma_release(host); +  	host->adma_table = NULL;  	host->align_buffer = NULL;  } diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index fe83ece6965b..a6a3ddcf97e7 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -487,6 +487,7 @@ struct sdhci_host {  	int irq;		/* Device IRQ */  	void __iomem *ioaddr;	/* Mapped address */ +	phys_addr_t mapbase;	/* physical address base */  	char *bounce_buffer;	/* For packing SDMA reads/writes */  	dma_addr_t bounce_addr;  	unsigned int bounce_buffer_size; @@ -535,6 +536,7 @@ struct sdhci_host {  	bool pending_reset;	/* Cmd/data reset is pending */  	bool irq_wake_enabled;	/* IRQ wakeup is enabled */  	bool v4_mode;		/* Host Version 4 Enable */ +	bool use_external_dma;	/* Host selects to use external DMA */  	struct mmc_request *mrqs_done[SDHCI_MAX_MRQS];	/* Requests done */  	struct mmc_command *cmd;	/* Current command */ @@ -556,7 +558,8 @@ struct sdhci_host {  	dma_addr_t adma_addr;	/* Mapped ADMA descr. table */  	dma_addr_t align_addr;	/* Mapped bounce buffer */ -	unsigned int desc_sz;	/* ADMA descriptor size */ +	unsigned int desc_sz;	/* ADMA current descriptor size */ +	unsigned int alloc_desc_sz;	/* ADMA descr. max size host supports */  	struct workqueue_struct *complete_wq;	/* Request completion wq */  	struct work_struct	complete_work;	/* Request completion work */ @@ -564,6 +567,11 @@ struct sdhci_host {  	struct timer_list timer;	/* Timer for timeouts */  	struct timer_list data_timer;	/* Timer for data timeouts */ +#if IS_ENABLED(CONFIG_MMC_SDHCI_EXTERNAL_DMA) +	struct dma_chan *rx_chan; +	struct dma_chan *tx_chan; +#endif +  	u32 caps;		/* CAPABILITY_0 */  	u32 caps1;		/* CAPABILITY_1 */  	bool read_caps;		/* Capability flags have been read */ @@ -795,5 +803,8 @@ void sdhci_end_tuning(struct sdhci_host *host);  void sdhci_reset_tuning(struct sdhci_host *host);  void sdhci_send_tuning(struct sdhci_host *host, u32 opcode);  void sdhci_abort_tuning(struct sdhci_host *host, u32 opcode); +void sdhci_switch_external_dma(struct sdhci_host *host, bool en); +void sdhci_set_data_timeout_irq(struct sdhci_host *host, bool enable); +void __sdhci_set_timeout(struct sdhci_host *host, struct mmc_command *cmd);  #endif /* __SDHCI_HW_H */ diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c index b8e897e31e2e..3afea580fbea 100644 --- a/drivers/mmc/host/sdhci_am654.c +++ b/drivers/mmc/host/sdhci_am654.c @@ -240,6 +240,35 @@ static void sdhci_am654_write_b(struct sdhci_host *host, u8 val, int reg)  	writeb(val, host->ioaddr + reg);  } +static int sdhci_am654_execute_tuning(struct mmc_host *mmc, u32 opcode) +{ +	struct sdhci_host *host = mmc_priv(mmc); +	int err = sdhci_execute_tuning(mmc, opcode); + +	if (err) +		return err; +	/* +	 * Tuning data remains in the buffer after tuning. +	 * Do a command and data reset to get rid of it +	 */ +	sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); + +	return 0; +} + +static u32 sdhci_am654_cqhci_irq(struct sdhci_host *host, u32 intmask) +{ +	int cmd_error = 0; +	int data_error = 0; + +	if (!sdhci_cqe_irq(host, intmask, &cmd_error, &data_error)) +		return intmask; + +	cqhci_irq(host->mmc, intmask, cmd_error, data_error); + +	return 0; +} +  static struct sdhci_ops sdhci_am654_ops = {  	.get_max_clock = sdhci_pltfm_clk_get_max_clock,  	.get_timeout_clock = sdhci_pltfm_clk_get_max_clock, @@ -248,13 +277,13 @@ static struct sdhci_ops sdhci_am654_ops = {  	.set_power = sdhci_am654_set_power,  	.set_clock = sdhci_am654_set_clock,  	.write_b = sdhci_am654_write_b, +	.irq = sdhci_am654_cqhci_irq,  	.reset = sdhci_reset,  };  static const struct sdhci_pltfm_data sdhci_am654_pdata = {  	.ops = &sdhci_am654_ops, -	.quirks = SDHCI_QUIRK_INVERTED_WRITE_PROTECT | -		  SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12, +	.quirks = SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12,  	.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,  }; @@ -263,19 +292,6 @@ static const struct sdhci_am654_driver_data sdhci_am654_drvdata = {  	.flags = IOMUX_PRESENT | FREQSEL_2_BIT | STRBSEL_4_BIT | DLL_PRESENT,  }; -static u32 sdhci_am654_cqhci_irq(struct sdhci_host *host, u32 intmask) -{ -	int cmd_error = 0; -	int data_error = 0; - -	if (!sdhci_cqe_irq(host, intmask, &cmd_error, &data_error)) -		return intmask; - -	cqhci_irq(host->mmc, intmask, cmd_error, data_error); - -	return 0; -} -  static struct sdhci_ops sdhci_j721e_8bit_ops = {  	.get_max_clock = sdhci_pltfm_clk_get_max_clock,  	.get_timeout_clock = sdhci_pltfm_clk_get_max_clock, @@ -290,8 +306,7 @@ static struct sdhci_ops sdhci_j721e_8bit_ops = {  static const struct sdhci_pltfm_data sdhci_j721e_8bit_pdata = {  	.ops = &sdhci_j721e_8bit_ops, -	.quirks = SDHCI_QUIRK_INVERTED_WRITE_PROTECT | -		  SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12, +	.quirks = SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12,  	.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,  }; @@ -314,8 +329,7 @@ static struct sdhci_ops sdhci_j721e_4bit_ops = {  static const struct sdhci_pltfm_data sdhci_j721e_4bit_pdata = {  	.ops = &sdhci_j721e_4bit_ops, -	.quirks = SDHCI_QUIRK_INVERTED_WRITE_PROTECT | -		  SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12, +	.quirks = SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12,  	.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,  }; @@ -491,7 +505,6 @@ static int sdhci_am654_probe(struct platform_device *pdev)  	struct sdhci_am654_data *sdhci_am654;  	const struct of_device_id *match;  	struct sdhci_host *host; -	struct resource *res;  	struct clk *clk_xin;  	struct device *dev = &pdev->dev;  	void __iomem *base; @@ -524,8 +537,7 @@ static int sdhci_am654_probe(struct platform_device *pdev)  		goto pm_runtime_disable;  	} -	res = platform_get_resource(pdev, IORESOURCE_MEM, 1); -	base = devm_ioremap_resource(dev, res); +	base = devm_platform_ioremap_resource(pdev, 1);  	if (IS_ERR(base)) {  		ret = PTR_ERR(base);  		goto pm_runtime_put; @@ -549,6 +561,8 @@ static int sdhci_am654_probe(struct platform_device *pdev)  		goto pm_runtime_put;  	} +	host->mmc_host_ops.execute_tuning = sdhci_am654_execute_tuning; +  	ret = sdhci_am654_init(host);  	if (ret)  		goto pm_runtime_put; diff --git a/drivers/mmc/host/sdhci_f_sdh30.c b/drivers/mmc/host/sdhci_f_sdh30.c index fa0dfc657c22..4625cc071b61 100644 --- a/drivers/mmc/host/sdhci_f_sdh30.c +++ b/drivers/mmc/host/sdhci_f_sdh30.c @@ -89,7 +89,6 @@ static int sdhci_f_sdh30_probe(struct platform_device *pdev)  {  	struct sdhci_host *host;  	struct device *dev = &pdev->dev; -	struct resource *res;  	int irq, ctrl = 0, ret = 0;  	struct f_sdhost_priv *priv;  	u32 reg = 0; @@ -123,8 +122,7 @@ static int sdhci_f_sdh30_probe(struct platform_device *pdev)  	host->ops = &sdhci_f_sdh30_ops;  	host->irq = irq; -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	host->ioaddr = devm_ioremap_resource(&pdev->dev, res); +	host->ioaddr = devm_platform_ioremap_resource(pdev, 0);  	if (IS_ERR(host->ioaddr)) {  		ret = PTR_ERR(host->ioaddr);  		goto err; diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 98c575de43c7..7e1fd557109c 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -432,8 +432,12 @@ static void sh_mmcif_request_dma(struct sh_mmcif_host *host)  		host->chan_rx = sh_mmcif_request_dma_pdata(host,  							pdata->slave_id_rx);  	} else { -		host->chan_tx = dma_request_slave_channel(dev, "tx"); -		host->chan_rx = dma_request_slave_channel(dev, "rx"); +		host->chan_tx = dma_request_chan(dev, "tx"); +		if (IS_ERR(host->chan_tx)) +			host->chan_tx = NULL; +		host->chan_rx = dma_request_chan(dev, "rx"); +		if (IS_ERR(host->chan_rx)) +			host->chan_rx = NULL;  	}  	dev_dbg(dev, "%s: got channel TX %p RX %p\n", __func__, host->chan_tx,  		host->chan_rx); @@ -1388,7 +1392,6 @@ static int sh_mmcif_probe(struct platform_device *pdev)  	struct sh_mmcif_host *host;  	struct device *dev = &pdev->dev;  	struct sh_mmcif_plat_data *pd = dev->platform_data; -	struct resource *res;  	void __iomem *reg;  	const char *name; @@ -1397,8 +1400,7 @@ static int sh_mmcif_probe(struct platform_device *pdev)  	if (irq[0] < 0)  		return -ENXIO; -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	reg = devm_ioremap_resource(dev, res); +	reg = devm_platform_ioremap_resource(pdev, 0);  	if (IS_ERR(reg))  		return PTR_ERR(reg); diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c index d577a6b0ceae..f87d7967457f 100644 --- a/drivers/mmc/host/sunxi-mmc.c +++ b/drivers/mmc/host/sunxi-mmc.c @@ -1273,8 +1273,7 @@ static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host,  	if (ret)  		return ret; -	host->reg_base = devm_ioremap_resource(&pdev->dev, -			      platform_get_resource(pdev, IORESOURCE_MEM, 0)); +	host->reg_base = devm_platform_ioremap_resource(pdev, 0);  	if (IS_ERR(host->reg_base))  		return PTR_ERR(host->reg_base); diff --git a/drivers/mmc/host/tmio_mmc_core.c b/drivers/mmc/host/tmio_mmc_core.c index c4a1d49fbea4..1e424bcdbd5f 100644 --- a/drivers/mmc/host/tmio_mmc_core.c +++ b/drivers/mmc/host/tmio_mmc_core.c @@ -1109,12 +1109,10 @@ struct tmio_mmc_host *tmio_mmc_host_alloc(struct platform_device *pdev,  {  	struct tmio_mmc_host *host;  	struct mmc_host *mmc; -	struct resource *res;  	void __iomem *ctl;  	int ret; -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	ctl = devm_ioremap_resource(&pdev->dev, res); +	ctl = devm_platform_ioremap_resource(pdev, 0);  	if (IS_ERR(ctl))  		return ERR_CAST(ctl); @@ -1181,7 +1179,7 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host)  	 * Look for a card detect GPIO, if it fails with anything  	 * else than a probe deferral, just live without it.  	 */ -	ret = mmc_gpiod_request_cd(mmc, "cd", 0, false, 0, NULL); +	ret = mmc_gpiod_request_cd(mmc, "cd", 0, false, 0);  	if (ret == -EPROBE_DEFER)  		return ret; diff --git a/drivers/mmc/host/uniphier-sd.c b/drivers/mmc/host/uniphier-sd.c index 0c72ec5546c3..a1683c49cb90 100644 --- a/drivers/mmc/host/uniphier-sd.c +++ b/drivers/mmc/host/uniphier-sd.c @@ -59,7 +59,6 @@  struct uniphier_sd_priv {  	struct tmio_mmc_data tmio_data;  	struct pinctrl *pinctrl; -	struct pinctrl_state *pinstate_default;  	struct pinctrl_state *pinstate_uhs;  	struct clk *clk;  	struct reset_control *rst; @@ -500,13 +499,12 @@ static int uniphier_sd_start_signal_voltage_switch(struct mmc_host *mmc,  {  	struct tmio_mmc_host *host = mmc_priv(mmc);  	struct uniphier_sd_priv *priv = uniphier_sd_priv(host); -	struct pinctrl_state *pinstate; +	struct pinctrl_state *pinstate = NULL;  	u32 val, tmp;  	switch (ios->signal_voltage) {  	case MMC_SIGNAL_VOLTAGE_330:  		val = UNIPHIER_SD_VOLT_330; -		pinstate = priv->pinstate_default;  		break;  	case MMC_SIGNAL_VOLTAGE_180:  		val = UNIPHIER_SD_VOLT_180; @@ -521,7 +519,10 @@ static int uniphier_sd_start_signal_voltage_switch(struct mmc_host *mmc,  	tmp |= FIELD_PREP(UNIPHIER_SD_VOLT_MASK, val);  	writel(tmp, host->ctl + UNIPHIER_SD_VOLT); -	pinctrl_select_state(priv->pinctrl, pinstate); +	if (pinstate) +		pinctrl_select_state(priv->pinctrl, pinstate); +	else +		pinctrl_select_default_state(mmc_dev(mmc));  	return 0;  } @@ -533,11 +534,6 @@ static int uniphier_sd_uhs_init(struct tmio_mmc_host *host,  	if (IS_ERR(priv->pinctrl))  		return PTR_ERR(priv->pinctrl); -	priv->pinstate_default = pinctrl_lookup_state(priv->pinctrl, -						      PINCTRL_STATE_DEFAULT); -	if (IS_ERR(priv->pinstate_default)) -		return PTR_ERR(priv->pinstate_default); -  	priv->pinstate_uhs = pinctrl_lookup_state(priv->pinctrl, "uhs");  	if (IS_ERR(priv->pinstate_uhs))  		return PTR_ERR(priv->pinstate_uhs); diff --git a/drivers/mmc/host/usdhi6rol0.c b/drivers/mmc/host/usdhi6rol0.c index b11ac2314328..9a0b1e4e405d 100644 --- a/drivers/mmc/host/usdhi6rol0.c +++ b/drivers/mmc/host/usdhi6rol0.c @@ -199,7 +199,6 @@ struct usdhi6_host {  	/* Pin control */  	struct pinctrl *pinctrl; -	struct pinctrl_state *pins_default;  	struct pinctrl_state *pins_uhs;  }; @@ -677,12 +676,14 @@ static void usdhi6_dma_request(struct usdhi6_host *host, phys_addr_t start)  	};  	int ret; -	host->chan_tx = dma_request_slave_channel(mmc_dev(host->mmc), "tx"); +	host->chan_tx = dma_request_chan(mmc_dev(host->mmc), "tx");  	dev_dbg(mmc_dev(host->mmc), "%s: TX: got channel %p\n", __func__,  		host->chan_tx); -	if (!host->chan_tx) +	if (IS_ERR(host->chan_tx)) { +		host->chan_tx = NULL;  		return; +	}  	cfg.direction = DMA_MEM_TO_DEV;  	cfg.dst_addr = start + USDHI6_SD_BUF0; @@ -692,12 +693,14 @@ static void usdhi6_dma_request(struct usdhi6_host *host, phys_addr_t start)  	if (ret < 0)  		goto e_release_tx; -	host->chan_rx = dma_request_slave_channel(mmc_dev(host->mmc), "rx"); +	host->chan_rx = dma_request_chan(mmc_dev(host->mmc), "rx");  	dev_dbg(mmc_dev(host->mmc), "%s: RX: got channel %p\n", __func__,  		host->chan_rx); -	if (!host->chan_rx) +	if (IS_ERR(host->chan_rx)) { +		host->chan_rx = NULL;  		goto e_release_tx; +	}  	cfg.direction = DMA_DEV_TO_MEM;  	cfg.src_addr = cfg.dst_addr; @@ -1162,8 +1165,7 @@ static int usdhi6_set_pinstates(struct usdhi6_host *host, int voltage)  					    host->pins_uhs);  	default: -		return pinctrl_select_state(host->pinctrl, -					    host->pins_default); +		return pinctrl_select_default_state(mmc_dev(host->mmc));  	}  } @@ -1770,17 +1772,6 @@ static int usdhi6_probe(struct platform_device *pdev)  	}  	host->pins_uhs = pinctrl_lookup_state(host->pinctrl, "state_uhs"); -	if (!IS_ERR(host->pins_uhs)) { -		host->pins_default = pinctrl_lookup_state(host->pinctrl, -							  PINCTRL_STATE_DEFAULT); - -		if (IS_ERR(host->pins_default)) { -			dev_err(dev, -				"UHS pinctrl requires a default pin state.\n"); -			ret = PTR_ERR(host->pins_default); -			goto e_free_mmc; -		} -	}  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	host->base = devm_ioremap_resource(dev, res); diff --git a/drivers/mmc/host/via-sdmmc.c b/drivers/mmc/host/via-sdmmc.c index f4ac064ff471..e48bddd95ce6 100644 --- a/drivers/mmc/host/via-sdmmc.c +++ b/drivers/mmc/host/via-sdmmc.c @@ -1106,7 +1106,7 @@ static int via_sd_probe(struct pci_dev *pcidev,  	len = pci_resource_len(pcidev, 0);  	base = pci_resource_start(pcidev, 0); -	sdhost->mmiobase = ioremap_nocache(base, len); +	sdhost->mmiobase = ioremap(base, len);  	if (!sdhost->mmiobase) {  		ret = -ENOMEM;  		goto free_mmc_host;  |