diff options
| -rw-r--r-- | arch/arm/mach-msm/dma.c | 72 | ||||
| -rw-r--r-- | arch/arm/mach-msm/include/mach/dma.h | 24 |
2 files changed, 71 insertions, 25 deletions
diff --git a/arch/arm/mach-msm/dma.c b/arch/arm/mach-msm/dma.c index 0c8f252637e..f5420f9585c 100644 --- a/arch/arm/mach-msm/dma.c +++ b/arch/arm/mach-msm/dma.c | |||
| @@ -26,7 +26,7 @@ enum { | |||
| 26 | }; | 26 | }; |
| 27 | 27 | ||
| 28 | static DEFINE_SPINLOCK(msm_dmov_lock); | 28 | static DEFINE_SPINLOCK(msm_dmov_lock); |
| 29 | static struct msm_dmov_cmd active_command; | 29 | static unsigned int channel_active; |
| 30 | static struct list_head ready_commands[MSM_DMOV_CHANNEL_COUNT]; | 30 | static struct list_head ready_commands[MSM_DMOV_CHANNEL_COUNT]; |
| 31 | static struct list_head active_commands[MSM_DMOV_CHANNEL_COUNT]; | 31 | static struct list_head active_commands[MSM_DMOV_CHANNEL_COUNT]; |
| 32 | unsigned int msm_dmov_print_mask = MSM_DMOV_PRINT_ERRORS; | 32 | unsigned 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 | ||
| 46 | void msm_dmov_stop_cmd(unsigned id, struct msm_dmov_cmd *cmd, int graceful) | ||
| 47 | { | ||
| 48 | writel((graceful << 31), DMOV_FLUSH0(id)); | ||
| 49 | } | ||
| 50 | |||
| 46 | void msm_dmov_enqueue_cmd(unsigned id, struct msm_dmov_cmd *cmd) | 51 | void 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 | ||
| 82 | static void dmov_exec_cmdptr_complete_func(struct msm_dmov_cmd *_cmd, unsigned int result) | 90 | static void |
| 91 | dmov_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) | |||
| 202 | static int __init msm_init_datamover(void) | 229 | static 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 | ||
| 213 | arch_initcall(msm_init_datamover); | 245 | arch_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 ad1c87f86d1..5ab5bdffab0 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 | ||
| 21 | struct msm_dmov_errdata { | ||
| 22 | uint32_t flush[6]; | ||
| 23 | }; | ||
| 24 | |||
| 21 | struct msm_dmov_cmd { | 25 | struct 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 | ||
| 28 | void msm_dmov_enqueue_cmd(unsigned id, struct msm_dmov_cmd *cmd); | 33 | void msm_dmov_enqueue_cmd(unsigned id, struct msm_dmov_cmd *cmd); |
| 29 | void msm_dmov_stop_cmd(unsigned id, struct msm_dmov_cmd *cmd); | 34 | void msm_dmov_stop_cmd(unsigned id, struct msm_dmov_cmd *cmd, int graceful); |
| 30 | int msm_dmov_exec_cmd(unsigned id, unsigned int cmdptr); | 35 | int 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 */ | ||
| 130 | typedef 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 */ |
