summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2012-08-18 15:22:51 +0200
committerAmaury Pouly <amaury.pouly@gmail.com>2012-08-18 15:22:51 +0200
commit246c2127a7fb9001781dff5bff41b53cc2215e98 (patch)
tree55bb40152bd5cc28822fbc3caa3a0d363a3f5030
parent51919937a9ecd2264fbac0e64a2737aaac8e2243 (diff)
downloadrockbox-246c2127a7fb9001781dff5bff41b53cc2215e98.tar.gz
rockbox-246c2127a7fb9001781dff5bff41b53cc2215e98.zip
imx233: small dma changes, update debug screen
Reduce DMA maximum transfer size since transfering 64Kb requires to set a size of 0 and it's not worth adding checks everywhere to handle this special case. Also add statistics about unaligned transfer (wrt to cache). Update debug screen accordingly and simplify it so it can fit smaller screens too. Change-Id: I18391702f5e100a21f6f8d1ebab28d9f2bd8c66f
-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);