diff options
author | Arve Hjønnevåg <arve@android.com> | 2009-06-25 20:03:14 -0400 |
---|---|---|
committer | Daniel Walker <dwalker@codeaurora.org> | 2010-05-12 12:14:14 -0400 |
commit | c5541079da3cd19626410d59455d3e0f34d65943 (patch) | |
tree | 46239df471eb9ddb8d942d94e457d932cb630e60 /arch/arm/mach-msm/dma.c | |
parent | a6407dd7b89f0de39d315eee64ad59dd68187b38 (diff) |
[ARM] msm: dma: Enable dma clock while dma is active
Signed-off-by: Arve Hjønnevåg <arve@android.com>
Diffstat (limited to 'arch/arm/mach-msm/dma.c')
-rw-r--r-- | arch/arm/mach-msm/dma.c | 17 |
1 files changed, 16 insertions, 1 deletions
diff --git a/arch/arm/mach-msm/dma.c b/arch/arm/mach-msm/dma.c index 09c0c0f9729..e80cad46892 100644 --- a/arch/arm/mach-msm/dma.c +++ b/arch/arm/mach-msm/dma.c | |||
@@ -13,6 +13,8 @@ | |||
13 | * | 13 | * |
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/clk.h> | ||
17 | #include <linux/err.h> | ||
16 | #include <linux/io.h> | 18 | #include <linux/io.h> |
17 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
18 | #include <mach/dma.h> | 20 | #include <mach/dma.h> |
@@ -26,6 +28,7 @@ enum { | |||
26 | }; | 28 | }; |
27 | 29 | ||
28 | static DEFINE_SPINLOCK(msm_dmov_lock); | 30 | static DEFINE_SPINLOCK(msm_dmov_lock); |
31 | static struct clk *msm_dmov_clk; | ||
29 | static unsigned int channel_active; | 32 | static unsigned int channel_active; |
30 | static struct list_head ready_commands[MSM_DMOV_CHANNEL_COUNT]; | 33 | static struct list_head ready_commands[MSM_DMOV_CHANNEL_COUNT]; |
31 | static struct list_head active_commands[MSM_DMOV_CHANNEL_COUNT]; | 34 | static struct list_head active_commands[MSM_DMOV_CHANNEL_COUNT]; |
@@ -54,6 +57,8 @@ void msm_dmov_enqueue_cmd(unsigned id, struct msm_dmov_cmd *cmd) | |||
54 | unsigned int status; | 57 | unsigned int status; |
55 | 58 | ||
56 | spin_lock_irqsave(&msm_dmov_lock, irq_flags); | 59 | spin_lock_irqsave(&msm_dmov_lock, irq_flags); |
60 | if (!channel_active) | ||
61 | clk_enable(msm_dmov_clk); | ||
57 | status = readl(DMOV_STATUS(id)); | 62 | status = readl(DMOV_STATUS(id)); |
58 | if (list_empty(&ready_commands[id]) && | 63 | if (list_empty(&ready_commands[id]) && |
59 | (status & DMOV_STATUS_CMD_PTR_RDY)) { | 64 | (status & DMOV_STATUS_CMD_PTR_RDY)) { |
@@ -70,6 +75,8 @@ void msm_dmov_enqueue_cmd(unsigned id, struct msm_dmov_cmd *cmd) | |||
70 | channel_active |= 1U << id; | 75 | channel_active |= 1U << id; |
71 | writel(cmd->cmdptr, DMOV_CMD_PTR(id)); | 76 | writel(cmd->cmdptr, DMOV_CMD_PTR(id)); |
72 | } else { | 77 | } else { |
78 | if (!channel_active) | ||
79 | clk_disable(msm_dmov_clk); | ||
73 | if (list_empty(&active_commands[id])) | 80 | if (list_empty(&active_commands[id])) |
74 | PRINT_ERROR("msm_dmov_enqueue_cmd(%d), error datamover stalled, status %x\n", id, status); | 81 | PRINT_ERROR("msm_dmov_enqueue_cmd(%d), error datamover stalled, status %x\n", id, status); |
75 | 82 | ||
@@ -219,8 +226,10 @@ static irqreturn_t msm_datamover_irq_handler(int irq, void *dev_id) | |||
219 | PRINT_FLOW("msm_datamover_irq_handler id %d, status %x\n", id, ch_status); | 226 | PRINT_FLOW("msm_datamover_irq_handler id %d, status %x\n", id, ch_status); |
220 | } | 227 | } |
221 | 228 | ||
222 | if (!channel_active) | 229 | if (!channel_active) { |
223 | disable_irq_nosync(INT_ADM_AARM); | 230 | disable_irq_nosync(INT_ADM_AARM); |
231 | clk_disable(msm_dmov_clk); | ||
232 | } | ||
224 | 233 | ||
225 | spin_unlock_irqrestore(&msm_dmov_lock, irq_flags); | 234 | spin_unlock_irqrestore(&msm_dmov_lock, irq_flags); |
226 | return IRQ_HANDLED; | 235 | return IRQ_HANDLED; |
@@ -230,11 +239,17 @@ static int __init msm_init_datamover(void) | |||
230 | { | 239 | { |
231 | int i; | 240 | int i; |
232 | int ret; | 241 | int ret; |
242 | struct clk *clk; | ||
243 | |||
233 | for (i = 0; i < MSM_DMOV_CHANNEL_COUNT; i++) { | 244 | for (i = 0; i < MSM_DMOV_CHANNEL_COUNT; i++) { |
234 | INIT_LIST_HEAD(&ready_commands[i]); | 245 | INIT_LIST_HEAD(&ready_commands[i]); |
235 | INIT_LIST_HEAD(&active_commands[i]); | 246 | INIT_LIST_HEAD(&active_commands[i]); |
236 | writel(DMOV_CONFIG_IRQ_EN | DMOV_CONFIG_FORCE_TOP_PTR_RSLT | DMOV_CONFIG_FORCE_FLUSH_RSLT, DMOV_CONFIG(i)); | 247 | writel(DMOV_CONFIG_IRQ_EN | DMOV_CONFIG_FORCE_TOP_PTR_RSLT | DMOV_CONFIG_FORCE_FLUSH_RSLT, DMOV_CONFIG(i)); |
237 | } | 248 | } |
249 | clk = clk_get(NULL, "adm_clk"); | ||
250 | if (IS_ERR(clk)) | ||
251 | return PTR_ERR(clk); | ||
252 | msm_dmov_clk = clk; | ||
238 | ret = request_irq(INT_ADM_AARM, msm_datamover_irq_handler, 0, "msmdatamover", NULL); | 253 | ret = request_irq(INT_ADM_AARM, msm_datamover_irq_handler, 0, "msmdatamover", NULL); |
239 | if (ret) | 254 | if (ret) |
240 | return ret; | 255 | return ret; |