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.c67
1 files changed, 58 insertions, 9 deletions
diff --git a/firmware/target/arm/imx233/dma-imx233.c b/firmware/target/arm/imx233/dma-imx233.c
index 5808731eef..81ae5aeb72 100644
--- a/firmware/target/arm/imx233/dma-imx233.c
+++ b/firmware/target/arm/imx233/dma-imx233.c
@@ -39,8 +39,13 @@ void imx233_dma_reset_channel(unsigned chan)
39 uint32_t bm = 1 << APB_GET_DMA_CHANNEL(chan); 39 uint32_t bm = 1 << APB_GET_DMA_CHANNEL(chan);
40 if(APB_IS_APBX_CHANNEL(chan)) 40 if(APB_IS_APBX_CHANNEL(chan))
41 { 41 {
42#if IMX233_SUBTARGET < 3780
43 BF_SETV(APBX_CTRL0, RESET_CHANNEL, bm);
44 while(BF_RD(APBX_CTRL0, RESET_CHANNEL) & bm);
45#else
42 BF_SETV(APBX_CHANNEL_CTRL, RESET_CHANNEL, bm); 46 BF_SETV(APBX_CHANNEL_CTRL, RESET_CHANNEL, bm);
43 while(BF_RD(APBX_CHANNEL_CTRL, RESET_CHANNEL) & bm); 47 while(BF_RD(APBX_CHANNEL_CTRL, RESET_CHANNEL) & bm);
48#endif
44 } 49 }
45 else 50 else
46 { 51 {
@@ -64,10 +69,17 @@ void imx233_dma_freeze_channel(unsigned chan, bool freeze)
64 uint32_t bm = 1 << APB_GET_DMA_CHANNEL(chan); 69 uint32_t bm = 1 << APB_GET_DMA_CHANNEL(chan);
65 if(APB_IS_APBX_CHANNEL(chan)) 70 if(APB_IS_APBX_CHANNEL(chan))
66 { 71 {
72#if IMX233_SUBTARGET < 3780
73 if(freeze)
74 BF_SETV(APBX_CTRL0, FREEZE_CHANNEL, bm);
75 else
76 BF_CLRV(APBX_CTRL0, FREEZE_CHANNEL, bm);
77#else
67 if(freeze) 78 if(freeze)
68 BF_SETV(APBX_CHANNEL_CTRL, FREEZE_CHANNEL, bm); 79 BF_SETV(APBX_CHANNEL_CTRL, FREEZE_CHANNEL, bm);
69 else 80 else
70 BF_CLRV(APBX_CHANNEL_CTRL, FREEZE_CHANNEL, bm); 81 BF_CLRV(APBX_CHANNEL_CTRL, FREEZE_CHANNEL, bm);
82#endif
71 } 83 }
72 else 84 else
73 { 85 {
@@ -104,28 +116,46 @@ void imx233_dma_clear_channel_interrupt(unsigned chan)
104 if(APB_IS_APBX_CHANNEL(chan)) 116 if(APB_IS_APBX_CHANNEL(chan))
105 { 117 {
106 BF_CLRV(APBX_CTRL1, CH_CMDCMPLT_IRQ, bm); 118 BF_CLRV(APBX_CTRL1, CH_CMDCMPLT_IRQ, bm);
119#if IMX233_SUBTARGET >= 3780
107 BF_CLRV(APBX_CTRL2, CH_ERROR_IRQ, bm); 120 BF_CLRV(APBX_CTRL2, CH_ERROR_IRQ, bm);
121#elif IMX233_SUBTARGET >= 3700
122 BF_CLRV(APBX_CTRL1, CH_AHB_ERROR_IRQ, bm);
123#endif
108 } 124 }
109 else 125 else
110 { 126 {
111 BF_CLRV(APBH_CTRL1, CH_CMDCMPLT_IRQ, bm); 127 BF_CLRV(APBH_CTRL1, CH_CMDCMPLT_IRQ, bm);
128#if IMX233_SUBTARGET >= 3780
112 BF_CLRV(APBH_CTRL2, CH_ERROR_IRQ, bm); 129 BF_CLRV(APBH_CTRL2, CH_ERROR_IRQ, bm);
130#elif IMX233_SUBTARGET >= 3700
131 BF_CLRV(APBH_CTRL1, CH_AHB_ERROR_IRQ, bm);
132#endif
113 } 133 }
114} 134}
115 135
116bool imx233_dma_is_channel_error_irq(unsigned chan) 136bool imx233_dma_is_channel_error_irq(unsigned chan)
117{ 137{
118 uint32_t bm = 1 << APB_GET_DMA_CHANNEL(chan); 138 uint32_t bm = 1 << APB_GET_DMA_CHANNEL(chan);
139#if IMX233_SUBTARGET >= 3780
119 if(APB_IS_APBX_CHANNEL(chan)) 140 if(APB_IS_APBX_CHANNEL(chan))
120 return !!(BF_RD(APBX_CTRL2, CH_ERROR_IRQ) & bm); 141 return !!(BF_RD(APBX_CTRL2, CH_ERROR_IRQ) & bm);
121 else 142 else
122 return !!(BF_RD(APBH_CTRL2, CH_ERROR_IRQ) & bm); 143 return !!(BF_RD(APBH_CTRL2, CH_ERROR_IRQ) & bm);
144#elif IMX233_SUBTARGET >= 3700
145 if(APB_IS_APBX_CHANNEL(chan))
146 return !!(BF_RD(APBX_CTRL1, CH_AHB_ERROR_IRQ) & bm);
147 else
148 return !!(BF_RD(APBH_CTRL1, CH_AHB_ERROR_IRQ) & bm);
149#else
150 (void) bm;
151 return false;
152#endif
123} 153}
124 154
125/* Commit and/or discard all DMA descriptors and buffers pointed by them, 155/* Commit and/or discard all DMA descriptors and buffers pointed by them,
126 * handle circular lists. At the same time, convert virtual pointers to 156 * handle circular lists. At the same time, convert virtual pointers to
127 * real ones */ 157 * real ones */
128static void imx233_dma_commit_and_discard(unsigned chan, struct apb_dma_command_t *cmd) 158void imx233_dma_prepare_command(unsigned chan, struct apb_dma_command_t *cmd)
129{ 159{
130 /* We handle circular descriptors by using unused bits: 160 /* We handle circular descriptors by using unused bits:
131 * bits 8-11 are not used by the hardware so we first go through the whole 161 * bits 8-11 are not used by the hardware so we first go through the whole
@@ -178,19 +208,27 @@ static void imx233_dma_commit_and_discard(unsigned chan, struct apb_dma_command_
178 } 208 }
179} 209}
180 210
181void imx233_dma_start_command(unsigned chan, struct apb_dma_command_t *cmd) 211void imx233_dma_set_next_command(unsigned chan, struct apb_dma_command_t *cmd)
182{ 212{
183 imx233_dma_commit_and_discard(chan, cmd);
184 if(APB_IS_APBX_CHANNEL(chan)) 213 if(APB_IS_APBX_CHANNEL(chan))
185 {
186 HW_APBX_CHn_NXTCMDAR(APB_GET_DMA_CHANNEL(chan)) = (uint32_t)PHYSICAL_ADDR(cmd); 214 HW_APBX_CHn_NXTCMDAR(APB_GET_DMA_CHANNEL(chan)) = (uint32_t)PHYSICAL_ADDR(cmd);
187 HW_APBX_CHn_SEMA(APB_GET_DMA_CHANNEL(chan)) = 1;
188 }
189 else 215 else
190 {
191 HW_APBH_CHn_NXTCMDAR(APB_GET_DMA_CHANNEL(chan)) = (uint32_t)PHYSICAL_ADDR(cmd); 216 HW_APBH_CHn_NXTCMDAR(APB_GET_DMA_CHANNEL(chan)) = (uint32_t)PHYSICAL_ADDR(cmd);
192 HW_APBH_CHn_SEMA(APB_GET_DMA_CHANNEL(chan)) = 1; 217}
193 } 218
219void imx233_dma_inc_sema(unsigned chan, unsigned amount)
220{
221 if(APB_IS_APBX_CHANNEL(chan))
222 HW_APBX_CHn_SEMA(APB_GET_DMA_CHANNEL(chan)) = amount;
223 else
224 HW_APBH_CHn_SEMA(APB_GET_DMA_CHANNEL(chan)) = amount;
225}
226
227void imx233_dma_start_command(unsigned chan, struct apb_dma_command_t *cmd)
228{
229 imx233_dma_prepare_command(chan, cmd);
230 imx233_dma_set_next_command(chan, cmd);
231 imx233_dma_inc_sema(chan, 1);
194} 232}
195 233
196int imx233_dma_wait_completion(unsigned chan, unsigned tmo) 234int imx233_dma_wait_completion(unsigned chan, unsigned tmo)
@@ -227,15 +265,26 @@ struct imx233_dma_info_t imx233_dma_get_info(unsigned chan, unsigned flags)
227 if(flags & DMA_INFO_APB_BYTES) 265 if(flags & DMA_INFO_APB_BYTES)
228 s.apb_bytes = apbx ? BF_RDn(APBX_CHn_DEBUG2, dmac, APB_BYTES) : BF_RDn(APBH_CHn_DEBUG2, dmac, APB_BYTES); 266 s.apb_bytes = apbx ? BF_RDn(APBX_CHn_DEBUG2, dmac, APB_BYTES) : BF_RDn(APBH_CHn_DEBUG2, dmac, APB_BYTES);
229 if(flags & DMA_INFO_FREEZED) 267 if(flags & DMA_INFO_FREEZED)
268#if IMX233_SUBTARGET < 3780
269 s.freezed = !!((apbx ? BF_RD(APBX_CTRL0, FREEZE_CHANNEL) : BF_RD(APBH_CTRL0, FREEZE_CHANNEL)) & bm);
270#else
230 s.freezed = !!((apbx ? BF_RD(APBX_CHANNEL_CTRL, FREEZE_CHANNEL) : BF_RD(APBH_CTRL0, FREEZE_CHANNEL)) & bm); 271 s.freezed = !!((apbx ? BF_RD(APBX_CHANNEL_CTRL, FREEZE_CHANNEL) : BF_RD(APBH_CTRL0, FREEZE_CHANNEL)) & bm);
272#endif
231 if(flags & DMA_INFO_GATED) 273 if(flags & DMA_INFO_GATED)
232 s.gated = apbx ? false : !!(BF_RD(APBH_CTRL0, CLKGATE_CHANNEL) & bm); 274 s.gated = apbx ? false : !!(BF_RD(APBH_CTRL0, CLKGATE_CHANNEL) & bm);
233 if(flags & DMA_INFO_INTERRUPT) 275 if(flags & DMA_INFO_INTERRUPT)
234 { 276 {
235 s.int_enabled = !!((apbx ? BF_RD(APBX_CTRL1, CH_CMDCMPLT_IRQ_EN) : BF_RD(APBH_CTRL1, CH_CMDCMPLT_IRQ_EN)) & bm); 277 s.int_enabled = !!((apbx ? BF_RD(APBX_CTRL1, CH_CMDCMPLT_IRQ_EN) : BF_RD(APBH_CTRL1, CH_CMDCMPLT_IRQ_EN)) & bm);
236 s.int_cmdcomplt = !!((apbx ? BF_RD(APBX_CTRL1, CH_CMDCMPLT_IRQ) : BF_RD(APBH_CTRL1, CH_CMDCMPLT_IRQ)) & bm); 278 s.int_cmdcomplt = !!((apbx ? BF_RD(APBX_CTRL1, CH_CMDCMPLT_IRQ) : BF_RD(APBH_CTRL1, CH_CMDCMPLT_IRQ)) & bm);
279#if IMX233_SUBTARGET >= 3780
237 s.int_error = !!((apbx ? BF_RD(APBX_CTRL2, CH_ERROR_IRQ) : BF_RD(APBH_CTRL2, CH_ERROR_IRQ)) & bm); 280 s.int_error = !!((apbx ? BF_RD(APBX_CTRL2, CH_ERROR_IRQ) : BF_RD(APBH_CTRL2, CH_ERROR_IRQ)) & bm);
281#elif IMX233_SUBTARGET >= 3700
282 s.int_error = !!((apbx ? BF_RD(APBX_CTRL1, CH_AHB_ERROR_IRQ) : BF_RD(APBH_CTRL1, CH_AHB_ERROR_IRQ)) & bm);
283#else
284 s.int_error = false;
285#endif
238 } 286 }
239 s.nr_unaligned = apb_nr_unaligned[chan]; 287 s.nr_unaligned = apb_nr_unaligned[chan];
240 return s; 288 return s;
241} 289}
290