diff options
author | Amaury Pouly <amaury.pouly@gmail.com> | 2013-06-17 00:16:19 +0200 |
---|---|---|
committer | Amaury Pouly <amaury.pouly@gmail.com> | 2013-06-17 00:29:25 +0200 |
commit | e671472c3f8bbbb4b5eaa94c283d0ade6cd50f5e (patch) | |
tree | fdcc26b996401532ba9fab765763ba2dc13d8628 /firmware/target/arm | |
parent | bdc572b8a1bfc9fedb4a2158626647a801c3f177 (diff) | |
download | rockbox-e671472c3f8bbbb4b5eaa94c283d0ade6cd50f5e.tar.gz rockbox-e671472c3f8bbbb4b5eaa94c283d0ade6cd50f5e.zip |
imx233: fix dma for stmp3600 and stmp3700, improve support
Add finer granularity to start command: now commands can be
prepared, schedule and semaphore increased independently.
Change-Id: Ib1ed1f20f4b46dc61b6dbab6ddec8b54e3d832b9
Diffstat (limited to 'firmware/target/arm')
-rw-r--r-- | firmware/target/arm/imx233/dma-imx233.c | 67 | ||||
-rw-r--r-- | firmware/target/arm/imx233/dma-imx233.h | 8 |
2 files changed, 66 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 | ||
116 | bool imx233_dma_is_channel_error_irq(unsigned chan) | 136 | bool 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 */ |
128 | static void imx233_dma_commit_and_discard(unsigned chan, struct apb_dma_command_t *cmd) | 158 | void 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 | ||
181 | void imx233_dma_start_command(unsigned chan, struct apb_dma_command_t *cmd) | 211 | void 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 | |
219 | void 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 | |||
227 | void 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 | ||
196 | int imx233_dma_wait_completion(unsigned chan, unsigned tmo) | 234 | int 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 | |||
diff --git a/firmware/target/arm/imx233/dma-imx233.h b/firmware/target/arm/imx233/dma-imx233.h index 692b8dc16d..a64b8a64d1 100644 --- a/firmware/target/arm/imx233/dma-imx233.h +++ b/firmware/target/arm/imx233/dma-imx233.h | |||
@@ -37,8 +37,12 @@ | |||
37 | #define APB_IS_APBX_CHANNEL(x) ((x) & 0x10) | 37 | #define APB_IS_APBX_CHANNEL(x) ((x) & 0x10) |
38 | #define APB_GET_DMA_CHANNEL(x) ((x) & 0xf) | 38 | #define APB_GET_DMA_CHANNEL(x) ((x) & 0xf) |
39 | 39 | ||
40 | #if IMX233_SUBTARGET >= 3700 | ||
40 | // NOTE: although undocumented, the iMX233 channel 0 is actually the LCDIF one | 41 | // NOTE: although undocumented, the iMX233 channel 0 is actually the LCDIF one |
41 | #define APB_LCDIF APBH_DMA_CHANNEL(0) | 42 | #define APB_LCDIF APBH_DMA_CHANNEL(0) |
43 | #else | ||
44 | #define APB_LCDIF APBX_DMA_CHANNEL(4) | ||
45 | #endif | ||
42 | 46 | ||
43 | #define APB_SSP(ssp) APBH_DMA_CHANNEL(ssp) | 47 | #define APB_SSP(ssp) APBH_DMA_CHANNEL(ssp) |
44 | #define APB_GPMI(dev) APBH_DMA_CHANNEL(4 + (dev)) | 48 | #define APB_GPMI(dev) APBH_DMA_CHANNEL(4 + (dev)) |
@@ -151,6 +155,10 @@ void imx233_dma_enable_channel_interrupt(unsigned chan, bool enable); | |||
151 | void imx233_dma_clear_channel_interrupt(unsigned chan); | 155 | void imx233_dma_clear_channel_interrupt(unsigned chan); |
152 | bool imx233_dma_is_channel_error_irq(unsigned chan); | 156 | bool imx233_dma_is_channel_error_irq(unsigned chan); |
153 | /* assume no command is in progress */ | 157 | /* assume no command is in progress */ |
158 | void imx233_dma_prepare_command(unsigned chan, struct apb_dma_command_t *cmd); | ||
159 | void imx233_dma_set_next_command(unsigned chan, struct apb_dma_command_t *cmd); | ||
160 | void imx233_dma_inc_sema(unsigned chan, unsigned amount); | ||
161 | /* wrapper around prepare_command, set_next_command, inc_sema(1) */ | ||
154 | void imx233_dma_start_command(unsigned chan, struct apb_dma_command_t *cmd); | 162 | void imx233_dma_start_command(unsigned chan, struct apb_dma_command_t *cmd); |
155 | /* return value of the semaphore */ | 163 | /* return value of the semaphore */ |
156 | int imx233_dma_wait_completion(unsigned chan, unsigned tmo); | 164 | int imx233_dma_wait_completion(unsigned chan, unsigned tmo); |