diff options
-rw-r--r-- | arch/arm/plat-nomadik/include/plat/ste_dma40.h | 13 | ||||
-rw-r--r-- | drivers/dma/ste_dma40.c | 72 | ||||
-rw-r--r-- | drivers/dma/ste_dma40_ll.c | 8 | ||||
-rw-r--r-- | drivers/dma/ste_dma40_ll.h | 30 |
4 files changed, 57 insertions, 66 deletions
diff --git a/arch/arm/plat-nomadik/include/plat/ste_dma40.h b/arch/arm/plat-nomadik/include/plat/ste_dma40.h index ee5d8b2e46dd..879a6c1ac60f 100644 --- a/arch/arm/plat-nomadik/include/plat/ste_dma40.h +++ b/arch/arm/plat-nomadik/include/plat/ste_dma40.h | |||
@@ -1,10 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * arch/arm/plat-nomadik/include/plat/ste_dma40.h | 2 | * Copyright (C) ST-Ericsson SA 2007-2010 |
3 | * | 3 | * Author: Per Friden <per.friden@stericsson.com> for ST-Ericsson |
4 | * Copyright (C) ST-Ericsson 2007-2010 | 4 | * Author: Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson |
5 | * License terms: GNU General Public License (GPL) version 2 | 5 | * License terms: GNU General Public License (GPL) version 2 |
6 | * Author: Per Friden <per.friden@stericsson.com> | ||
7 | * Author: Jonas Aaberg <jonas.aberg@stericsson.com> | ||
8 | */ | 6 | */ |
9 | 7 | ||
10 | 8 | ||
@@ -73,6 +71,9 @@ | |||
73 | #define STEDMA40_PSIZE_LOG_8 STEDMA40_PSIZE_PHY_8 | 71 | #define STEDMA40_PSIZE_LOG_8 STEDMA40_PSIZE_PHY_8 |
74 | #define STEDMA40_PSIZE_LOG_16 STEDMA40_PSIZE_PHY_16 | 72 | #define STEDMA40_PSIZE_LOG_16 STEDMA40_PSIZE_PHY_16 |
75 | 73 | ||
74 | /* Maximum number of possible physical channels */ | ||
75 | #define STEDMA40_MAX_PHYS 32 | ||
76 | |||
76 | enum stedma40_flow_ctrl { | 77 | enum stedma40_flow_ctrl { |
77 | STEDMA40_NO_FLOW_CTRL, | 78 | STEDMA40_NO_FLOW_CTRL, |
78 | STEDMA40_FLOW_CTRL, | 79 | STEDMA40_FLOW_CTRL, |
@@ -160,7 +161,7 @@ struct stedma40_platform_data { | |||
160 | struct stedma40_chan_cfg *memcpy_conf_phy; | 161 | struct stedma40_chan_cfg *memcpy_conf_phy; |
161 | struct stedma40_chan_cfg *memcpy_conf_log; | 162 | struct stedma40_chan_cfg *memcpy_conf_log; |
162 | unsigned int llis_per_log; | 163 | unsigned int llis_per_log; |
163 | int disabled_channels[8]; | 164 | int disabled_channels[STEDMA40_MAX_PHYS]; |
164 | }; | 165 | }; |
165 | 166 | ||
166 | /** | 167 | /** |
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index b8987e791055..7a4919bf1e92 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c | |||
@@ -1,11 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * driver/dma/ste_dma40.c | 2 | * Copyright (C) ST-Ericsson SA 2007-2010 |
3 | * | 3 | * Author: Per Friden <per.friden@stericsson.com> for ST-Ericsson |
4 | * Copyright (C) ST-Ericsson 2007-2010 | 4 | * Author: Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson |
5 | * License terms: GNU General Public License (GPL) version 2 | 5 | * License terms: GNU General Public License (GPL) version 2 |
6 | * Author: Per Friden <per.friden@stericsson.com> | ||
7 | * Author: Jonas Aaberg <jonas.aberg@stericsson.com> | ||
8 | * | ||
9 | */ | 6 | */ |
10 | 7 | ||
11 | #include <linux/kernel.h> | 8 | #include <linux/kernel.h> |
@@ -90,7 +87,6 @@ struct d40_lli_pool { | |||
90 | * @txd: DMA engine struct. Used for among other things for communication | 87 | * @txd: DMA engine struct. Used for among other things for communication |
91 | * during a transfer. | 88 | * during a transfer. |
92 | * @node: List entry. | 89 | * @node: List entry. |
93 | * @dir: The transfer direction of this job. | ||
94 | * @is_in_client_list: true if the client owns this descriptor. | 90 | * @is_in_client_list: true if the client owns this descriptor. |
95 | * @is_hw_linked: true if this job will automatically be continued for | 91 | * @is_hw_linked: true if this job will automatically be continued for |
96 | * the previous one. | 92 | * the previous one. |
@@ -112,7 +108,6 @@ struct d40_desc { | |||
112 | struct dma_async_tx_descriptor txd; | 108 | struct dma_async_tx_descriptor txd; |
113 | struct list_head node; | 109 | struct list_head node; |
114 | 110 | ||
115 | enum dma_data_direction dir; | ||
116 | bool is_in_client_list; | 111 | bool is_in_client_list; |
117 | bool is_hw_linked; | 112 | bool is_hw_linked; |
118 | }; | 113 | }; |
@@ -149,9 +144,7 @@ struct d40_lcla_pool { | |||
149 | * this physical channel. Can also be free or physically allocated. | 144 | * this physical channel. Can also be free or physically allocated. |
150 | * @allocated_dst: Same as for src but is dst. | 145 | * @allocated_dst: Same as for src but is dst. |
151 | * allocated_dst and allocated_src uses the D40_ALLOC* defines as well as | 146 | * allocated_dst and allocated_src uses the D40_ALLOC* defines as well as |
152 | * event line number. Both allocated_src and allocated_dst can not be | 147 | * event line number. |
153 | * allocated to a physical channel, since the interrupt handler has then | ||
154 | * no way of figure out which one the interrupt belongs to. | ||
155 | */ | 148 | */ |
156 | struct d40_phy_res { | 149 | struct d40_phy_res { |
157 | spinlock_t lock; | 150 | spinlock_t lock; |
@@ -237,7 +230,6 @@ struct d40_chan { | |||
237 | * @dma_both: dma_device channels that can do both memcpy and slave transfers. | 230 | * @dma_both: dma_device channels that can do both memcpy and slave transfers. |
238 | * @dma_slave: dma_device channels that can do only do slave transfers. | 231 | * @dma_slave: dma_device channels that can do only do slave transfers. |
239 | * @dma_memcpy: dma_device channels that can do only do memcpy transfers. | 232 | * @dma_memcpy: dma_device channels that can do only do memcpy transfers. |
240 | * @phy_chans: Room for all possible physical channels in system. | ||
241 | * @log_chans: Room for all possible logical channels in system. | 233 | * @log_chans: Room for all possible logical channels in system. |
242 | * @lookup_log_chans: Used to map interrupt number to logical channel. Points | 234 | * @lookup_log_chans: Used to map interrupt number to logical channel. Points |
243 | * to log_chans entries. | 235 | * to log_chans entries. |
@@ -500,7 +492,8 @@ err: | |||
500 | static int d40_channel_execute_command(struct d40_chan *d40c, | 492 | static int d40_channel_execute_command(struct d40_chan *d40c, |
501 | enum d40_command command) | 493 | enum d40_command command) |
502 | { | 494 | { |
503 | int status, i; | 495 | u32 status; |
496 | int i; | ||
504 | void __iomem *active_reg; | 497 | void __iomem *active_reg; |
505 | int ret = 0; | 498 | int ret = 0; |
506 | unsigned long flags; | 499 | unsigned long flags; |
@@ -568,16 +561,12 @@ static void d40_term_all(struct d40_chan *d40c) | |||
568 | /* Release active descriptors */ | 561 | /* Release active descriptors */ |
569 | while ((d40d = d40_first_active_get(d40c))) { | 562 | while ((d40d = d40_first_active_get(d40c))) { |
570 | d40_desc_remove(d40d); | 563 | d40_desc_remove(d40d); |
571 | |||
572 | /* Return desc to free-list */ | ||
573 | d40_desc_free(d40c, d40d); | 564 | d40_desc_free(d40c, d40d); |
574 | } | 565 | } |
575 | 566 | ||
576 | /* Release queued descriptors waiting for transfer */ | 567 | /* Release queued descriptors waiting for transfer */ |
577 | while ((d40d = d40_first_queued(d40c))) { | 568 | while ((d40d = d40_first_queued(d40c))) { |
578 | d40_desc_remove(d40d); | 569 | d40_desc_remove(d40d); |
579 | |||
580 | /* Return desc to free-list */ | ||
581 | d40_desc_free(d40c, d40d); | 570 | d40_desc_free(d40c, d40d); |
582 | } | 571 | } |
583 | 572 | ||
@@ -973,9 +962,6 @@ static void dma_tc_handle(struct d40_chan *d40c) | |||
973 | { | 962 | { |
974 | struct d40_desc *d40d; | 963 | struct d40_desc *d40d; |
975 | 964 | ||
976 | if (!d40c->phy_chan) | ||
977 | return; | ||
978 | |||
979 | /* Get first active entry from list */ | 965 | /* Get first active entry from list */ |
980 | d40d = d40_first_active_get(d40c); | 966 | d40d = d40_first_active_get(d40c); |
981 | 967 | ||
@@ -1001,7 +987,7 @@ static void dma_tc_handle(struct d40_chan *d40c) | |||
1001 | static void dma_tasklet(unsigned long data) | 987 | static void dma_tasklet(unsigned long data) |
1002 | { | 988 | { |
1003 | struct d40_chan *d40c = (struct d40_chan *) data; | 989 | struct d40_chan *d40c = (struct d40_chan *) data; |
1004 | struct d40_desc *d40d_fin; | 990 | struct d40_desc *d40d; |
1005 | unsigned long flags; | 991 | unsigned long flags; |
1006 | dma_async_tx_callback callback; | 992 | dma_async_tx_callback callback; |
1007 | void *callback_param; | 993 | void *callback_param; |
@@ -1009,12 +995,12 @@ static void dma_tasklet(unsigned long data) | |||
1009 | spin_lock_irqsave(&d40c->lock, flags); | 995 | spin_lock_irqsave(&d40c->lock, flags); |
1010 | 996 | ||
1011 | /* Get first active entry from list */ | 997 | /* Get first active entry from list */ |
1012 | d40d_fin = d40_first_active_get(d40c); | 998 | d40d = d40_first_active_get(d40c); |
1013 | 999 | ||
1014 | if (d40d_fin == NULL) | 1000 | if (d40d == NULL) |
1015 | goto err; | 1001 | goto err; |
1016 | 1002 | ||
1017 | d40c->completed = d40d_fin->txd.cookie; | 1003 | d40c->completed = d40d->txd.cookie; |
1018 | 1004 | ||
1019 | /* | 1005 | /* |
1020 | * If terminating a channel pending_tx is set to zero. | 1006 | * If terminating a channel pending_tx is set to zero. |
@@ -1026,19 +1012,18 @@ static void dma_tasklet(unsigned long data) | |||
1026 | } | 1012 | } |
1027 | 1013 | ||
1028 | /* Callback to client */ | 1014 | /* Callback to client */ |
1029 | callback = d40d_fin->txd.callback; | 1015 | callback = d40d->txd.callback; |
1030 | callback_param = d40d_fin->txd.callback_param; | 1016 | callback_param = d40d->txd.callback_param; |
1031 | 1017 | ||
1032 | if (async_tx_test_ack(&d40d_fin->txd)) { | 1018 | if (async_tx_test_ack(&d40d->txd)) { |
1033 | d40_pool_lli_free(d40d_fin); | 1019 | d40_pool_lli_free(d40d); |
1034 | d40_desc_remove(d40d_fin); | 1020 | d40_desc_remove(d40d); |
1035 | /* Return desc to free-list */ | 1021 | d40_desc_free(d40c, d40d); |
1036 | d40_desc_free(d40c, d40d_fin); | ||
1037 | } else { | 1022 | } else { |
1038 | if (!d40d_fin->is_in_client_list) { | 1023 | if (!d40d->is_in_client_list) { |
1039 | d40_desc_remove(d40d_fin); | 1024 | d40_desc_remove(d40d); |
1040 | list_add_tail(&d40d_fin->node, &d40c->client); | 1025 | list_add_tail(&d40d->node, &d40c->client); |
1041 | d40d_fin->is_in_client_list = true; | 1026 | d40d->is_in_client_list = true; |
1042 | } | 1027 | } |
1043 | } | 1028 | } |
1044 | 1029 | ||
@@ -1049,7 +1034,7 @@ static void dma_tasklet(unsigned long data) | |||
1049 | 1034 | ||
1050 | spin_unlock_irqrestore(&d40c->lock, flags); | 1035 | spin_unlock_irqrestore(&d40c->lock, flags); |
1051 | 1036 | ||
1052 | if (callback && (d40d_fin->txd.flags & DMA_PREP_INTERRUPT)) | 1037 | if (callback && (d40d->txd.flags & DMA_PREP_INTERRUPT)) |
1053 | callback(callback_param); | 1038 | callback(callback_param); |
1054 | 1039 | ||
1055 | return; | 1040 | return; |
@@ -1127,7 +1112,6 @@ static irqreturn_t d40_handle_interrupt(int irq, void *data) | |||
1127 | return IRQ_HANDLED; | 1112 | return IRQ_HANDLED; |
1128 | } | 1113 | } |
1129 | 1114 | ||
1130 | |||
1131 | static int d40_validate_conf(struct d40_chan *d40c, | 1115 | static int d40_validate_conf(struct d40_chan *d40c, |
1132 | struct stedma40_chan_cfg *conf) | 1116 | struct stedma40_chan_cfg *conf) |
1133 | { | 1117 | { |
@@ -1432,7 +1416,6 @@ static int d40_free_dma(struct d40_chan *d40c) | |||
1432 | list_for_each_entry_safe(d, _d, &d40c->client, node) { | 1416 | list_for_each_entry_safe(d, _d, &d40c->client, node) { |
1433 | d40_pool_lli_free(d); | 1417 | d40_pool_lli_free(d); |
1434 | d40_desc_remove(d); | 1418 | d40_desc_remove(d); |
1435 | /* Return desc to free-list */ | ||
1436 | d40_desc_free(d40c, d); | 1419 | d40_desc_free(d40c, d); |
1437 | } | 1420 | } |
1438 | 1421 | ||
@@ -2793,8 +2776,10 @@ static int __init d40_lcla_allocate(struct d40_base *base) | |||
2793 | if (i < MAX_LCLA_ALLOC_ATTEMPTS) { | 2776 | if (i < MAX_LCLA_ALLOC_ATTEMPTS) { |
2794 | base->lcla_pool.base = (void *)page_list[i]; | 2777 | base->lcla_pool.base = (void *)page_list[i]; |
2795 | } else { | 2778 | } else { |
2796 | /* After many attempts, no succees with finding the correct | 2779 | /* |
2797 | * alignment try with allocating a big buffer */ | 2780 | * After many attempts and no succees with finding the correct |
2781 | * alignment, try with allocating a big buffer. | ||
2782 | */ | ||
2798 | dev_warn(base->dev, | 2783 | dev_warn(base->dev, |
2799 | "[%s] Failed to get %d pages @ 18 bit align.\n", | 2784 | "[%s] Failed to get %d pages @ 18 bit align.\n", |
2800 | __func__, base->lcla_pool.pages); | 2785 | __func__, base->lcla_pool.pages); |
@@ -2916,8 +2901,9 @@ failure: | |||
2916 | if (!base->lcla_pool.base_unaligned && base->lcla_pool.base) | 2901 | if (!base->lcla_pool.base_unaligned && base->lcla_pool.base) |
2917 | free_pages((unsigned long)base->lcla_pool.base, | 2902 | free_pages((unsigned long)base->lcla_pool.base, |
2918 | base->lcla_pool.pages); | 2903 | base->lcla_pool.pages); |
2919 | if (base->lcla_pool.base_unaligned) | 2904 | |
2920 | kfree(base->lcla_pool.base_unaligned); | 2905 | kfree(base->lcla_pool.base_unaligned); |
2906 | |||
2921 | if (base->phy_lcpa) | 2907 | if (base->phy_lcpa) |
2922 | release_mem_region(base->phy_lcpa, | 2908 | release_mem_region(base->phy_lcpa, |
2923 | base->lcpa_size); | 2909 | base->lcpa_size); |
diff --git a/drivers/dma/ste_dma40_ll.c b/drivers/dma/ste_dma40_ll.c index 67076726b874..92a0960fba08 100644 --- a/drivers/dma/ste_dma40_ll.c +++ b/drivers/dma/ste_dma40_ll.c | |||
@@ -1,10 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * driver/dma/ste_dma40_ll.c | 2 | * Copyright (C) ST-Ericsson SA 2007-2010 |
3 | * | 3 | * Author: Per Friden <per.friden@stericsson.com> for ST-Ericsson |
4 | * Copyright (C) ST-Ericsson 2007-2010 | 4 | * Author: Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson |
5 | * License terms: GNU General Public License (GPL) version 2 | 5 | * License terms: GNU General Public License (GPL) version 2 |
6 | * Author: Per Friden <per.friden@stericsson.com> | ||
7 | * Author: Jonas Aaberg <jonas.aberg@stericsson.com> | ||
8 | */ | 6 | */ |
9 | 7 | ||
10 | #include <linux/kernel.h> | 8 | #include <linux/kernel.h> |
diff --git a/drivers/dma/ste_dma40_ll.h b/drivers/dma/ste_dma40_ll.h index be35fadddf75..a51ec187b5cf 100644 --- a/drivers/dma/ste_dma40_ll.h +++ b/drivers/dma/ste_dma40_ll.h | |||
@@ -1,10 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * driver/dma/ste_dma40_ll.h | 2 | * Copyright (C) ST-Ericsson SA 2007-2010 |
3 | * | 3 | * Author: Per Friden <per.friden@stericsson.com> for ST-Ericsson SA |
4 | * Copyright (C) ST-Ericsson 2007-2010 | 4 | * Author: Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson SA |
5 | * License terms: GNU General Public License (GPL) version 2 | 5 | * License terms: GNU General Public License (GPL) version 2 |
6 | * Author: Per Friden <per.friden@stericsson.com> | ||
7 | * Author: Jonas Aaberg <jonas.aberg@stericsson.com> | ||
8 | */ | 6 | */ |
9 | #ifndef STE_DMA40_LL_H | 7 | #ifndef STE_DMA40_LL_H |
10 | #define STE_DMA40_LL_H | 8 | #define STE_DMA40_LL_H |
@@ -289,10 +287,13 @@ struct d40_lcla_elem { | |||
289 | /* Physical channels */ | 287 | /* Physical channels */ |
290 | 288 | ||
291 | void d40_phy_cfg(struct stedma40_chan_cfg *cfg, | 289 | void d40_phy_cfg(struct stedma40_chan_cfg *cfg, |
292 | u32 *src_cfg, u32 *dst_cfg, bool is_log); | 290 | u32 *src_cfg, |
291 | u32 *dst_cfg, | ||
292 | bool is_log); | ||
293 | 293 | ||
294 | void d40_log_cfg(struct stedma40_chan_cfg *cfg, | 294 | void d40_log_cfg(struct stedma40_chan_cfg *cfg, |
295 | u32 *lcsp1, u32 *lcsp2); | 295 | u32 *lcsp1, |
296 | u32 *lcsp2); | ||
296 | 297 | ||
297 | int d40_phy_sg_to_lli(struct scatterlist *sg, | 298 | int d40_phy_sg_to_lli(struct scatterlist *sg, |
298 | int sg_len, | 299 | int sg_len, |
@@ -321,10 +322,13 @@ void d40_phy_lli_write(void __iomem *virtbase, | |||
321 | /* Logical channels */ | 322 | /* Logical channels */ |
322 | 323 | ||
323 | void d40_log_fill_lli(struct d40_log_lli *lli, | 324 | void d40_log_fill_lli(struct d40_log_lli *lli, |
324 | dma_addr_t data, u32 data_size, | 325 | dma_addr_t data, |
325 | u32 lli_next_off, u32 reg_cfg, | 326 | u32 data_size, |
327 | u32 lli_next_off, | ||
328 | u32 reg_cfg, | ||
326 | u32 data_width, | 329 | u32 data_width, |
327 | bool term_int, bool addr_inc); | 330 | bool term_int, |
331 | bool addr_inc); | ||
328 | 332 | ||
329 | int d40_log_sg_to_dev(struct d40_lcla_elem *lcla, | 333 | int d40_log_sg_to_dev(struct d40_lcla_elem *lcla, |
330 | struct scatterlist *sg, | 334 | struct scatterlist *sg, |
@@ -334,7 +338,8 @@ int d40_log_sg_to_dev(struct d40_lcla_elem *lcla, | |||
334 | u32 src_data_width, | 338 | u32 src_data_width, |
335 | u32 dst_data_width, | 339 | u32 dst_data_width, |
336 | enum dma_data_direction direction, | 340 | enum dma_data_direction direction, |
337 | dma_addr_t dev_addr, int max_len, | 341 | dma_addr_t dev_addr, |
342 | int max_len, | ||
338 | int llis_per_log); | 343 | int llis_per_log); |
339 | 344 | ||
340 | int d40_log_lli_write(struct d40_log_lli_full *lcpa, | 345 | int d40_log_lli_write(struct d40_log_lli_full *lcpa, |
@@ -350,6 +355,7 @@ int d40_log_sg_to_lli(int lcla_id, | |||
350 | struct d40_log_lli *lli_sg, | 355 | struct d40_log_lli *lli_sg, |
351 | u32 lcsp13, /* src or dst*/ | 356 | u32 lcsp13, /* src or dst*/ |
352 | u32 data_width, | 357 | u32 data_width, |
353 | int max_len, int llis_per_log); | 358 | int max_len, |
359 | int llis_per_log); | ||
354 | 360 | ||
355 | #endif /* STE_DMA40_LLI_H */ | 361 | #endif /* STE_DMA40_LLI_H */ |