diff options
Diffstat (limited to 'firmware/target/arm/imx233/dma-imx233.c')
-rw-r--r-- | firmware/target/arm/imx233/dma-imx233.c | 27 |
1 files changed, 18 insertions, 9 deletions
diff --git a/firmware/target/arm/imx233/dma-imx233.c b/firmware/target/arm/imx233/dma-imx233.c index 8a42bd12da..eba41958a9 100644 --- a/firmware/target/arm/imx233/dma-imx233.c +++ b/firmware/target/arm/imx233/dma-imx233.c | |||
@@ -107,7 +107,8 @@ bool imx233_dma_is_channel_error_irq(unsigned chan) | |||
107 | } | 107 | } |
108 | 108 | ||
109 | /* Commit and/or discard all DMA descriptors and buffers pointed by them, | 109 | /* Commit and/or discard all DMA descriptors and buffers pointed by them, |
110 | * handle circular lists */ | 110 | * handle circular lists. At the same time, convert virtual pointers to |
111 | * real ones */ | ||
111 | static void imx233_dma_commit_and_discard(struct apb_dma_command_t *cmd) | 112 | static void imx233_dma_commit_and_discard(struct apb_dma_command_t *cmd) |
112 | { | 113 | { |
113 | /* We handle circular descriptors by using unused bits: | 114 | /* We handle circular descriptors by using unused bits: |
@@ -121,13 +122,15 @@ static void imx233_dma_commit_and_discard(struct apb_dma_command_t *cmd) | |||
121 | { | 122 | { |
122 | cur->cmd = (cur->cmd & ~HW_APB_CHx_CMD__UNUSED_BM) | HW_APB_CHx_CMD__UNUSED_MAGIC; | 123 | cur->cmd = (cur->cmd & ~HW_APB_CHx_CMD__UNUSED_BM) | HW_APB_CHx_CMD__UNUSED_MAGIC; |
123 | int op = cur->cmd & HW_APB_CHx_CMD__COMMAND_BM; | 124 | int op = cur->cmd & HW_APB_CHx_CMD__COMMAND_BM; |
124 | int sz = (cur->cmd & HW_APB_CHx_CMD__XFER_COUNT_BM) >> HW_APB_CHx_CMD__XFER_COUNT_BP; | 125 | int sz = __XTRACT_EX(cur->cmd, HW_APB_CHx_CMD__XFER_COUNT); |
125 | /* device > host: discard */ | 126 | /* device > host: discard */ |
126 | if(op == HW_APB_CHx_CMD__COMMAND__WRITE) | 127 | if(op == HW_APB_CHx_CMD__COMMAND__WRITE) |
127 | discard_dcache_range(cur->buffer, sz); | 128 | discard_dcache_range(cur->buffer, sz); |
128 | /* host > device: commit and discard */ | 129 | /* host > device: commit and discard */ |
129 | else if(op == HW_APB_CHx_CMD__COMMAND__READ) | 130 | else if(op == HW_APB_CHx_CMD__COMMAND__READ) |
130 | commit_discard_dcache_range(cur->buffer, sz); | 131 | commit_discard_dcache_range(cur->buffer, sz); |
132 | /* Virtual to physical buffer pointer conversion */ | ||
133 | cur->buffer = PHYSICAL_ADDR(cur->buffer); | ||
131 | /* chain ? */ | 134 | /* chain ? */ |
132 | if(cur->cmd & HW_APB_CHx_CMD__CHAIN) | 135 | if(cur->cmd & HW_APB_CHx_CMD__CHAIN) |
133 | cur = cur->next; | 136 | cur = cur->next; |
@@ -139,15 +142,21 @@ static void imx233_dma_commit_and_discard(struct apb_dma_command_t *cmd) | |||
139 | while((cur->cmd & HW_APB_CHx_CMD__UNUSED_BM) != 0) | 142 | while((cur->cmd & HW_APB_CHx_CMD__UNUSED_BM) != 0) |
140 | { | 143 | { |
141 | cur->cmd = cur->cmd & ~HW_APB_CHx_CMD__UNUSED_BM; | 144 | cur->cmd = cur->cmd & ~HW_APB_CHx_CMD__UNUSED_BM; |
142 | int sz = (cur->cmd & HW_APB_CHx_CMD__CMDWORDS_BM) >> HW_APB_CHx_CMD__CMDWORDS_BP; | 145 | int sz = __XTRACT_EX(cur->cmd, HW_APB_CHx_CMD__CMDWORDS) * sizeof(uint32_t); |
143 | /* commit descriptor (don't discard since we access it after) */ | 146 | /* commit descriptor and discard descriptor */ |
144 | commit_dcache_range(cur, | ||
145 | sizeof(struct apb_dma_command_t) + sizeof(uint32_t) * sz); | ||
146 | /* chain ? */ | 147 | /* chain ? */ |
147 | if(cur->cmd & HW_APB_CHx_CMD__CHAIN) | 148 | if(cur->cmd & HW_APB_CHx_CMD__CHAIN) |
148 | cur = cur->next; | 149 | { |
150 | struct apb_dma_command_t *next = cur->next; | ||
151 | cur->next = PHYSICAL_ADDR(cur->next); | ||
152 | commit_dcache_range(cur, sizeof(struct apb_dma_command_t) + sz); | ||
153 | cur = next; | ||
154 | } | ||
149 | else | 155 | else |
156 | { | ||
157 | commit_dcache_range(cur, sizeof(struct apb_dma_command_t) + sz); | ||
150 | break; | 158 | break; |
159 | } | ||
151 | } | 160 | } |
152 | } | 161 | } |
153 | 162 | ||
@@ -156,12 +165,12 @@ void imx233_dma_start_command(unsigned chan, struct apb_dma_command_t *cmd) | |||
156 | imx233_dma_commit_and_discard(cmd); | 165 | imx233_dma_commit_and_discard(cmd); |
157 | if(APB_IS_APBX_CHANNEL(chan)) | 166 | if(APB_IS_APBX_CHANNEL(chan)) |
158 | { | 167 | { |
159 | HW_APBX_CHx_NXTCMDAR(APB_GET_DMA_CHANNEL(chan)) = (uint32_t)cmd; | 168 | HW_APBX_CHx_NXTCMDAR(APB_GET_DMA_CHANNEL(chan)) = (uint32_t)PHYSICAL_ADDR(cmd); |
160 | HW_APBX_CHx_SEMA(APB_GET_DMA_CHANNEL(chan)) = 1; | 169 | HW_APBX_CHx_SEMA(APB_GET_DMA_CHANNEL(chan)) = 1; |
161 | } | 170 | } |
162 | else | 171 | else |
163 | { | 172 | { |
164 | HW_APBH_CHx_NXTCMDAR(APB_GET_DMA_CHANNEL(chan)) = (uint32_t)cmd; | 173 | HW_APBH_CHx_NXTCMDAR(APB_GET_DMA_CHANNEL(chan)) = (uint32_t)PHYSICAL_ADDR(cmd); |
165 | HW_APBH_CHx_SEMA(APB_GET_DMA_CHANNEL(chan)) = 1; | 174 | HW_APBH_CHx_SEMA(APB_GET_DMA_CHANNEL(chan)) = 1; |
166 | } | 175 | } |
167 | } | 176 | } |