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 = { |
