diff options
author | Laxman Dewangan <ldewangan@nvidia.com> | 2013-04-24 05:54:27 -0400 |
---|---|---|
committer | Vinod Koul <vinod.koul@intel.com> | 2013-05-02 12:49:20 -0400 |
commit | 3065c194670b61e213656ce25976d7c8a95e3c93 (patch) | |
tree | f2d9b86bbe35623d9885f517f38c965f569675af | |
parent | b2396f7984ea09e83d489cfca6d5da62cc22945a (diff) |
dma: tegra: implement suspend/resume callbacks
Implement suspend/resume callbacks to store APB DMA channel's
register on suspend and restore APB DMA channel's register on
resume.
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
-rw-r--r-- | drivers/dma/tegra20-apb-dma.c | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c index 5a0b66c2a60c..ce193409ebd3 100644 --- a/drivers/dma/tegra20-apb-dma.c +++ b/drivers/dma/tegra20-apb-dma.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/of.h> | 30 | #include <linux/of.h> |
31 | #include <linux/of_device.h> | 31 | #include <linux/of_device.h> |
32 | #include <linux/platform_device.h> | 32 | #include <linux/platform_device.h> |
33 | #include <linux/pm.h> | ||
33 | #include <linux/pm_runtime.h> | 34 | #include <linux/pm_runtime.h> |
34 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
35 | #include <linux/clk/tegra.h> | 36 | #include <linux/clk/tegra.h> |
@@ -199,6 +200,7 @@ struct tegra_dma_channel { | |||
199 | 200 | ||
200 | /* Channel-slave specific configuration */ | 201 | /* Channel-slave specific configuration */ |
201 | struct dma_slave_config dma_sconfig; | 202 | struct dma_slave_config dma_sconfig; |
203 | struct tegra_dma_channel_regs channel_reg; | ||
202 | }; | 204 | }; |
203 | 205 | ||
204 | /* tegra_dma: Tegra DMA specific information */ | 206 | /* tegra_dma: Tegra DMA specific information */ |
@@ -1440,11 +1442,74 @@ static int tegra_dma_runtime_resume(struct device *dev) | |||
1440 | return 0; | 1442 | return 0; |
1441 | } | 1443 | } |
1442 | 1444 | ||
1445 | #ifdef CONFIG_PM_SLEEP | ||
1446 | static int tegra_dma_pm_suspend(struct device *dev) | ||
1447 | { | ||
1448 | struct tegra_dma *tdma = dev_get_drvdata(dev); | ||
1449 | int i; | ||
1450 | int ret; | ||
1451 | |||
1452 | /* Enable clock before accessing register */ | ||
1453 | ret = tegra_dma_runtime_resume(dev); | ||
1454 | if (ret < 0) | ||
1455 | return ret; | ||
1456 | |||
1457 | tdma->reg_gen = tdma_read(tdma, TEGRA_APBDMA_GENERAL); | ||
1458 | for (i = 0; i < tdma->chip_data->nr_channels; i++) { | ||
1459 | struct tegra_dma_channel *tdc = &tdma->channels[i]; | ||
1460 | struct tegra_dma_channel_regs *ch_reg = &tdc->channel_reg; | ||
1461 | |||
1462 | ch_reg->csr = tdc_read(tdc, TEGRA_APBDMA_CHAN_CSR); | ||
1463 | ch_reg->ahb_ptr = tdc_read(tdc, TEGRA_APBDMA_CHAN_AHBPTR); | ||
1464 | ch_reg->apb_ptr = tdc_read(tdc, TEGRA_APBDMA_CHAN_APBPTR); | ||
1465 | ch_reg->ahb_seq = tdc_read(tdc, TEGRA_APBDMA_CHAN_AHBSEQ); | ||
1466 | ch_reg->apb_seq = tdc_read(tdc, TEGRA_APBDMA_CHAN_APBSEQ); | ||
1467 | } | ||
1468 | |||
1469 | /* Disable clock */ | ||
1470 | tegra_dma_runtime_suspend(dev); | ||
1471 | return 0; | ||
1472 | } | ||
1473 | |||
1474 | static int tegra_dma_pm_resume(struct device *dev) | ||
1475 | { | ||
1476 | struct tegra_dma *tdma = dev_get_drvdata(dev); | ||
1477 | int i; | ||
1478 | int ret; | ||
1479 | |||
1480 | /* Enable clock before accessing register */ | ||
1481 | ret = tegra_dma_runtime_resume(dev); | ||
1482 | if (ret < 0) | ||
1483 | return ret; | ||
1484 | |||
1485 | tdma_write(tdma, TEGRA_APBDMA_GENERAL, tdma->reg_gen); | ||
1486 | tdma_write(tdma, TEGRA_APBDMA_CONTROL, 0); | ||
1487 | tdma_write(tdma, TEGRA_APBDMA_IRQ_MASK_SET, 0xFFFFFFFFul); | ||
1488 | |||
1489 | for (i = 0; i < tdma->chip_data->nr_channels; i++) { | ||
1490 | struct tegra_dma_channel *tdc = &tdma->channels[i]; | ||
1491 | struct tegra_dma_channel_regs *ch_reg = &tdc->channel_reg; | ||
1492 | |||
1493 | tdc_write(tdc, TEGRA_APBDMA_CHAN_APBSEQ, ch_reg->apb_seq); | ||
1494 | tdc_write(tdc, TEGRA_APBDMA_CHAN_APBPTR, ch_reg->apb_ptr); | ||
1495 | tdc_write(tdc, TEGRA_APBDMA_CHAN_AHBSEQ, ch_reg->ahb_seq); | ||
1496 | tdc_write(tdc, TEGRA_APBDMA_CHAN_AHBPTR, ch_reg->ahb_ptr); | ||
1497 | tdc_write(tdc, TEGRA_APBDMA_CHAN_CSR, | ||
1498 | (ch_reg->csr & ~TEGRA_APBDMA_CSR_ENB)); | ||
1499 | } | ||
1500 | |||
1501 | /* Disable clock */ | ||
1502 | tegra_dma_runtime_suspend(dev); | ||
1503 | return 0; | ||
1504 | } | ||
1505 | #endif | ||
1506 | |||
1443 | static const struct dev_pm_ops tegra_dma_dev_pm_ops = { | 1507 | static const struct dev_pm_ops tegra_dma_dev_pm_ops = { |
1444 | #ifdef CONFIG_PM_RUNTIME | 1508 | #ifdef CONFIG_PM_RUNTIME |
1445 | .runtime_suspend = tegra_dma_runtime_suspend, | 1509 | .runtime_suspend = tegra_dma_runtime_suspend, |
1446 | .runtime_resume = tegra_dma_runtime_resume, | 1510 | .runtime_resume = tegra_dma_runtime_resume, |
1447 | #endif | 1511 | #endif |
1512 | SET_SYSTEM_SLEEP_PM_OPS(tegra_dma_pm_suspend, tegra_dma_pm_resume) | ||
1448 | }; | 1513 | }; |
1449 | 1514 | ||
1450 | static struct platform_driver tegra_dmac_driver = { | 1515 | static struct platform_driver tegra_dmac_driver = { |