diff options
Diffstat (limited to 'drivers/mmc/host')
36 files changed, 620 insertions, 267 deletions
| diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index b236dfe2e879..a4d4c757eea0 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -278,6 +278,7 @@ config MMC_SDHCI_ESDHC_IMX  	tristate "SDHCI support for the Freescale eSDHC/uSDHC i.MX controller"  	depends on ARCH_MXC || COMPILE_TEST  	depends on MMC_SDHCI_PLTFM +	depends on OF  	select MMC_SDHCI_IO_ACCESSORS  	select MMC_CQHCI  	help @@ -707,6 +708,7 @@ config MMC_SDHI  	tristate "Renesas SDHI SD/SDIO controller support"  	depends on SUPERH || ARCH_RENESAS || COMPILE_TEST  	select MMC_TMIO_CORE +	select RESET_CONTROLLER if ARCH_RENESAS  	help  	  This provides support for the SDHI SD/SDIO controller found in  	  Renesas SuperH, ARM and ARM64 based SoCs diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index 6df5c4774260..14004cc09aaa 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile @@ -34,9 +34,7 @@ obj-$(CONFIG_MMC_TIFM_SD)	+= tifm_sd.o  obj-$(CONFIG_MMC_MVSDIO)	+= mvsdio.o  obj-$(CONFIG_MMC_DAVINCI)       += davinci_mmc.o  obj-$(CONFIG_MMC_SPI)		+= mmc_spi.o -ifeq ($(CONFIG_OF),y)  obj-$(CONFIG_MMC_SPI)		+= of_mmc_spi.o -endif  obj-$(CONFIG_MMC_S3C)   	+= s3cmci.o  obj-$(CONFIG_MMC_SDRICOH_CS)	+= sdricoh_cs.o  obj-$(CONFIG_MMC_TMIO)		+= tmio_mmc.o diff --git a/drivers/mmc/host/cavium.c b/drivers/mmc/host/cavium.c index 4bb8f2800a2b..95a41983c6c0 100644 --- a/drivers/mmc/host/cavium.c +++ b/drivers/mmc/host/cavium.c @@ -656,8 +656,7 @@ static void cvm_mmc_dma_request(struct mmc_host *mmc,  	if (!mrq->data || !mrq->data->sg || !mrq->data->sg_len ||  	    !mrq->stop || mrq->stop->opcode != MMC_STOP_TRANSMISSION) { -		dev_err(&mmc->card->dev, -			"Error: cmv_mmc_dma_request no data\n"); +		dev_err(&mmc->card->dev, "Error: %s no data\n", __func__);  		goto error;  	} diff --git a/drivers/mmc/host/dw_mmc-k3.c b/drivers/mmc/host/dw_mmc-k3.c index 29d2494eb27a..0311a37dd4ab 100644 --- a/drivers/mmc/host/dw_mmc-k3.c +++ b/drivers/mmc/host/dw_mmc-k3.c @@ -1,7 +1,7 @@  // SPDX-License-Identifier: GPL-2.0-or-later  /*   * Copyright (c) 2013 Linaro Ltd. - * Copyright (c) 2013 Hisilicon Limited. + * Copyright (c) 2013 HiSilicon Limited.   */  #include <linux/bitops.h> diff --git a/drivers/mmc/host/dw_mmc-rockchip.c b/drivers/mmc/host/dw_mmc-rockchip.c index 753502ce3c85..d36991acd6df 100644 --- a/drivers/mmc/host/dw_mmc-rockchip.c +++ b/drivers/mmc/host/dw_mmc-rockchip.c @@ -61,7 +61,7 @@ static void dw_mci_rk3288_set_ios(struct dw_mci *host, struct mmc_ios *ios)  	}  	/* Make sure we use phases which we can enumerate with */ -	if (!IS_ERR(priv->sample_clk)) +	if (!IS_ERR(priv->sample_clk) && ios->timing <= MMC_TIMING_SD_HS)  		clk_set_phase(priv->sample_clk, priv->default_sample_phase);  	/* diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 2f4de30f650b..d333130d1531 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -2606,8 +2606,6 @@ static void dw_mci_handle_cd(struct dw_mci *host)  {  	struct dw_mci_slot *slot = host->slot; -	if (slot->mmc->ops->card_event) -		slot->mmc->ops->card_event(slot->mmc);  	mmc_detect_change(slot->mmc,  		msecs_to_jiffies(host->pdata->detect_delay_ms));  } @@ -3095,10 +3093,8 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)  	/* find reset controller when exist */  	pdata->rstc = devm_reset_control_get_optional_exclusive(dev, "reset"); -	if (IS_ERR(pdata->rstc)) { -		if (PTR_ERR(pdata->rstc) == -EPROBE_DEFER) -			return ERR_PTR(-EPROBE_DEFER); -	} +	if (IS_ERR(pdata->rstc)) +		return ERR_CAST(pdata->rstc);  	if (device_property_read_u32(dev, "fifo-depth", &pdata->fifo_depth))  		dev_info(dev, @@ -3204,7 +3200,7 @@ int dw_mci_probe(struct dw_mci *host)  		goto err_clk_ciu;  	} -	if (!IS_ERR(host->pdata->rstc)) { +	if (host->pdata->rstc) {  		reset_control_assert(host->pdata->rstc);  		usleep_range(10, 50);  		reset_control_deassert(host->pdata->rstc); @@ -3344,8 +3340,7 @@ err_dmaunmap:  	if (host->use_dma && host->dma_ops->exit)  		host->dma_ops->exit(host); -	if (!IS_ERR(host->pdata->rstc)) -		reset_control_assert(host->pdata->rstc); +	reset_control_assert(host->pdata->rstc);  err_clk_ciu:  	clk_disable_unprepare(host->ciu_clk); @@ -3373,8 +3368,7 @@ void dw_mci_remove(struct dw_mci *host)  	if (host->use_dma && host->dma_ops->exit)  		host->dma_ops->exit(host); -	if (!IS_ERR(host->pdata->rstc)) -		reset_control_assert(host->pdata->rstc); +	reset_control_assert(host->pdata->rstc);  	clk_disable_unprepare(host->ciu_clk);  	clk_disable_unprepare(host->biu_clk); diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c index eb6c02bc4a02..b8b771b643cc 100644 --- a/drivers/mmc/host/meson-gx-mmc.c +++ b/drivers/mmc/host/meson-gx-mmc.c @@ -247,8 +247,9 @@ static void meson_mmc_get_transfer_mode(struct mmc_host *mmc,  		 */  		for_each_sg(data->sg, sg, data->sg_len, i) {  			if (sg->length % data->blksz) { -				WARN_ONCE(1, "unaligned sg len %u blksize %u\n", -					  sg->length, data->blksz); +				dev_warn_once(mmc_dev(mmc), +					      "unaligned sg len %u blksize %u, disabling descriptor DMA for transfer\n", +					      sg->length, data->blksz);  				return;  			}  		} diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c index 02f4fd26e76a..9776a03a10f5 100644 --- a/drivers/mmc/host/mmc_spi.c +++ b/drivers/mmc/host/mmc_spi.c @@ -1397,6 +1397,8 @@ static int mmc_spi_probe(struct spi_device *spi)  	host->ones = ones; +	dev_set_drvdata(&spi->dev, mmc); +  	/* Platform data is used to hook up things like card sensing  	 * and power switching gpios.  	 */ @@ -1413,8 +1415,6 @@ static int mmc_spi_probe(struct spi_device *spi)  			host->powerup_msecs = 250;  	} -	dev_set_drvdata(&spi->dev, mmc); -  	/* preallocate dma buffers */  	host->data = kmalloc(sizeof(*host->data), GFP_KERNEL);  	if (!host->data) @@ -1494,8 +1494,8 @@ fail_glue_init:  fail_dma:  	kfree(host->data);  fail_nobuf1: -	mmc_free_host(mmc);  	mmc_spi_put_pdata(spi); +	mmc_free_host(mmc);  nomem:  	kfree(ones);  	return status; @@ -1518,8 +1518,8 @@ static int mmc_spi_remove(struct spi_device *spi)  	kfree(host->ones);  	spi->max_speed_hz = mmc->f_max; -	mmc_free_host(mmc);  	mmc_spi_put_pdata(spi); +	mmc_free_host(mmc);  	return 0;  } diff --git a/drivers/mmc/host/moxart-mmc.c b/drivers/mmc/host/moxart-mmc.c index 89bff4e8ec10..bde298887579 100644 --- a/drivers/mmc/host/moxart-mmc.c +++ b/drivers/mmc/host/moxart-mmc.c @@ -257,7 +257,6 @@ static void moxart_dma_complete(void *param)  static void moxart_transfer_dma(struct mmc_data *data, struct moxart_host *host)  {  	u32 len, dir_slave; -	long dma_time;  	struct dma_async_tx_descriptor *desc = NULL;  	struct dma_chan *dma_chan; @@ -294,8 +293,8 @@ static void moxart_transfer_dma(struct mmc_data *data, struct moxart_host *host)  	data->bytes_xfered += host->data_remain; -	dma_time = wait_for_completion_interruptible_timeout( -		   &host->dma_complete, host->timeout); +	wait_for_completion_interruptible_timeout(&host->dma_complete, +						  host->timeout);  	dma_unmap_sg(dma_chan->device->dev,  		     data->sg, data->sg_len, @@ -395,7 +394,6 @@ static void moxart_prepare_data(struct moxart_host *host)  static void moxart_request(struct mmc_host *mmc, struct mmc_request *mrq)  {  	struct moxart_host *host = mmc_priv(mmc); -	long pio_time;  	unsigned long flags;  	u32 status; @@ -431,8 +429,8 @@ static void moxart_request(struct mmc_host *mmc, struct mmc_request *mrq)  			spin_unlock_irqrestore(&host->lock, flags);  			/* PIO transfers start from interrupt. */ -			pio_time = wait_for_completion_interruptible_timeout( -				   &host->pio_complete, host->timeout); +			wait_for_completion_interruptible_timeout(&host->pio_complete, +								  host->timeout);  			spin_lock_irqsave(&host->lock, flags);  		} diff --git a/drivers/mmc/host/of_mmc_spi.c b/drivers/mmc/host/of_mmc_spi.c index 3c4d950a4755..9d480a05f655 100644 --- a/drivers/mmc/host/of_mmc_spi.c +++ b/drivers/mmc/host/of_mmc_spi.c @@ -19,11 +19,6 @@  #include <linux/mmc/core.h>  #include <linux/mmc/host.h> -/* For archs that don't support NO_IRQ (such as mips), provide a dummy value */ -#ifndef NO_IRQ -#define NO_IRQ 0 -#endif -  MODULE_LICENSE("GPL");  struct of_mmc_spi { @@ -54,22 +49,22 @@ static void of_mmc_spi_exit(struct device *dev, void *mmc)  struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi)  { +	struct mmc_host *mmc = dev_get_drvdata(&spi->dev);  	struct device *dev = &spi->dev; -	struct device_node *np = dev->of_node;  	struct of_mmc_spi *oms; -	if (dev->platform_data || !np) +	if (dev->platform_data || !dev_fwnode(dev))  		return dev->platform_data;  	oms = kzalloc(sizeof(*oms), GFP_KERNEL);  	if (!oms)  		return NULL; -	if (mmc_of_parse_voltage(np, &oms->pdata.ocr_mask) <= 0) +	if (mmc_of_parse_voltage(mmc, &oms->pdata.ocr_mask) < 0)  		goto err_ocr; -	oms->detect_irq = irq_of_parse_and_map(np, 0); -	if (oms->detect_irq != 0) { +	oms->detect_irq = spi->irq; +	if (oms->detect_irq > 0) {  		oms->pdata.init = of_mmc_spi_init;  		oms->pdata.exit = of_mmc_spi_exit;  	} else { @@ -87,10 +82,9 @@ EXPORT_SYMBOL(mmc_spi_get_pdata);  void mmc_spi_put_pdata(struct spi_device *spi)  {  	struct device *dev = &spi->dev; -	struct device_node *np = dev->of_node;  	struct of_mmc_spi *oms = to_of_mmc_spi(dev); -	if (!dev->platform_data || !np) +	if (!dev->platform_data || !dev_fwnode(dev))  		return;  	kfree(oms); diff --git a/drivers/mmc/host/owl-mmc.c b/drivers/mmc/host/owl-mmc.c index 5490962dc8e5..3dc143b03939 100644 --- a/drivers/mmc/host/owl-mmc.c +++ b/drivers/mmc/host/owl-mmc.c @@ -581,7 +581,6 @@ static int owl_mmc_probe(struct platform_device *pdev)  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	owl_host->base = devm_ioremap_resource(&pdev->dev, res);  	if (IS_ERR(owl_host->base)) { -		dev_err(&pdev->dev, "Failed to remap registers\n");  		ret = PTR_ERR(owl_host->base);  		goto err_free_host;  	} diff --git a/drivers/mmc/host/renesas_sdhi.h b/drivers/mmc/host/renesas_sdhi.h index cb962c7883dc..53eded81a53e 100644 --- a/drivers/mmc/host/renesas_sdhi.h +++ b/drivers/mmc/host/renesas_sdhi.h @@ -70,6 +70,8 @@ struct renesas_sdhi {  	DECLARE_BITMAP(smpcmp, BITS_PER_LONG);  	unsigned int tap_num;  	unsigned int tap_set; + +	struct reset_control *rstc;  };  #define host_to_priv(host) \ diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index 158c21e5a942..635bf31a6735 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -20,6 +20,7 @@  #include <linux/clk.h>  #include <linux/delay.h> +#include <linux/iopoll.h>  #include <linux/kernel.h>  #include <linux/mfd/tmio.h>  #include <linux/mmc/host.h> @@ -32,6 +33,7 @@  #include <linux/platform_device.h>  #include <linux/pm_domain.h>  #include <linux/regulator/consumer.h> +#include <linux/reset.h>  #include <linux/sh_dma.h>  #include <linux/slab.h>  #include <linux/sys_soc.h> @@ -557,24 +559,35 @@ static int renesas_sdhi_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_io  	return 0;  } +static void renesas_sdhi_scc_reset(struct tmio_mmc_host *host, struct renesas_sdhi *priv) +{ +	renesas_sdhi_disable_scc(host->mmc); +	renesas_sdhi_reset_hs400_mode(host, priv); +	priv->needs_adjust_hs400 = false; + +	sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL, +		       ~SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN & +		       sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL)); +} +  /* only populated for TMIO_MMC_MIN_RCAR2 */  static void renesas_sdhi_reset(struct tmio_mmc_host *host)  {  	struct renesas_sdhi *priv = host_to_priv(host); +	int ret;  	u16 val; -	if (priv->scc_ctl) { -		renesas_sdhi_disable_scc(host->mmc); -		renesas_sdhi_reset_hs400_mode(host, priv); +	if (priv->rstc) { +		reset_control_reset(priv->rstc); +		/* Unknown why but without polling reset status, it will hang */ +		read_poll_timeout(reset_control_status, ret, ret == 0, 1, 100, +				  false, priv->rstc);  		priv->needs_adjust_hs400 = false; - -		sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL, -			       ~SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN & -			       sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL)); +		renesas_sdhi_set_clock(host, host->clk_cache); +	} else if (priv->scc_ctl) { +		renesas_sdhi_scc_reset(host, priv);  	} -	sd_ctrl_write32_as_16_and_16(host, CTL_IRQ_MASK, TMIO_MASK_INIT_RCAR2); -  	if (sd_ctrl_read16(host, CTL_VERSION) >= SDHI_VER_GEN3_SD) {  		val = sd_ctrl_read16(host, CTL_SD_MEM_CARD_OPT);  		val |= CARD_OPT_EXTOP; @@ -691,7 +704,7 @@ static int renesas_sdhi_execute_tuning(struct mmc_host *mmc, u32 opcode)  	ret = renesas_sdhi_select_tuning(host);  	if (ret < 0) -		renesas_sdhi_reset(host); +		renesas_sdhi_scc_reset(host, priv);  	return ret;  } @@ -1034,6 +1047,7 @@ int renesas_sdhi_probe(struct platform_device *pdev,  		host->ops.start_signal_voltage_switch =  			renesas_sdhi_start_signal_voltage_switch;  		host->sdcard_irq_setbit_mask = TMIO_STAT_ALWAYS_SET_27; +		host->sdcard_irq_mask_all = TMIO_MASK_ALL_RCAR2;  		host->reset = renesas_sdhi_reset;  	} @@ -1076,6 +1090,10 @@ int renesas_sdhi_probe(struct platform_device *pdev,  	if (ret)  		goto efree; +	priv->rstc = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL); +	if (IS_ERR(priv->rstc)) +		return PTR_ERR(priv->rstc); +  	ver = sd_ctrl_read16(host, CTL_VERSION);  	/* GEN2_SDR104 is first known SDHI to use 32bit block count */  	if (ver < SDHI_VER_GEN2_SDR104 && mmc_data->max_blk_count > U16_MAX) diff --git a/drivers/mmc/host/renesas_sdhi_internal_dmac.c b/drivers/mmc/host/renesas_sdhi_internal_dmac.c index ff97f15e317c..e8f4863d8f1a 100644 --- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c +++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c @@ -97,7 +97,7 @@ static const struct renesas_sdhi_of_data of_rza2_compatible = {  			  TMIO_MMC_HAVE_CBSY,  	.tmio_ocr_mask	= MMC_VDD_32_33,  	.capabilities	= MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ | -			  MMC_CAP_CMD23, +			  MMC_CAP_CMD23 | MMC_CAP_WAIT_WHILE_BUSY,  	.bus_shift	= 2,  	.scc_offset	= 0 - 0x1000,  	.taps		= rcar_gen3_scc_taps, @@ -111,7 +111,7 @@ static const struct renesas_sdhi_of_data of_rcar_gen3_compatible = {  	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_CLK_ACTUAL |  			  TMIO_MMC_HAVE_CBSY | TMIO_MMC_MIN_RCAR2,  	.capabilities	= MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ | -			  MMC_CAP_CMD23, +			  MMC_CAP_CMD23 | MMC_CAP_WAIT_WHILE_BUSY,  	.capabilities2	= MMC_CAP2_NO_WRITE_PROTECT | MMC_CAP2_MERGE_CAPABLE,  	.bus_shift	= 2,  	.scc_offset	= 0x1000, diff --git a/drivers/mmc/host/renesas_sdhi_sys_dmac.c b/drivers/mmc/host/renesas_sdhi_sys_dmac.c index c5f789675302..ffa64211f4de 100644 --- a/drivers/mmc/host/renesas_sdhi_sys_dmac.c +++ b/drivers/mmc/host/renesas_sdhi_sys_dmac.c @@ -33,12 +33,14 @@ static const struct renesas_sdhi_of_data of_rz_compatible = {  	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_32BIT_DATA_PORT |  			  TMIO_MMC_HAVE_CBSY,  	.tmio_ocr_mask	= MMC_VDD_32_33, -	.capabilities	= MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ, +	.capabilities	= MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ | +			  MMC_CAP_WAIT_WHILE_BUSY,  };  static const struct renesas_sdhi_of_data of_rcar_gen1_compatible = {  	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_CLK_ACTUAL, -	.capabilities	= MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ, +	.capabilities	= MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ | +			  MMC_CAP_WAIT_WHILE_BUSY,  	.capabilities2	= MMC_CAP2_NO_WRITE_PROTECT,  }; @@ -58,7 +60,7 @@ static const struct renesas_sdhi_of_data of_rcar_gen2_compatible = {  	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_CLK_ACTUAL |  			  TMIO_MMC_HAVE_CBSY | TMIO_MMC_MIN_RCAR2,  	.capabilities	= MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ | -			  MMC_CAP_CMD23, +			  MMC_CAP_CMD23 | MMC_CAP_WAIT_WHILE_BUSY,  	.capabilities2	= MMC_CAP2_NO_WRITE_PROTECT,  	.dma_buswidth	= DMA_SLAVE_BUSWIDTH_4_BYTES,  	.dma_rx_offset	= 0x2000, diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c index b6574e7fd26b..c3fbf8c825c4 100644 --- a/drivers/mmc/host/sdhci-acpi.c +++ b/drivers/mmc/host/sdhci-acpi.c @@ -772,6 +772,7 @@ static const struct sdhci_acpi_uid_slot sdhci_acpi_uids[] = {  	{ "QCOM8051", NULL, &sdhci_acpi_slot_qcom_sd_3v },  	{ "QCOM8052", NULL, &sdhci_acpi_slot_qcom_sd },  	{ "AMDI0040", NULL, &sdhci_acpi_slot_amd_emmc }, +	{ "AMDI0041", NULL, &sdhci_acpi_slot_amd_emmc },  	{ },  }; @@ -789,6 +790,7 @@ static const struct acpi_device_id sdhci_acpi_ids[] = {  	{ "QCOM8051" },  	{ "QCOM8052" },  	{ "AMDI0040" }, +	{ "AMDI0041" },  	{ },  };  MODULE_DEVICE_TABLE(acpi, sdhci_acpi_ids); diff --git a/drivers/mmc/host/sdhci-brcmstb.c b/drivers/mmc/host/sdhci-brcmstb.c index f9780c65ebe9..f24623aac2db 100644 --- a/drivers/mmc/host/sdhci-brcmstb.c +++ b/drivers/mmc/host/sdhci-brcmstb.c @@ -199,7 +199,6 @@ static int sdhci_brcmstb_add_host(struct sdhci_host *host,  	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); diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index a20459744d21..b991cf0e60c5 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -434,10 +434,10 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg)  			 * Do not advertise faster UHS modes if there are no  			 * pinctrl states for 100MHz/200MHz.  			 */ -			if (IS_ERR_OR_NULL(imx_data->pins_100mhz) || -			    IS_ERR_OR_NULL(imx_data->pins_200mhz)) -				val &= ~(SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_DDR50 -					 | SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_HS400); +			if (IS_ERR_OR_NULL(imx_data->pins_100mhz)) +				val &= ~(SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_DDR50); +			if (IS_ERR_OR_NULL(imx_data->pins_200mhz)) +				val &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_HS400);  		}  	} @@ -1453,7 +1453,6 @@ static const struct cqhci_host_ops esdhc_cqhci_ops = {  	.dumpregs	= esdhc_sdhci_dumpregs,  }; -#ifdef CONFIG_OF  static int  sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,  			 struct sdhci_host *host, @@ -1486,9 +1485,9 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,  	if (of_property_read_u32(np, "fsl,delay-line", &boarddata->delay_line))  		boarddata->delay_line = 0; -	mmc_of_parse_voltage(np, &host->ocr_mask); +	mmc_of_parse_voltage(host->mmc, &host->ocr_mask); -	if (esdhc_is_usdhc(imx_data)) { +	if (esdhc_is_usdhc(imx_data) && !IS_ERR(imx_data->pinctrl)) {  		imx_data->pins_100mhz = pinctrl_lookup_state(imx_data->pinctrl,  						ESDHC_PINCTRL_STATE_100MHZ);  		imx_data->pins_200mhz = pinctrl_lookup_state(imx_data->pinctrl, @@ -1505,20 +1504,9 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,  	return 0;  } -#else -static inline int -sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, -			 struct sdhci_host *host, -			 struct pltfm_imx_data *imx_data) -{ -	return -ENODEV; -} -#endif  static int sdhci_esdhc_imx_probe(struct platform_device *pdev)  { -	const struct of_device_id *of_id = -			of_match_device(imx_esdhc_dt_ids, &pdev->dev);  	struct sdhci_pltfm_host *pltfm_host;  	struct sdhci_host *host;  	struct cqhci_host *cq_host; @@ -1534,7 +1522,7 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)  	imx_data = sdhci_pltfm_priv(pltfm_host); -	imx_data->socdata = of_id->data; +	imx_data->socdata = device_get_match_data(&pdev->dev);  	if (imx_data->socdata->flags & ESDHC_FLAG_PMQOS)  		cpu_latency_qos_add_request(&imx_data->pm_qos_req, 0); diff --git a/drivers/mmc/host/sdhci-esdhc-mcf.c b/drivers/mmc/host/sdhci-esdhc-mcf.c index ca7a1690b2a8..05926bf5ecf9 100644 --- a/drivers/mmc/host/sdhci-esdhc-mcf.c +++ b/drivers/mmc/host/sdhci-esdhc-mcf.c @@ -367,14 +367,14 @@ static int esdhc_mcf_plat_init(struct sdhci_host *host,  			       struct pltfm_mcf_data *mcf_data)  {  	struct mcf_esdhc_platform_data *plat_data; +	struct device *dev = mmc_dev(host->mmc); -	if (!host->mmc->parent->platform_data) { -		dev_err(mmc_dev(host->mmc), "no platform data!\n"); +	if (!dev->platform_data) { +		dev_err(dev, "no platform data!\n");  		return -EINVAL;  	} -	plat_data = (struct mcf_esdhc_platform_data *) -			host->mmc->parent->platform_data; +	plat_data = (struct mcf_esdhc_platform_data *)dev->platform_data;  	/* Card_detect */  	switch (plat_data->cd_type) { diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index 5e1da4df096f..e44b7a66b73c 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -264,7 +264,6 @@ struct sdhci_msm_host {  	struct clk_bulk_data bulk_clks[5];  	unsigned long clk_rate;  	struct mmc_host *mmc; -	struct opp_table *opp_table;  	bool use_14lpp_dll_reset;  	bool tuning_done;  	bool calibration_done; @@ -1864,7 +1863,6 @@ static int sdhci_msm_ice_init(struct sdhci_msm_host *msm_host,  	struct mmc_host *mmc = msm_host->mmc;  	struct device *dev = mmc_dev(mmc);  	struct resource *res; -	int err;  	if (!(cqhci_readl(cq_host, CQHCI_CAP) & CQHCI_CAP_CS))  		return 0; @@ -1882,11 +1880,8 @@ static int sdhci_msm_ice_init(struct sdhci_msm_host *msm_host,  	}  	msm_host->ice_mem = devm_ioremap_resource(dev, res); -	if (IS_ERR(msm_host->ice_mem)) { -		err = PTR_ERR(msm_host->ice_mem); -		dev_err(dev, "Failed to map ICE registers; err=%d\n", err); -		return err; -	} +	if (IS_ERR(msm_host->ice_mem)) +		return PTR_ERR(msm_host->ice_mem);  	if (!sdhci_msm_ice_supported(msm_host))  		goto disable; @@ -2551,17 +2546,15 @@ static int sdhci_msm_probe(struct platform_device *pdev)  	if (ret)  		goto bus_clk_disable; -	msm_host->opp_table = dev_pm_opp_set_clkname(&pdev->dev, "core"); -	if (IS_ERR(msm_host->opp_table)) { -		ret = PTR_ERR(msm_host->opp_table); +	ret = devm_pm_opp_set_clkname(&pdev->dev, "core"); +	if (ret)  		goto bus_clk_disable; -	}  	/* OPP table is optional */ -	ret = dev_pm_opp_of_add_table(&pdev->dev); +	ret = devm_pm_opp_of_add_table(&pdev->dev);  	if (ret && ret != -ENODEV) {  		dev_err(&pdev->dev, "Invalid OPP table in Device tree\n"); -		goto opp_put_clkname; +		goto bus_clk_disable;  	}  	/* Vote for maximum clock rate for maximum performance */ @@ -2587,7 +2580,7 @@ static int sdhci_msm_probe(struct platform_device *pdev)  	ret = clk_bulk_prepare_enable(ARRAY_SIZE(msm_host->bulk_clks),  				      msm_host->bulk_clks);  	if (ret) -		goto opp_cleanup; +		goto bus_clk_disable;  	/*  	 * xo clock is needed for FLL feature of cm_dll. @@ -2732,10 +2725,6 @@ pm_runtime_disable:  clk_disable:  	clk_bulk_disable_unprepare(ARRAY_SIZE(msm_host->bulk_clks),  				   msm_host->bulk_clks); -opp_cleanup: -	dev_pm_opp_of_remove_table(&pdev->dev); -opp_put_clkname: -	dev_pm_opp_put_clkname(msm_host->opp_table);  bus_clk_disable:  	if (!IS_ERR(msm_host->bus_clk))  		clk_disable_unprepare(msm_host->bus_clk); @@ -2754,8 +2743,6 @@ static int sdhci_msm_remove(struct platform_device *pdev)  	sdhci_remove_host(host, dead); -	dev_pm_opp_of_remove_table(&pdev->dev); -	dev_pm_opp_put_clkname(msm_host->opp_table);  	pm_runtime_get_sync(&pdev->dev);  	pm_runtime_disable(&pdev->dev);  	pm_runtime_put_noidle(&pdev->dev); diff --git a/drivers/mmc/host/sdhci-of-aspeed.c b/drivers/mmc/host/sdhci-of-aspeed.c index 7d8692e90996..d001c51074a0 100644 --- a/drivers/mmc/host/sdhci-of-aspeed.c +++ b/drivers/mmc/host/sdhci-of-aspeed.c @@ -181,7 +181,7 @@ aspeed_sdhci_configure_phase(struct sdhci_host *host, unsigned long rate)  	struct aspeed_sdhci *sdhci;  	struct device *dev; -	dev = host->mmc->parent; +	dev = mmc_dev(host->mmc);  	sdhci = sdhci_pltfm_priv(sdhci_priv(host));  	if (!sdhci->phase_desc) diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c index 59d8d96ce206..bac874ab0b33 100644 --- a/drivers/mmc/host/sdhci-of-dwcmshc.c +++ b/drivers/mmc/host/sdhci-of-dwcmshc.c @@ -7,11 +7,14 @@   * Author: Jisheng Zhang <jszhang@kernel.org>   */ +#include <linux/acpi.h>  #include <linux/clk.h>  #include <linux/dma-mapping.h> +#include <linux/iopoll.h>  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/of.h> +#include <linux/of_device.h>  #include <linux/sizes.h>  #include "sdhci-pltfm.h" @@ -21,11 +24,52 @@  /* DWCMSHC specific Mode Select value */  #define DWCMSHC_CTRL_HS400		0x7 +/* DWC IP vendor area 1 pointer */ +#define DWCMSHC_P_VENDOR_AREA1		0xe8 +#define DWCMSHC_AREA1_MASK		GENMASK(11, 0) +/* Offset inside the  vendor area 1 */ +#define DWCMSHC_HOST_CTRL3		0x8 +#define DWCMSHC_EMMC_CONTROL		0x2c +#define DWCMSHC_ENHANCED_STROBE		BIT(8) +#define DWCMSHC_EMMC_ATCTRL		0x40 + +/* Rockchip specific Registers */ +#define DWCMSHC_EMMC_DLL_CTRL		0x800 +#define DWCMSHC_EMMC_DLL_RXCLK		0x804 +#define DWCMSHC_EMMC_DLL_TXCLK		0x808 +#define DWCMSHC_EMMC_DLL_STRBIN		0x80c +#define DLL_STRBIN_TAPNUM_FROM_SW	BIT(24) +#define DWCMSHC_EMMC_DLL_STATUS0	0x840 +#define DWCMSHC_EMMC_DLL_START		BIT(0) +#define DWCMSHC_EMMC_DLL_LOCKED		BIT(8) +#define DWCMSHC_EMMC_DLL_TIMEOUT	BIT(9) +#define DWCMSHC_EMMC_DLL_RXCLK_SRCSEL	29 +#define DWCMSHC_EMMC_DLL_START_POINT	16 +#define DWCMSHC_EMMC_DLL_INC		8 +#define DWCMSHC_EMMC_DLL_DLYENA		BIT(27) +#define DLL_TXCLK_TAPNUM_DEFAULT	0x8 +#define DLL_STRBIN_TAPNUM_DEFAULT	0x8 +#define DLL_TXCLK_TAPNUM_FROM_SW	BIT(24) +#define DLL_RXCLK_NO_INVERTER		1 +#define DLL_RXCLK_INVERTER		0 +#define DLL_LOCK_WO_TMOUT(x) \ +	((((x) & DWCMSHC_EMMC_DLL_LOCKED) == DWCMSHC_EMMC_DLL_LOCKED) && \ +	(((x) & DWCMSHC_EMMC_DLL_TIMEOUT) == 0)) +#define RK3568_MAX_CLKS 3 +  #define BOUNDARY_OK(addr, len) \  	((addr | (SZ_128M - 1)) == ((addr + len - 1) | (SZ_128M - 1))) +struct rk3568_priv { +	/* Rockchip specified optional clocks */ +	struct clk_bulk_data rockchip_clks[RK3568_MAX_CLKS]; +	u8 txclk_tapnum; +}; +  struct dwcmshc_priv {  	struct clk	*bus_clk; +	int vendor_specific_area1; /* P_VENDOR_SPECIFIC_AREA reg */ +	void *priv; /* pointer to SoC private stuff */  };  /* @@ -51,6 +95,16 @@ static void dwcmshc_adma_write_desc(struct sdhci_host *host, void **desc,  	sdhci_adma_write_desc(host, desc, addr, len, cmd);  } +static unsigned int dwcmshc_get_max_clock(struct sdhci_host *host) +{ +	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + +	if (pltfm_host->clk) +		return sdhci_pltfm_clk_get_max_clock(host); +	else +		return pltfm_host->clock; +} +  static void dwcmshc_check_auto_cmd23(struct mmc_host *mmc,  				     struct mmc_request *mrq)  { @@ -100,10 +154,120 @@ static void dwcmshc_set_uhs_signaling(struct sdhci_host *host,  	sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);  } +static void dwcmshc_hs400_enhanced_strobe(struct mmc_host *mmc, +					  struct mmc_ios *ios) +{ +	u32 vendor; +	struct sdhci_host *host = mmc_priv(mmc); +	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); +	struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host); +	int reg = priv->vendor_specific_area1 + DWCMSHC_EMMC_CONTROL; + +	vendor = sdhci_readl(host, reg); +	if (ios->enhanced_strobe) +		vendor |= DWCMSHC_ENHANCED_STROBE; +	else +		vendor &= ~DWCMSHC_ENHANCED_STROBE; + +	sdhci_writel(host, vendor, reg); +} + +static void dwcmshc_rk3568_set_clock(struct sdhci_host *host, unsigned int clock) +{ +	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); +	struct dwcmshc_priv *dwc_priv = sdhci_pltfm_priv(pltfm_host); +	struct rk3568_priv *priv = dwc_priv->priv; +	u8 txclk_tapnum = DLL_TXCLK_TAPNUM_DEFAULT; +	u32 extra, reg; +	int err; + +	host->mmc->actual_clock = 0; + +	/* +	 * DO NOT TOUCH THIS SETTING. RX clk inverter unit is enabled +	 * by default, but it shouldn't be enabled. We should anyway +	 * disable it before issuing any cmds. +	 */ +	extra = DWCMSHC_EMMC_DLL_DLYENA | +		DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL; +	sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_RXCLK); + +	if (clock == 0) +		return; + +	/* Rockchip platform only support 375KHz for identify mode */ +	if (clock <= 400000) +		clock = 375000; + +	err = clk_set_rate(pltfm_host->clk, clock); +	if (err) +		dev_err(mmc_dev(host->mmc), "fail to set clock %d", clock); + +	sdhci_set_clock(host, clock); + +	/* Disable cmd conflict check */ +	reg = dwc_priv->vendor_specific_area1 + DWCMSHC_HOST_CTRL3; +	extra = sdhci_readl(host, reg); +	extra &= ~BIT(0); +	sdhci_writel(host, extra, reg); + +	if (clock <= 400000) { +		/* Disable DLL to reset sample clock */ +		sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_CTRL); +		return; +	} + +	/* Reset DLL */ +	sdhci_writel(host, BIT(1), DWCMSHC_EMMC_DLL_CTRL); +	udelay(1); +	sdhci_writel(host, 0x0, DWCMSHC_EMMC_DLL_CTRL); + +	/* Init DLL settings */ +	extra = 0x5 << DWCMSHC_EMMC_DLL_START_POINT | +		0x2 << DWCMSHC_EMMC_DLL_INC | +		DWCMSHC_EMMC_DLL_START; +	sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_CTRL); +	err = readl_poll_timeout(host->ioaddr + DWCMSHC_EMMC_DLL_STATUS0, +				 extra, DLL_LOCK_WO_TMOUT(extra), 1, +				 500 * USEC_PER_MSEC); +	if (err) { +		dev_err(mmc_dev(host->mmc), "DLL lock timeout!\n"); +		return; +	} + +	extra = 0x1 << 16 | /* tune clock stop en */ +		0x2 << 17 | /* pre-change delay */ +		0x3 << 19;  /* post-change delay */ +	sdhci_writel(host, extra, dwc_priv->vendor_specific_area1 + DWCMSHC_EMMC_ATCTRL); + +	if (host->mmc->ios.timing == MMC_TIMING_MMC_HS200 || +	    host->mmc->ios.timing == MMC_TIMING_MMC_HS400) +		txclk_tapnum = priv->txclk_tapnum; + +	extra = DWCMSHC_EMMC_DLL_DLYENA | +		DLL_TXCLK_TAPNUM_FROM_SW | +		txclk_tapnum; +	sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_TXCLK); + +	extra = DWCMSHC_EMMC_DLL_DLYENA | +		DLL_STRBIN_TAPNUM_DEFAULT | +		DLL_STRBIN_TAPNUM_FROM_SW; +	sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_STRBIN); +} +  static const struct sdhci_ops sdhci_dwcmshc_ops = {  	.set_clock		= sdhci_set_clock,  	.set_bus_width		= sdhci_set_bus_width,  	.set_uhs_signaling	= dwcmshc_set_uhs_signaling, +	.get_max_clock		= dwcmshc_get_max_clock, +	.reset			= sdhci_reset, +	.adma_write_desc	= dwcmshc_adma_write_desc, +}; + +static const struct sdhci_ops sdhci_dwcmshc_rk3568_ops = { +	.set_clock		= dwcmshc_rk3568_set_clock, +	.set_bus_width		= sdhci_set_bus_width, +	.set_uhs_signaling	= dwcmshc_set_uhs_signaling,  	.get_max_clock		= sdhci_pltfm_clk_get_max_clock,  	.reset			= sdhci_reset,  	.adma_write_desc	= dwcmshc_adma_write_desc, @@ -115,15 +279,86 @@ static const struct sdhci_pltfm_data sdhci_dwcmshc_pdata = {  	.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,  }; +static const struct sdhci_pltfm_data sdhci_dwcmshc_rk3568_pdata = { +	.ops = &sdhci_dwcmshc_rk3568_ops, +	.quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | +		  SDHCI_QUIRK_BROKEN_TIMEOUT_VAL, +	.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | +		   SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN, +}; + +static int dwcmshc_rk3568_init(struct sdhci_host *host, struct dwcmshc_priv *dwc_priv) +{ +	int err; +	struct rk3568_priv *priv = dwc_priv->priv; + +	priv->rockchip_clks[0].id = "axi"; +	priv->rockchip_clks[1].id = "block"; +	priv->rockchip_clks[2].id = "timer"; +	err = devm_clk_bulk_get_optional(mmc_dev(host->mmc), RK3568_MAX_CLKS, +					 priv->rockchip_clks); +	if (err) { +		dev_err(mmc_dev(host->mmc), "failed to get clocks %d\n", err); +		return err; +	} + +	err = clk_bulk_prepare_enable(RK3568_MAX_CLKS, priv->rockchip_clks); +	if (err) { +		dev_err(mmc_dev(host->mmc), "failed to enable clocks %d\n", err); +		return err; +	} + +	if (of_property_read_u8(mmc_dev(host->mmc)->of_node, "rockchip,txclk-tapnum", +				&priv->txclk_tapnum)) +		priv->txclk_tapnum = DLL_TXCLK_TAPNUM_DEFAULT; + +	/* Disable cmd conflict check */ +	sdhci_writel(host, 0x0, dwc_priv->vendor_specific_area1 + DWCMSHC_HOST_CTRL3); +	/* Reset previous settings */ +	sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_TXCLK); +	sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_STRBIN); + +	return 0; +} + +static const struct of_device_id sdhci_dwcmshc_dt_ids[] = { +	{ +		.compatible = "rockchip,rk3568-dwcmshc", +		.data = &sdhci_dwcmshc_rk3568_pdata, +	}, +	{ +		.compatible = "snps,dwcmshc-sdhci", +		.data = &sdhci_dwcmshc_pdata, +	}, +	{}, +}; +MODULE_DEVICE_TABLE(of, sdhci_dwcmshc_dt_ids); + +#ifdef CONFIG_ACPI +static const struct acpi_device_id sdhci_dwcmshc_acpi_ids[] = { +	{ .id = "MLNXBF30" }, +	{} +}; +#endif +  static int dwcmshc_probe(struct platform_device *pdev)  { +	struct device *dev = &pdev->dev;  	struct sdhci_pltfm_host *pltfm_host;  	struct sdhci_host *host;  	struct dwcmshc_priv *priv; +	struct rk3568_priv *rk_priv = NULL; +	const struct sdhci_pltfm_data *pltfm_data;  	int err;  	u32 extra; -	host = sdhci_pltfm_init(pdev, &sdhci_dwcmshc_pdata, +	pltfm_data = of_device_get_match_data(&pdev->dev); +	if (!pltfm_data) { +		dev_err(&pdev->dev, "Error: No device match data found\n"); +		return -ENODEV; +	} + +	host = sdhci_pltfm_init(pdev, pltfm_data,  				sizeof(struct dwcmshc_priv));  	if (IS_ERR(host))  		return PTR_ERR(host); @@ -131,7 +366,7 @@ static int dwcmshc_probe(struct platform_device *pdev)  	/*  	 * extra adma table cnt for cross 128M boundary handling.  	 */ -	extra = DIV_ROUND_UP_ULL(dma_get_required_mask(&pdev->dev), SZ_128M); +	extra = DIV_ROUND_UP_ULL(dma_get_required_mask(dev), SZ_128M);  	if (extra > SDHCI_MAX_SEGS)  		extra = SDHCI_MAX_SEGS;  	host->adma_table_cnt += extra; @@ -139,19 +374,21 @@ static int dwcmshc_probe(struct platform_device *pdev)  	pltfm_host = sdhci_priv(host);  	priv = sdhci_pltfm_priv(pltfm_host); -	pltfm_host->clk = devm_clk_get(&pdev->dev, "core"); -	if (IS_ERR(pltfm_host->clk)) { -		err = PTR_ERR(pltfm_host->clk); -		dev_err(&pdev->dev, "failed to get core clk: %d\n", err); -		goto free_pltfm; +	if (dev->of_node) { +		pltfm_host->clk = devm_clk_get(dev, "core"); +		if (IS_ERR(pltfm_host->clk)) { +			err = PTR_ERR(pltfm_host->clk); +			dev_err(dev, "failed to get core clk: %d\n", err); +			goto free_pltfm; +		} +		err = clk_prepare_enable(pltfm_host->clk); +		if (err) +			goto free_pltfm; + +		priv->bus_clk = devm_clk_get(dev, "bus"); +		if (!IS_ERR(priv->bus_clk)) +			clk_prepare_enable(priv->bus_clk);  	} -	err = clk_prepare_enable(pltfm_host->clk); -	if (err) -		goto free_pltfm; - -	priv->bus_clk = devm_clk_get(&pdev->dev, "bus"); -	if (!IS_ERR(priv->bus_clk)) -		clk_prepare_enable(priv->bus_clk);  	err = mmc_of_parse(host->mmc);  	if (err) @@ -159,7 +396,27 @@ static int dwcmshc_probe(struct platform_device *pdev)  	sdhci_get_of_property(pdev); +	priv->vendor_specific_area1 = +		sdhci_readl(host, DWCMSHC_P_VENDOR_AREA1) & DWCMSHC_AREA1_MASK; +  	host->mmc_host_ops.request = dwcmshc_request; +	host->mmc_host_ops.hs400_enhanced_strobe = dwcmshc_hs400_enhanced_strobe; + +	if (pltfm_data == &sdhci_dwcmshc_rk3568_pdata) { +		rk_priv = devm_kzalloc(&pdev->dev, sizeof(struct rk3568_priv), GFP_KERNEL); +		if (!rk_priv) { +			err = -ENOMEM; +			goto err_clk; +		} + +		priv->priv = rk_priv; + +		err = dwcmshc_rk3568_init(host, priv); +		if (err) +			goto err_clk; +	} + +	host->mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY;  	err = sdhci_add_host(host);  	if (err) @@ -170,6 +427,9 @@ static int dwcmshc_probe(struct platform_device *pdev)  err_clk:  	clk_disable_unprepare(pltfm_host->clk);  	clk_disable_unprepare(priv->bus_clk); +	if (rk_priv) +		clk_bulk_disable_unprepare(RK3568_MAX_CLKS, +					   rk_priv->rockchip_clks);  free_pltfm:  	sdhci_pltfm_free(pdev);  	return err; @@ -180,12 +440,15 @@ static int dwcmshc_remove(struct platform_device *pdev)  	struct sdhci_host *host = platform_get_drvdata(pdev);  	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);  	struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host); +	struct rk3568_priv *rk_priv = priv->priv;  	sdhci_remove_host(host, 0);  	clk_disable_unprepare(pltfm_host->clk);  	clk_disable_unprepare(priv->bus_clk); - +	if (rk_priv) +		clk_bulk_disable_unprepare(RK3568_MAX_CLKS, +					   rk_priv->rockchip_clks);  	sdhci_pltfm_free(pdev);  	return 0; @@ -197,6 +460,7 @@ static int dwcmshc_suspend(struct device *dev)  	struct sdhci_host *host = dev_get_drvdata(dev);  	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);  	struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host); +	struct rk3568_priv *rk_priv = priv->priv;  	int ret;  	ret = sdhci_suspend_host(host); @@ -207,6 +471,10 @@ static int dwcmshc_suspend(struct device *dev)  	if (!IS_ERR(priv->bus_clk))  		clk_disable_unprepare(priv->bus_clk); +	if (rk_priv) +		clk_bulk_disable_unprepare(RK3568_MAX_CLKS, +					   rk_priv->rockchip_clks); +  	return ret;  } @@ -215,6 +483,7 @@ static int dwcmshc_resume(struct device *dev)  	struct sdhci_host *host = dev_get_drvdata(dev);  	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);  	struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host); +	struct rk3568_priv *rk_priv = priv->priv;  	int ret;  	ret = clk_prepare_enable(pltfm_host->clk); @@ -227,23 +496,25 @@ static int dwcmshc_resume(struct device *dev)  			return ret;  	} +	if (rk_priv) { +		ret = clk_bulk_prepare_enable(RK3568_MAX_CLKS, +					      rk_priv->rockchip_clks); +		if (ret) +			return ret; +	} +  	return sdhci_resume_host(host);  }  #endif  static SIMPLE_DEV_PM_OPS(dwcmshc_pmops, dwcmshc_suspend, dwcmshc_resume); -static const struct of_device_id sdhci_dwcmshc_dt_ids[] = { -	{ .compatible = "snps,dwcmshc-sdhci" }, -	{} -}; -MODULE_DEVICE_TABLE(of, sdhci_dwcmshc_dt_ids); -  static struct platform_driver sdhci_dwcmshc_driver = {  	.driver	= {  		.name	= "sdhci-dwcmshc",  		.probe_type = PROBE_PREFER_ASYNCHRONOUS,  		.of_match_table = sdhci_dwcmshc_dt_ids, +		.acpi_match_table = ACPI_PTR(sdhci_dwcmshc_acpi_ids),  		.pm = &dwcmshc_pmops,  	},  	.probe	= dwcmshc_probe, diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index ab5ab969f711..a593b1fbd69e 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c @@ -1489,7 +1489,7 @@ static int sdhci_esdhc_probe(struct platform_device *pdev)  	if (ret)  		goto err; -	mmc_of_parse_voltage(np, &host->ocr_mask); +	mmc_of_parse_voltage(host->mmc, &host->ocr_mask);  	ret = sdhci_add_host(host);  	if (ret) diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c index 9552708846ca..be19785227fe 100644 --- a/drivers/mmc/host/sdhci-pci-core.c +++ b/drivers/mmc/host/sdhci-pci-core.c @@ -516,6 +516,7 @@ struct intel_host {  	int	drv_strength;  	bool	d3_retune;  	bool	rpm_retune_ok; +	bool	needs_pwr_off;  	u32	glk_rx_ctrl1;  	u32	glk_tun_val;  	u32	active_ltr; @@ -643,9 +644,25 @@ out:  static void sdhci_intel_set_power(struct sdhci_host *host, unsigned char mode,  				  unsigned short vdd)  { +	struct sdhci_pci_slot *slot = sdhci_priv(host); +	struct intel_host *intel_host = sdhci_pci_priv(slot);  	int cntr;  	u8 reg; +	/* +	 * Bus power may control card power, but a full reset still may not +	 * reset the power, whereas a direct write to SDHCI_POWER_CONTROL can. +	 * That might be needed to initialize correctly, if the card was left +	 * powered on previously. +	 */ +	if (intel_host->needs_pwr_off) { +		intel_host->needs_pwr_off = false; +		if (mode != MMC_POWER_OFF) { +			sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); +			usleep_range(10000, 12500); +		} +	} +  	sdhci_set_power(host, mode, vdd);  	if (mode == MMC_POWER_OFF) @@ -958,7 +975,7 @@ static int glk_emmc_probe_slot(struct sdhci_pci_slot *slot)  		slot->host->mmc->caps2 |= MMC_CAP2_CQE;  	if (slot->chip->pdev->device != PCI_DEVICE_ID_INTEL_GLK_EMMC) { -		slot->host->mmc->caps2 |= MMC_CAP2_HS400_ES, +		slot->host->mmc->caps2 |= MMC_CAP2_HS400_ES;  		slot->host->mmc_host_ops.hs400_enhanced_strobe =  						intel_hs400_enhanced_strobe;  		slot->host->mmc->caps2 |= MMC_CAP2_CQE_DCMD; @@ -1135,6 +1152,14 @@ static int byt_sdio_probe_slot(struct sdhci_pci_slot *slot)  	return 0;  } +static void byt_needs_pwr_off(struct sdhci_pci_slot *slot) +{ +	struct intel_host *intel_host = sdhci_pci_priv(slot); +	u8 reg = sdhci_readb(slot->host, SDHCI_POWER_CONTROL); + +	intel_host->needs_pwr_off = reg  & SDHCI_POWER_ON; +} +  static int byt_sd_probe_slot(struct sdhci_pci_slot *slot)  {  	byt_probe_slot(slot); @@ -1152,6 +1177,8 @@ static int byt_sd_probe_slot(struct sdhci_pci_slot *slot)  	    slot->chip->pdev->subsystem_device == PCI_SUBDEVICE_ID_NI_78E3)  		slot->host->mmc->caps2 |= MMC_CAP2_AVOID_3_3V; +	byt_needs_pwr_off(slot); +  	return 0;  } @@ -1903,6 +1930,8 @@ static const struct pci_device_id pci_ids[] = {  	SDHCI_PCI_DEVICE(INTEL, CMLH_SD,   intel_byt_sd),  	SDHCI_PCI_DEVICE(INTEL, JSL_EMMC,  intel_glk_emmc),  	SDHCI_PCI_DEVICE(INTEL, JSL_SD,    intel_byt_sd), +	SDHCI_PCI_DEVICE(INTEL, LKF_EMMC,  intel_glk_emmc), +	SDHCI_PCI_DEVICE(INTEL, LKF_SD,    intel_byt_sd),  	SDHCI_PCI_DEVICE(O2, 8120,     o2),  	SDHCI_PCI_DEVICE(O2, 8220,     o2),  	SDHCI_PCI_DEVICE(O2, 8221,     o2), diff --git a/drivers/mmc/host/sdhci-pci-gli.c b/drivers/mmc/host/sdhci-pci-gli.c index 4a0f69b97a78..592d79082f58 100644 --- a/drivers/mmc/host/sdhci-pci-gli.c +++ b/drivers/mmc/host/sdhci-pci-gli.c @@ -22,6 +22,10 @@  #define   GLI_9750_WT_EN_ON	    0x1  #define   GLI_9750_WT_EN_OFF	    0x0 +#define SDHCI_GLI_9750_CFG2          0x848 +#define   SDHCI_GLI_9750_CFG2_L1DLY    GENMASK(28, 24) +#define   GLI_9750_CFG2_L1DLY_VALUE    0x1F +  #define SDHCI_GLI_9750_DRIVING      0x860  #define   SDHCI_GLI_9750_DRIVING_1    GENMASK(11, 0)  #define   SDHCI_GLI_9750_DRIVING_2    GENMASK(27, 26) @@ -90,7 +94,7 @@  #define PCIE_GLI_9763E_CFG2      0x8A4  #define   GLI_9763E_CFG2_L1DLY     GENMASK(28, 19) -#define   GLI_9763E_CFG2_L1DLY_MAX 0x3FF +#define   GLI_9763E_CFG2_L1DLY_MID 0x50  #define PCIE_GLI_9763E_MMC_CTRL  0x960  #define   GLI_9763E_HS400_SLOW     BIT(3) @@ -113,6 +117,10 @@  #define   PCI_GLI_9755_LFCLK    GENMASK(14, 12)  #define   PCI_GLI_9755_DMACLK   BIT(29) +#define PCI_GLI_9755_CFG2          0x48 +#define   PCI_GLI_9755_CFG2_L1DLY    GENMASK(28, 24) +#define   GLI_9755_CFG2_L1DLY_VALUE  0x1F +  #define PCI_GLI_9755_PLL            0x64  #define   PCI_GLI_9755_PLL_LDIV       GENMASK(9, 0)  #define   PCI_GLI_9755_PLL_PDIV       GENMASK(14, 12) @@ -123,6 +131,9 @@  #define PCI_GLI_9755_PLLSSC        0x68  #define   PCI_GLI_9755_PLLSSC_PPM    GENMASK(15, 0) +#define PCI_GLI_9755_SerDes  0x70 +#define PCI_GLI_9755_SCP_DIS   BIT(19) +  #define GLI_MAX_TUNING_LOOP 40  /* Genesys Logic chipset */ @@ -405,6 +416,22 @@ static void sdhci_gl9750_set_clock(struct sdhci_host *host, unsigned int clock)  	sdhci_enable_clk(host, clk);  } +static void gl9750_hw_setting(struct sdhci_host *host) +{ +	u32 value; + +	gl9750_wt_on(host); + +	value = sdhci_readl(host, SDHCI_GLI_9750_CFG2); +	value &= ~SDHCI_GLI_9750_CFG2_L1DLY; +	/* set ASPM L1 entry delay to 7.9us */ +	value |= FIELD_PREP(SDHCI_GLI_9750_CFG2_L1DLY, +			    GLI_9750_CFG2_L1DLY_VALUE); +	sdhci_writel(host, value, SDHCI_GLI_9750_CFG2); + +	gl9750_wt_off(host); +} +  static void gli_pcie_enable_msi(struct sdhci_pci_slot *slot)  {  	int ret; @@ -547,6 +574,18 @@ static void gl9755_hw_setting(struct sdhci_pci_slot *slot)  	value &= ~PCI_GLI_9755_DMACLK;  	pci_write_config_dword(pdev, PCI_GLI_9755_PECONF, value); +	/* enable short circuit protection */ +	pci_read_config_dword(pdev, PCI_GLI_9755_SerDes, &value); +	value &= ~PCI_GLI_9755_SCP_DIS; +	pci_write_config_dword(pdev, PCI_GLI_9755_SerDes, value); + +	pci_read_config_dword(pdev, PCI_GLI_9755_CFG2, &value); +	value &= ~PCI_GLI_9755_CFG2_L1DLY; +	/* set ASPM L1 entry delay to 7.9us */ +	value |= FIELD_PREP(PCI_GLI_9755_CFG2_L1DLY, +			    GLI_9755_CFG2_L1DLY_VALUE); +	pci_write_config_dword(pdev, PCI_GLI_9755_CFG2, value); +  	gl9755_wt_off(pdev);  } @@ -554,6 +593,7 @@ static int gli_probe_slot_gl9750(struct sdhci_pci_slot *slot)  {  	struct sdhci_host *host = slot->host; +	gl9750_hw_setting(host);  	gli_pcie_enable_msi(slot);  	slot->host->mmc->caps2 |= MMC_CAP2_NO_SDIO;  	sdhci_enable_v4_mode(host); @@ -802,8 +842,8 @@ static void gli_set_gl9763e(struct sdhci_pci_slot *slot)  	pci_read_config_dword(pdev, PCIE_GLI_9763E_CFG2, &value);  	value &= ~GLI_9763E_CFG2_L1DLY; -	/* set ASPM L1 entry delay to 260us */ -	value |= FIELD_PREP(GLI_9763E_CFG2_L1DLY, GLI_9763E_CFG2_L1DLY_MAX); +	/* set ASPM L1 entry delay to 20us */ +	value |= FIELD_PREP(GLI_9763E_CFG2_L1DLY, GLI_9763E_CFG2_L1DLY_MID);  	pci_write_config_dword(pdev, PCIE_GLI_9763E_CFG2, value);  	pci_read_config_dword(pdev, PCIE_GLI_9763E_CLKRXDLY, &value); diff --git a/drivers/mmc/host/sdhci-pci-o2micro.c b/drivers/mmc/host/sdhci-pci-o2micro.c index 94e3f72f6405..51d55a87aebe 100644 --- a/drivers/mmc/host/sdhci-pci-o2micro.c +++ b/drivers/mmc/host/sdhci-pci-o2micro.c @@ -706,6 +706,8 @@ static int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip)  			ret = pci_read_config_dword(chip->pdev,  						    O2_SD_FUNC_REG0,  						    &scratch_32); +			if (ret) +				return ret;  			scratch_32 = ((scratch_32 & 0xFF000000) >> 24);  			/* Check Whether subId is 0x11 or 0x12 */ @@ -716,6 +718,8 @@ static int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip)  				ret = pci_read_config_dword(chip->pdev,  							    O2_SD_FUNC_REG4,  							    &scratch_32); +				if (ret) +					return ret;  				/* Enable Base Clk setting change */  				scratch_32 |= O2_SD_FREG4_ENABLE_CLK_SET; @@ -795,6 +799,8 @@ static int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip)  		ret = pci_read_config_dword(chip->pdev,  					    O2_SD_PLL_SETTING, &scratch_32); +		if (ret) +			return ret;  		if ((scratch_32 & 0xff000000) == 0x01000000) {  			scratch_32 &= 0x0000FFFF; @@ -812,6 +818,8 @@ static int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip)  			ret = pci_read_config_dword(chip->pdev,  						    O2_SD_FUNC_REG4,  						    &scratch_32); +			if (ret) +				return ret;  			scratch_32 |= (1 << 22);  			pci_write_config_dword(chip->pdev,  					       O2_SD_FUNC_REG4, scratch_32); diff --git a/drivers/mmc/host/sdhci-pci.h b/drivers/mmc/host/sdhci-pci.h index d0ed232af0eb..8f90c4163bb5 100644 --- a/drivers/mmc/host/sdhci-pci.h +++ b/drivers/mmc/host/sdhci-pci.h @@ -57,6 +57,8 @@  #define PCI_DEVICE_ID_INTEL_CMLH_SD	0x06f5  #define PCI_DEVICE_ID_INTEL_JSL_EMMC	0x4dc4  #define PCI_DEVICE_ID_INTEL_JSL_SD	0x4df8 +#define PCI_DEVICE_ID_INTEL_LKF_EMMC	0x98c4 +#define PCI_DEVICE_ID_INTEL_LKF_SD	0x98f8  #define PCI_DEVICE_ID_SYSKONNECT_8000	0x8000  #define PCI_DEVICE_ID_VIA_95D0		0x95d0 diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index f48a788a9d3d..862f033d235d 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c @@ -20,6 +20,7 @@  #include <linux/gpio.h>  #include <linux/module.h>  #include <linux/of.h> +#include <linux/of_device.h>  #include <linux/of_gpio.h>  #include <linux/pm.h>  #include <linux/pm_runtime.h> @@ -129,7 +130,7 @@ struct sdhci_s3c {  };  /** - * struct sdhci_s3c_driver_data - S3C SDHCI platform specific driver data + * struct sdhci_s3c_drv_data - S3C SDHCI platform specific driver data   * @sdhci_quirks: sdhci host specific quirks.   * @no_divider: no or non-standard internal clock divider.   * @@ -461,28 +462,21 @@ static int sdhci_s3c_parse_dt(struct device *dev,  }  #endif -#ifdef CONFIG_OF -static const struct of_device_id sdhci_s3c_dt_match[]; -#endif - -static inline struct sdhci_s3c_drv_data *sdhci_s3c_get_driver_data( +static inline const struct sdhci_s3c_drv_data *sdhci_s3c_get_driver_data(  			struct platform_device *pdev)  {  #ifdef CONFIG_OF -	if (pdev->dev.of_node) { -		const struct of_device_id *match; -		match = of_match_node(sdhci_s3c_dt_match, pdev->dev.of_node); -		return (struct sdhci_s3c_drv_data *)match->data; -	} +	if (pdev->dev.of_node) +		return of_device_get_match_data(&pdev->dev);  #endif -	return (struct sdhci_s3c_drv_data *) +	return (const struct sdhci_s3c_drv_data *)  			platform_get_device_id(pdev)->driver_data;  }  static int sdhci_s3c_probe(struct platform_device *pdev)  {  	struct s3c_sdhci_platdata *pdata; -	struct sdhci_s3c_drv_data *drv_data; +	const struct sdhci_s3c_drv_data *drv_data;  	struct device *dev = &pdev->dev;  	struct sdhci_host *host;  	struct sdhci_s3c *sc; @@ -767,7 +761,7 @@ static const struct platform_device_id sdhci_s3c_driver_ids[] = {  MODULE_DEVICE_TABLE(platform, sdhci_s3c_driver_ids);  #ifdef CONFIG_OF -static struct sdhci_s3c_drv_data exynos4_sdhci_drv_data = { +static const struct sdhci_s3c_drv_data exynos4_sdhci_drv_data = {  	.no_divider = true,  }; diff --git a/drivers/mmc/host/sdhci-st.c b/drivers/mmc/host/sdhci-st.c index 962872aec164..d41582c21aa3 100644 --- a/drivers/mmc/host/sdhci-st.c +++ b/drivers/mmc/host/sdhci-st.c @@ -362,11 +362,10 @@ static int sdhci_st_probe(struct platform_device *pdev)  	if (IS_ERR(icnclk))  		icnclk = NULL; -	rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL); +	rstc = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL);  	if (IS_ERR(rstc)) -		rstc = NULL; -	else -		reset_control_deassert(rstc); +		return PTR_ERR(rstc); +	reset_control_deassert(rstc);  	host = sdhci_pltfm_init(pdev, &sdhci_st_pdata, sizeof(*pdata));  	if (IS_ERR(host)) { @@ -401,10 +400,8 @@ static int sdhci_st_probe(struct platform_device *pdev)  	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,  					   "top-mmc-delay");  	pdata->top_ioaddr = devm_ioremap_resource(&pdev->dev, res); -	if (IS_ERR(pdata->top_ioaddr)) { -		dev_warn(&pdev->dev, "FlashSS Top Dly registers not available"); +	if (IS_ERR(pdata->top_ioaddr))  		pdata->top_ioaddr = NULL; -	}  	pltfm_host->clk = clk;  	pdata->icnclk = icnclk; @@ -432,8 +429,7 @@ err_icnclk:  err_of:  	sdhci_pltfm_free(pdev);  err_pltfm_init: -	if (rstc) -		reset_control_assert(rstc); +	reset_control_assert(rstc);  	return ret;  } @@ -450,8 +446,7 @@ static int sdhci_st_remove(struct platform_device *pdev)  	clk_disable_unprepare(pdata->icnclk); -	if (rstc) -		reset_control_assert(rstc); +	reset_control_assert(rstc);  	return ret;  } @@ -471,8 +466,7 @@ static int sdhci_st_suspend(struct device *dev)  	if (ret)  		goto out; -	if (pdata->rstc) -		reset_control_assert(pdata->rstc); +	reset_control_assert(pdata->rstc);  	clk_disable_unprepare(pdata->icnclk);  	clk_disable_unprepare(pltfm_host->clk); @@ -498,8 +492,7 @@ static int sdhci_st_resume(struct device *dev)  		return ret;  	} -	if (pdata->rstc) -		reset_control_deassert(pdata->rstc); +	reset_control_deassert(pdata->rstc);  	st_mmcss_cconfig(np, host); diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index 41d193fa77bb..387ce9cdbd7c 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c @@ -119,6 +119,10 @@  /* SDMMC CQE Base Address for Tegra Host Ver 4.1 and Higher */  #define SDHCI_TEGRA_CQE_BASE_ADDR			0xF000 +#define SDHCI_TEGRA_CQE_TRNS_MODE	(SDHCI_TRNS_MULTI | \ +					 SDHCI_TRNS_BLK_CNT_EN | \ +					 SDHCI_TRNS_DMA) +  struct sdhci_tegra_soc_data {  	const struct sdhci_pltfm_data *pdata;  	u64 dma_mask; @@ -596,49 +600,49 @@ static void tegra_sdhci_parse_pad_autocal_dt(struct sdhci_host *host)  			&tegra_host->autocal_offsets;  	int err; -	err = device_property_read_u32(host->mmc->parent, +	err = device_property_read_u32(mmc_dev(host->mmc),  			"nvidia,pad-autocal-pull-up-offset-3v3",  			&autocal->pull_up_3v3);  	if (err)  		autocal->pull_up_3v3 = 0; -	err = device_property_read_u32(host->mmc->parent, +	err = device_property_read_u32(mmc_dev(host->mmc),  			"nvidia,pad-autocal-pull-down-offset-3v3",  			&autocal->pull_down_3v3);  	if (err)  		autocal->pull_down_3v3 = 0; -	err = device_property_read_u32(host->mmc->parent, +	err = device_property_read_u32(mmc_dev(host->mmc),  			"nvidia,pad-autocal-pull-up-offset-1v8",  			&autocal->pull_up_1v8);  	if (err)  		autocal->pull_up_1v8 = 0; -	err = device_property_read_u32(host->mmc->parent, +	err = device_property_read_u32(mmc_dev(host->mmc),  			"nvidia,pad-autocal-pull-down-offset-1v8",  			&autocal->pull_down_1v8);  	if (err)  		autocal->pull_down_1v8 = 0; -	err = device_property_read_u32(host->mmc->parent, +	err = device_property_read_u32(mmc_dev(host->mmc),  			"nvidia,pad-autocal-pull-up-offset-sdr104",  			&autocal->pull_up_sdr104);  	if (err)  		autocal->pull_up_sdr104 = autocal->pull_up_1v8; -	err = device_property_read_u32(host->mmc->parent, +	err = device_property_read_u32(mmc_dev(host->mmc),  			"nvidia,pad-autocal-pull-down-offset-sdr104",  			&autocal->pull_down_sdr104);  	if (err)  		autocal->pull_down_sdr104 = autocal->pull_down_1v8; -	err = device_property_read_u32(host->mmc->parent, +	err = device_property_read_u32(mmc_dev(host->mmc),  			"nvidia,pad-autocal-pull-up-offset-hs400",  			&autocal->pull_up_hs400);  	if (err)  		autocal->pull_up_hs400 = autocal->pull_up_1v8; -	err = device_property_read_u32(host->mmc->parent, +	err = device_property_read_u32(mmc_dev(host->mmc),  			"nvidia,pad-autocal-pull-down-offset-hs400",  			&autocal->pull_down_hs400);  	if (err) @@ -653,7 +657,7 @@ static void tegra_sdhci_parse_pad_autocal_dt(struct sdhci_host *host)  	if (!(tegra_host->soc_data->nvquirks & NVQUIRK_NEEDS_PAD_CONTROL))  		return; -	err = device_property_read_u32(host->mmc->parent, +	err = device_property_read_u32(mmc_dev(host->mmc),  			"nvidia,pad-autocal-pull-up-offset-3v3-timeout",  			&autocal->pull_up_3v3_timeout);  	if (err) { @@ -664,7 +668,7 @@ static void tegra_sdhci_parse_pad_autocal_dt(struct sdhci_host *host)  		autocal->pull_up_3v3_timeout = 0;  	} -	err = device_property_read_u32(host->mmc->parent, +	err = device_property_read_u32(mmc_dev(host->mmc),  			"nvidia,pad-autocal-pull-down-offset-3v3-timeout",  			&autocal->pull_down_3v3_timeout);  	if (err) { @@ -675,7 +679,7 @@ static void tegra_sdhci_parse_pad_autocal_dt(struct sdhci_host *host)  		autocal->pull_down_3v3_timeout = 0;  	} -	err = device_property_read_u32(host->mmc->parent, +	err = device_property_read_u32(mmc_dev(host->mmc),  			"nvidia,pad-autocal-pull-up-offset-1v8-timeout",  			&autocal->pull_up_1v8_timeout);  	if (err) { @@ -686,7 +690,7 @@ static void tegra_sdhci_parse_pad_autocal_dt(struct sdhci_host *host)  		autocal->pull_up_1v8_timeout = 0;  	} -	err = device_property_read_u32(host->mmc->parent, +	err = device_property_read_u32(mmc_dev(host->mmc),  			"nvidia,pad-autocal-pull-down-offset-1v8-timeout",  			&autocal->pull_down_1v8_timeout);  	if (err) { @@ -720,17 +724,17 @@ static void tegra_sdhci_parse_tap_and_trim(struct sdhci_host *host)  	struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);  	int err; -	err = device_property_read_u32(host->mmc->parent, "nvidia,default-tap", +	err = device_property_read_u32(mmc_dev(host->mmc), "nvidia,default-tap",  				       &tegra_host->default_tap);  	if (err)  		tegra_host->default_tap = 0; -	err = device_property_read_u32(host->mmc->parent, "nvidia,default-trim", +	err = device_property_read_u32(mmc_dev(host->mmc), "nvidia,default-trim",  				       &tegra_host->default_trim);  	if (err)  		tegra_host->default_trim = 0; -	err = device_property_read_u32(host->mmc->parent, "nvidia,dqs-trim", +	err = device_property_read_u32(mmc_dev(host->mmc), "nvidia,dqs-trim",  				       &tegra_host->dqs_trim);  	if (err)  		tegra_host->dqs_trim = 0x11; @@ -741,7 +745,7 @@ static void tegra_sdhci_parse_dt(struct sdhci_host *host)  	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);  	struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host); -	if (device_property_read_bool(host->mmc->parent, "supports-cqe")) +	if (device_property_read_bool(mmc_dev(host->mmc), "supports-cqe"))  		tegra_host->enable_hwcq = true;  	else  		tegra_host->enable_hwcq = false; @@ -1156,6 +1160,7 @@ static void tegra_sdhci_voltage_switch(struct sdhci_host *host)  static void tegra_cqhci_writel(struct cqhci_host *cq_host, u32 val, int reg)  {  	struct mmc_host *mmc = cq_host->mmc; +	struct sdhci_host *host = mmc_priv(mmc);  	u8 ctrl;  	ktime_t timeout;  	bool timed_out; @@ -1170,6 +1175,7 @@ static void tegra_cqhci_writel(struct cqhci_host *cq_host, u32 val, int reg)  	 */  	if (reg == CQHCI_CTL && !(val & CQHCI_HALT) &&  	    cqhci_readl(cq_host, CQHCI_CTL) & CQHCI_HALT) { +		sdhci_writew(host, SDHCI_TEGRA_CQE_TRNS_MODE, SDHCI_TRANSFER_MODE);  		sdhci_cqe_enable(mmc);  		writel(val, cq_host->mmio + reg);  		timeout = ktime_add_us(ktime_get(), 50); @@ -1205,6 +1211,7 @@ static void sdhci_tegra_update_dcmd_desc(struct mmc_host *mmc,  static void sdhci_tegra_cqe_enable(struct mmc_host *mmc)  {  	struct cqhci_host *cq_host = mmc->cqe_private; +	struct sdhci_host *host = mmc_priv(mmc);  	u32 val;  	/* @@ -1218,6 +1225,7 @@ static void sdhci_tegra_cqe_enable(struct mmc_host *mmc)  		if (val & CQHCI_ENABLE)  			cqhci_writel(cq_host, (val & ~CQHCI_ENABLE),  				     CQHCI_CFG); +		sdhci_writew(host, SDHCI_TEGRA_CQE_TRNS_MODE, SDHCI_TRANSFER_MODE);  		sdhci_cqe_enable(mmc);  		if (val & CQHCI_ENABLE)  			cqhci_writel(cq_host, val, CQHCI_CFG); @@ -1281,12 +1289,36 @@ static void tegra_sdhci_set_timeout(struct sdhci_host *host,  	__sdhci_set_timeout(host, cmd);  } +static void sdhci_tegra_cqe_pre_enable(struct mmc_host *mmc) +{ +	struct cqhci_host *cq_host = mmc->cqe_private; +	u32 reg; + +	reg = cqhci_readl(cq_host, CQHCI_CFG); +	reg |= CQHCI_ENABLE; +	cqhci_writel(cq_host, reg, CQHCI_CFG); +} + +static void sdhci_tegra_cqe_post_disable(struct mmc_host *mmc) +{ +	struct cqhci_host *cq_host = mmc->cqe_private; +	struct sdhci_host *host = mmc_priv(mmc); +	u32 reg; + +	reg = cqhci_readl(cq_host, CQHCI_CFG); +	reg &= ~CQHCI_ENABLE; +	cqhci_writel(cq_host, reg, CQHCI_CFG); +	sdhci_writew(host, 0x0, SDHCI_TRANSFER_MODE); +} +  static const struct cqhci_host_ops sdhci_tegra_cqhci_ops = {  	.write_l    = tegra_cqhci_writel,  	.enable	= sdhci_tegra_cqe_enable,  	.disable = sdhci_cqe_disable,  	.dumpregs = sdhci_tegra_dumpregs,  	.update_dcmd_desc = sdhci_tegra_update_dcmd_desc, +	.pre_enable = sdhci_tegra_cqe_pre_enable, +	.post_disable = sdhci_tegra_cqe_post_disable,  };  static int tegra_sdhci_set_dma_mask(struct sdhci_host *host) @@ -1529,7 +1561,7 @@ static int sdhci_tegra_add_host(struct sdhci_host *host)  	host->mmc->caps2 |= MMC_CAP2_CQE | MMC_CAP2_CQE_DCMD; -	cq_host = devm_kzalloc(host->mmc->parent, +	cq_host = devm_kzalloc(mmc_dev(host->mmc),  				sizeof(*cq_host), GFP_KERNEL);  	if (!cq_host) {  		ret = -ENOMEM; diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 2d73407ee52e..bf238ade1602 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -188,7 +188,7 @@ static void sdhci_runtime_pm_bus_on(struct sdhci_host *host)  	if (host->bus_on)  		return;  	host->bus_on = true; -	pm_runtime_get_noresume(host->mmc->parent); +	pm_runtime_get_noresume(mmc_dev(host->mmc));  }  static void sdhci_runtime_pm_bus_off(struct sdhci_host *host) @@ -196,7 +196,7 @@ static void sdhci_runtime_pm_bus_off(struct sdhci_host *host)  	if (!host->bus_on)  		return;  	host->bus_on = false; -	pm_runtime_put_noidle(host->mmc->parent); +	pm_runtime_put_noidle(mmc_dev(host->mmc));  }  void sdhci_reset(struct sdhci_host *host, u8 mask) @@ -648,7 +648,7 @@ static int sdhci_pre_dma_transfer(struct sdhci_host *host,  			}  		}  		/* Switch ownership to the DMA */ -		dma_sync_single_for_device(host->mmc->parent, +		dma_sync_single_for_device(mmc_dev(host->mmc),  					   host->bounce_addr,  					   host->bounce_buffer_size,  					   mmc_get_dma_dir(data)); @@ -907,7 +907,7 @@ static void sdhci_calc_sw_timeout(struct sdhci_host *host,  	if (data) {  		blksz = data->blksz; -		freq = host->mmc->actual_clock ? : host->clock; +		freq = mmc->actual_clock ? : host->clock;  		transfer_time = (u64)blksz * NSEC_PER_SEC * (8 / bus_width);  		do_div(transfer_time, freq);  		/* multiply by '2' to account for any unknowns */ @@ -1176,7 +1176,7 @@ 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"); +	host->tx_chan = dma_request_chan(mmc_dev(mmc), "tx");  	if (IS_ERR(host->tx_chan)) {  		ret = PTR_ERR(host->tx_chan);  		if (ret != -EPROBE_DEFER) @@ -1185,7 +1185,7 @@ static int sdhci_external_dma_init(struct sdhci_host *host)  		return ret;  	} -	host->rx_chan = dma_request_chan(mmc->parent, "rx"); +	host->rx_chan = dma_request_chan(mmc_dev(mmc), "rx");  	if (IS_ERR(host->rx_chan)) {  		if (host->tx_chan) {  			dma_release_channel(host->tx_chan); @@ -2269,14 +2269,14 @@ void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)  		if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK &&  		    host->clock) { -			host->timeout_clk = host->mmc->actual_clock ? -						host->mmc->actual_clock / 1000 : +			host->timeout_clk = mmc->actual_clock ? +						mmc->actual_clock / 1000 :  						host->clock / 1000; -			host->mmc->max_busy_timeout = +			mmc->max_busy_timeout =  				host->ops->get_max_timeout_count ?  				host->ops->get_max_timeout_count(host) :  				1 << 27; -			host->mmc->max_busy_timeout /= host->timeout_clk; +			mmc->max_busy_timeout /= host->timeout_clk;  		}  	} @@ -2399,7 +2399,7 @@ static int sdhci_get_cd(struct mmc_host *mmc)  		return 0;  	/* If nonremovable, assume that the card is always present. */ -	if (!mmc_card_is_removable(host->mmc)) +	if (!mmc_card_is_removable(mmc))  		return 1;  	/* @@ -2489,14 +2489,14 @@ void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)  	unsigned long flags;  	if (enable) -		pm_runtime_get_noresume(host->mmc->parent); +		pm_runtime_get_noresume(mmc_dev(mmc));  	spin_lock_irqsave(&host->lock, flags);  	sdhci_enable_sdio_irq_nolock(host, enable);  	spin_unlock_irqrestore(&host->lock, flags);  	if (!enable) -		pm_runtime_put_noidle(host->mmc->parent); +		pm_runtime_put_noidle(mmc_dev(mmc));  }  EXPORT_SYMBOL_GPL(sdhci_enable_sdio_irq); @@ -2837,7 +2837,7 @@ int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)  		goto out;  	} -	host->mmc->retune_period = tuning_count; +	mmc->retune_period = tuning_count;  	if (host->tuning_delay < 0)  		host->tuning_delay = opcode == MMC_SEND_TUNING_BLOCK; @@ -2886,11 +2886,10 @@ static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable)  static void sdhci_post_req(struct mmc_host *mmc, struct mmc_request *mrq,  				int err)  { -	struct sdhci_host *host = mmc_priv(mmc);  	struct mmc_data *data = mrq->data;  	if (data->host_cookie != COOKIE_UNMAPPED) -		dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, +		dma_unmap_sg(mmc_dev(mmc), data->sg, data->sg_len,  			     mmc_get_dma_dir(data));  	data->host_cookie = COOKIE_UNMAPPED; @@ -2941,9 +2940,9 @@ static void sdhci_card_event(struct mmc_host *mmc)  	/* Check sdhci_has_requests() first in case we are runtime suspended */  	if (sdhci_has_requests(host) && !present) {  		pr_err("%s: Card removed during transfer!\n", -			mmc_hostname(host->mmc)); +			mmc_hostname(mmc));  		pr_err("%s: Resetting controller.\n", -			mmc_hostname(host->mmc)); +			mmc_hostname(mmc));  		sdhci_do_reset(host, SDHCI_RESET_CMD);  		sdhci_do_reset(host, SDHCI_RESET_DATA); @@ -2997,6 +2996,37 @@ static bool sdhci_request_done(struct sdhci_host *host)  	}  	/* +	 * The controller needs a reset of internal state machines +	 * upon error conditions. +	 */ +	if (sdhci_needs_reset(host, mrq)) { +		/* +		 * Do not finish until command and data lines are available for +		 * reset. Note there can only be one other mrq, so it cannot +		 * also be in mrqs_done, otherwise host->cmd and host->data_cmd +		 * would both be null. +		 */ +		if (host->cmd || host->data_cmd) { +			spin_unlock_irqrestore(&host->lock, flags); +			return true; +		} + +		/* Some controllers need this kick or reset won't work here */ +		if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET) +			/* This is to force an update */ +			host->ops->set_clock(host, host->clock); + +		/* +		 * Spec says we should do both at the same time, but Ricoh +		 * controllers do not like that. +		 */ +		sdhci_do_reset(host, SDHCI_RESET_CMD); +		sdhci_do_reset(host, SDHCI_RESET_DATA); + +		host->pending_reset = false; +	} + +	/*  	 * Always unmap the data buffers if they were mapped by  	 * sdhci_prepare_data() whenever we finish with a request.  	 * This avoids leaking DMA mappings on error. @@ -3033,7 +3063,7 @@ static bool sdhci_request_done(struct sdhci_host *host)  						length = host->bounce_buffer_size;  					}  					dma_sync_single_for_cpu( -						host->mmc->parent, +						mmc_dev(host->mmc),  						host->bounce_addr,  						host->bounce_buffer_size,  						DMA_FROM_DEVICE); @@ -3044,7 +3074,7 @@ static bool sdhci_request_done(struct sdhci_host *host)  				} else {  					/* No copying, just switch ownership */  					dma_sync_single_for_cpu( -						host->mmc->parent, +						mmc_dev(host->mmc),  						host->bounce_addr,  						host->bounce_buffer_size,  						mmc_get_dma_dir(data)); @@ -3059,35 +3089,6 @@ static bool sdhci_request_done(struct sdhci_host *host)  		}  	} -	/* -	 * The controller needs a reset of internal state machines -	 * upon error conditions. -	 */ -	if (sdhci_needs_reset(host, mrq)) { -		/* -		 * Do not finish until command and data lines are available for -		 * reset. Note there can only be one other mrq, so it cannot -		 * also be in mrqs_done, otherwise host->cmd and host->data_cmd -		 * would both be null. -		 */ -		if (host->cmd || host->data_cmd) { -			spin_unlock_irqrestore(&host->lock, flags); -			return true; -		} - -		/* Some controllers need this kick or reset won't work here */ -		if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET) -			/* This is to force an update */ -			host->ops->set_clock(host, host->clock); - -		/* Spec says we should do both at the same time, but Ricoh -		   controllers do not like that. */ -		sdhci_do_reset(host, SDHCI_RESET_CMD); -		sdhci_do_reset(host, SDHCI_RESET_DATA); - -		host->pending_reset = false; -	} -  	host->mrqs_done[i] = NULL;  	spin_unlock_irqrestore(&host->lock, flags); @@ -3675,7 +3676,7 @@ int sdhci_resume_host(struct sdhci_host *host)  			host->ops->enable_dma(host);  	} -	if ((host->mmc->pm_flags & MMC_PM_KEEP_POWER) && +	if ((mmc->pm_flags & MMC_PM_KEEP_POWER) &&  	    (host->quirks2 & SDHCI_QUIRK2_HOST_OFF_CARD_ON)) {  		/* Card keeps power but host controller does not */  		sdhci_init(host, 0); @@ -3683,7 +3684,7 @@ int sdhci_resume_host(struct sdhci_host *host)  		host->clock = 0;  		mmc->ops->set_ios(mmc, &mmc->ios);  	} else { -		sdhci_init(host, (host->mmc->pm_flags & MMC_PM_KEEP_POWER)); +		sdhci_init(host, (mmc->pm_flags & MMC_PM_KEEP_POWER));  	}  	if (host->irq_wake_enabled) { @@ -3691,7 +3692,7 @@ int sdhci_resume_host(struct sdhci_host *host)  	} else {  		ret = request_threaded_irq(host->irq, sdhci_irq,  					   sdhci_thread_irq, IRQF_SHARED, -					   mmc_hostname(host->mmc), host); +					   mmc_hostname(mmc), host);  		if (ret)  			return ret;  	} @@ -4052,7 +4053,7 @@ static void sdhci_allocate_bounce_buffer(struct sdhci_host *host)  	 * speedups by the help of a bounce buffer to group scattered  	 * reads/writes together.  	 */ -	host->bounce_buffer = devm_kmalloc(mmc->parent, +	host->bounce_buffer = devm_kmalloc(mmc_dev(mmc),  					   bounce_size,  					   GFP_KERNEL);  	if (!host->bounce_buffer) { @@ -4066,11 +4067,11 @@ static void sdhci_allocate_bounce_buffer(struct sdhci_host *host)  		return;  	} -	host->bounce_addr = dma_map_single(mmc->parent, +	host->bounce_addr = dma_map_single(mmc_dev(mmc),  					   host->bounce_buffer,  					   bounce_size,  					   DMA_BIDIRECTIONAL); -	ret = dma_mapping_error(mmc->parent, host->bounce_addr); +	ret = dma_mapping_error(mmc_dev(mmc), host->bounce_addr);  	if (ret)  		/* Again fall back to max_segs == 1 */  		return; @@ -4378,7 +4379,7 @@ int sdhci_setup_host(struct sdhci_host *host)  	if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) &&  	    mmc_card_is_removable(mmc) && -	    mmc_gpio_get_cd(host->mmc) < 0) +	    mmc_gpio_get_cd(mmc) < 0)  		mmc->caps |= MMC_CAP_NEEDS_POLL;  	if (!IS_ERR(mmc->supply.vqmmc)) { diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c index 7a34649b0754..1fad6e442688 100644 --- a/drivers/mmc/host/sdhci_am654.c +++ b/drivers/mmc/host/sdhci_am654.c @@ -558,7 +558,7 @@ static int sdhci_am654_cqe_add_host(struct sdhci_host *host)  	struct cqhci_host *cq_host;  	int ret; -	cq_host = devm_kzalloc(host->mmc->parent, sizeof(struct cqhci_host), +	cq_host = devm_kzalloc(mmc_dev(host->mmc), sizeof(struct cqhci_host),  			       GFP_KERNEL);  	if (!cq_host)  		return -ENOMEM; diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h index 2d1db9396d4a..f936aad945ce 100644 --- a/drivers/mmc/host/tmio_mmc.h +++ b/drivers/mmc/host/tmio_mmc.h @@ -100,8 +100,8 @@  /* Define some IRQ masks */  /* This is the mask used at reset by the chip */ -#define TMIO_MASK_INIT_RCAR2	0x8b7f031d /* Initial value for R-Car Gen2+ */  #define TMIO_MASK_ALL           0x837f031d +#define TMIO_MASK_ALL_RCAR2	0x8b7f031d  #define TMIO_MASK_READOP  (TMIO_STAT_RXRDY | TMIO_STAT_DATAEND)  #define TMIO_MASK_WRITEOP (TMIO_STAT_TXRQ | TMIO_STAT_DATAEND)  #define TMIO_MASK_CMD     (TMIO_STAT_CMDRESPEND | TMIO_STAT_CMDTIMEOUT | \ @@ -164,6 +164,7 @@ struct tmio_mmc_host {  	u32			sdio_irq_mask;  	unsigned int		clk_cache;  	u32			sdcard_irq_setbit_mask; +	u32			sdcard_irq_mask_all;  	spinlock_t		lock;		/* protect host private data */  	unsigned long		last_req_ts; diff --git a/drivers/mmc/host/tmio_mmc_core.c b/drivers/mmc/host/tmio_mmc_core.c index 49c2d406c48e..7dfc26f48c18 100644 --- a/drivers/mmc/host/tmio_mmc_core.c +++ b/drivers/mmc/host/tmio_mmc_core.c @@ -164,6 +164,21 @@ static void tmio_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)  	}  } +static void tmio_mmc_set_bus_width(struct tmio_mmc_host *host, +				   unsigned char bus_width) +{ +	u16 reg = sd_ctrl_read16(host, CTL_SD_MEM_CARD_OPT) +				& ~(CARD_OPT_WIDTH | CARD_OPT_WIDTH8); + +	/* reg now applies to MMC_BUS_WIDTH_4 */ +	if (bus_width == MMC_BUS_WIDTH_1) +		reg |= CARD_OPT_WIDTH; +	else if (bus_width == MMC_BUS_WIDTH_8) +		reg |= CARD_OPT_WIDTH8; + +	sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, reg); +} +  static void tmio_mmc_reset(struct tmio_mmc_host *host)  {  	/* FIXME - should we set stop clock reg here */ @@ -172,15 +187,23 @@ static void tmio_mmc_reset(struct tmio_mmc_host *host)  	sd_ctrl_write16(host, CTL_RESET_SD, 0x0001);  	usleep_range(10000, 11000); +	tmio_mmc_abort_dma(host); +  	if (host->reset)  		host->reset(host); -	tmio_mmc_abort_dma(host); +	sd_ctrl_write32_as_16_and_16(host, CTL_IRQ_MASK, host->sdcard_irq_mask_all); +	host->sdcard_irq_mask = host->sdcard_irq_mask_all; + +	tmio_mmc_set_bus_width(host, host->mmc->ios.bus_width);  	if (host->pdata->flags & TMIO_MMC_SDIO_IRQ) {  		sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK, host->sdio_irq_mask);  		sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0001);  	} + +	if (host->mmc->card) +		mmc_retune_needed(host->mmc);  }  static void tmio_mmc_reset_work(struct work_struct *work) @@ -874,21 +897,6 @@ static void tmio_mmc_power_off(struct tmio_mmc_host *host)  		host->set_pwr(host->pdev, 0);  } -static void tmio_mmc_set_bus_width(struct tmio_mmc_host *host, -				   unsigned char bus_width) -{ -	u16 reg = sd_ctrl_read16(host, CTL_SD_MEM_CARD_OPT) -				& ~(CARD_OPT_WIDTH | CARD_OPT_WIDTH8); - -	/* reg now applies to MMC_BUS_WIDTH_4 */ -	if (bus_width == MMC_BUS_WIDTH_1) -		reg |= CARD_OPT_WIDTH; -	else if (bus_width == MMC_BUS_WIDTH_8) -		reg |= CARD_OPT_WIDTH8; - -	sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, reg); -} -  static unsigned int tmio_mmc_get_timeout_cycles(struct tmio_mmc_host *host)  {  	u16 val = sd_ctrl_read16(host, CTL_SD_MEM_CARD_OPT); @@ -1161,15 +1169,6 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host)  				  !mmc_card_is_removable(mmc));  	/* -	 * On Gen2+, eMMC with NONREMOVABLE currently fails because native -	 * hotplug gets disabled. It seems RuntimePM related yet we need further -	 * research. Since we are planning a PM overhaul anyway, let's enforce -	 * for now the device being active by enabling native hotplug always. -	 */ -	if (pdata->flags & TMIO_MMC_MIN_RCAR2) -		_host->native_hotplug = true; - -	/*  	 * While using internal tmio hardware logic for card detection, we need  	 * to ensure it stays powered for it to work.  	 */ @@ -1180,12 +1179,12 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host)  	if (pdata->flags & TMIO_MMC_SDIO_IRQ)  		_host->sdio_irq_mask = TMIO_SDIO_MASK_ALL; +	if (!_host->sdcard_irq_mask_all) +		_host->sdcard_irq_mask_all = TMIO_MASK_ALL; +  	_host->set_clock(_host, 0);  	tmio_mmc_reset(_host); -	_host->sdcard_irq_mask = sd_ctrl_read16_and_16_as_32(_host, CTL_IRQ_MASK); -	tmio_mmc_disable_mmc_irqs(_host, TMIO_MASK_ALL); -  	if (_host->native_hotplug)  		tmio_mmc_enable_mmc_irqs(_host,  				TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT); @@ -1238,7 +1237,7 @@ void tmio_mmc_host_remove(struct tmio_mmc_host *host)  	cancel_work_sync(&host->done);  	cancel_delayed_work_sync(&host->delayed_reset_work);  	tmio_mmc_release_dma(host); -	tmio_mmc_disable_mmc_irqs(host, TMIO_MASK_ALL); +	tmio_mmc_disable_mmc_irqs(host, host->sdcard_irq_mask_all);  	if (host->native_hotplug)  		pm_runtime_put_noidle(&pdev->dev); @@ -1268,7 +1267,7 @@ int tmio_mmc_host_runtime_suspend(struct device *dev)  {  	struct tmio_mmc_host *host = dev_get_drvdata(dev); -	tmio_mmc_disable_mmc_irqs(host, TMIO_MASK_ALL); +	tmio_mmc_disable_mmc_irqs(host, host->sdcard_irq_mask_all);  	if (host->clk_cache)  		host->set_clock(host, 0); @@ -1295,8 +1294,6 @@ int tmio_mmc_host_runtime_resume(struct device *dev)  	tmio_mmc_enable_dma(host, true); -	mmc_retune_needed(host->mmc); -  	return 0;  }  EXPORT_SYMBOL_GPL(tmio_mmc_host_runtime_resume); diff --git a/drivers/mmc/host/uniphier-sd.c b/drivers/mmc/host/uniphier-sd.c index 2413b6750cec..ccbf9885a52b 100644 --- a/drivers/mmc/host/uniphier-sd.c +++ b/drivers/mmc/host/uniphier-sd.c @@ -635,7 +635,7 @@ static int uniphier_sd_probe(struct platform_device *pdev)  	ret = tmio_mmc_host_probe(host);  	if (ret) -		goto free_host; +		goto disable_clk;  	ret = devm_request_irq(dev, irq, tmio_mmc_irq, IRQF_SHARED,  			       dev_name(dev), host); @@ -646,6 +646,8 @@ static int uniphier_sd_probe(struct platform_device *pdev)  remove_host:  	tmio_mmc_host_remove(host); +disable_clk: +	uniphier_sd_clk_disable(host);  free_host:  	tmio_mmc_host_free(host); @@ -658,6 +660,7 @@ static int uniphier_sd_remove(struct platform_device *pdev)  	tmio_mmc_host_remove(host);  	uniphier_sd_clk_disable(host); +	tmio_mmc_host_free(host);  	return 0;  } diff --git a/drivers/mmc/host/via-sdmmc.c b/drivers/mmc/host/via-sdmmc.c index 4f4c0813f9fd..a1d098560099 100644 --- a/drivers/mmc/host/via-sdmmc.c +++ b/drivers/mmc/host/via-sdmmc.c @@ -1271,7 +1271,6 @@ static int __maybe_unused via_sd_suspend(struct device *dev)  static int __maybe_unused via_sd_resume(struct device *dev)  {  	struct via_crdr_mmc_host *sdhost; -	int ret = 0;  	u8 gatt;  	sdhost = dev_get_drvdata(dev); @@ -1292,7 +1291,7 @@ static int __maybe_unused via_sd_resume(struct device *dev)  	via_restore_pcictrlreg(sdhost);  	via_init_sdc_pm(sdhost); -	return ret; +	return 0;  }  static SIMPLE_DEV_PM_OPS(via_sd_pm_ops, via_sd_suspend, via_sd_resume); | 
