summaryrefslogtreecommitdiff
path: root/firmware/target/arm/imx233/dma-imx233.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/imx233/dma-imx233.c')
-rw-r--r--firmware/target/arm/imx233/dma-imx233.c16
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
31static int apb_nr_unaligned[32];
32
30void imx233_dma_init(void) 33void 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 */
145static void imx233_dma_commit_and_discard(struct apb_dma_command_t *cmd) 148static 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
196void imx233_dma_start_command(unsigned chan, struct apb_dma_command_t *cmd) 201void 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
211void imx233_dma_wait_completion(unsigned chan) 216int 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
223struct imx233_dma_info_t imx233_dma_get_info(unsigned chan, unsigned flags) 230struct 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