diff options
Diffstat (limited to 'drivers/mmc')
| -rw-r--r-- | drivers/mmc/host/dw_mmc-exynos.c | 8 | ||||
| -rw-r--r-- | drivers/mmc/host/dw_mmc-pltfm.c | 6 | ||||
| -rw-r--r-- | drivers/mmc/host/dw_mmc-pltfm.h | 2 | ||||
| -rw-r--r-- | drivers/mmc/host/dw_mmc.c | 62 | ||||
| -rw-r--r-- | drivers/mmc/host/mxcmmc.c | 2 | ||||
| -rw-r--r-- | drivers/mmc/host/omap_hsmmc.c | 19 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci-dove.c | 38 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci-of-esdhc.c | 11 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci-pci.c | 2 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci-pltfm.c | 7 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci-s3c.c | 30 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci.c | 42 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci.h | 1 | ||||
| -rw-r--r-- | drivers/mmc/host/sh_mmcif.c | 2 | 
14 files changed, 139 insertions, 93 deletions
diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c index 660bbc52886..4d50da61816 100644 --- a/drivers/mmc/host/dw_mmc-exynos.c +++ b/drivers/mmc/host/dw_mmc-exynos.c @@ -208,7 +208,7 @@ static unsigned long exynos5250_dwmmc_caps[4] = {  	MMC_CAP_CMD23,  }; -static struct dw_mci_drv_data exynos5250_drv_data = { +static const struct dw_mci_drv_data exynos5250_drv_data = {  	.caps			= exynos5250_dwmmc_caps,  	.init			= dw_mci_exynos_priv_init,  	.setup_clock		= dw_mci_exynos_setup_clock, @@ -220,14 +220,14 @@ static struct dw_mci_drv_data exynos5250_drv_data = {  static const struct of_device_id dw_mci_exynos_match[] = {  	{ .compatible = "samsung,exynos5250-dw-mshc", -			.data = (void *)&exynos5250_drv_data, }, +			.data = &exynos5250_drv_data, },  	{},  }; -MODULE_DEVICE_TABLE(of, dw_mci_pltfm_match); +MODULE_DEVICE_TABLE(of, dw_mci_exynos_match);  int dw_mci_exynos_probe(struct platform_device *pdev)  { -	struct dw_mci_drv_data *drv_data; +	const struct dw_mci_drv_data *drv_data;  	const struct of_device_id *match;  	match = of_match_node(dw_mci_exynos_match, pdev->dev.of_node); diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c index c960ca7ffbe..917936bee5d 100644 --- a/drivers/mmc/host/dw_mmc-pltfm.c +++ b/drivers/mmc/host/dw_mmc-pltfm.c @@ -24,7 +24,7 @@  #include "dw_mmc.h"  int dw_mci_pltfm_register(struct platform_device *pdev, -				struct dw_mci_drv_data *drv_data) +				const struct dw_mci_drv_data *drv_data)  {  	struct dw_mci *host;  	struct resource	*regs; @@ -50,8 +50,8 @@ int dw_mci_pltfm_register(struct platform_device *pdev,  	if (!host->regs)  		return -ENOMEM; -	if (host->drv_data->init) { -		ret = host->drv_data->init(host); +	if (drv_data && drv_data->init) { +		ret = drv_data->init(host);  		if (ret)  			return ret;  	} diff --git a/drivers/mmc/host/dw_mmc-pltfm.h b/drivers/mmc/host/dw_mmc-pltfm.h index 301f24541fc..2ac37b81de4 100644 --- a/drivers/mmc/host/dw_mmc-pltfm.h +++ b/drivers/mmc/host/dw_mmc-pltfm.h @@ -13,7 +13,7 @@  #define _DW_MMC_PLTFM_H_  extern int dw_mci_pltfm_register(struct platform_device *pdev, -				struct dw_mci_drv_data *drv_data); +				const struct dw_mci_drv_data *drv_data);  extern int __devexit dw_mci_pltfm_remove(struct platform_device *pdev);  extern const struct dev_pm_ops dw_mci_pltfm_pmops; diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index c2828f35c3b..c0667c8af2b 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -232,6 +232,7 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)  {  	struct mmc_data	*data;  	struct dw_mci_slot *slot = mmc_priv(mmc); +	struct dw_mci_drv_data *drv_data = slot->host->drv_data;  	u32 cmdr;  	cmd->error = -EINPROGRESS; @@ -261,8 +262,8 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)  			cmdr |= SDMMC_CMD_DAT_WR;  	} -	if (slot->host->drv_data->prepare_command) -		slot->host->drv_data->prepare_command(slot->host, &cmdr); +	if (drv_data && drv_data->prepare_command) +		drv_data->prepare_command(slot->host, &cmdr);  	return cmdr;  } @@ -434,7 +435,7 @@ static int dw_mci_idmac_init(struct dw_mci *host)  	return 0;  } -static struct dw_mci_dma_ops dw_mci_idmac_ops = { +static const struct dw_mci_dma_ops dw_mci_idmac_ops = {  	.init = dw_mci_idmac_init,  	.start = dw_mci_idmac_start_dma,  	.stop = dw_mci_idmac_stop_dma, @@ -772,6 +773,7 @@ static void dw_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)  static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)  {  	struct dw_mci_slot *slot = mmc_priv(mmc); +	struct dw_mci_drv_data *drv_data = slot->host->drv_data;  	u32 regs;  	/* set default 1 bit mode */ @@ -807,8 +809,8 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)  		slot->clock = ios->clock;  	} -	if (slot->host->drv_data->set_ios) -		slot->host->drv_data->set_ios(slot->host, ios); +	if (drv_data && drv_data->set_ios) +		drv_data->set_ios(slot->host, ios);  	switch (ios->power_mode) {  	case MMC_POWER_UP: @@ -1815,6 +1817,7 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)  {  	struct mmc_host *mmc;  	struct dw_mci_slot *slot; +	struct dw_mci_drv_data *drv_data = host->drv_data;  	int ctrl_id, ret;  	u8 bus_width; @@ -1854,8 +1857,8 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)  	} else {  		ctrl_id = to_platform_device(host->dev)->id;  	} -	if (host->drv_data && host->drv_data->caps) -		mmc->caps |= host->drv_data->caps[ctrl_id]; +	if (drv_data && drv_data->caps) +		mmc->caps |= drv_data->caps[ctrl_id];  	if (host->pdata->caps2)  		mmc->caps2 = host->pdata->caps2; @@ -1867,10 +1870,10 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)  	else  		bus_width = 1; -	if (host->drv_data->setup_bus) { +	if (drv_data && drv_data->setup_bus) {  		struct device_node *slot_np;  		slot_np = dw_mci_of_find_slot_node(host->dev, slot->id); -		ret = host->drv_data->setup_bus(host, slot_np, bus_width); +		ret = drv_data->setup_bus(host, slot_np, bus_width);  		if (ret)  			goto err_setup_bus;  	} @@ -1968,7 +1971,7 @@ static void dw_mci_init_dma(struct dw_mci *host)  	/* Determine which DMA interface to use */  #ifdef CONFIG_MMC_DW_IDMAC  	host->dma_ops = &dw_mci_idmac_ops; -	dev_info(&host->dev, "Using internal DMA controller.\n"); +	dev_info(host->dev, "Using internal DMA controller.\n");  #endif  	if (!host->dma_ops) @@ -2035,6 +2038,7 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)  	struct dw_mci_board *pdata;  	struct device *dev = host->dev;  	struct device_node *np = dev->of_node; +	struct dw_mci_drv_data *drv_data = host->drv_data;  	int idx, ret;  	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); @@ -2062,8 +2066,8 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)  	of_property_read_u32(np, "card-detect-delay", &pdata->detect_delay_ms); -	if (host->drv_data->parse_dt) { -		ret = host->drv_data->parse_dt(host); +	if (drv_data && drv_data->parse_dt) { +		ret = drv_data->parse_dt(host);  		if (ret)  			return ERR_PTR(ret);  	} @@ -2080,6 +2084,7 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)  int dw_mci_probe(struct dw_mci *host)  { +	struct dw_mci_drv_data *drv_data = host->drv_data;  	int width, i, ret = 0;  	u32 fifo_size;  	int init_slots = 0; @@ -2127,8 +2132,8 @@ int dw_mci_probe(struct dw_mci *host)  	else  		host->bus_hz = clk_get_rate(host->ciu_clk); -	if (host->drv_data->setup_clock) { -		ret = host->drv_data->setup_clock(host); +	if (drv_data && drv_data->setup_clock) { +		ret = drv_data->setup_clock(host);  		if (ret) {  			dev_err(host->dev,  				"implementation specific clock setup failed\n"); @@ -2228,6 +2233,21 @@ int dw_mci_probe(struct dw_mci *host)  	else  		host->num_slots = ((mci_readl(host, HCON) >> 1) & 0x1F) + 1; +	/* +	 * Enable interrupts for command done, data over, data empty, card det, +	 * receive ready and error such as transmit, receive timeout, crc error +	 */ +	mci_writel(host, RINTSTS, 0xFFFFFFFF); +	mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER | +		   SDMMC_INT_TXDR | SDMMC_INT_RXDR | +		   DW_MCI_ERROR_FLAGS | SDMMC_INT_CD); +	mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */ + +	dev_info(host->dev, "DW MMC controller at irq %d, " +		 "%d bit host data width, " +		 "%u deep fifo\n", +		 host->irq, width, fifo_size); +  	/* We need at least one slot to succeed */  	for (i = 0; i < host->num_slots; i++) {  		ret = dw_mci_init_slot(host, i); @@ -2257,20 +2277,6 @@ int dw_mci_probe(struct dw_mci *host)  	else  		host->data_offset = DATA_240A_OFFSET; -	/* -	 * Enable interrupts for command done, data over, data empty, card det, -	 * receive ready and error such as transmit, receive timeout, crc error -	 */ -	mci_writel(host, RINTSTS, 0xFFFFFFFF); -	mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER | -		   SDMMC_INT_TXDR | SDMMC_INT_RXDR | -		   DW_MCI_ERROR_FLAGS | SDMMC_INT_CD); -	mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */ - -	dev_info(host->dev, "DW MMC controller at irq %d, " -		 "%d bit host data width, " -		 "%u deep fifo\n", -		 host->irq, width, fifo_size);  	if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO)  		dev_info(host->dev, "Internal DMAC interrupt fix enabled.\n"); diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index 565c2e4fac7..6290b7f1ccf 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c @@ -1134,4 +1134,4 @@ module_platform_driver(mxcmci_driver);  MODULE_DESCRIPTION("i.MX Multimedia Card Interface Driver");  MODULE_AUTHOR("Sascha Hauer, Pengutronix");  MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:imx-mmc"); +MODULE_ALIAS("platform:mxc-mmc"); diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 54bfd0cc106..fedd258cc4e 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -178,7 +178,8 @@ struct omap_hsmmc_host {  static int omap_hsmmc_card_detect(struct device *dev, int slot)  { -	struct omap_mmc_platform_data *mmc = dev->platform_data; +	struct omap_hsmmc_host *host = dev_get_drvdata(dev); +	struct omap_mmc_platform_data *mmc = host->pdata;  	/* NOTE: assumes card detect signal is active-low */  	return !gpio_get_value_cansleep(mmc->slots[0].switch_pin); @@ -186,7 +187,8 @@ static int omap_hsmmc_card_detect(struct device *dev, int slot)  static int omap_hsmmc_get_wp(struct device *dev, int slot)  { -	struct omap_mmc_platform_data *mmc = dev->platform_data; +	struct omap_hsmmc_host *host = dev_get_drvdata(dev); +	struct omap_mmc_platform_data *mmc = host->pdata;  	/* NOTE: assumes write protect signal is active-high */  	return gpio_get_value_cansleep(mmc->slots[0].gpio_wp); @@ -194,7 +196,8 @@ static int omap_hsmmc_get_wp(struct device *dev, int slot)  static int omap_hsmmc_get_cover_state(struct device *dev, int slot)  { -	struct omap_mmc_platform_data *mmc = dev->platform_data; +	struct omap_hsmmc_host *host = dev_get_drvdata(dev); +	struct omap_mmc_platform_data *mmc = host->pdata;  	/* NOTE: assumes card detect signal is active-low */  	return !gpio_get_value_cansleep(mmc->slots[0].switch_pin); @@ -204,7 +207,8 @@ static int omap_hsmmc_get_cover_state(struct device *dev, int slot)  static int omap_hsmmc_suspend_cdirq(struct device *dev, int slot)  { -	struct omap_mmc_platform_data *mmc = dev->platform_data; +	struct omap_hsmmc_host *host = dev_get_drvdata(dev); +	struct omap_mmc_platform_data *mmc = host->pdata;  	disable_irq(mmc->slots[0].card_detect_irq);  	return 0; @@ -212,7 +216,8 @@ static int omap_hsmmc_suspend_cdirq(struct device *dev, int slot)  static int omap_hsmmc_resume_cdirq(struct device *dev, int slot)  { -	struct omap_mmc_platform_data *mmc = dev->platform_data; +	struct omap_hsmmc_host *host = dev_get_drvdata(dev); +	struct omap_mmc_platform_data *mmc = host->pdata;  	enable_irq(mmc->slots[0].card_detect_irq);  	return 0; @@ -2009,9 +2014,9 @@ static int __devexit omap_hsmmc_remove(struct platform_device *pdev)  		clk_put(host->dbclk);  	} -	mmc_free_host(host->mmc); +	omap_hsmmc_gpio_free(host->pdata);  	iounmap(host->base); -	omap_hsmmc_gpio_free(pdev->dev.platform_data); +	mmc_free_host(host->mmc);  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	if (res) diff --git a/drivers/mmc/host/sdhci-dove.c b/drivers/mmc/host/sdhci-dove.c index 90140eb03e3..8fd50a21103 100644 --- a/drivers/mmc/host/sdhci-dove.c +++ b/drivers/mmc/host/sdhci-dove.c @@ -19,6 +19,7 @@   * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.   */ +#include <linux/err.h>  #include <linux/io.h>  #include <linux/clk.h>  #include <linux/err.h> @@ -84,30 +85,32 @@ static int __devinit sdhci_dove_probe(struct platform_device *pdev)  	struct sdhci_dove_priv *priv;  	int ret; -	ret = sdhci_pltfm_register(pdev, &sdhci_dove_pdata); -	if (ret) -		goto sdhci_dove_register_fail; -  	priv = devm_kzalloc(&pdev->dev, sizeof(struct sdhci_dove_priv),  			    GFP_KERNEL);  	if (!priv) {  		dev_err(&pdev->dev, "unable to allocate private data"); -		ret = -ENOMEM; -		goto sdhci_dove_allocate_fail; +		return -ENOMEM;  	} +	priv->clk = clk_get(&pdev->dev, NULL); +	if (!IS_ERR(priv->clk)) +		clk_prepare_enable(priv->clk); + +	ret = sdhci_pltfm_register(pdev, &sdhci_dove_pdata); +	if (ret) +		goto sdhci_dove_register_fail; +  	host = platform_get_drvdata(pdev);  	pltfm_host = sdhci_priv(host);  	pltfm_host->priv = priv; -	priv->clk = clk_get(&pdev->dev, NULL); -	if (!IS_ERR(priv->clk)) -		clk_prepare_enable(priv->clk);  	return 0; -sdhci_dove_allocate_fail: -	sdhci_pltfm_unregister(pdev);  sdhci_dove_register_fail: +	if (!IS_ERR(priv->clk)) { +		clk_disable_unprepare(priv->clk); +		clk_put(priv->clk); +	}  	return ret;  } @@ -117,14 +120,13 @@ static int __devexit sdhci_dove_remove(struct platform_device *pdev)  	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);  	struct sdhci_dove_priv *priv = pltfm_host->priv; -	if (priv->clk) { -		if (!IS_ERR(priv->clk)) { -			clk_disable_unprepare(priv->clk); -			clk_put(priv->clk); -		} -		devm_kfree(&pdev->dev, priv->clk); +	sdhci_pltfm_unregister(pdev); + +	if (!IS_ERR(priv->clk)) { +		clk_disable_unprepare(priv->clk); +		clk_put(priv->clk);  	} -	return sdhci_pltfm_unregister(pdev); +	return 0;  }  static const struct of_device_id sdhci_dove_of_match_table[] __devinitdata = { diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index ae5fcbfa1ee..63d219f57ca 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c @@ -169,6 +169,16 @@ static void esdhc_of_resume(struct sdhci_host *host)  }  #endif +static void esdhc_of_platform_init(struct sdhci_host *host) +{ +	u32 vvn; + +	vvn = in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS); +	vvn = (vvn & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT; +	if (vvn == VENDOR_V_22) +		host->quirks2 |= SDHCI_QUIRK2_HOST_NO_CMD23; +} +  static struct sdhci_ops sdhci_esdhc_ops = {  	.read_l = esdhc_readl,  	.read_w = esdhc_readw, @@ -180,6 +190,7 @@ static struct sdhci_ops sdhci_esdhc_ops = {  	.enable_dma = esdhc_of_enable_dma,  	.get_max_clock = esdhc_of_get_max_clock,  	.get_min_clock = esdhc_of_get_min_clock, +	.platform_init = esdhc_of_platform_init,  #ifdef CONFIG_PM  	.platform_suspend = esdhc_of_suspend,  	.platform_resume = esdhc_of_resume, diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index 4bb74b042a0..04936f353ce 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c @@ -1196,7 +1196,7 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(  		return ERR_PTR(-ENODEV);  	} -	if (pci_resource_len(pdev, bar) != 0x100) { +	if (pci_resource_len(pdev, bar) < 0x100) {  		dev_err(&pdev->dev, "Invalid iomem size. You may "  			"experience problems.\n");  	} diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c index 65551a9709c..27164457f86 100644 --- a/drivers/mmc/host/sdhci-pltfm.c +++ b/drivers/mmc/host/sdhci-pltfm.c @@ -150,6 +150,13 @@ struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev,  		goto err_remap;  	} +	/* +	 * Some platforms need to probe the controller to be able to +	 * determine which caps should be used. +	 */ +	if (host->ops && host->ops->platform_init) +		host->ops->platform_init(host); +  	platform_set_drvdata(pdev, host);  	return host; diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index 2903949594c..a54dd5d7a5f 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c @@ -211,8 +211,8 @@ static void sdhci_s3c_set_clock(struct sdhci_host *host, unsigned int clock)  	if (ourhost->cur_clk != best_src) {  		struct clk *clk = ourhost->clk_bus[best_src]; -		clk_enable(clk); -		clk_disable(ourhost->clk_bus[ourhost->cur_clk]); +		clk_prepare_enable(clk); +		clk_disable_unprepare(ourhost->clk_bus[ourhost->cur_clk]);  		/* turn clock off to card before changing clock source */  		writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL); @@ -607,7 +607,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)  	}  	/* enable the local io clock and keep it running for the moment. */ -	clk_enable(sc->clk_io); +	clk_prepare_enable(sc->clk_io);  	for (clks = 0, ptr = 0; ptr < MAX_BUS_CLK; ptr++) {  		struct clk *clk; @@ -638,7 +638,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)  	}  #ifndef CONFIG_PM_RUNTIME -	clk_enable(sc->clk_bus[sc->cur_clk]); +	clk_prepare_enable(sc->clk_bus[sc->cur_clk]);  #endif  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -747,13 +747,14 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)  		sdhci_s3c_setup_card_detect_gpio(sc);  #ifdef CONFIG_PM_RUNTIME -	clk_disable(sc->clk_io); +	if (pdata->cd_type != S3C_SDHCI_CD_INTERNAL) +		clk_disable_unprepare(sc->clk_io);  #endif  	return 0;   err_req_regs:  #ifndef CONFIG_PM_RUNTIME -	clk_disable(sc->clk_bus[sc->cur_clk]); +	clk_disable_unprepare(sc->clk_bus[sc->cur_clk]);  #endif  	for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) {  		if (sc->clk_bus[ptr]) { @@ -762,7 +763,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)  	}   err_no_busclks: -	clk_disable(sc->clk_io); +	clk_disable_unprepare(sc->clk_io);  	clk_put(sc->clk_io);   err_io_clk: @@ -794,7 +795,8 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev)  		gpio_free(sc->ext_cd_gpio);  #ifdef CONFIG_PM_RUNTIME -	clk_enable(sc->clk_io); +	if (pdata->cd_type != S3C_SDHCI_CD_INTERNAL) +		clk_prepare_enable(sc->clk_io);  #endif  	sdhci_remove_host(host, 1); @@ -802,14 +804,14 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev)  	pm_runtime_disable(&pdev->dev);  #ifndef CONFIG_PM_RUNTIME -	clk_disable(sc->clk_bus[sc->cur_clk]); +	clk_disable_unprepare(sc->clk_bus[sc->cur_clk]);  #endif  	for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) {  		if (sc->clk_bus[ptr]) {  			clk_put(sc->clk_bus[ptr]);  		}  	} -	clk_disable(sc->clk_io); +	clk_disable_unprepare(sc->clk_io);  	clk_put(sc->clk_io);  	if (pdev->dev.of_node) { @@ -849,8 +851,8 @@ static int sdhci_s3c_runtime_suspend(struct device *dev)  	ret = sdhci_runtime_suspend_host(host); -	clk_disable(ourhost->clk_bus[ourhost->cur_clk]); -	clk_disable(busclk); +	clk_disable_unprepare(ourhost->clk_bus[ourhost->cur_clk]); +	clk_disable_unprepare(busclk);  	return ret;  } @@ -861,8 +863,8 @@ static int sdhci_s3c_runtime_resume(struct device *dev)  	struct clk *busclk = ourhost->clk_io;  	int ret; -	clk_enable(busclk); -	clk_enable(ourhost->clk_bus[ourhost->cur_clk]); +	clk_prepare_enable(busclk); +	clk_prepare_enable(ourhost->clk_bus[ourhost->cur_clk]);  	ret = sdhci_runtime_resume_host(host);  	return ret;  } diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 7922adb4238..c7851c0aabc 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1315,16 +1315,19 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)  		 */  		if ((host->flags & SDHCI_NEEDS_RETUNING) &&  		    !(present_state & (SDHCI_DOING_WRITE | SDHCI_DOING_READ))) { -			/* eMMC uses cmd21 while sd and sdio use cmd19 */ -			tuning_opcode = mmc->card->type == MMC_TYPE_MMC ? -				MMC_SEND_TUNING_BLOCK_HS200 : -				MMC_SEND_TUNING_BLOCK; -			spin_unlock_irqrestore(&host->lock, flags); -			sdhci_execute_tuning(mmc, tuning_opcode); -			spin_lock_irqsave(&host->lock, flags); +			if (mmc->card) { +				/* eMMC uses cmd21 but sd and sdio use cmd19 */ +				tuning_opcode = +					mmc->card->type == MMC_TYPE_MMC ? +					MMC_SEND_TUNING_BLOCK_HS200 : +					MMC_SEND_TUNING_BLOCK; +				spin_unlock_irqrestore(&host->lock, flags); +				sdhci_execute_tuning(mmc, tuning_opcode); +				spin_lock_irqsave(&host->lock, flags); -			/* Restore original mmc_request structure */ -			host->mrq = mrq; +				/* Restore original mmc_request structure */ +				host->mrq = mrq; +			}  		}  		if (mrq->sbc && !(host->flags & SDHCI_AUTO_CMD23)) @@ -2837,6 +2840,9 @@ int sdhci_add_host(struct sdhci_host *host)  	if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA))  		mmc->caps |= MMC_CAP_4_BIT_DATA; +	if (host->quirks2 & SDHCI_QUIRK2_HOST_NO_CMD23) +		mmc->caps &= ~MMC_CAP_CMD23; +  	if (caps[0] & SDHCI_CAN_DO_HISPD)  		mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; @@ -2846,9 +2852,12 @@ int sdhci_add_host(struct sdhci_host *host)  	/* If vqmmc regulator and no 1.8V signalling, then there's no UHS */  	host->vqmmc = regulator_get(mmc_dev(mmc), "vqmmc"); -	if (IS_ERR(host->vqmmc)) { -		pr_info("%s: no vqmmc regulator found\n", mmc_hostname(mmc)); -		host->vqmmc = NULL; +	if (IS_ERR_OR_NULL(host->vqmmc)) { +		if (PTR_ERR(host->vqmmc) < 0) { +			pr_info("%s: no vqmmc regulator found\n", +				mmc_hostname(mmc)); +			host->vqmmc = NULL; +		}  	}  	else if (regulator_is_supported_voltage(host->vqmmc, 1800000, 1800000))  		regulator_enable(host->vqmmc); @@ -2904,9 +2913,12 @@ int sdhci_add_host(struct sdhci_host *host)  	ocr_avail = 0;  	host->vmmc = regulator_get(mmc_dev(mmc), "vmmc"); -	if (IS_ERR(host->vmmc)) { -		pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc)); -		host->vmmc = NULL; +	if (IS_ERR_OR_NULL(host->vmmc)) { +		if (PTR_ERR(host->vmmc) < 0) { +			pr_info("%s: no vmmc regulator found\n", +				mmc_hostname(mmc)); +			host->vmmc = NULL; +		}  	} else  		regulator_enable(host->vmmc); diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 97653ea8942..71a4a7ed46c 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -278,6 +278,7 @@ struct sdhci_ops {  	void	(*hw_reset)(struct sdhci_host *host);  	void	(*platform_suspend)(struct sdhci_host *host);  	void	(*platform_resume)(struct sdhci_host *host); +	void	(*platform_init)(struct sdhci_host *host);  };  #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 11d2bc3b51d..d25bc97dc5c 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -1466,9 +1466,9 @@ static int __devexit sh_mmcif_remove(struct platform_device *pdev)  	platform_set_drvdata(pdev, NULL); +	clk_disable(host->hclk);  	mmc_free_host(host->mmc);  	pm_runtime_put_sync(&pdev->dev); -	clk_disable(host->hclk);  	pm_runtime_disable(&pdev->dev);  	return 0;  |