Commit 2a2d0f63 authored by Vinod Koul's avatar Vinod Koul

Merge branch 'topic/tegra' into for-linus

parents c8b9dd2b 05e866b4
...@@ -296,7 +296,7 @@ static struct tegra_dma_desc *tegra_dma_desc_get( ...@@ -296,7 +296,7 @@ static struct tegra_dma_desc *tegra_dma_desc_get(
spin_unlock_irqrestore(&tdc->lock, flags); spin_unlock_irqrestore(&tdc->lock, flags);
/* Allocate DMA desc */ /* Allocate DMA desc */
dma_desc = kzalloc(sizeof(*dma_desc), GFP_ATOMIC); dma_desc = kzalloc(sizeof(*dma_desc), GFP_NOWAIT);
if (!dma_desc) { if (!dma_desc) {
dev_err(tdc2dev(tdc), "dma_desc alloc failed\n"); dev_err(tdc2dev(tdc), "dma_desc alloc failed\n");
return NULL; return NULL;
...@@ -336,7 +336,7 @@ static struct tegra_dma_sg_req *tegra_dma_sg_req_get( ...@@ -336,7 +336,7 @@ static struct tegra_dma_sg_req *tegra_dma_sg_req_get(
} }
spin_unlock_irqrestore(&tdc->lock, flags); spin_unlock_irqrestore(&tdc->lock, flags);
sg_req = kzalloc(sizeof(struct tegra_dma_sg_req), GFP_ATOMIC); sg_req = kzalloc(sizeof(struct tegra_dma_sg_req), GFP_NOWAIT);
if (!sg_req) if (!sg_req)
dev_err(tdc2dev(tdc), "sg_req alloc failed\n"); dev_err(tdc2dev(tdc), "sg_req alloc failed\n");
return sg_req; return sg_req;
...@@ -1186,10 +1186,12 @@ static int tegra_dma_alloc_chan_resources(struct dma_chan *dc) ...@@ -1186,10 +1186,12 @@ static int tegra_dma_alloc_chan_resources(struct dma_chan *dc)
dma_cookie_init(&tdc->dma_chan); dma_cookie_init(&tdc->dma_chan);
tdc->config_init = false; tdc->config_init = false;
ret = clk_prepare_enable(tdma->dma_clk);
ret = pm_runtime_get_sync(tdma->dev);
if (ret < 0) if (ret < 0)
dev_err(tdc2dev(tdc), "clk_prepare_enable failed: %d\n", ret);
return ret; return ret;
return 0;
} }
static void tegra_dma_free_chan_resources(struct dma_chan *dc) static void tegra_dma_free_chan_resources(struct dma_chan *dc)
...@@ -1232,7 +1234,7 @@ static void tegra_dma_free_chan_resources(struct dma_chan *dc) ...@@ -1232,7 +1234,7 @@ static void tegra_dma_free_chan_resources(struct dma_chan *dc)
list_del(&sg_req->node); list_del(&sg_req->node);
kfree(sg_req); kfree(sg_req);
} }
clk_disable_unprepare(tdma->dma_clk); pm_runtime_put(tdma->dev);
tdc->slave_id = 0; tdc->slave_id = 0;
} }
...@@ -1356,20 +1358,14 @@ static int tegra_dma_probe(struct platform_device *pdev) ...@@ -1356,20 +1358,14 @@ static int tegra_dma_probe(struct platform_device *pdev)
spin_lock_init(&tdma->global_lock); spin_lock_init(&tdma->global_lock);
pm_runtime_enable(&pdev->dev); pm_runtime_enable(&pdev->dev);
if (!pm_runtime_enabled(&pdev->dev)) { if (!pm_runtime_enabled(&pdev->dev))
ret = tegra_dma_runtime_resume(&pdev->dev); ret = tegra_dma_runtime_resume(&pdev->dev);
if (ret) { else
dev_err(&pdev->dev, "dma_runtime_resume failed %d\n", ret = pm_runtime_get_sync(&pdev->dev);
ret);
goto err_pm_disable;
}
}
/* Enable clock before accessing registers */
ret = clk_prepare_enable(tdma->dma_clk);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "clk_prepare_enable failed: %d\n", ret); pm_runtime_disable(&pdev->dev);
goto err_pm_disable; return ret;
} }
/* Reset DMA controller */ /* Reset DMA controller */
...@@ -1382,7 +1378,7 @@ static int tegra_dma_probe(struct platform_device *pdev) ...@@ -1382,7 +1378,7 @@ static int tegra_dma_probe(struct platform_device *pdev)
tdma_write(tdma, TEGRA_APBDMA_CONTROL, 0); tdma_write(tdma, TEGRA_APBDMA_CONTROL, 0);
tdma_write(tdma, TEGRA_APBDMA_IRQ_MASK_SET, 0xFFFFFFFFul); tdma_write(tdma, TEGRA_APBDMA_IRQ_MASK_SET, 0xFFFFFFFFul);
clk_disable_unprepare(tdma->dma_clk); pm_runtime_put(&pdev->dev);
INIT_LIST_HEAD(&tdma->dma_dev.channels); INIT_LIST_HEAD(&tdma->dma_dev.channels);
for (i = 0; i < cdata->nr_channels; i++) { for (i = 0; i < cdata->nr_channels; i++) {
...@@ -1400,8 +1396,7 @@ static int tegra_dma_probe(struct platform_device *pdev) ...@@ -1400,8 +1396,7 @@ static int tegra_dma_probe(struct platform_device *pdev)
} }
tdc->irq = res->start; tdc->irq = res->start;
snprintf(tdc->name, sizeof(tdc->name), "apbdma.%d", i); snprintf(tdc->name, sizeof(tdc->name), "apbdma.%d", i);
ret = devm_request_irq(&pdev->dev, tdc->irq, ret = request_irq(tdc->irq, tegra_dma_isr, 0, tdc->name, tdc);
tegra_dma_isr, 0, tdc->name, tdc);
if (ret) { if (ret) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
"request_irq failed with err %d channel %d\n", "request_irq failed with err %d channel %d\n",
...@@ -1482,10 +1477,11 @@ static int tegra_dma_probe(struct platform_device *pdev) ...@@ -1482,10 +1477,11 @@ static int tegra_dma_probe(struct platform_device *pdev)
err_irq: err_irq:
while (--i >= 0) { while (--i >= 0) {
struct tegra_dma_channel *tdc = &tdma->channels[i]; struct tegra_dma_channel *tdc = &tdma->channels[i];
free_irq(tdc->irq, tdc);
tasklet_kill(&tdc->tasklet); tasklet_kill(&tdc->tasklet);
} }
err_pm_disable:
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
if (!pm_runtime_status_suspended(&pdev->dev)) if (!pm_runtime_status_suspended(&pdev->dev))
tegra_dma_runtime_suspend(&pdev->dev); tegra_dma_runtime_suspend(&pdev->dev);
...@@ -1502,6 +1498,7 @@ static int tegra_dma_remove(struct platform_device *pdev) ...@@ -1502,6 +1498,7 @@ static int tegra_dma_remove(struct platform_device *pdev)
for (i = 0; i < tdma->chip_data->nr_channels; ++i) { for (i = 0; i < tdma->chip_data->nr_channels; ++i) {
tdc = &tdma->channels[i]; tdc = &tdma->channels[i];
free_irq(tdc->irq, tdc);
tasklet_kill(&tdc->tasklet); tasklet_kill(&tdc->tasklet);
} }
...@@ -1514,8 +1511,7 @@ static int tegra_dma_remove(struct platform_device *pdev) ...@@ -1514,8 +1511,7 @@ static int tegra_dma_remove(struct platform_device *pdev)
static int tegra_dma_runtime_suspend(struct device *dev) static int tegra_dma_runtime_suspend(struct device *dev)
{ {
struct platform_device *pdev = to_platform_device(dev); struct tegra_dma *tdma = dev_get_drvdata(dev);
struct tegra_dma *tdma = platform_get_drvdata(pdev);
clk_disable_unprepare(tdma->dma_clk); clk_disable_unprepare(tdma->dma_clk);
return 0; return 0;
...@@ -1523,8 +1519,7 @@ static int tegra_dma_runtime_suspend(struct device *dev) ...@@ -1523,8 +1519,7 @@ static int tegra_dma_runtime_suspend(struct device *dev)
static int tegra_dma_runtime_resume(struct device *dev) static int tegra_dma_runtime_resume(struct device *dev)
{ {
struct platform_device *pdev = to_platform_device(dev); struct tegra_dma *tdma = dev_get_drvdata(dev);
struct tegra_dma *tdma = platform_get_drvdata(pdev);
int ret; int ret;
ret = clk_prepare_enable(tdma->dma_clk); ret = clk_prepare_enable(tdma->dma_clk);
...@@ -1543,7 +1538,7 @@ static int tegra_dma_pm_suspend(struct device *dev) ...@@ -1543,7 +1538,7 @@ static int tegra_dma_pm_suspend(struct device *dev)
int ret; int ret;
/* Enable clock before accessing register */ /* Enable clock before accessing register */
ret = tegra_dma_runtime_resume(dev); ret = pm_runtime_get_sync(dev);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -1552,15 +1547,22 @@ static int tegra_dma_pm_suspend(struct device *dev) ...@@ -1552,15 +1547,22 @@ static int tegra_dma_pm_suspend(struct device *dev)
struct tegra_dma_channel *tdc = &tdma->channels[i]; struct tegra_dma_channel *tdc = &tdma->channels[i];
struct tegra_dma_channel_regs *ch_reg = &tdc->channel_reg; struct tegra_dma_channel_regs *ch_reg = &tdc->channel_reg;
/* Only save the state of DMA channels that are in use */
if (!tdc->config_init)
continue;
ch_reg->csr = tdc_read(tdc, TEGRA_APBDMA_CHAN_CSR); ch_reg->csr = tdc_read(tdc, TEGRA_APBDMA_CHAN_CSR);
ch_reg->ahb_ptr = tdc_read(tdc, TEGRA_APBDMA_CHAN_AHBPTR); ch_reg->ahb_ptr = tdc_read(tdc, TEGRA_APBDMA_CHAN_AHBPTR);
ch_reg->apb_ptr = tdc_read(tdc, TEGRA_APBDMA_CHAN_APBPTR); ch_reg->apb_ptr = tdc_read(tdc, TEGRA_APBDMA_CHAN_APBPTR);
ch_reg->ahb_seq = tdc_read(tdc, TEGRA_APBDMA_CHAN_AHBSEQ); ch_reg->ahb_seq = tdc_read(tdc, TEGRA_APBDMA_CHAN_AHBSEQ);
ch_reg->apb_seq = tdc_read(tdc, TEGRA_APBDMA_CHAN_APBSEQ); ch_reg->apb_seq = tdc_read(tdc, TEGRA_APBDMA_CHAN_APBSEQ);
if (tdma->chip_data->support_separate_wcount_reg)
ch_reg->wcount = tdc_read(tdc,
TEGRA_APBDMA_CHAN_WCOUNT);
} }
/* Disable clock */ /* Disable clock */
tegra_dma_runtime_suspend(dev); pm_runtime_put(dev);
return 0; return 0;
} }
...@@ -1571,7 +1573,7 @@ static int tegra_dma_pm_resume(struct device *dev) ...@@ -1571,7 +1573,7 @@ static int tegra_dma_pm_resume(struct device *dev)
int ret; int ret;
/* Enable clock before accessing register */ /* Enable clock before accessing register */
ret = tegra_dma_runtime_resume(dev); ret = pm_runtime_get_sync(dev);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -1583,6 +1585,13 @@ static int tegra_dma_pm_resume(struct device *dev) ...@@ -1583,6 +1585,13 @@ static int tegra_dma_pm_resume(struct device *dev)
struct tegra_dma_channel *tdc = &tdma->channels[i]; struct tegra_dma_channel *tdc = &tdma->channels[i];
struct tegra_dma_channel_regs *ch_reg = &tdc->channel_reg; struct tegra_dma_channel_regs *ch_reg = &tdc->channel_reg;
/* Only restore the state of DMA channels that are in use */
if (!tdc->config_init)
continue;
if (tdma->chip_data->support_separate_wcount_reg)
tdc_write(tdc, TEGRA_APBDMA_CHAN_WCOUNT,
ch_reg->wcount);
tdc_write(tdc, TEGRA_APBDMA_CHAN_APBSEQ, ch_reg->apb_seq); tdc_write(tdc, TEGRA_APBDMA_CHAN_APBSEQ, ch_reg->apb_seq);
tdc_write(tdc, TEGRA_APBDMA_CHAN_APBPTR, ch_reg->apb_ptr); tdc_write(tdc, TEGRA_APBDMA_CHAN_APBPTR, ch_reg->apb_ptr);
tdc_write(tdc, TEGRA_APBDMA_CHAN_AHBSEQ, ch_reg->ahb_seq); tdc_write(tdc, TEGRA_APBDMA_CHAN_AHBSEQ, ch_reg->ahb_seq);
...@@ -1592,16 +1601,14 @@ static int tegra_dma_pm_resume(struct device *dev) ...@@ -1592,16 +1601,14 @@ static int tegra_dma_pm_resume(struct device *dev)
} }
/* Disable clock */ /* Disable clock */
tegra_dma_runtime_suspend(dev); pm_runtime_put(dev);
return 0; return 0;
} }
#endif #endif
static const struct dev_pm_ops tegra_dma_dev_pm_ops = { static const struct dev_pm_ops tegra_dma_dev_pm_ops = {
#ifdef CONFIG_PM SET_RUNTIME_PM_OPS(tegra_dma_runtime_suspend, tegra_dma_runtime_resume,
.runtime_suspend = tegra_dma_runtime_suspend, NULL)
.runtime_resume = tegra_dma_runtime_resume,
#endif
SET_SYSTEM_SLEEP_PM_OPS(tegra_dma_pm_suspend, tegra_dma_pm_resume) SET_SYSTEM_SLEEP_PM_OPS(tegra_dma_pm_suspend, tegra_dma_pm_resume)
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment