diff options
-rw-r--r-- | firmware/target/arm/imx233/debug-imx233.c | 14 | ||||
-rw-r--r-- | firmware/target/arm/imx233/dma-imx233.c | 16 | ||||
-rw-r--r-- | firmware/target/arm/imx233/dma-imx233.h | 12 |
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 | ||
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 | ||
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 | ||
199 | void imx233_dma_init(void); | 202 | void imx233_dma_init(void); |
200 | void imx233_dma_reset_channel(unsigned chan); | 203 | void imx233_dma_reset_channel(unsigned chan); |
@@ -208,7 +211,8 @@ void imx233_dma_clear_channel_interrupt(unsigned chan); | |||
208 | bool imx233_dma_is_channel_error_irq(unsigned chan); | 211 | bool imx233_dma_is_channel_error_irq(unsigned chan); |
209 | /* assume no command is in progress */ | 212 | /* assume no command is in progress */ |
210 | void imx233_dma_start_command(unsigned chan, struct apb_dma_command_t *cmd); | 213 | void imx233_dma_start_command(unsigned chan, struct apb_dma_command_t *cmd); |
211 | void imx233_dma_wait_completion(unsigned chan); | 214 | /* return value of the semaphore */ |
215 | int 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 ! */ |
214 | struct imx233_dma_info_t imx233_dma_get_info(unsigned chan, unsigned flags); | 218 | struct imx233_dma_info_t imx233_dma_get_info(unsigned chan, unsigned flags); |