diff options
Diffstat (limited to 'drivers/mmc/host/sh_mmcif.c')
| -rw-r--r-- | drivers/mmc/host/sh_mmcif.c | 141 | 
1 files changed, 68 insertions, 73 deletions
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 36629a024aa..656fbba4c42 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -381,73 +381,75 @@ static void sh_mmcif_start_dma_tx(struct sh_mmcif_host *host)  		desc, cookie);  } -static void sh_mmcif_request_dma(struct sh_mmcif_host *host, -				 struct sh_mmcif_plat_data *pdata) +static struct dma_chan * +sh_mmcif_request_dma_one(struct sh_mmcif_host *host, +			 struct sh_mmcif_plat_data *pdata, +			 enum dma_transfer_direction direction)  { -	struct resource *res = platform_get_resource(host->pd, IORESOURCE_MEM, 0);  	struct dma_slave_config cfg; +	struct dma_chan *chan; +	unsigned int slave_id; +	struct resource *res;  	dma_cap_mask_t mask;  	int ret; -	host->dma_active = false; - -	if (pdata) { -		if (pdata->slave_id_tx <= 0 || pdata->slave_id_rx <= 0) -			return; -	} else if (!host->pd->dev.of_node) { -		return; -	} - -	/* We can only either use DMA for both Tx and Rx or not use it at all */  	dma_cap_zero(mask);  	dma_cap_set(DMA_SLAVE, mask); -	host->chan_tx = dma_request_slave_channel_compat(mask, shdma_chan_filter, -				pdata ? (void *)pdata->slave_id_tx : NULL, -				&host->pd->dev, "tx"); -	dev_dbg(&host->pd->dev, "%s: TX: got channel %p\n", __func__, -		host->chan_tx); +	if (pdata) +		slave_id = direction == DMA_MEM_TO_DEV +			 ? pdata->slave_id_tx : pdata->slave_id_rx; +	else +		slave_id = 0; + +	chan = dma_request_slave_channel_compat(mask, shdma_chan_filter, +				(void *)(unsigned long)slave_id, &host->pd->dev, +				direction == DMA_MEM_TO_DEV ? "tx" : "rx"); -	if (!host->chan_tx) -		return; +	dev_dbg(&host->pd->dev, "%s: %s: got channel %p\n", __func__, +		direction == DMA_MEM_TO_DEV ? "TX" : "RX", chan); + +	if (!chan) +		return NULL; + +	res = platform_get_resource(host->pd, IORESOURCE_MEM, 0);  	/* In the OF case the driver will get the slave ID from the DT */ -	if (pdata) -		cfg.slave_id = pdata->slave_id_tx; -	cfg.direction = DMA_MEM_TO_DEV; +	cfg.slave_id = slave_id; +	cfg.direction = direction;  	cfg.dst_addr = res->start + MMCIF_CE_DATA;  	cfg.src_addr = 0; -	ret = dmaengine_slave_config(host->chan_tx, &cfg); -	if (ret < 0) -		goto ecfgtx; +	ret = dmaengine_slave_config(chan, &cfg); +	if (ret < 0) { +		dma_release_channel(chan); +		return NULL; +	} -	host->chan_rx = dma_request_slave_channel_compat(mask, shdma_chan_filter, -				pdata ? (void *)pdata->slave_id_rx : NULL, -				&host->pd->dev, "rx"); -	dev_dbg(&host->pd->dev, "%s: RX: got channel %p\n", __func__, -		host->chan_rx); +	return chan; +} -	if (!host->chan_rx) -		goto erqrx; +static void sh_mmcif_request_dma(struct sh_mmcif_host *host, +				 struct sh_mmcif_plat_data *pdata) +{ +	host->dma_active = false; -	if (pdata) -		cfg.slave_id = pdata->slave_id_rx; -	cfg.direction = DMA_DEV_TO_MEM; -	cfg.dst_addr = 0; -	cfg.src_addr = res->start + MMCIF_CE_DATA; -	ret = dmaengine_slave_config(host->chan_rx, &cfg); -	if (ret < 0) -		goto ecfgrx; +	if (pdata) { +		if (pdata->slave_id_tx <= 0 || pdata->slave_id_rx <= 0) +			return; +	} else if (!host->pd->dev.of_node) { +		return; +	} -	return; +	/* We can only either use DMA for both Tx and Rx or not use it at all */ +	host->chan_tx = sh_mmcif_request_dma_one(host, pdata, DMA_MEM_TO_DEV); +	if (!host->chan_tx) +		return; -ecfgrx: -	dma_release_channel(host->chan_rx); -	host->chan_rx = NULL; -erqrx: -ecfgtx: -	dma_release_channel(host->chan_tx); -	host->chan_tx = NULL; +	host->chan_rx = sh_mmcif_request_dma_one(host, pdata, DMA_DEV_TO_MEM); +	if (!host->chan_rx) { +		dma_release_channel(host->chan_tx); +		host->chan_tx = NULL; +	}  }  static void sh_mmcif_release_dma(struct sh_mmcif_host *host) @@ -801,12 +803,13 @@ static u32 sh_mmcif_set_cmd(struct sh_mmcif_host *host,  			break;  		}  		switch (host->timing) { -		case MMC_TIMING_UHS_DDR50: +		case MMC_TIMING_MMC_DDR52:  			/*  			 * MMC core will only set this timing, if the host -			 * advertises the MMC_CAP_UHS_DDR50 capability. MMCIF -			 * implementations with this capability, e.g. sh73a0, -			 * will have to set it in their platform data. +			 * advertises the MMC_CAP_1_8V_DDR/MMC_CAP_1_2V_DDR +			 * capability. MMCIF implementations with this +			 * capability, e.g. sh73a0, will have to set it +			 * in their platform data.  			 */  			tmp |= CMD_SET_DARS;  			break; @@ -964,7 +967,7 @@ static void sh_mmcif_request(struct mmc_host *mmc, struct mmc_request *mrq)  static int sh_mmcif_clk_update(struct sh_mmcif_host *host)  { -	int ret = clk_enable(host->hclk); +	int ret = clk_prepare_enable(host->hclk);  	if (!ret) {  		host->clk = clk_get_rate(host->hclk); @@ -1018,7 +1021,7 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)  		}  		if (host->power) {  			pm_runtime_put_sync(&host->pd->dev); -			clk_disable(host->hclk); +			clk_disable_unprepare(host->hclk);  			host->power = false;  			if (ios->power_mode == MMC_POWER_OFF)  				sh_mmcif_set_power(host, ios); @@ -1466,7 +1469,7 @@ static int sh_mmcif_probe(struct platform_device *pdev)  	mutex_init(&host->thread_lock); -	clk_disable(host->hclk); +	clk_disable_unprepare(host->hclk);  	ret = mmc_add_host(mmc);  	if (ret < 0)  		goto emmcaddh; @@ -1487,7 +1490,7 @@ ereqirq1:  ereqirq0:  	pm_runtime_suspend(&pdev->dev);  eresume: -	clk_disable(host->hclk); +	clk_disable_unprepare(host->hclk);  eclkupdate:  	clk_put(host->hclk);  eclkget: @@ -1505,7 +1508,7 @@ static int sh_mmcif_remove(struct platform_device *pdev)  	int irq[2];  	host->dying = true; -	clk_enable(host->hclk); +	clk_prepare_enable(host->hclk);  	pm_runtime_get_sync(&pdev->dev);  	dev_pm_qos_hide_latency_limit(&pdev->dev); @@ -1530,7 +1533,7 @@ static int sh_mmcif_remove(struct platform_device *pdev)  	if (irq[1] >= 0)  		free_irq(irq[1], host); -	clk_disable(host->hclk); +	clk_disable_unprepare(host->hclk);  	mmc_free_host(host->mmc);  	pm_runtime_put_sync(&pdev->dev);  	pm_runtime_disable(&pdev->dev); @@ -1538,28 +1541,21 @@ static int sh_mmcif_remove(struct platform_device *pdev)  	return 0;  } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int sh_mmcif_suspend(struct device *dev)  {  	struct sh_mmcif_host *host = dev_get_drvdata(dev); -	int ret = mmc_suspend_host(host->mmc); -	if (!ret) -		sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL); +	sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL); -	return ret; +	return 0;  }  static int sh_mmcif_resume(struct device *dev)  { -	struct sh_mmcif_host *host = dev_get_drvdata(dev); - -	return mmc_resume_host(host->mmc); +	return 0;  } -#else -#define sh_mmcif_suspend	NULL -#define sh_mmcif_resume		NULL -#endif	/* CONFIG_PM */ +#endif  static const struct of_device_id mmcif_of_match[] = {  	{ .compatible = "renesas,sh-mmcif" }, @@ -1568,8 +1564,7 @@ static const struct of_device_id mmcif_of_match[] = {  MODULE_DEVICE_TABLE(of, mmcif_of_match);  static const struct dev_pm_ops sh_mmcif_dev_pm_ops = { -	.suspend = sh_mmcif_suspend, -	.resume = sh_mmcif_resume, +	SET_SYSTEM_SLEEP_PM_OPS(sh_mmcif_suspend, sh_mmcif_resume)  };  static struct platform_driver sh_mmcif_driver = {  | 
