diff options
Diffstat (limited to 'firmware/target/arm/imx233/dma-imx233.c')
-rw-r--r-- | firmware/target/arm/imx233/dma-imx233.c | 16 |
1 files changed, 12 insertions, 4 deletions
diff --git a/firmware/target/arm/imx233/dma-imx233.c b/firmware/target/arm/imx233/dma-imx233.c index 8dac284a38..cba1317f4f 100644 --- a/firmware/target/arm/imx233/dma-imx233.c +++ b/firmware/target/arm/imx233/dma-imx233.c | |||
@@ -27,6 +27,9 @@ | |||
27 | #include "lcd.h" | 27 | #include "lcd.h" |
28 | #include "string.h" | 28 | #include "string.h" |
29 | 29 | ||
30 | // statistics about unaligned transfers | ||
31 | static int apb_nr_unaligned[32]; | ||
32 | |||
30 | void imx233_dma_init(void) | 33 | void imx233_dma_init(void) |
31 | { | 34 | { |
32 | /* Enable APHB and APBX */ | 35 | /* Enable APHB and APBX */ |
@@ -142,7 +145,7 @@ bool imx233_dma_is_channel_error_irq(unsigned chan) | |||
142 | /* Commit and/or discard all DMA descriptors and buffers pointed by them, | 145 | /* Commit and/or discard all DMA descriptors and buffers pointed by them, |
143 | * handle circular lists. At the same time, convert virtual pointers to | 146 | * handle circular lists. At the same time, convert virtual pointers to |
144 | * real ones */ | 147 | * real ones */ |
145 | static void imx233_dma_commit_and_discard(struct apb_dma_command_t *cmd) | 148 | static void imx233_dma_commit_and_discard(unsigned chan, struct apb_dma_command_t *cmd) |
146 | { | 149 | { |
147 | /* We handle circular descriptors by using unused bits: | 150 | /* We handle circular descriptors by using unused bits: |
148 | * bits 8-11 are not used by the hardware so we first go through the whole | 151 | * bits 8-11 are not used by the hardware so we first go through the whole |
@@ -162,6 +165,8 @@ static void imx233_dma_commit_and_discard(struct apb_dma_command_t *cmd) | |||
162 | /* host > device: commit and discard */ | 165 | /* host > device: commit and discard */ |
163 | else if(op == HW_APB_CHx_CMD__COMMAND__READ) | 166 | else if(op == HW_APB_CHx_CMD__COMMAND__READ) |
164 | commit_discard_dcache_range(cur->buffer, sz); | 167 | commit_discard_dcache_range(cur->buffer, sz); |
168 | if((uint32_t)cur->buffer % CACHEALIGN_SIZE) | ||
169 | apb_nr_unaligned[chan]++; | ||
165 | /* Virtual to physical buffer pointer conversion */ | 170 | /* Virtual to physical buffer pointer conversion */ |
166 | cur->buffer = PHYSICAL_ADDR(cur->buffer); | 171 | cur->buffer = PHYSICAL_ADDR(cur->buffer); |
167 | /* chain ? */ | 172 | /* chain ? */ |
@@ -195,7 +200,7 @@ static void imx233_dma_commit_and_discard(struct apb_dma_command_t *cmd) | |||
195 | 200 | ||
196 | void imx233_dma_start_command(unsigned chan, struct apb_dma_command_t *cmd) | 201 | void imx233_dma_start_command(unsigned chan, struct apb_dma_command_t *cmd) |
197 | { | 202 | { |
198 | imx233_dma_commit_and_discard(cmd); | 203 | imx233_dma_commit_and_discard(chan, cmd); |
199 | if(APB_IS_APBX_CHANNEL(chan)) | 204 | if(APB_IS_APBX_CHANNEL(chan)) |
200 | { | 205 | { |
201 | HW_APBX_CHx_NXTCMDAR(APB_GET_DMA_CHANNEL(chan)) = (uint32_t)PHYSICAL_ADDR(cmd); | 206 | HW_APBX_CHx_NXTCMDAR(APB_GET_DMA_CHANNEL(chan)) = (uint32_t)PHYSICAL_ADDR(cmd); |
@@ -208,16 +213,18 @@ void imx233_dma_start_command(unsigned chan, struct apb_dma_command_t *cmd) | |||
208 | } | 213 | } |
209 | } | 214 | } |
210 | 215 | ||
211 | void imx233_dma_wait_completion(unsigned chan) | 216 | int imx233_dma_wait_completion(unsigned chan, unsigned tmo) |
212 | { | 217 | { |
218 | tmo += current_tick; | ||
213 | volatile uint32_t *sema; | 219 | volatile uint32_t *sema; |
214 | if(APB_IS_APBX_CHANNEL(chan)) | 220 | if(APB_IS_APBX_CHANNEL(chan)) |
215 | sema = &HW_APBX_CHx_SEMA(APB_GET_DMA_CHANNEL(chan)); | 221 | sema = &HW_APBX_CHx_SEMA(APB_GET_DMA_CHANNEL(chan)); |
216 | else | 222 | else |
217 | sema = &HW_APBH_CHx_SEMA(APB_GET_DMA_CHANNEL(chan)); | 223 | sema = &HW_APBH_CHx_SEMA(APB_GET_DMA_CHANNEL(chan)); |
218 | 224 | ||
219 | while(*sema & HW_APB_CHx_SEMA__PHORE_BM) | 225 | while(*sema & HW_APB_CHx_SEMA__PHORE_BM && !TIME_AFTER(current_tick, tmo)) |
220 | yield(); | 226 | yield(); |
227 | return __XTRACT_EX(*sema, HW_APB_CHx_SEMA__PHORE); | ||
221 | } | 228 | } |
222 | 229 | ||
223 | struct imx233_dma_info_t imx233_dma_get_info(unsigned chan, unsigned flags) | 230 | struct imx233_dma_info_t imx233_dma_get_info(unsigned chan, unsigned flags) |
@@ -254,6 +261,7 @@ struct imx233_dma_info_t imx233_dma_get_info(unsigned chan, unsigned flags) | |||
254 | s.int_error = apbx ? HW_APBX_CTRL2 & HW_APBX_CTRL2__CHx_ERROR_IRQ(dmac) : | 261 | s.int_error = apbx ? HW_APBX_CTRL2 & HW_APBX_CTRL2__CHx_ERROR_IRQ(dmac) : |
255 | HW_APBH_CTRL2 & HW_APBH_CTRL2__CHx_ERROR_IRQ(dmac); | 262 | HW_APBH_CTRL2 & HW_APBH_CTRL2__CHx_ERROR_IRQ(dmac); |
256 | } | 263 | } |
264 | s.nr_unaligned = apb_nr_unaligned[chan]; | ||
257 | return s; | 265 | return s; |
258 | } | 266 | } |
259 | 267 | ||