aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBoojin Kim <boojin.kim@samsung.com>2012-06-19 00:26:53 -0400
committerKukjin Kim <kgene.kim@samsung.com>2012-06-19 19:07:35 -0400
commitfbb20e81bd26e41667d8d0929fd08ed60b24d9ec (patch)
treeac4c11ddc5d99377018c5bc6b4c05fe5c7281afd
parent485802a6c524e62b5924849dd727ddbb1497cc71 (diff)
ARM: SAMSUNG: Add config() function in DMA common operations
This patch adds config() that configures DMA transmit option. This function was originally included in request(). But, Some DMA client driver requires to change the configuration after request(). So, This patch picks up it from request(). Signed-off-by: Boojin Kim <boojin.kim@samsung.com> Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
-rw-r--r--arch/arm/plat-samsung/dma-ops.c77
-rw-r--r--arch/arm/plat-samsung/include/plat/dma-ops.h20
-rw-r--r--arch/arm/plat-samsung/s3c-dma-ops.c39
3 files changed, 77 insertions, 59 deletions
diff --git a/arch/arm/plat-samsung/dma-ops.c b/arch/arm/plat-samsung/dma-ops.c
index eb9f4f53400..f9eb353d768 100644
--- a/arch/arm/plat-samsung/dma-ops.c
+++ b/arch/arm/plat-samsung/dma-ops.c
@@ -19,72 +19,80 @@
19#include <mach/dma.h> 19#include <mach/dma.h>
20 20
21static unsigned samsung_dmadev_request(enum dma_ch dma_ch, 21static unsigned samsung_dmadev_request(enum dma_ch dma_ch,
22 struct samsung_dma_info *info) 22 struct samsung_dma_req *param)
23{ 23{
24 struct dma_chan *chan;
25 dma_cap_mask_t mask; 24 dma_cap_mask_t mask;
26 struct dma_slave_config slave_config;
27 void *filter_param; 25 void *filter_param;
28 26
29 dma_cap_zero(mask); 27 dma_cap_zero(mask);
30 dma_cap_set(info->cap, mask); 28 dma_cap_set(param->cap, mask);
31 29
32 /* 30 /*
33 * If a dma channel property of a device node from device tree is 31 * If a dma channel property of a device node from device tree is
34 * specified, use that as the fliter parameter. 32 * specified, use that as the fliter parameter.
35 */ 33 */
36 filter_param = (dma_ch == DMACH_DT_PROP) ? (void *)info->dt_dmach_prop : 34 filter_param = (dma_ch == DMACH_DT_PROP) ?
37 (void *)dma_ch; 35 (void *)param->dt_dmach_prop : (void *)dma_ch;
38 chan = dma_request_channel(mask, pl330_filter, filter_param); 36 return (unsigned)dma_request_channel(mask, pl330_filter, filter_param);
37}
39 38
40 if (info->direction == DMA_DEV_TO_MEM) { 39static int samsung_dmadev_release(unsigned ch,
40 struct s3c2410_dma_client *client)
41{
42 dma_release_channel((struct dma_chan *)ch);
43
44 return 0;
45}
46
47static int samsung_dmadev_config(unsigned ch,
48 struct samsung_dma_config *param)
49{
50 struct dma_chan *chan = (struct dma_chan *)ch;
51 struct dma_slave_config slave_config;
52
53 if (param->direction == DMA_DEV_TO_MEM) {
41 memset(&slave_config, 0, sizeof(struct dma_slave_config)); 54 memset(&slave_config, 0, sizeof(struct dma_slave_config));
42 slave_config.direction = info->direction; 55 slave_config.direction = param->direction;
43 slave_config.src_addr = info->fifo; 56 slave_config.src_addr = param->fifo;
44 slave_config.src_addr_width = info->width; 57 slave_config.src_addr_width = param->width;
45 slave_config.src_maxburst = 1; 58 slave_config.src_maxburst = 1;
46 dmaengine_slave_config(chan, &slave_config); 59 dmaengine_slave_config(chan, &slave_config);
47 } else if (info->direction == DMA_MEM_TO_DEV) { 60 } else if (param->direction == DMA_MEM_TO_DEV) {
48 memset(&slave_config, 0, sizeof(struct dma_slave_config)); 61 memset(&slave_config, 0, sizeof(struct dma_slave_config));
49 slave_config.direction = info->direction; 62 slave_config.direction = param->direction;
50 slave_config.dst_addr = info->fifo; 63 slave_config.dst_addr = param->fifo;
51 slave_config.dst_addr_width = info->width; 64 slave_config.dst_addr_width = param->width;
52 slave_config.dst_maxburst = 1; 65 slave_config.dst_maxburst = 1;
53 dmaengine_slave_config(chan, &slave_config); 66 dmaengine_slave_config(chan, &slave_config);
67 } else {
68 pr_warn("unsupported direction\n");
69 return -EINVAL;
54 } 70 }
55 71
56 return (unsigned)chan;
57}
58
59static int samsung_dmadev_release(unsigned ch,
60 struct s3c2410_dma_client *client)
61{
62 dma_release_channel((struct dma_chan *)ch);
63
64 return 0; 72 return 0;
65} 73}
66 74
67static int samsung_dmadev_prepare(unsigned ch, 75static int samsung_dmadev_prepare(unsigned ch,
68 struct samsung_dma_prep_info *info) 76 struct samsung_dma_prep *param)
69{ 77{
70 struct scatterlist sg; 78 struct scatterlist sg;
71 struct dma_chan *chan = (struct dma_chan *)ch; 79 struct dma_chan *chan = (struct dma_chan *)ch;
72 struct dma_async_tx_descriptor *desc; 80 struct dma_async_tx_descriptor *desc;
73 81
74 switch (info->cap) { 82 switch (param->cap) {
75 case DMA_SLAVE: 83 case DMA_SLAVE:
76 sg_init_table(&sg, 1); 84 sg_init_table(&sg, 1);
77 sg_dma_len(&sg) = info->len; 85 sg_dma_len(&sg) = param->len;
78 sg_set_page(&sg, pfn_to_page(PFN_DOWN(info->buf)), 86 sg_set_page(&sg, pfn_to_page(PFN_DOWN(param->buf)),
79 info->len, offset_in_page(info->buf)); 87 param->len, offset_in_page(param->buf));
80 sg_dma_address(&sg) = info->buf; 88 sg_dma_address(&sg) = param->buf;
81 89
82 desc = dmaengine_prep_slave_sg(chan, 90 desc = dmaengine_prep_slave_sg(chan,
83 &sg, 1, info->direction, DMA_PREP_INTERRUPT); 91 &sg, 1, param->direction, DMA_PREP_INTERRUPT);
84 break; 92 break;
85 case DMA_CYCLIC: 93 case DMA_CYCLIC:
86 desc = dmaengine_prep_dma_cyclic(chan, 94 desc = dmaengine_prep_dma_cyclic(chan, param->buf,
87 info->buf, info->len, info->period, info->direction); 95 param->len, param->period, param->direction);
88 break; 96 break;
89 default: 97 default:
90 dev_err(&chan->dev->device, "unsupported format\n"); 98 dev_err(&chan->dev->device, "unsupported format\n");
@@ -96,8 +104,8 @@ static int samsung_dmadev_prepare(unsigned ch,
96 return -EFAULT; 104 return -EFAULT;
97 } 105 }
98 106
99 desc->callback = info->fp; 107 desc->callback = param->fp;
100 desc->callback_param = info->fp_param; 108 desc->callback_param = param->fp_param;
101 109
102 dmaengine_submit((struct dma_async_tx_descriptor *)desc); 110 dmaengine_submit((struct dma_async_tx_descriptor *)desc);
103 111
@@ -119,6 +127,7 @@ static inline int samsung_dmadev_flush(unsigned ch)
119static struct samsung_dma_ops dmadev_ops = { 127static struct samsung_dma_ops dmadev_ops = {
120 .request = samsung_dmadev_request, 128 .request = samsung_dmadev_request,
121 .release = samsung_dmadev_release, 129 .release = samsung_dmadev_release,
130 .config = samsung_dmadev_config,
122 .prepare = samsung_dmadev_prepare, 131 .prepare = samsung_dmadev_prepare,
123 .trigger = samsung_dmadev_trigger, 132 .trigger = samsung_dmadev_trigger,
124 .started = NULL, 133 .started = NULL,
diff --git a/arch/arm/plat-samsung/include/plat/dma-ops.h b/arch/arm/plat-samsung/include/plat/dma-ops.h
index 71a6827c770..f5144cdd300 100644
--- a/arch/arm/plat-samsung/include/plat/dma-ops.h
+++ b/arch/arm/plat-samsung/include/plat/dma-ops.h
@@ -16,7 +16,13 @@
16#include <linux/dmaengine.h> 16#include <linux/dmaengine.h>
17#include <mach/dma.h> 17#include <mach/dma.h>
18 18
19struct samsung_dma_prep_info { 19struct samsung_dma_req {
20 enum dma_transaction_type cap;
21 struct property *dt_dmach_prop;
22 struct s3c2410_dma_client *client;
23};
24
25struct samsung_dma_prep {
20 enum dma_transaction_type cap; 26 enum dma_transaction_type cap;
21 enum dma_transfer_direction direction; 27 enum dma_transfer_direction direction;
22 dma_addr_t buf; 28 dma_addr_t buf;
@@ -26,19 +32,17 @@ struct samsung_dma_prep_info {
26 void *fp_param; 32 void *fp_param;
27}; 33};
28 34
29struct samsung_dma_info { 35struct samsung_dma_config {
30 enum dma_transaction_type cap;
31 enum dma_transfer_direction direction; 36 enum dma_transfer_direction direction;
32 enum dma_slave_buswidth width; 37 enum dma_slave_buswidth width;
33 dma_addr_t fifo; 38 dma_addr_t fifo;
34 struct s3c2410_dma_client *client;
35 struct property *dt_dmach_prop;
36}; 39};
37 40
38struct samsung_dma_ops { 41struct samsung_dma_ops {
39 unsigned (*request)(enum dma_ch ch, struct samsung_dma_info *info); 42 unsigned (*request)(enum dma_ch ch, struct samsung_dma_req *param);
40 int (*release)(unsigned ch, struct s3c2410_dma_client *client); 43 int (*release)(unsigned ch, void *param);
41 int (*prepare)(unsigned ch, struct samsung_dma_prep_info *info); 44 int (*config)(unsigned ch, struct samsung_dma_config *param);
45 int (*prepare)(unsigned ch, struct samsung_dma_prep *param);
42 int (*trigger)(unsigned ch); 46 int (*trigger)(unsigned ch);
43 int (*started)(unsigned ch); 47 int (*started)(unsigned ch);
44 int (*flush)(unsigned ch); 48 int (*flush)(unsigned ch);
diff --git a/arch/arm/plat-samsung/s3c-dma-ops.c b/arch/arm/plat-samsung/s3c-dma-ops.c
index 78149491282..f99448c48d3 100644
--- a/arch/arm/plat-samsung/s3c-dma-ops.c
+++ b/arch/arm/plat-samsung/s3c-dma-ops.c
@@ -36,30 +36,26 @@ static void s3c_dma_cb(struct s3c2410_dma_chan *channel, void *param,
36} 36}
37 37
38static unsigned s3c_dma_request(enum dma_ch dma_ch, 38static unsigned s3c_dma_request(enum dma_ch dma_ch,
39 struct samsung_dma_info *info) 39 struct samsung_dma_req *param)
40{ 40{
41 struct cb_data *data; 41 struct cb_data *data;
42 42
43 if (s3c2410_dma_request(dma_ch, info->client, NULL) < 0) { 43 if (s3c2410_dma_request(dma_ch, param->client, NULL) < 0) {
44 s3c2410_dma_free(dma_ch, info->client); 44 s3c2410_dma_free(dma_ch, param->client);
45 return 0; 45 return 0;
46 } 46 }
47 47
48 if (param->cap == DMA_CYCLIC)
49 s3c2410_dma_setflags(dma_ch, S3C2410_DMAF_CIRCULAR);
50
48 data = kzalloc(sizeof(struct cb_data), GFP_KERNEL); 51 data = kzalloc(sizeof(struct cb_data), GFP_KERNEL);
49 data->ch = dma_ch; 52 data->ch = dma_ch;
50 list_add_tail(&data->node, &dma_list); 53 list_add_tail(&data->node, &dma_list);
51 54
52 s3c2410_dma_devconfig(dma_ch, info->direction, info->fifo);
53
54 if (info->cap == DMA_CYCLIC)
55 s3c2410_dma_setflags(dma_ch, S3C2410_DMAF_CIRCULAR);
56
57 s3c2410_dma_config(dma_ch, info->width);
58
59 return (unsigned)dma_ch; 55 return (unsigned)dma_ch;
60} 56}
61 57
62static int s3c_dma_release(unsigned ch, struct s3c2410_dma_client *client) 58static int s3c_dma_release(unsigned ch, void *param)
63{ 59{
64 struct cb_data *data; 60 struct cb_data *data;
65 61
@@ -68,16 +64,24 @@ static int s3c_dma_release(unsigned ch, struct s3c2410_dma_client *client)
68 break; 64 break;
69 list_del(&data->node); 65 list_del(&data->node);
70 66
71 s3c2410_dma_free(ch, client); 67 s3c2410_dma_free(ch, param);
72 kfree(data); 68 kfree(data);
73 69
74 return 0; 70 return 0;
75} 71}
76 72
77static int s3c_dma_prepare(unsigned ch, struct samsung_dma_prep_info *info) 73static int s3c_dma_config(unsigned ch, struct samsung_dma_config *param)
74{
75 s3c2410_dma_devconfig(ch, param->direction, param->fifo);
76 s3c2410_dma_config(ch, param->width);
77
78 return 0;
79}
80
81static int s3c_dma_prepare(unsigned ch, struct samsung_dma_prep *param)
78{ 82{
79 struct cb_data *data; 83 struct cb_data *data;
80 int len = (info->cap == DMA_CYCLIC) ? info->period : info->len; 84 int len = (param->cap == DMA_CYCLIC) ? param->period : param->len;
81 85
82 list_for_each_entry(data, &dma_list, node) 86 list_for_each_entry(data, &dma_list, node)
83 if (data->ch == ch) 87 if (data->ch == ch)
@@ -85,11 +89,11 @@ static int s3c_dma_prepare(unsigned ch, struct samsung_dma_prep_info *info)
85 89
86 if (!data->fp) { 90 if (!data->fp) {
87 s3c2410_dma_set_buffdone_fn(ch, s3c_dma_cb); 91 s3c2410_dma_set_buffdone_fn(ch, s3c_dma_cb);
88 data->fp = info->fp; 92 data->fp = param->fp;
89 data->fp_param = info->fp_param; 93 data->fp_param = param->fp_param;
90 } 94 }
91 95
92 s3c2410_dma_enqueue(ch, (void *)data, info->buf, len); 96 s3c2410_dma_enqueue(ch, (void *)data, param->buf, len);
93 97
94 return 0; 98 return 0;
95} 99}
@@ -117,6 +121,7 @@ static inline int s3c_dma_stop(unsigned ch)
117static struct samsung_dma_ops s3c_dma_ops = { 121static struct samsung_dma_ops s3c_dma_ops = {
118 .request = s3c_dma_request, 122 .request = s3c_dma_request,
119 .release = s3c_dma_release, 123 .release = s3c_dma_release,
124 .config = s3c_dma_config,
120 .prepare = s3c_dma_prepare, 125 .prepare = s3c_dma_prepare,
121 .trigger = s3c_dma_trigger, 126 .trigger = s3c_dma_trigger,
122 .started = s3c_dma_started, 127 .started = s3c_dma_started,