diff options
Diffstat (limited to 'drivers/dma/imx-dma.c')
-rw-r--r-- | drivers/dma/imx-dma.c | 64 |
1 files changed, 18 insertions, 46 deletions
diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c index 6e03f928ca81..629be353c63a 100644 --- a/drivers/dma/imx-dma.c +++ b/drivers/dma/imx-dma.c | |||
@@ -111,29 +111,6 @@ enum imxdma_prep_type { | |||
111 | IMXDMA_DESC_CYCLIC, | 111 | IMXDMA_DESC_CYCLIC, |
112 | }; | 112 | }; |
113 | 113 | ||
114 | /* | ||
115 | * struct imxdma_channel_internal - i.MX specific DMA extension | ||
116 | * @name: name specified by DMA client | ||
117 | * @irq_handler: client callback for end of transfer | ||
118 | * @err_handler: client callback for error condition | ||
119 | * @data: clients context data for callbacks | ||
120 | * @dma_mode: direction of the transfer %DMA_MODE_READ or %DMA_MODE_WRITE | ||
121 | * @sg: pointer to the actual read/written chunk for scatter-gather emulation | ||
122 | * @resbytes: total residual number of bytes to transfer | ||
123 | * (it can be lower or same as sum of SG mapped chunk sizes) | ||
124 | * @sgcount: number of chunks to be read/written | ||
125 | * | ||
126 | * Structure is used for IMX DMA processing. It would be probably good | ||
127 | * @struct dma_struct in the future for external interfacing and use | ||
128 | * @struct imxdma_channel_internal only as extension to it. | ||
129 | */ | ||
130 | |||
131 | struct imxdma_channel_internal { | ||
132 | struct timer_list watchdog; | ||
133 | |||
134 | int hw_chaining; | ||
135 | }; | ||
136 | |||
137 | struct imxdma_desc { | 114 | struct imxdma_desc { |
138 | struct list_head node; | 115 | struct list_head node; |
139 | struct dma_async_tx_descriptor desc; | 116 | struct dma_async_tx_descriptor desc; |
@@ -156,7 +133,8 @@ struct imxdma_desc { | |||
156 | }; | 133 | }; |
157 | 134 | ||
158 | struct imxdma_channel { | 135 | struct imxdma_channel { |
159 | struct imxdma_channel_internal internal; | 136 | int hw_chaining; |
137 | struct timer_list watchdog; | ||
160 | struct imxdma_engine *imxdma; | 138 | struct imxdma_engine *imxdma; |
161 | unsigned int channel; | 139 | unsigned int channel; |
162 | 140 | ||
@@ -217,10 +195,10 @@ static unsigned imx_dmav1_readl(unsigned offset) | |||
217 | return __raw_readl(imx_dmav1_baseaddr + offset); | 195 | return __raw_readl(imx_dmav1_baseaddr + offset); |
218 | } | 196 | } |
219 | 197 | ||
220 | static int imxdma_hw_chain(struct imxdma_channel_internal *imxdma) | 198 | static int imxdma_hw_chain(struct imxdma_channel *imxdmac) |
221 | { | 199 | { |
222 | if (cpu_is_mx27()) | 200 | if (cpu_is_mx27()) |
223 | return imxdma->hw_chaining; | 201 | return imxdmac->hw_chaining; |
224 | else | 202 | else |
225 | return 0; | 203 | return 0; |
226 | } | 204 | } |
@@ -269,7 +247,7 @@ static void imxdma_enable_hw(struct imxdma_desc *d) | |||
269 | CCR_ACRPT, DMA_CCR(channel)); | 247 | CCR_ACRPT, DMA_CCR(channel)); |
270 | 248 | ||
271 | if ((cpu_is_mx21() || cpu_is_mx27()) && | 249 | if ((cpu_is_mx21() || cpu_is_mx27()) && |
272 | d->sg && imxdma_hw_chain(&imxdmac->internal)) { | 250 | d->sg && imxdma_hw_chain(imxdmac)) { |
273 | d->sg = sg_next(d->sg); | 251 | d->sg = sg_next(d->sg); |
274 | if (d->sg) { | 252 | if (d->sg) { |
275 | u32 tmp; | 253 | u32 tmp; |
@@ -290,8 +268,8 @@ static void imxdma_disable_hw(struct imxdma_channel *imxdmac) | |||
290 | 268 | ||
291 | pr_debug("imxdma%d: imx_dma_disable\n", channel); | 269 | pr_debug("imxdma%d: imx_dma_disable\n", channel); |
292 | 270 | ||
293 | if (imxdma_hw_chain(&imxdmac->internal)) | 271 | if (imxdma_hw_chain(imxdmac)) |
294 | del_timer(&imxdmac->internal.watchdog); | 272 | del_timer(&imxdmac->watchdog); |
295 | 273 | ||
296 | local_irq_save(flags); | 274 | local_irq_save(flags); |
297 | imx_dmav1_writel(imx_dmav1_readl(DMA_DIMR) | (1 << channel), DMA_DIMR); | 275 | imx_dmav1_writel(imx_dmav1_readl(DMA_DIMR) | (1 << channel), DMA_DIMR); |
@@ -316,7 +294,6 @@ static void imxdma_watchdog(unsigned long data) | |||
316 | static irqreturn_t imxdma_err_handler(int irq, void *dev_id) | 294 | static irqreturn_t imxdma_err_handler(int irq, void *dev_id) |
317 | { | 295 | { |
318 | struct imxdma_engine *imxdma = dev_id; | 296 | struct imxdma_engine *imxdma = dev_id; |
319 | struct imxdma_channel_internal *internal; | ||
320 | unsigned int err_mask; | 297 | unsigned int err_mask; |
321 | int i, disr; | 298 | int i, disr; |
322 | int errcode; | 299 | int errcode; |
@@ -336,7 +313,6 @@ static irqreturn_t imxdma_err_handler(int irq, void *dev_id) | |||
336 | for (i = 0; i < IMX_DMA_CHANNELS; i++) { | 313 | for (i = 0; i < IMX_DMA_CHANNELS; i++) { |
337 | if (!(err_mask & (1 << i))) | 314 | if (!(err_mask & (1 << i))) |
338 | continue; | 315 | continue; |
339 | internal = &imxdma->channel[i].internal; | ||
340 | errcode = 0; | 316 | errcode = 0; |
341 | 317 | ||
342 | if (imx_dmav1_readl(DMA_DBTOSR) & (1 << i)) { | 318 | if (imx_dmav1_readl(DMA_DBTOSR) & (1 << i)) { |
@@ -370,7 +346,6 @@ static irqreturn_t imxdma_err_handler(int irq, void *dev_id) | |||
370 | 346 | ||
371 | static void dma_irq_handle_channel(struct imxdma_channel *imxdmac) | 347 | static void dma_irq_handle_channel(struct imxdma_channel *imxdmac) |
372 | { | 348 | { |
373 | struct imxdma_channel_internal *imxdma = &imxdmac->internal; | ||
374 | int chno = imxdmac->channel; | 349 | int chno = imxdmac->channel; |
375 | struct imxdma_desc *desc; | 350 | struct imxdma_desc *desc; |
376 | 351 | ||
@@ -394,11 +369,11 @@ static void dma_irq_handle_channel(struct imxdma_channel *imxdmac) | |||
394 | 369 | ||
395 | tmp = imx_dmav1_readl(DMA_CCR(chno)); | 370 | tmp = imx_dmav1_readl(DMA_CCR(chno)); |
396 | 371 | ||
397 | if (imxdma_hw_chain(imxdma)) { | 372 | if (imxdma_hw_chain(imxdmac)) { |
398 | /* FIXME: The timeout should probably be | 373 | /* FIXME: The timeout should probably be |
399 | * configurable | 374 | * configurable |
400 | */ | 375 | */ |
401 | mod_timer(&imxdma->watchdog, | 376 | mod_timer(&imxdmac->watchdog, |
402 | jiffies + msecs_to_jiffies(500)); | 377 | jiffies + msecs_to_jiffies(500)); |
403 | 378 | ||
404 | tmp |= CCR_CEN | CCR_RPT | CCR_ACRPT; | 379 | tmp |= CCR_CEN | CCR_RPT | CCR_ACRPT; |
@@ -417,8 +392,8 @@ static void dma_irq_handle_channel(struct imxdma_channel *imxdmac) | |||
417 | return; | 392 | return; |
418 | } | 393 | } |
419 | 394 | ||
420 | if (imxdma_hw_chain(imxdma)) { | 395 | if (imxdma_hw_chain(imxdmac)) { |
421 | del_timer(&imxdma->watchdog); | 396 | del_timer(&imxdmac->watchdog); |
422 | return; | 397 | return; |
423 | } | 398 | } |
424 | } | 399 | } |
@@ -432,7 +407,6 @@ out: | |||
432 | static irqreturn_t dma_irq_handler(int irq, void *dev_id) | 407 | static irqreturn_t dma_irq_handler(int irq, void *dev_id) |
433 | { | 408 | { |
434 | struct imxdma_engine *imxdma = dev_id; | 409 | struct imxdma_engine *imxdma = dev_id; |
435 | struct imxdma_channel_internal *internal; | ||
436 | int i, disr; | 410 | int i, disr; |
437 | 411 | ||
438 | if (cpu_is_mx21() || cpu_is_mx27()) | 412 | if (cpu_is_mx21() || cpu_is_mx27()) |
@@ -445,10 +419,8 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id) | |||
445 | 419 | ||
446 | imx_dmav1_writel(disr, DMA_DISR); | 420 | imx_dmav1_writel(disr, DMA_DISR); |
447 | for (i = 0; i < IMX_DMA_CHANNELS; i++) { | 421 | for (i = 0; i < IMX_DMA_CHANNELS; i++) { |
448 | if (disr & (1 << i)) { | 422 | if (disr & (1 << i)) |
449 | internal = &imxdma->channel[i].internal; | ||
450 | dma_irq_handle_channel(&imxdma->channel[i]); | 423 | dma_irq_handle_channel(&imxdma->channel[i]); |
451 | } | ||
452 | } | 424 | } |
453 | 425 | ||
454 | return IRQ_HANDLED; | 426 | return IRQ_HANDLED; |
@@ -591,8 +563,8 @@ static int imxdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, | |||
591 | break; | 563 | break; |
592 | } | 564 | } |
593 | 565 | ||
594 | imxdmac->internal.hw_chaining = 1; | 566 | imxdmac->hw_chaining = 1; |
595 | if (!imxdma_hw_chain(&imxdmac->internal)) | 567 | if (!imxdma_hw_chain(imxdmac)) |
596 | return -EINVAL; | 568 | return -EINVAL; |
597 | imxdmac->ccr_from_device = (mode | IMX_DMA_TYPE_FIFO) | | 569 | imxdmac->ccr_from_device = (mode | IMX_DMA_TYPE_FIFO) | |
598 | ((IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR) << 2) | | 570 | ((IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR) << 2) | |
@@ -917,7 +889,7 @@ static int __init imxdma_probe(struct platform_device *pdev) | |||
917 | /* Initialize channel parameters */ | 889 | /* Initialize channel parameters */ |
918 | for (i = 0; i < IMX_DMA_CHANNELS; i++) { | 890 | for (i = 0; i < IMX_DMA_CHANNELS; i++) { |
919 | struct imxdma_channel *imxdmac = &imxdma->channel[i]; | 891 | struct imxdma_channel *imxdmac = &imxdma->channel[i]; |
920 | memset(&imxdmac->internal, 0, sizeof(imxdmac->internal)); | 892 | |
921 | if (cpu_is_mx21() || cpu_is_mx27()) { | 893 | if (cpu_is_mx21() || cpu_is_mx27()) { |
922 | ret = request_irq(MX2x_INT_DMACH0 + i, | 894 | ret = request_irq(MX2x_INT_DMACH0 + i, |
923 | dma_irq_handler, 0, "DMA", imxdma); | 895 | dma_irq_handler, 0, "DMA", imxdma); |
@@ -926,9 +898,9 @@ static int __init imxdma_probe(struct platform_device *pdev) | |||
926 | MX2x_INT_DMACH0 + i, i); | 898 | MX2x_INT_DMACH0 + i, i); |
927 | goto err_init; | 899 | goto err_init; |
928 | } | 900 | } |
929 | init_timer(&imxdmac->internal.watchdog); | 901 | init_timer(&imxdmac->watchdog); |
930 | imxdmac->internal.watchdog.function = &imxdma_watchdog; | 902 | imxdmac->watchdog.function = &imxdma_watchdog; |
931 | imxdmac->internal.watchdog.data = (unsigned long)imxdmac; | 903 | imxdmac->watchdog.data = (unsigned long)imxdmac; |
932 | } | 904 | } |
933 | 905 | ||
934 | imxdmac->imxdma = imxdma; | 906 | imxdmac->imxdma = imxdma; |