summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/target/arm/imx233/debug-imx233.c14
-rw-r--r--firmware/target/arm/imx233/dma-imx233.c16
-rw-r--r--firmware/target/arm/imx233/dma-imx233.h12
3 files changed, 26 insertions, 16 deletions
diff --git a/firmware/target/arm/imx233/debug-imx233.c b/firmware/target/arm/imx233/debug-imx233.c
index 90a9336f05..8553fd8509 100644
--- a/firmware/target/arm/imx233/debug-imx233.c
+++ b/firmware/target/arm/imx233/debug-imx233.c
@@ -111,17 +111,15 @@ bool dbg_hw_info_dma(void)
111 111
112 lcd_clear_display(); 112 lcd_clear_display();
113 113
114 lcd_putsf(0, 0, "I G F C E name bar apb ahb"); 114 lcd_putsf(0, 0, "S C name bar apb ahb una");
115 for(unsigned i = 0; i < ARRAYLEN(dbg_channels); i++) 115 for(unsigned i = 0; i < ARRAYLEN(dbg_channels); i++)
116 { 116 {
117 struct imx233_dma_info_t info = imx233_dma_get_info(dbg_channels[i].chan, DMA_INFO_ALL); 117 struct imx233_dma_info_t info = imx233_dma_get_info(dbg_channels[i].chan, DMA_INFO_ALL);
118 lcd_putsf(0, i + 1, "%c %c %c %c %c %4s %x %x %x", 118 lcd_putsf(0, i + 1, "%c %c %4s %8x %3x %3x %3x",
119 info.int_enabled ? 'i' : ' ', 119 info.gated ? 'g' : info.freezed ? 'f' : ' ',
120 info.gated ? 'g' : ' ', 120 !info.int_enabled ? '-' : info.int_error ? 'e' : info.int_cmdcomplt ? 'c' : ' ',
121 info.freezed ? 'f' : ' ', 121 dbg_channels[i].name, info.bar, info.apb_bytes, info.ahb_bytes,
122 info.int_cmdcomplt ? 'c' : ' ', 122 info.nr_unaligned);
123 info.int_error ? 'e' : ' ',
124 dbg_channels[i].name, info.bar, info.apb_bytes, info.ahb_bytes);
125 } 123 }
126 124
127 lcd_update(); 125 lcd_update();
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
diff --git a/firmware/target/arm/imx233/dma-imx233.h b/firmware/target/arm/imx233/dma-imx233.h
index ee836c2186..00b69ecf96 100644
--- a/firmware/target/arm/imx233/dma-imx233.h
+++ b/firmware/target/arm/imx233/dma-imx233.h
@@ -154,6 +154,7 @@ struct imx233_dma_info_t
154 bool int_enabled; 154 bool int_enabled;
155 bool int_cmdcomplt; 155 bool int_cmdcomplt;
156 bool int_error; 156 bool int_error;
157 int nr_unaligned;
157}; 158};
158 159
159#define APBH_DMA_CHANNEL(i) i 160#define APBH_DMA_CHANNEL(i) i
@@ -168,6 +169,7 @@ struct imx233_dma_info_t
168#define APB_NAND(dev) APBH_DMA_CHANNEL(HW_APBH_NAND(dev)) 169#define APB_NAND(dev) APBH_DMA_CHANNEL(HW_APBH_NAND(dev))
169 170
170#define HW_APB_CHx_CMD__COMMAND_BM 0x3 171#define HW_APB_CHx_CMD__COMMAND_BM 0x3
172#define HW_APB_CHx_CMD__COMMAND_BP 0
171#define HW_APB_CHx_CMD__COMMAND__NO_XFER 0 173#define HW_APB_CHx_CMD__COMMAND__NO_XFER 0
172#define HW_APB_CHx_CMD__COMMAND__WRITE 1 174#define HW_APB_CHx_CMD__COMMAND__WRITE 1
173#define HW_APB_CHx_CMD__COMMAND__READ 2 175#define HW_APB_CHx_CMD__COMMAND__READ 2
@@ -180,7 +182,7 @@ struct imx233_dma_info_t
180#define HW_APB_CHx_CMD__SEMAPHORE (1 << 6) 182#define HW_APB_CHx_CMD__SEMAPHORE (1 << 6)
181#define HW_APB_CHx_CMD__WAIT4ENDCMD (1 << 7) 183#define HW_APB_CHx_CMD__WAIT4ENDCMD (1 << 7)
182/* An errata advise not to use it */ 184/* An errata advise not to use it */
183//#define HW_APB_CHx_CMD__HALTONTERMINATE (1 << 8) 185#define HW_APB_CHx_CMD__HALTONTERMINATE (1 << 8)
184#define HW_APB_CHx_CMD__CMDWORDS_BM 0xf000 186#define HW_APB_CHx_CMD__CMDWORDS_BM 0xf000
185#define HW_APB_CHx_CMD__CMDWORDS_BP 12 187#define HW_APB_CHx_CMD__CMDWORDS_BP 12
186#define HW_APB_CHx_CMD__XFER_COUNT_BM 0xffff0000 188#define HW_APB_CHx_CMD__XFER_COUNT_BM 0xffff0000
@@ -193,8 +195,9 @@ struct imx233_dma_info_t
193#define HW_APB_CHx_SEMA__PHORE_BM 0xff0000 195#define HW_APB_CHx_SEMA__PHORE_BM 0xff0000
194#define HW_APB_CHx_SEMA__PHORE_BP 16 196#define HW_APB_CHx_SEMA__PHORE_BP 16
195 197
196/* A single descriptor cannot transfer more than 2^16 bytes */ 198/* A single descriptor cannot transfer more than 2^16 bytes but because of the
197#define IMX233_MAX_SINGLE_DMA_XFER_SIZE (1 << 16) 199 * weird 0=64KiB, it's safer to restrict to 2^15 */
200#define IMX233_MAX_SINGLE_DMA_XFER_SIZE (1 << 15)
198 201
199void imx233_dma_init(void); 202void imx233_dma_init(void);
200void imx233_dma_reset_channel(unsigned chan); 203void imx233_dma_reset_channel(unsigned chan);
@@ -208,7 +211,8 @@ void imx233_dma_clear_channel_interrupt(unsigned chan);
208bool imx233_dma_is_channel_error_irq(unsigned chan); 211bool imx233_dma_is_channel_error_irq(unsigned chan);
209/* assume no command is in progress */ 212/* assume no command is in progress */
210void imx233_dma_start_command(unsigned chan, struct apb_dma_command_t *cmd); 213void imx233_dma_start_command(unsigned chan, struct apb_dma_command_t *cmd);
211void imx233_dma_wait_completion(unsigned chan); 214/* return value of the semaphore */
215int imx233_dma_wait_completion(unsigned chan, unsigned tmo);
212/* get some info 216/* get some info
213 * WARNING: if channel is not freezed, data might not be coherent ! */ 217 * WARNING: if channel is not freezed, data might not be coherent ! */
214struct imx233_dma_info_t imx233_dma_get_info(unsigned chan, unsigned flags); 218struct imx233_dma_info_t imx233_dma_get_info(unsigned chan, unsigned flags);