]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - sitara-epos/sitara-epos-kernel.git/blob - arch/arm/plat-omap/sdma2edma.c
arm:omap:am33xx: Basic cpuidle support
[sitara-epos/sitara-epos-kernel.git] / arch / arm / plat-omap / sdma2edma.c
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)
109         edma_free_channel((unsigned)lch);
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)
125         edma_start((unsigned)lch);
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)
140         edma_stop((unsigned)lch);
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)
157         edma_clean_channel((unsigned)lch);
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)
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);
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)
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);
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)
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);
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)
283         printk(KERN_WARNING "omap_set_dma_src_burst_mode: un-supported SDMA"
284                                 " wrapper\n");
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)
290         printk(KERN_WARNING "omap_set_dma_dest_burst_mode: un-supported SDMA"
291                                 " wrapper\n");
293 EXPORT_SYMBOL(omap_set_dma_dest_burst_mode);
295 dma_addr_t omap_get_dma_dst_pos(int lch)
297         printk(KERN_WARNING "omap_get_dma_dst_pos: un-supported in SDMA"
298                                 " wrapper\n");
299         return 0;
301 EXPORT_SYMBOL(omap_get_dma_dst_pos);
303 int omap_get_dma_active_status(int lch)
305         printk(KERN_WARNING "omap_get_dma_active_status: un-supported in SDMA"
306                                 " wrapper\n");
307         return 0;
309 EXPORT_SYMBOL(omap_get_dma_active_status);
311 void omap_dma_global_context_save(void)
313         printk(KERN_WARNING "omap_dma_global_context_save: un-supported in SDMA"
314                                 " wrapper\n");
316 EXPORT_SYMBOL(omap_dma_global_context_save);
318 void omap_dma_global_context_restore(void)
320         printk(KERN_WARNING "omap_dma_global_context_restore: un-supported in"
321                                 "SDMA wrapper\n");
323 EXPORT_SYMBOL(omap_dma_global_context_restore);
325 int omap_dma_running(void)
327         printk(KERN_WARNING "omap_dma_running: un-supported in SDMA wrapper\n");
329         return 0;
331 EXPORT_SYMBOL(omap_dma_running);
333 void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color)
335         printk(KERN_WARNING "omap_set_dma_color_mode: un-supported in"
336                                 "SDMA wrapper\n");
338 EXPORT_SYMBOL(omap_set_dma_color_mode);
340 void omap_set_dma_dest_data_pack(int lch, int enable)
342         printk(KERN_WARNING "omap_set_dma_dest_data_pack: un-supported in"
343                                 "SDMA wrapper\n");
345 EXPORT_SYMBOL(omap_set_dma_dest_data_pack);
347 void omap_set_dma_src_data_pack(int lch, int enable)
349         printk(KERN_WARNING "omap_set_dma_src_data_pack: un-supported in"
350                                 "SDMA wrapper\n");
352 EXPORT_SYMBOL(omap_set_dma_src_data_pack);
354 void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode)
356         printk(KERN_WARNING "omap_set_dma_write_mode: un-supported in"
357                                 "SDMA wrapper\n");
359 EXPORT_SYMBOL(omap_set_dma_write_mode);