diff options
author | Chaitanya Bandi <bandik@nvidia.com> | 2013-08-27 20:18:12 +0530 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2013-09-14 13:43:58 -0700 |
commit | 62003f912a82e8396649eb63fb3910809df9bab4 (patch) | |
tree | 3523340453d7ea12d1d80c100b1832c3a86d3649 /drivers/dma | |
parent | 84e5f74cc08eb1718cbba9b6c39724a72d9688d6 (diff) |
dma: tegra: Use runtime_pm for enabling/disabling clock
Used runtime pm APIs for clock enabling/disabling and
also made changes such that clock is not enabled during
idle.
Bug 1326667
Change-Id: I7cf478006e11b3a63271c8c7b0a8f0e9406cbbca
Signed-off-by: Chaitanya Bandi <bandik@nvidia.com>
Reviewed-on: http://git-master/r/265931
GVS: Gerrit_Virtual_Submit
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>
Diffstat (limited to 'drivers/dma')
-rw-r--r-- | drivers/dma/tegra20-apb-dma.c | 28 |
1 files changed, 18 insertions, 10 deletions
diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c index abf696b71040..1f69262be9a7 100644 --- a/drivers/dma/tegra20-apb-dma.c +++ b/drivers/dma/tegra20-apb-dma.c @@ -1,7 +1,7 @@ /* * DMA driver for Nvidia's Tegra20 APB DMA controller. * - * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2012-13, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -600,6 +600,11 @@ static void handle_once_dma_done(struct tegra_dma_channel *tdc, list_add_tail(&sgreq->node, &tdc->free_sg_req); /* Do not start DMA if it is going to be terminate */ + if (list_empty(&tdc->pending_sg_req)) { + clk_disable_unprepare(tdc->tdma->dma_clk); + pm_runtime_put(tdc->tdma->dev); + } + if (to_terminate || list_empty(&tdc->pending_sg_req)) return; @@ -703,12 +708,21 @@ static void tegra_dma_issue_pending(struct dma_chan *dc) { struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc); unsigned long flags; + int ret; spin_lock_irqsave(&tdc->lock, flags); if (list_empty(&tdc->pending_sg_req)) { dev_err(tdc2dev(tdc), "No DMA request\n"); goto end; } + + pm_runtime_get(tdc->tdma->dev); + ret = clk_prepare_enable(tdc->tdma->dma_clk); + if (ret < 0) { + dev_err(tdc2dev(tdc), "clk_enable failed: %d\n", ret); + return; + } + if (!tdc->busy) { tdc_start_head_req(tdc); @@ -772,6 +786,8 @@ static void tegra_dma_terminate_all(struct dma_chan *dc) get_current_xferred_count(tdc, sgreq, wcount); } tegra_dma_resume(tdc); + clk_disable_unprepare(tdc->tdma->dma_clk); + pm_runtime_put(tdc->tdma->dev); skip_dma_stop: tegra_dma_abort_all(tdc); @@ -1193,22 +1209,15 @@ struct dma_async_tx_descriptor *tegra_dma_prep_dma_cyclic( static int tegra_dma_alloc_chan_resources(struct dma_chan *dc) { struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc); - struct tegra_dma *tdma = tdc->tdma; - int ret; dma_cookie_init(&tdc->dma_chan); tdc->config_init = false; - ret = clk_prepare_enable(tdma->dma_clk); - if (ret < 0) - dev_err(tdc2dev(tdc), "clk_prepare_enable failed: %d\n", ret); - return ret; + return 0; } static void tegra_dma_free_chan_resources(struct dma_chan *dc) { struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc); - struct tegra_dma *tdma = tdc->tdma; - struct tegra_dma_desc *dma_desc; struct tegra_dma_sg_req *sg_req; struct list_head dma_desc_list; @@ -1243,7 +1252,6 @@ static void tegra_dma_free_chan_resources(struct dma_chan *dc) list_del(&sg_req->node); kfree(sg_req); } - clk_disable_unprepare(tdma->dma_clk); } /* Tegra20 specific DMA controller information */ |