1 /*
2 * sdma2edma.c
3 *
4 * SDMA to EDMA3 Wrapper.
5 *
6 * NOTE: Since we are invoking EDMA API, comments for all APIs in this file
7 * are EDMA specific.
8 *
9 * Copyright (C) 2010-2011 Texas Instruments.
10 * Author: Mansoor Ahamed <mansoor.ahamed@ti.com>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 */
27 #include <linux/module.h>
28 #include <linux/init.h>
29 #include <linux/sched.h>
30 #include <linux/spinlock.h>
31 #include <linux/errno.h>
32 #include <linux/interrupt.h>
33 #include <linux/irq.h>
34 #include <linux/io.h>
36 #include <asm/system.h>
37 #include <mach/hardware.h>
38 #include <plat/dma.h>
39 #include <plat/tc.h>
41 /* some edma specific hacks which might change */
42 #include <mach/edma.h>
44 /**
45 * omap_request_dma - allocate DMA channel and paired parameter RAM
46 * @dev_id: specific channel to allocate; negative for "any unmapped channel"
47 * @callback: optional; to be issued on DMA completion or errors
48 * @data: passed to callback
49 * @dma_ch_out: allocated channel number returned in this variable
50 *
51 * This allocates a DMA channel and its associated parameter RAM slot.
52 * The parameter RAM is initialized to hold a dummy transfer.
53 *
54 * Normal use is to pass a specific channel number as @channel, to make
55 * use of hardware events mapped to that channel. When the channel will
56 * be used only for software triggering or event chaining, channels not
57 * mapped to hardware events (or mapped to unused events) are preferable.
58 *
59 * DMA transfers start from a channel using edma_start(), or by
60 * chaining. When the transfer described in that channel's parameter RAM
61 * slot completes, that slot's data may be reloaded through a link.
62 *
63 * DMA errors are only reported to the @callback associated with the
64 * channel driving that transfer, but transfer completion callbacks can
65 * be sent to another channel under control of the TCC field in
66 * the option word of the transfer's parameter RAM set. Drivers must not
67 * use DMA transfer completion callbacks for channels they did not allocate.
68 * (The same applies to TCC codes used in transfer chaining.)
69 *
70 * TODO: -
71 * . In the edma call, last param i.e TC hard coded to EVENTQ_2
72 * . The callback's ch_status which should be used in McSPI driver
73 * to stop/clean EDMA is currently ignored in some driver (eg. McSPI)
74 */
75 int omap_request_dma(int dev_id, const char *dev_name,
76 void (*callback)(int lch, u16 ch_status, void *data),
77 void *data, int *dma_ch_out)
78 {
79 struct edmacc_param p_ram;
80 typedef void (*EDMA_CALLBACK)(unsigned, u16, void*);
81 EDMA_CALLBACK edma_callback = (EDMA_CALLBACK)(callback);
83 *dma_ch_out = edma_alloc_channel(dev_id, edma_callback, data, EVENTQ_2);
84 if (*dma_ch_out < 0)
85 return -1;
87 /* enable interrupts */
88 edma_read_slot(*dma_ch_out, &p_ram);
89 p_ram.opt |= TCINTEN | EDMA_TCC(EDMA_CHAN_SLOT(*dma_ch_out));
90 edma_write_slot(*dma_ch_out, &p_ram);
92 return 0;
93 }
94 EXPORT_SYMBOL(omap_request_dma);
96 /**
97 * omap_free_dma - deallocate DMA channel
98 * @lch: dma channel returned from edma_alloc_channel()
99 *
100 * This deallocates the DMA channel and associated parameter RAM slot
101 * allocated by omap_request_dma().
102 *
103 * Callers are responsible for ensuring the channel is inactive, and
104 * will not be reactivated by linking, chaining, or software calls to
105 * omap_start_dma().
106 */
107 void omap_free_dma(int lch)
108 {
109 edma_free_channel((unsigned)lch);
110 }
111 EXPORT_SYMBOL(omap_free_dma);
113 /**
114 * omap_start_dma - start dma on a channel
115 * @lch: channel being activated
116 *
117 * Channels with event associations will be triggered by their hardware
118 * events, and channels without such associations will be triggered by
119 * software. (At this writing there is no interface for using software
120 * triggers except with channels that don't support hardware triggers.)
121 *
122 */
123 void omap_start_dma(int lch)
124 {
125 edma_start((unsigned)lch);
126 }
127 EXPORT_SYMBOL(omap_start_dma);
129 /**
130 * omap_stop_dma - stops dma on the channel passed
131 * @lch: channel being deactivated
132 *
133 * When @lch is a channel, any active transfer is paused and
134 * all pending hardware events are cleared. The current transfer
135 * may not be resumed, and the channel's Parameter RAM should be
136 * reinitialized before being reused.
137 */
138 void omap_stop_dma(int lch)
139 {
140 edma_stop((unsigned)lch);
141 }
142 EXPORT_SYMBOL(omap_stop_dma);
144 /**
145 * omap_cleanup_dma - Bring back DMA to initial state
146 * @lch: channel being cleaned up
147 *
148 * It cleans ParamEntry and bring back EDMA to initial state if media has
149 * been removed before EDMA has finished.It is usedful for removable media.
150 *
151 *
152 * FIXME this should not be needed ... edma_stop() should suffice.
153 *
154 */
155 void omap_cleanup_dma(int lch)
156 {
157 edma_clean_channel((unsigned)lch);
158 }
159 EXPORT_SYMBOL(omap_cleanup_dma);
161 /**
162 * omap_set_dma_transfer_params - configure DMA transfer parameters
163 * @lch: parameter RAM slot being configured
164 * @data_type: how many bytes per array (at least one)
165 * @elem_count: how many arrays per frame (at least one)
166 * @frame_count: how many frames per block (at least one)
167 * @sync_mode: ASYNC or ABSYNC
168 * @dma_trigger: device id (not used)
169 * @src_or_dst_synch: not used
170 *
171 * See the EDMA3 documentation to understand how to configure and link
172 * transfers using the fields in PaRAM slots. If you are not doing it
173 * all at once with edma_write_slot(), you will use this routine
174 * plus two calls each for source and destination, setting the initial
175 * address and saying how to index that address.
176 *
177 * An example of an A-Synchronized transfer is a serial link using a
178 * single word shift register. In that case, @acnt would be equal to
179 * that word size; the serial controller issues a DMA synchronization
180 * event to transfer each word, and memory access by the DMA transfer
181 * controller will be word-at-a-time.
182 *
183 * An example of an AB-Synchronized transfer is a device using a FIFO.
184 * In that case, @acnt equals the FIFO width and @bcnt equals its depth.
185 * The controller with the FIFO issues DMA synchronization events when
186 * the FIFO threshold is reached, and the DMA transfer controller will
187 * transfer one frame to (or from) the FIFO. It will probably use
188 * efficient burst modes to access memory.
189 *
190 * . dma_trigger and channel number, this is ignored for EDMA
191 * . Setting bcnt_rld same as bcnt
192 * TODO
193 * . what is src_or_dst_synch?
194 */
195 void omap_set_dma_transfer_params(int lch, int data_type, int elem_count,
196 int frame_count, int sync_mode,
197 int dma_trigger, int src_or_dst_synch)
198 {
199 int d_type[3] = {1, 2, 4};
200 if ((enum sync_dimension)sync_mode > ABSYNC) {
201 printk(KERN_ERR "SDMA2EDMA: Line:%d : Param \'sync_mode\' out"
202 " of range\n", __LINE__);
203 return;
204 }
206 /* translate data_type */
207 data_type = d_type[data_type];
209 edma_set_transfer_params(lch, (u16)data_type, (u16)elem_count,
210 (u16)frame_count, (u16)elem_count,
211 (enum sync_dimension)sync_mode);
212 }
213 EXPORT_SYMBOL(omap_set_dma_transfer_params);
215 /**
216 * omap_set_dma_dest_params - Set initial DMA destination addr in param RAM slot
217 * @lch: parameter RAM slot being configured
218 * @dest_port: not used
219 * @dest_amode: INCR, except in very rare cases
220 * @dest_start: physical address of destination (memory, controller FIFO, etc)
221 * @dst_ei: byte offset between destination arrays in a frame
222 * @dst_fi: byte offset between destination frames in a block
223 *
224 * Note that the destination address is modified during the DMA transfer
225 * according to edma_set_dest_index().
226 *
227 * TODO
228 * . Not sure about dst_ei and dst_fi
229 * . fifo_width for edma is not available in sdma API hence setting it to
230 * W8BIT
231 * . dest_port is ignored
232 */
233 void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode,
234 unsigned long dest_start, int dst_ei, int dst_fi)
235 {
236 if ((enum address_mode)dest_amode > FIFO) {
237 printk(KERN_ERR "SDMA2EDMA: Line:%d : Param \'dest_amode\' out"
238 " of range\n", __LINE__);
239 return;
240 }
242 edma_set_dest((unsigned)lch, (dma_addr_t)dest_start,
243 !dest_amode, W32BIT);
244 edma_set_dest_index((unsigned)(lch), (s16)dst_ei, (s16)dst_fi);
245 }
246 EXPORT_SYMBOL(omap_set_dma_dest_params);
248 /**
249 * omap_set_dma_src_params - Set initial DMA source addr in param RAM slot
250 * @lch: parameter RAM slot being configured
251 * @src_port: not used
252 * @src_amode: INCR, except in very rare cases
253 * @src_start: physical address of destination (memory, controller FIFO, etc)
254 * @src_ei: byte offset between destination arrays in a frame
255 * @src_fi: byte offset between destination frames in a block
256 *
257 * Note that the source address is modified during the DMA transfer
258 * according to edma_set_src_index().
259 *
260 * TODO
261 * . Not sure about src_ei and src_fi
262 * . fifo_width for edma is not available in sdma API hence setting it to
263 * W8BIT
264 * . src_port is ignored
265 */
266 void omap_set_dma_src_params(int lch, int src_port, int src_amode,
267 unsigned long src_start, int src_ei, int src_fi)
268 {
269 if ((enum address_mode)src_amode > FIFO) {
270 printk(KERN_ERR "SDMA2EDMA: Line:%d : Param \'src_amode\' out "
271 "of range\n", __LINE__);
272 return;
273 }
275 edma_set_src((unsigned)lch, (dma_addr_t)src_start,
276 !src_amode, W32BIT);
277 edma_set_src_index((unsigned)(lch), (s16)src_ei, (s16)src_fi);
278 }
279 EXPORT_SYMBOL(omap_set_dma_src_params);
281 void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
282 {
283 printk(KERN_WARNING "omap_set_dma_src_burst_mode: un-supported SDMA"
284 " wrapper\n");
285 }
286 EXPORT_SYMBOL(omap_set_dma_src_burst_mode);
288 void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
289 {
290 printk(KERN_WARNING "omap_set_dma_dest_burst_mode: un-supported SDMA"
291 " wrapper\n");
292 }
293 EXPORT_SYMBOL(omap_set_dma_dest_burst_mode);
295 dma_addr_t omap_get_dma_dst_pos(int lch)
296 {
297 printk(KERN_WARNING "omap_get_dma_dst_pos: un-supported in SDMA"
298 " wrapper\n");
299 return 0;
300 }
301 EXPORT_SYMBOL(omap_get_dma_dst_pos);
303 int omap_get_dma_active_status(int lch)
304 {
305 printk(KERN_WARNING "omap_get_dma_active_status: un-supported in SDMA"
306 " wrapper\n");
307 return 0;
308 }
309 EXPORT_SYMBOL(omap_get_dma_active_status);
311 void omap_dma_global_context_save(void)
312 {
313 printk(KERN_WARNING "omap_dma_global_context_save: un-supported in SDMA"
314 " wrapper\n");
315 }
316 EXPORT_SYMBOL(omap_dma_global_context_save);
318 void omap_dma_global_context_restore(void)
319 {
320 printk(KERN_WARNING "omap_dma_global_context_restore: un-supported in"
321 "SDMA wrapper\n");
322 }
323 EXPORT_SYMBOL(omap_dma_global_context_restore);
325 int omap_dma_running(void)
326 {
327 printk(KERN_WARNING "omap_dma_running: un-supported in SDMA wrapper\n");
329 return 0;
330 }
331 EXPORT_SYMBOL(omap_dma_running);
333 void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color)
334 {
335 printk(KERN_WARNING "omap_set_dma_color_mode: un-supported in"
336 "SDMA wrapper\n");
337 }
338 EXPORT_SYMBOL(omap_set_dma_color_mode);
340 void omap_set_dma_dest_data_pack(int lch, int enable)
341 {
342 printk(KERN_WARNING "omap_set_dma_dest_data_pack: un-supported in"
343 "SDMA wrapper\n");
344 }
345 EXPORT_SYMBOL(omap_set_dma_dest_data_pack);
347 void omap_set_dma_src_data_pack(int lch, int enable)
348 {
349 printk(KERN_WARNING "omap_set_dma_src_data_pack: un-supported in"
350 "SDMA wrapper\n");
351 }
352 EXPORT_SYMBOL(omap_set_dma_src_data_pack);
354 void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode)
355 {
356 printk(KERN_WARNING "omap_set_dma_write_mode: un-supported in"
357 "SDMA wrapper\n");
358 }
359 EXPORT_SYMBOL(omap_set_dma_write_mode);