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.c159
1 files changed, 68 insertions, 91 deletions
diff --git a/firmware/target/arm/imx233/dma-imx233.c b/firmware/target/arm/imx233/dma-imx233.c
index 3d156b2dfd..5808731eef 100644
--- a/firmware/target/arm/imx233/dma-imx233.c
+++ b/firmware/target/arm/imx233/dma-imx233.c
@@ -36,22 +36,17 @@ void imx233_dma_init(void)
36 36
37void imx233_dma_reset_channel(unsigned chan) 37void imx233_dma_reset_channel(unsigned chan)
38{ 38{
39 volatile uint32_t *ptr; 39 uint32_t bm = 1 << APB_GET_DMA_CHANNEL(chan);
40 uint32_t bm;
41 if(APB_IS_APBX_CHANNEL(chan)) 40 if(APB_IS_APBX_CHANNEL(chan))
42 { 41 {
43 ptr = &HW_APBX_CHANNEL_CTRL; 42 BF_SETV(APBX_CHANNEL_CTRL, RESET_CHANNEL, bm);
44 bm = HW_APBX_CHANNEL_CTRL__RESET_CHANNEL(APB_GET_DMA_CHANNEL(chan)); 43 while(BF_RD(APBX_CHANNEL_CTRL, RESET_CHANNEL) & bm);
45 } 44 }
46 else 45 else
47 { 46 {
48 ptr = &HW_APBH_CTRL0; 47 BF_SETV(APBH_CTRL0, RESET_CHANNEL, bm);
49 bm = HW_APBH_CTRL0__RESET_CHANNEL(APB_GET_DMA_CHANNEL(chan)); 48 while(BF_RD(APBH_CTRL0, RESET_CHANNEL) & bm);
50 } 49 }
51 __REG_SET(*ptr) = bm;
52 /* wait for end of reset */
53 while(*ptr & bm)
54 ;
55} 50}
56 51
57void imx233_dma_clkgate_channel(unsigned chan, bool enable_clock) 52void imx233_dma_clkgate_channel(unsigned chan, bool enable_clock)
@@ -59,84 +54,72 @@ void imx233_dma_clkgate_channel(unsigned chan, bool enable_clock)
59 if(APB_IS_APBX_CHANNEL(chan)) 54 if(APB_IS_APBX_CHANNEL(chan))
60 return; 55 return;
61 if(enable_clock) 56 if(enable_clock)
62 __REG_CLR(HW_APBH_CTRL0) = 57 BF_CLRV(APBH_CTRL0, CLKGATE_CHANNEL, 1 << APB_GET_DMA_CHANNEL(chan));
63 HW_APBH_CTRL0__CLKGATE_CHANNEL(APB_GET_DMA_CHANNEL(chan));
64 else 58 else
65 __REG_SET(HW_APBH_CTRL0) = 59 BF_SETV(APBH_CTRL0, CLKGATE_CHANNEL, 1 << APB_GET_DMA_CHANNEL(chan));
66 HW_APBH_CTRL0__CLKGATE_CHANNEL(APB_GET_DMA_CHANNEL(chan));
67} 60}
68 61
69void imx233_dma_freeze_channel(unsigned chan, bool freeze) 62void imx233_dma_freeze_channel(unsigned chan, bool freeze)
70{ 63{
71 volatile uint32_t *ptr; 64 uint32_t bm = 1 << APB_GET_DMA_CHANNEL(chan);
72 uint32_t bm;
73 if(APB_IS_APBX_CHANNEL(chan)) 65 if(APB_IS_APBX_CHANNEL(chan))
74 { 66 {
75 ptr = &HW_APBX_CHANNEL_CTRL; 67 if(freeze)
76 bm = HW_APBX_CHANNEL_CTRL__FREEZE_CHANNEL(APB_GET_DMA_CHANNEL(chan)); 68 BF_SETV(APBX_CHANNEL_CTRL, FREEZE_CHANNEL, bm);
69 else
70 BF_CLRV(APBX_CHANNEL_CTRL, FREEZE_CHANNEL, bm);
77 } 71 }
78 else 72 else
79 { 73 {
80 ptr = &HW_APBH_CTRL0; 74 if(freeze)
81 bm = HW_APBH_CTRL0__FREEZE_CHANNEL(APB_GET_DMA_CHANNEL(chan)); 75 BF_SETV(APBH_CTRL0, FREEZE_CHANNEL, bm);
76 else
77 BF_CLRV(APBH_CTRL0, FREEZE_CHANNEL, bm);
82 } 78 }
83
84 if(freeze)
85 __REG_SET(*ptr) = bm;
86 else
87 __REG_CLR(*ptr) = bm;
88} 79}
89 80
90void imx233_dma_enable_channel_interrupt(unsigned chan, bool enable) 81void imx233_dma_enable_channel_interrupt(unsigned chan, bool enable)
91{ 82{
92 volatile uint32_t *ptr; 83 uint32_t bm = 1 << APB_GET_DMA_CHANNEL(chan);
93 uint32_t bm;
94 if(APB_IS_APBX_CHANNEL(chan)) 84 if(APB_IS_APBX_CHANNEL(chan))
95 { 85 {
96 ptr = &HW_APBX_CTRL1; 86 if(enable)
97 bm = HW_APBX_CTRL1__CHx_CMDCMPLT_IRQ_EN(APB_GET_DMA_CHANNEL(chan)); 87 BF_SETV(APBX_CTRL1, CH_CMDCMPLT_IRQ_EN, bm);
88 else
89 BF_CLRV(APBX_CTRL1, CH_CMDCMPLT_IRQ_EN, bm);
98 } 90 }
99 else 91 else
100 { 92 {
101 ptr = &HW_APBH_CTRL1; 93 if(enable)
102 bm = HW_APBH_CTRL1__CHx_CMDCMPLT_IRQ_EN(APB_GET_DMA_CHANNEL(chan)); 94 BF_SETV(APBH_CTRL1, CH_CMDCMPLT_IRQ_EN, bm);
103 } 95 else
104 96 BF_CLRV(APBH_CTRL1, CH_CMDCMPLT_IRQ_EN, bm);
105 if(enable)
106 {
107 __REG_SET(*ptr) = bm;
108 imx233_dma_clear_channel_interrupt(chan);
109 } 97 }
110 else 98 imx233_dma_clear_channel_interrupt(chan);
111 __REG_CLR(*ptr) = bm;
112} 99}
113 100
114void imx233_dma_clear_channel_interrupt(unsigned chan) 101void imx233_dma_clear_channel_interrupt(unsigned chan)
115{ 102{
103 uint32_t bm = 1 << APB_GET_DMA_CHANNEL(chan);
116 if(APB_IS_APBX_CHANNEL(chan)) 104 if(APB_IS_APBX_CHANNEL(chan))
117 { 105 {
118 __REG_CLR(HW_APBX_CTRL1) = 106 BF_CLRV(APBX_CTRL1, CH_CMDCMPLT_IRQ, bm);
119 HW_APBX_CTRL1__CHx_CMDCMPLT_IRQ(APB_GET_DMA_CHANNEL(chan)); 107 BF_CLRV(APBX_CTRL2, CH_ERROR_IRQ, bm);
120 __REG_CLR(HW_APBX_CTRL2) =
121 HW_APBX_CTRL2__CHx_ERROR_IRQ(APB_GET_DMA_CHANNEL(chan));
122 } 108 }
123 else 109 else
124 { 110 {
125 __REG_CLR(HW_APBH_CTRL1) = 111 BF_CLRV(APBH_CTRL1, CH_CMDCMPLT_IRQ, bm);
126 HW_APBH_CTRL1__CHx_CMDCMPLT_IRQ(APB_GET_DMA_CHANNEL(chan)); 112 BF_CLRV(APBH_CTRL2, CH_ERROR_IRQ, bm);
127 __REG_CLR(HW_APBH_CTRL2) =
128 HW_APBH_CTRL2__CHx_ERROR_IRQ(APB_GET_DMA_CHANNEL(chan));
129 } 113 }
130} 114}
131 115
132bool imx233_dma_is_channel_error_irq(unsigned chan) 116bool imx233_dma_is_channel_error_irq(unsigned chan)
133{ 117{
118 uint32_t bm = 1 << APB_GET_DMA_CHANNEL(chan);
134 if(APB_IS_APBX_CHANNEL(chan)) 119 if(APB_IS_APBX_CHANNEL(chan))
135 return !!(HW_APBX_CTRL2 & 120 return !!(BF_RD(APBX_CTRL2, CH_ERROR_IRQ) & bm);
136 HW_APBX_CTRL2__CHx_ERROR_IRQ(APB_GET_DMA_CHANNEL(chan)));
137 else 121 else
138 return !!(HW_APBH_CTRL2 & 122 return !!(BF_RD(APBH_CTRL2, CH_ERROR_IRQ) & bm);
139 HW_APBH_CTRL2__CHx_ERROR_IRQ(APB_GET_DMA_CHANNEL(chan)));
140} 123}
141 124
142/* Commit and/or discard all DMA descriptors and buffers pointed by them, 125/* Commit and/or discard all DMA descriptors and buffers pointed by them,
@@ -150,37 +133,37 @@ static void imx233_dma_commit_and_discard(unsigned chan, struct apb_dma_command_
150 * and then we go through the list another time to clear the mark and 133 * and then we go through the list another time to clear the mark and
151 * commit the descriptors */ 134 * commit the descriptors */
152 struct apb_dma_command_t *cur = cmd; 135 struct apb_dma_command_t *cur = cmd;
153 136
154 while((cur->cmd & HW_APB_CHx_CMD__UNUSED_BM) != HW_APB_CHx_CMD__UNUSED_MAGIC) 137 while(BF_RDX(cur->cmd, APB_CHx_CMD, UNUSED) != BV_APB_CHx_CMD_UNUSED__MAGIC)
155 { 138 {
156 cur->cmd = (cur->cmd & ~HW_APB_CHx_CMD__UNUSED_BM) | HW_APB_CHx_CMD__UNUSED_MAGIC; 139 BF_WR_VX(cur->cmd, APB_CHx_CMD, UNUSED, MAGIC);
157 int op = cur->cmd & HW_APB_CHx_CMD__COMMAND_BM; 140 int op = BF_RDX(cur->cmd, APB_CHx_CMD, COMMAND);
158 int sz = __XTRACT_EX(cur->cmd, HW_APB_CHx_CMD__XFER_COUNT); 141 int sz = BF_RDX(cur->cmd, APB_CHx_CMD, XFER_COUNT);
159 /* device > host: discard */ 142 /* device > host: discard */
160 if(op == HW_APB_CHx_CMD__COMMAND__WRITE) 143 if(op == BV_APB_CHx_CMD_COMMAND__WRITE)
161 discard_dcache_range(cur->buffer, sz); 144 discard_dcache_range(cur->buffer, sz);
162 /* host > device: commit and discard */ 145 /* host > device: commit and discard */
163 else if(op == HW_APB_CHx_CMD__COMMAND__READ) 146 else if(op == BV_APB_CHx_CMD_COMMAND__READ)
164 commit_discard_dcache_range(cur->buffer, sz); 147 commit_discard_dcache_range(cur->buffer, sz);
165 if((uint32_t)cur->buffer % CACHEALIGN_SIZE) 148 if((uint32_t)cur->buffer % CACHEALIGN_SIZE)
166 apb_nr_unaligned[chan]++; 149 apb_nr_unaligned[chan]++;
167 /* Virtual to physical buffer pointer conversion */ 150 /* Virtual to physical buffer pointer conversion */
168 cur->buffer = PHYSICAL_ADDR(cur->buffer); 151 cur->buffer = PHYSICAL_ADDR(cur->buffer);
169 /* chain ? */ 152 /* chain ? */
170 if(cur->cmd & HW_APB_CHx_CMD__CHAIN) 153 if(cur->cmd & BM_APB_CHx_CMD_CHAIN)
171 cur = cur->next; 154 cur = cur->next;
172 else 155 else
173 break; 156 break;
174 } 157 }
175 158
176 cur = cmd; 159 cur = cmd;
177 while((cur->cmd & HW_APB_CHx_CMD__UNUSED_BM) != 0) 160 while(BF_RDX(cur->cmd, APB_CHx, CMD_UNUSED) != 0)
178 { 161 {
179 cur->cmd = cur->cmd & ~HW_APB_CHx_CMD__UNUSED_BM; 162 BF_WRX(cur->cmd, APB_CHx, CMD_UNUSED, 0);
180 int sz = __XTRACT_EX(cur->cmd, HW_APB_CHx_CMD__CMDWORDS) * sizeof(uint32_t); 163 int sz = BF_RDX(cur->cmd, APB_CHx_CMD, CMDWORDS) * sizeof(uint32_t);
181 /* commit descriptor and discard descriptor */ 164 /* commit descriptor and discard descriptor */
182 /* chain ? */ 165 /* chain ? */
183 if(cur->cmd & HW_APB_CHx_CMD__CHAIN) 166 if(cur->cmd & BM_APB_CHx_CMD_CHAIN)
184 { 167 {
185 struct apb_dma_command_t *next = cur->next; 168 struct apb_dma_command_t *next = cur->next;
186 cur->next = PHYSICAL_ADDR(cur->next); 169 cur->next = PHYSICAL_ADDR(cur->next);
@@ -200,28 +183,28 @@ void imx233_dma_start_command(unsigned chan, struct apb_dma_command_t *cmd)
200 imx233_dma_commit_and_discard(chan, cmd); 183 imx233_dma_commit_and_discard(chan, cmd);
201 if(APB_IS_APBX_CHANNEL(chan)) 184 if(APB_IS_APBX_CHANNEL(chan))
202 { 185 {
203 HW_APBX_CHx_NXTCMDAR(APB_GET_DMA_CHANNEL(chan)) = (uint32_t)PHYSICAL_ADDR(cmd); 186 HW_APBX_CHn_NXTCMDAR(APB_GET_DMA_CHANNEL(chan)) = (uint32_t)PHYSICAL_ADDR(cmd);
204 HW_APBX_CHx_SEMA(APB_GET_DMA_CHANNEL(chan)) = 1; 187 HW_APBX_CHn_SEMA(APB_GET_DMA_CHANNEL(chan)) = 1;
205 } 188 }
206 else 189 else
207 { 190 {
208 HW_APBH_CHx_NXTCMDAR(APB_GET_DMA_CHANNEL(chan)) = (uint32_t)PHYSICAL_ADDR(cmd); 191 HW_APBH_CHn_NXTCMDAR(APB_GET_DMA_CHANNEL(chan)) = (uint32_t)PHYSICAL_ADDR(cmd);
209 HW_APBH_CHx_SEMA(APB_GET_DMA_CHANNEL(chan)) = 1; 192 HW_APBH_CHn_SEMA(APB_GET_DMA_CHANNEL(chan)) = 1;
210 } 193 }
211} 194}
212 195
213int imx233_dma_wait_completion(unsigned chan, unsigned tmo) 196int imx233_dma_wait_completion(unsigned chan, unsigned tmo)
214{ 197{
215 tmo += current_tick; 198 tmo += current_tick;
216 volatile uint32_t *sema; 199 int value = 0;
217 if(APB_IS_APBX_CHANNEL(chan)) 200 if(APB_IS_APBX_CHANNEL(chan))
218 sema = &HW_APBX_CHx_SEMA(APB_GET_DMA_CHANNEL(chan)); 201 while((value = BF_RDn(APBX_CHn_SEMA, APB_GET_DMA_CHANNEL(chan), PHORE)) && !TIME_AFTER(current_tick, tmo))
202 yield();
219 else 203 else
220 sema = &HW_APBH_CHx_SEMA(APB_GET_DMA_CHANNEL(chan)); 204 while((value = BF_RDn(APBH_CHn_SEMA, APB_GET_DMA_CHANNEL(chan), PHORE)) && !TIME_AFTER(current_tick, tmo))
205 yield();
221 206
222 while(*sema & HW_APB_CHx_SEMA__PHORE_BM && !TIME_AFTER(current_tick, tmo)) 207 return value;
223 yield();
224 return __XTRACT_EX(*sema, HW_APB_CHx_SEMA__PHORE);
225} 208}
226 209
227struct imx233_dma_info_t imx233_dma_get_info(unsigned chan, unsigned flags) 210struct imx233_dma_info_t imx233_dma_get_info(unsigned chan, unsigned flags)
@@ -230,35 +213,29 @@ struct imx233_dma_info_t imx233_dma_get_info(unsigned chan, unsigned flags)
230 memset(&s, 0, sizeof(s)); 213 memset(&s, 0, sizeof(s));
231 bool apbx = APB_IS_APBX_CHANNEL(chan); 214 bool apbx = APB_IS_APBX_CHANNEL(chan);
232 int dmac = APB_GET_DMA_CHANNEL(chan); 215 int dmac = APB_GET_DMA_CHANNEL(chan);
216 uint32_t bm = 1 << dmac;
233 if(flags & DMA_INFO_CURCMDADDR) 217 if(flags & DMA_INFO_CURCMDADDR)
234 s.cur_cmd_addr = apbx ? HW_APBX_CHx_CURCMDAR(dmac) : HW_APBH_CHx_CURCMDAR(dmac); 218 s.cur_cmd_addr = apbx ? HW_APBX_CHn_CURCMDAR(dmac) : HW_APBH_CHn_CURCMDAR(dmac);
235 if(flags & DMA_INFO_NXTCMDADDR) 219 if(flags & DMA_INFO_NXTCMDADDR)
236 s.nxt_cmd_addr = apbx ? HW_APBX_CHx_NXTCMDAR(dmac) : HW_APBH_CHx_NXTCMDAR(dmac); 220 s.nxt_cmd_addr = apbx ? HW_APBX_CHn_NXTCMDAR(dmac) : HW_APBH_CHn_NXTCMDAR(dmac);
237 if(flags & DMA_INFO_CMD) 221 if(flags & DMA_INFO_CMD)
238 s.cmd = apbx ? HW_APBX_CHx_CMD(dmac) : HW_APBH_CHx_CMD(dmac); 222 s.cmd = apbx ? HW_APBX_CHn_CMD(dmac) : HW_APBH_CHn_CMD(dmac);
239 if(flags & DMA_INFO_BAR) 223 if(flags & DMA_INFO_BAR)
240 s.bar = apbx ? HW_APBX_CHx_BAR(dmac) : HW_APBH_CHx_BAR(dmac); 224 s.bar = apbx ? HW_APBX_CHn_BAR(dmac) : HW_APBH_CHn_BAR(dmac);
241 if(flags & DMA_INFO_AHB_BYTES) 225 if(flags & DMA_INFO_AHB_BYTES)
242 s.ahb_bytes = apbx ? __XTRACT_EX(HW_APBX_CHx_DEBUG2(dmac), HW_APBX_CHx_DEBUG2__AHB_BYTES) : 226 s.ahb_bytes = apbx ? BF_RDn(APBX_CHn_DEBUG2, dmac, AHB_BYTES) : BF_RDn(APBH_CHn_DEBUG2, dmac, AHB_BYTES);
243 __XTRACT_EX(HW_APBH_CHx_DEBUG2(dmac), HW_APBH_CHx_DEBUG2__AHB_BYTES);
244 if(flags & DMA_INFO_APB_BYTES) 227 if(flags & DMA_INFO_APB_BYTES)
245 s.apb_bytes = apbx ? __XTRACT_EX(HW_APBX_CHx_DEBUG2(dmac), HW_APBX_CHx_DEBUG2__APB_BYTES) : 228 s.apb_bytes = apbx ? BF_RDn(APBX_CHn_DEBUG2, dmac, APB_BYTES) : BF_RDn(APBH_CHn_DEBUG2, dmac, APB_BYTES);
246 __XTRACT_EX(HW_APBH_CHx_DEBUG2(dmac), HW_APBH_CHx_DEBUG2__APB_BYTES);
247 if(flags & DMA_INFO_FREEZED) 229 if(flags & DMA_INFO_FREEZED)
248 s.freezed = apbx ? HW_APBX_CHANNEL_CTRL & HW_APBX_CHANNEL_CTRL__FREEZE_CHANNEL(dmac) : 230 s.freezed = !!((apbx ? BF_RD(APBX_CHANNEL_CTRL, FREEZE_CHANNEL) : BF_RD(APBH_CTRL0, FREEZE_CHANNEL)) & bm);
249 HW_APBH_CTRL0 & HW_APBH_CTRL0__FREEZE_CHANNEL(dmac);
250 if(flags & DMA_INFO_GATED) 231 if(flags & DMA_INFO_GATED)
251 s.gated = apbx ? false : HW_APBH_CTRL0 & HW_APBH_CTRL0__CLKGATE_CHANNEL(dmac); 232 s.gated = apbx ? false : !!(BF_RD(APBH_CTRL0, CLKGATE_CHANNEL) & bm);
252 if(flags & DMA_INFO_INTERRUPT) 233 if(flags & DMA_INFO_INTERRUPT)
253 { 234 {
254 s.int_enabled = apbx ? HW_APBX_CTRL1 & HW_APBX_CTRL1__CHx_CMDCMPLT_IRQ_EN(dmac) : 235 s.int_enabled = !!((apbx ? BF_RD(APBX_CTRL1, CH_CMDCMPLT_IRQ_EN) : BF_RD(APBH_CTRL1, CH_CMDCMPLT_IRQ_EN)) & bm);
255 HW_APBH_CTRL1 & HW_APBH_CTRL1__CHx_CMDCMPLT_IRQ_EN(dmac); 236 s.int_cmdcomplt = !!((apbx ? BF_RD(APBX_CTRL1, CH_CMDCMPLT_IRQ) : BF_RD(APBH_CTRL1, CH_CMDCMPLT_IRQ)) & bm);
256 s.int_cmdcomplt = apbx ? HW_APBX_CTRL1 & HW_APBX_CTRL1__CHx_CMDCMPLT_IRQ(dmac) : 237 s.int_error = !!((apbx ? BF_RD(APBX_CTRL2, CH_ERROR_IRQ) : BF_RD(APBH_CTRL2, CH_ERROR_IRQ)) & bm);
257 HW_APBH_CTRL1 & HW_APBH_CTRL1__CHx_CMDCMPLT_IRQ(dmac);
258 s.int_error = apbx ? HW_APBX_CTRL2 & HW_APBX_CTRL2__CHx_ERROR_IRQ(dmac) :
259 HW_APBH_CTRL2 & HW_APBH_CTRL2__CHx_ERROR_IRQ(dmac);
260 } 238 }
261 s.nr_unaligned = apb_nr_unaligned[chan]; 239 s.nr_unaligned = apb_nr_unaligned[chan];
262 return s; 240 return s;
263} 241}
264