diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2013-11-02 09:26:57 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2014-04-03 19:27:43 -0400 |
commit | b9e97822da374f52aaf99cb502f531ff2184b8f5 (patch) | |
tree | de5205a5f5b51cfdf268d9c774b9240d8bd8fbe9 | |
parent | 1b416c4b41351c3eb8fc42dbb4cd8eba463c0813 (diff) |
dmaengine: omap-dma: program hardware directly
Program the transfer parameters directly into the hardware, rather
than using the functions in arch/arm/plat-omap/dma.c.
Acked-by: Tony Lindgren <tony@atomide.com>
Acked-by: Vinod Koul <vinod.koul@intel.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r-- | drivers/dma/omap-dma.c | 142 | ||||
-rw-r--r-- | include/linux/omap-dma.h | 6 |
2 files changed, 130 insertions, 18 deletions
diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index 4ac26bf0ad30..47a3fa5bc38e 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c | |||
@@ -99,16 +99,94 @@ static void omap_dma_start_sg(struct omap_chan *c, struct omap_desc *d, | |||
99 | unsigned idx) | 99 | unsigned idx) |
100 | { | 100 | { |
101 | struct omap_sg *sg = d->sg + idx; | 101 | struct omap_sg *sg = d->sg + idx; |
102 | uint32_t val; | ||
103 | |||
104 | if (d->dir == DMA_DEV_TO_MEM) { | ||
105 | if (dma_omap1()) { | ||
106 | val = c->plat->dma_read(CSDP, c->dma_ch); | ||
107 | val &= ~(0x1f << 9); | ||
108 | val |= OMAP_DMA_PORT_EMIFF << 9; | ||
109 | c->plat->dma_write(val, CSDP, c->dma_ch); | ||
110 | } | ||
102 | 111 | ||
103 | if (d->dir == DMA_DEV_TO_MEM) | 112 | val = c->plat->dma_read(CCR, c->dma_ch); |
104 | omap_set_dma_dest_params(c->dma_ch, OMAP_DMA_PORT_EMIFF, | 113 | val &= ~(0x03 << 14); |
105 | OMAP_DMA_AMODE_POST_INC, sg->addr, 0, 0); | 114 | val |= OMAP_DMA_AMODE_POST_INC << 14; |
106 | else | 115 | c->plat->dma_write(val, CCR, c->dma_ch); |
107 | omap_set_dma_src_params(c->dma_ch, OMAP_DMA_PORT_EMIFF, | 116 | |
108 | OMAP_DMA_AMODE_POST_INC, sg->addr, 0, 0); | 117 | c->plat->dma_write(sg->addr, CDSA, c->dma_ch); |
118 | c->plat->dma_write(0, CDEI, c->dma_ch); | ||
119 | c->plat->dma_write(0, CDFI, c->dma_ch); | ||
120 | } else { | ||
121 | if (dma_omap1()) { | ||
122 | val = c->plat->dma_read(CSDP, c->dma_ch); | ||
123 | val &= ~(0x1f << 2); | ||
124 | val |= OMAP_DMA_PORT_EMIFF << 2; | ||
125 | c->plat->dma_write(val, CSDP, c->dma_ch); | ||
126 | } | ||
127 | |||
128 | val = c->plat->dma_read(CCR, c->dma_ch); | ||
129 | val &= ~(0x03 << 12); | ||
130 | val |= OMAP_DMA_AMODE_POST_INC << 12; | ||
131 | c->plat->dma_write(val, CCR, c->dma_ch); | ||
132 | |||
133 | c->plat->dma_write(sg->addr, CSSA, c->dma_ch); | ||
134 | c->plat->dma_write(0, CSEI, c->dma_ch); | ||
135 | c->plat->dma_write(0, CSFI, c->dma_ch); | ||
136 | } | ||
137 | |||
138 | val = c->plat->dma_read(CSDP, c->dma_ch); | ||
139 | val &= ~0x03; | ||
140 | val |= d->es; | ||
141 | c->plat->dma_write(val, CSDP, c->dma_ch); | ||
142 | |||
143 | if (dma_omap1()) { | ||
144 | val = c->plat->dma_read(CCR, c->dma_ch); | ||
145 | val &= ~(1 << 5); | ||
146 | if (d->sync_mode == OMAP_DMA_SYNC_FRAME) | ||
147 | val |= 1 << 5; | ||
148 | c->plat->dma_write(val, CCR, c->dma_ch); | ||
149 | |||
150 | val = c->plat->dma_read(CCR2, c->dma_ch); | ||
151 | val &= ~(1 << 2); | ||
152 | if (d->sync_mode == OMAP_DMA_SYNC_BLOCK) | ||
153 | val |= 1 << 2; | ||
154 | c->plat->dma_write(val, CCR2, c->dma_ch); | ||
155 | } else if (c->dma_sig) { | ||
156 | val = c->plat->dma_read(CCR, c->dma_ch); | ||
157 | |||
158 | /* DMA_SYNCHRO_CONTROL_UPPER depends on the channel number */ | ||
159 | val &= ~((1 << 23) | (3 << 19) | 0x1f); | ||
160 | val |= (c->dma_sig & ~0x1f) << 14; | ||
161 | val |= c->dma_sig & 0x1f; | ||
162 | |||
163 | if (d->sync_mode & OMAP_DMA_SYNC_FRAME) | ||
164 | val |= 1 << 5; | ||
165 | else | ||
166 | val &= ~(1 << 5); | ||
167 | |||
168 | if (d->sync_mode & OMAP_DMA_SYNC_BLOCK) | ||
169 | val |= 1 << 18; | ||
170 | else | ||
171 | val &= ~(1 << 18); | ||
172 | |||
173 | switch (d->sync_type) { | ||
174 | case OMAP_DMA_DST_SYNC_PREFETCH: | ||
175 | val &= ~(1 << 24); /* dest synch */ | ||
176 | val |= 1 << 23; /* Prefetch */ | ||
177 | break; | ||
178 | case 0: | ||
179 | val &= ~(1 << 24); /* dest synch */ | ||
180 | break; | ||
181 | default: | ||
182 | val |= 1 << 24; /* source synch */ | ||
183 | break; | ||
184 | } | ||
185 | c->plat->dma_write(val, CCR, c->dma_ch); | ||
186 | } | ||
109 | 187 | ||
110 | omap_set_dma_transfer_params(c->dma_ch, d->es, sg->en, sg->fn, | 188 | c->plat->dma_write(sg->en, CEN, c->dma_ch); |
111 | d->sync_mode, c->dma_sig, d->sync_type); | 189 | c->plat->dma_write(sg->fn, CFN, c->dma_ch); |
112 | 190 | ||
113 | omap_start_dma(c->dma_ch); | 191 | omap_start_dma(c->dma_ch); |
114 | } | 192 | } |
@@ -117,6 +195,7 @@ static void omap_dma_start_desc(struct omap_chan *c) | |||
117 | { | 195 | { |
118 | struct virt_dma_desc *vd = vchan_next_desc(&c->vc); | 196 | struct virt_dma_desc *vd = vchan_next_desc(&c->vc); |
119 | struct omap_desc *d; | 197 | struct omap_desc *d; |
198 | uint32_t val; | ||
120 | 199 | ||
121 | if (!vd) { | 200 | if (!vd) { |
122 | c->desc = NULL; | 201 | c->desc = NULL; |
@@ -128,12 +207,39 @@ static void omap_dma_start_desc(struct omap_chan *c) | |||
128 | c->desc = d = to_omap_dma_desc(&vd->tx); | 207 | c->desc = d = to_omap_dma_desc(&vd->tx); |
129 | c->sgidx = 0; | 208 | c->sgidx = 0; |
130 | 209 | ||
131 | if (d->dir == DMA_DEV_TO_MEM) | 210 | if (d->dir == DMA_DEV_TO_MEM) { |
132 | omap_set_dma_src_params(c->dma_ch, d->periph_port, | 211 | if (dma_omap1()) { |
133 | OMAP_DMA_AMODE_CONSTANT, d->dev_addr, 0, d->fi); | 212 | val = c->plat->dma_read(CSDP, c->dma_ch); |
134 | else | 213 | val &= ~(0x1f << 2); |
135 | omap_set_dma_dest_params(c->dma_ch, d->periph_port, | 214 | val |= d->periph_port << 2; |
136 | OMAP_DMA_AMODE_CONSTANT, d->dev_addr, 0, d->fi); | 215 | c->plat->dma_write(val, CSDP, c->dma_ch); |
216 | } | ||
217 | |||
218 | val = c->plat->dma_read(CCR, c->dma_ch); | ||
219 | val &= ~(0x03 << 12); | ||
220 | val |= OMAP_DMA_AMODE_CONSTANT << 12; | ||
221 | c->plat->dma_write(val, CCR, c->dma_ch); | ||
222 | |||
223 | c->plat->dma_write(d->dev_addr, CSSA, c->dma_ch); | ||
224 | c->plat->dma_write(0, CSEI, c->dma_ch); | ||
225 | c->plat->dma_write(d->fi, CSFI, c->dma_ch); | ||
226 | } else { | ||
227 | if (dma_omap1()) { | ||
228 | val = c->plat->dma_read(CSDP, c->dma_ch); | ||
229 | val &= ~(0x1f << 9); | ||
230 | val |= d->periph_port << 9; | ||
231 | c->plat->dma_write(val, CSDP, c->dma_ch); | ||
232 | } | ||
233 | |||
234 | val = c->plat->dma_read(CCR, c->dma_ch); | ||
235 | val &= ~(0x03 << 14); | ||
236 | val |= OMAP_DMA_AMODE_CONSTANT << 14; | ||
237 | c->plat->dma_write(val, CCR, c->dma_ch); | ||
238 | |||
239 | c->plat->dma_write(d->dev_addr, CDSA, c->dma_ch); | ||
240 | c->plat->dma_write(0, CDEI, c->dma_ch); | ||
241 | c->plat->dma_write(d->fi, CDFI, c->dma_ch); | ||
242 | } | ||
137 | 243 | ||
138 | omap_dma_start_sg(c, d, 0); | 244 | omap_dma_start_sg(c, d, 0); |
139 | } | 245 | } |
@@ -452,8 +558,12 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( | |||
452 | } | 558 | } |
453 | 559 | ||
454 | if (dma_omap2plus()) { | 560 | if (dma_omap2plus()) { |
455 | omap_set_dma_src_burst_mode(c->dma_ch, OMAP_DMA_DATA_BURST_16); | 561 | uint32_t val; |
456 | omap_set_dma_dest_burst_mode(c->dma_ch, OMAP_DMA_DATA_BURST_16); | 562 | |
563 | val = c->plat->dma_read(CSDP, c->dma_ch); | ||
564 | val |= 0x03 << 7; /* src burst mode 16 */ | ||
565 | val |= 0x03 << 14; /* dst burst mode 16 */ | ||
566 | c->plat->dma_write(val, CSDP, c->dma_ch); | ||
457 | } | 567 | } |
458 | 568 | ||
459 | return vchan_tx_prep(&c->vc, &d->vd, flags); | 569 | return vchan_tx_prep(&c->vc, &d->vd, flags); |
diff --git a/include/linux/omap-dma.h b/include/linux/omap-dma.h index 14742fc2aefe..d631658e2237 100644 --- a/include/linux/omap-dma.h +++ b/include/linux/omap-dma.h | |||
@@ -289,8 +289,10 @@ struct omap_system_dma_plat_info { | |||
289 | #define dma_omap2plus() 0 | 289 | #define dma_omap2plus() 0 |
290 | #endif | 290 | #endif |
291 | #define dma_omap1() (!dma_omap2plus()) | 291 | #define dma_omap1() (!dma_omap2plus()) |
292 | #define dma_omap15xx() ((dma_omap1() && (d->dev_caps & ENABLE_1510_MODE))) | 292 | #define __dma_omap15xx(d) (dma_omap1() && (d)->dev_caps & ENABLE_1510_MODE) |
293 | #define dma_omap16xx() ((dma_omap1() && (d->dev_caps & ENABLE_16XX_MODE))) | 293 | #define __dma_omap16xx(d) (dma_omap1() && (d)->dev_caps & ENABLE_16XX_MODE) |
294 | #define dma_omap15xx() __dma_omap15xx(d) | ||
295 | #define dma_omap16xx() __dma_omap16xx(d) | ||
294 | 296 | ||
295 | extern struct omap_system_dma_plat_info *omap_get_plat_info(void); | 297 | extern struct omap_system_dma_plat_info *omap_get_plat_info(void); |
296 | 298 | ||