aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-msm
diff options
context:
space:
mode:
authorBrian Swetland <swetland@google.com>2008-09-10 17:58:25 -0400
committerBrian Swetland <swetland@google.com>2008-10-22 05:41:00 -0400
commit8a0f6f17c43933a4768ab79b9ac3ad24cd3c2c3f (patch)
tree3768860bbca3d9bc25ddaab987aedd88a901d7fe /arch/arm/mach-msm
parent600f7cfebeef74a6ba961c507079e3629da5dd7a (diff)
[ARM] msm: dma: various basic dma improvements and bugfixes
San: - Propagate DM errors to the originator of the request. - Implement msm_dmov_stop_cmd() - Add return value to init code - Modify msm_dmov_stop_cmd() to support ungraceful flushing Arve: - Disable datamover interrupt when not in use. We turn off the interrrupt to allow power collapse from idle. Signed-off-by: San Mehat <san@android.com> Signed-off-by: Arve Hjønnevåg <arve@android.com> Signed-off-by: Brian Swetland <swetland@google.com>
Diffstat (limited to 'arch/arm/mach-msm')
-rw-r--r--arch/arm/mach-msm/dma.c72
-rw-r--r--arch/arm/mach-msm/include/mach/dma.h24
2 files changed, 71 insertions, 25 deletions
diff --git a/arch/arm/mach-msm/dma.c b/arch/arm/mach-msm/dma.c
index 0c8f252637e1..f5420f9585c5 100644
--- a/arch/arm/mach-msm/dma.c
+++ b/arch/arm/mach-msm/dma.c
@@ -26,7 +26,7 @@ enum {
26}; 26};
27 27
28static DEFINE_SPINLOCK(msm_dmov_lock); 28static DEFINE_SPINLOCK(msm_dmov_lock);
29static struct msm_dmov_cmd active_command; 29static unsigned int channel_active;
30static struct list_head ready_commands[MSM_DMOV_CHANNEL_COUNT]; 30static struct list_head ready_commands[MSM_DMOV_CHANNEL_COUNT];
31static struct list_head active_commands[MSM_DMOV_CHANNEL_COUNT]; 31static struct list_head active_commands[MSM_DMOV_CHANNEL_COUNT];
32unsigned int msm_dmov_print_mask = MSM_DMOV_PRINT_ERRORS; 32unsigned int msm_dmov_print_mask = MSM_DMOV_PRINT_ERRORS;
@@ -43,6 +43,11 @@ unsigned int msm_dmov_print_mask = MSM_DMOV_PRINT_ERRORS;
43#define PRINT_FLOW(format, args...) \ 43#define PRINT_FLOW(format, args...) \
44 MSM_DMOV_DPRINTF(MSM_DMOV_PRINT_FLOW, format, args); 44 MSM_DMOV_DPRINTF(MSM_DMOV_PRINT_FLOW, format, args);
45 45
46void msm_dmov_stop_cmd(unsigned id, struct msm_dmov_cmd *cmd, int graceful)
47{
48 writel((graceful << 31), DMOV_FLUSH0(id));
49}
50
46void msm_dmov_enqueue_cmd(unsigned id, struct msm_dmov_cmd *cmd) 51void msm_dmov_enqueue_cmd(unsigned id, struct msm_dmov_cmd *cmd)
47{ 52{
48 unsigned long irq_flags; 53 unsigned long irq_flags;
@@ -60,6 +65,9 @@ void msm_dmov_enqueue_cmd(unsigned id, struct msm_dmov_cmd *cmd)
60#endif 65#endif
61 PRINT_IO("msm_dmov_enqueue_cmd(%d), start command, status %x\n", id, status); 66 PRINT_IO("msm_dmov_enqueue_cmd(%d), start command, status %x\n", id, status);
62 list_add_tail(&cmd->list, &active_commands[id]); 67 list_add_tail(&cmd->list, &active_commands[id]);
68 if (!channel_active)
69 enable_irq(INT_ADM_AARM);
70 channel_active |= 1U << id;
63 writel(cmd->cmdptr, DMOV_CMD_PTR(id)); 71 writel(cmd->cmdptr, DMOV_CMD_PTR(id));
64 } else { 72 } else {
65 if (list_empty(&active_commands[id])) 73 if (list_empty(&active_commands[id]))
@@ -76,21 +84,19 @@ struct msm_dmov_exec_cmdptr_cmd {
76 struct completion complete; 84 struct completion complete;
77 unsigned id; 85 unsigned id;
78 unsigned int result; 86 unsigned int result;
79 unsigned int flush[6]; 87 struct msm_dmov_errdata err;
80}; 88};
81 89
82static void dmov_exec_cmdptr_complete_func(struct msm_dmov_cmd *_cmd, unsigned int result) 90static void
91dmov_exec_cmdptr_complete_func(struct msm_dmov_cmd *_cmd,
92 unsigned int result,
93 struct msm_dmov_errdata *err)
83{ 94{
84 struct msm_dmov_exec_cmdptr_cmd *cmd = container_of(_cmd, struct msm_dmov_exec_cmdptr_cmd, dmov_cmd); 95 struct msm_dmov_exec_cmdptr_cmd *cmd = container_of(_cmd, struct msm_dmov_exec_cmdptr_cmd, dmov_cmd);
85 cmd->result = result; 96 cmd->result = result;
86 if (result != 0x80000002) { 97 if (result != 0x80000002 && err)
87 cmd->flush[0] = readl(DMOV_FLUSH0(cmd->id)); 98 memcpy(&cmd->err, err, sizeof(struct msm_dmov_errdata));
88 cmd->flush[1] = readl(DMOV_FLUSH1(cmd->id)); 99
89 cmd->flush[2] = readl(DMOV_FLUSH2(cmd->id));
90 cmd->flush[3] = readl(DMOV_FLUSH3(cmd->id));
91 cmd->flush[4] = readl(DMOV_FLUSH4(cmd->id));
92 cmd->flush[5] = readl(DMOV_FLUSH5(cmd->id));
93 }
94 complete(&cmd->complete); 100 complete(&cmd->complete);
95} 101}
96 102
@@ -111,7 +117,7 @@ int msm_dmov_exec_cmd(unsigned id, unsigned int cmdptr)
111 if (cmd.result != 0x80000002) { 117 if (cmd.result != 0x80000002) {
112 PRINT_ERROR("dmov_exec_cmdptr(%d): ERROR, result: %x\n", id, cmd.result); 118 PRINT_ERROR("dmov_exec_cmdptr(%d): ERROR, result: %x\n", id, cmd.result);
113 PRINT_ERROR("dmov_exec_cmdptr(%d): flush: %x %x %x %x\n", 119 PRINT_ERROR("dmov_exec_cmdptr(%d): flush: %x %x %x %x\n",
114 id, cmd.flush[0], cmd.flush[1], cmd.flush[2], cmd.flush[3]); 120 id, cmd.err.flush[0], cmd.err.flush[1], cmd.err.flush[2], cmd.err.flush[3]);
115 return -EIO; 121 return -EIO;
116 } 122 }
117 PRINT_FLOW("dmov_exec_cmdptr(%d, %x) done\n", id, cmdptr); 123 PRINT_FLOW("dmov_exec_cmdptr(%d, %x) done\n", id, cmdptr);
@@ -159,25 +165,40 @@ static irqreturn_t msm_datamover_irq_handler(int irq, void *dev_id)
159 "for %p, result %x\n", id, cmd, ch_result); 165 "for %p, result %x\n", id, cmd, ch_result);
160 if (cmd) { 166 if (cmd) {
161 list_del(&cmd->list); 167 list_del(&cmd->list);
162 cmd->complete_func(cmd, ch_result); 168 cmd->complete_func(cmd, ch_result, NULL);
163 } 169 }
164 } 170 }
165 if (ch_result & DMOV_RSLT_FLUSH) { 171 if (ch_result & DMOV_RSLT_FLUSH) {
166 unsigned int flush0 = readl(DMOV_FLUSH0(id)); 172 struct msm_dmov_errdata errdata;
173
174 errdata.flush[0] = readl(DMOV_FLUSH0(id));
175 errdata.flush[1] = readl(DMOV_FLUSH1(id));
176 errdata.flush[2] = readl(DMOV_FLUSH2(id));
177 errdata.flush[3] = readl(DMOV_FLUSH3(id));
178 errdata.flush[4] = readl(DMOV_FLUSH4(id));
179 errdata.flush[5] = readl(DMOV_FLUSH5(id));
167 PRINT_FLOW("msm_datamover_irq_handler id %d, status %x\n", id, ch_status); 180 PRINT_FLOW("msm_datamover_irq_handler id %d, status %x\n", id, ch_status);
168 PRINT_FLOW("msm_datamover_irq_handler id %d, flush, result %x, flush0 %x\n", id, ch_result, flush0); 181 PRINT_FLOW("msm_datamover_irq_handler id %d, flush, result %x, flush0 %x\n", id, ch_result, errdata.flush[0]);
169 if (cmd) { 182 if (cmd) {
170 list_del(&cmd->list); 183 list_del(&cmd->list);
171 cmd->complete_func(cmd, ch_result); 184 cmd->complete_func(cmd, ch_result, &errdata);
172 } 185 }
173 } 186 }
174 if (ch_result & DMOV_RSLT_ERROR) { 187 if (ch_result & DMOV_RSLT_ERROR) {
175 unsigned int flush0 = readl(DMOV_FLUSH0(id)); 188 struct msm_dmov_errdata errdata;
189
190 errdata.flush[0] = readl(DMOV_FLUSH0(id));
191 errdata.flush[1] = readl(DMOV_FLUSH1(id));
192 errdata.flush[2] = readl(DMOV_FLUSH2(id));
193 errdata.flush[3] = readl(DMOV_FLUSH3(id));
194 errdata.flush[4] = readl(DMOV_FLUSH4(id));
195 errdata.flush[5] = readl(DMOV_FLUSH5(id));
196
176 PRINT_ERROR("msm_datamover_irq_handler id %d, status %x\n", id, ch_status); 197 PRINT_ERROR("msm_datamover_irq_handler id %d, status %x\n", id, ch_status);
177 PRINT_ERROR("msm_datamover_irq_handler id %d, error, result %x, flush0 %x\n", id, ch_result, flush0); 198 PRINT_ERROR("msm_datamover_irq_handler id %d, error, result %x, flush0 %x\n", id, ch_result, errdata.flush[0]);
178 if (cmd) { 199 if (cmd) {
179 list_del(&cmd->list); 200 list_del(&cmd->list);
180 cmd->complete_func(cmd, ch_result); 201 cmd->complete_func(cmd, ch_result, &errdata);
181 } 202 }
182 /* this does not seem to work, once we get an error */ 203 /* this does not seem to work, once we get an error */
183 /* the datamover will no longer accept commands */ 204 /* the datamover will no longer accept commands */
@@ -193,8 +214,14 @@ static irqreturn_t msm_datamover_irq_handler(int irq, void *dev_id)
193 writel(cmd->cmdptr, DMOV_CMD_PTR(id)); 214 writel(cmd->cmdptr, DMOV_CMD_PTR(id));
194 } 215 }
195 } while (ch_status & DMOV_STATUS_RSLT_VALID); 216 } while (ch_status & DMOV_STATUS_RSLT_VALID);
217 if (list_empty(&active_commands[id]) && list_empty(&ready_commands[id]))
218 channel_active &= ~(1U << id);
196 PRINT_FLOW("msm_datamover_irq_handler id %d, status %x\n", id, ch_status); 219 PRINT_FLOW("msm_datamover_irq_handler id %d, status %x\n", id, ch_status);
197 } 220 }
221
222 if (!channel_active)
223 disable_irq(INT_ADM_AARM);
224
198 spin_unlock_irqrestore(&msm_dmov_lock, irq_flags); 225 spin_unlock_irqrestore(&msm_dmov_lock, irq_flags);
199 return IRQ_HANDLED; 226 return IRQ_HANDLED;
200} 227}
@@ -202,12 +229,17 @@ static irqreturn_t msm_datamover_irq_handler(int irq, void *dev_id)
202static int __init msm_init_datamover(void) 229static int __init msm_init_datamover(void)
203{ 230{
204 int i; 231 int i;
232 int ret;
205 for (i = 0; i < MSM_DMOV_CHANNEL_COUNT; i++) { 233 for (i = 0; i < MSM_DMOV_CHANNEL_COUNT; i++) {
206 INIT_LIST_HEAD(&ready_commands[i]); 234 INIT_LIST_HEAD(&ready_commands[i]);
207 INIT_LIST_HEAD(&active_commands[i]); 235 INIT_LIST_HEAD(&active_commands[i]);
208 writel(DMOV_CONFIG_IRQ_EN | DMOV_CONFIG_FORCE_TOP_PTR_RSLT | DMOV_CONFIG_FORCE_FLUSH_RSLT, DMOV_CONFIG(i)); 236 writel(DMOV_CONFIG_IRQ_EN | DMOV_CONFIG_FORCE_TOP_PTR_RSLT | DMOV_CONFIG_FORCE_FLUSH_RSLT, DMOV_CONFIG(i));
209 } 237 }
210 return request_irq(INT_ADM_AARM, msm_datamover_irq_handler, 0, "msmdatamover", NULL); 238 ret = request_irq(INT_ADM_AARM, msm_datamover_irq_handler, 0, "msmdatamover", NULL);
239 if (ret)
240 return ret;
241 disable_irq(INT_ADM_AARM);
242 return 0;
211} 243}
212 244
213arch_initcall(msm_init_datamover); 245arch_initcall(msm_init_datamover);
diff --git a/arch/arm/mach-msm/include/mach/dma.h b/arch/arm/mach-msm/include/mach/dma.h
index ad1c87f86d10..5ab5bdffab07 100644
--- a/arch/arm/mach-msm/include/mach/dma.h
+++ b/arch/arm/mach-msm/include/mach/dma.h
@@ -1,4 +1,4 @@
1/* arch/arm/mach-msm/include/mach/dma.h 1/* linux/include/asm-arm/arch-msm/dma.h
2 * 2 *
3 * Copyright (C) 2007 Google, Inc. 3 * Copyright (C) 2007 Google, Inc.
4 * 4 *
@@ -18,17 +18,21 @@
18#include <linux/list.h> 18#include <linux/list.h>
19#include <mach/msm_iomap.h> 19#include <mach/msm_iomap.h>
20 20
21struct msm_dmov_errdata {
22 uint32_t flush[6];
23};
24
21struct msm_dmov_cmd { 25struct msm_dmov_cmd {
22 struct list_head list; 26 struct list_head list;
23 unsigned int cmdptr; 27 unsigned int cmdptr;
24 void (*complete_func)(struct msm_dmov_cmd *cmd, unsigned int result); 28 void (*complete_func)(struct msm_dmov_cmd *cmd,
25/* void (*user_result_func)(struct msm_dmov_cmd *cmd); */ 29 unsigned int result,
30 struct msm_dmov_errdata *err);
26}; 31};
27 32
28void msm_dmov_enqueue_cmd(unsigned id, struct msm_dmov_cmd *cmd); 33void msm_dmov_enqueue_cmd(unsigned id, struct msm_dmov_cmd *cmd);
29void msm_dmov_stop_cmd(unsigned id, struct msm_dmov_cmd *cmd); 34void msm_dmov_stop_cmd(unsigned id, struct msm_dmov_cmd *cmd, int graceful);
30int msm_dmov_exec_cmd(unsigned id, unsigned int cmdptr); 35int msm_dmov_exec_cmd(unsigned id, unsigned int cmdptr);
31/* int msm_dmov_exec_cmd_etc(unsigned id, unsigned int cmdptr, int timeout, int interruptible); */
32 36
33 37
34 38
@@ -122,6 +126,16 @@ typedef struct {
122 unsigned _reserved; 126 unsigned _reserved;
123} dmov_sg; 127} dmov_sg;
124 128
129/* Box mode */
130typedef struct {
131 uint32_t cmd;
132 uint32_t src_row_addr;
133 uint32_t dst_row_addr;
134 uint32_t src_dst_len;
135 uint32_t num_rows;
136 uint32_t row_offset;
137} dmov_box;
138
125/* bits for the cmd field of the above structures */ 139/* bits for the cmd field of the above structures */
126 140
127#define CMD_LC (1 << 31) /* last command */ 141#define CMD_LC (1 << 31) /* last command */