source: soft/giet_vm/giet_drivers/dma_driver.c

Last change on this file was 529, checked in by alain, 10 years ago

1) Removing the IOC driver (integrated in the FAT library).
2) Simplifying the BDV, HBA, SDC, RDK drivers: they support
only two modes (synchronous => polling / descheduling => IRQ),
and only one access function (for both read/write).

File size: 10.7 KB
Line 
1///////////////////////////////////////////////////////////////////////////////////
2// File     : dma_driver.c
3// Date     : 23/11/2013
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7
8#include <giet_config.h>
9#include <hard_config.h>
10#include <dma_driver.h>
11#include <tty0.h>
12#include <vmem.h>
13#include <utils.h>
14#include <io.h>
15
16#if !defined(X_SIZE)
17# error: You must define X_SIZE in the hard_config.h file
18#endif
19
20#if !defined(Y_SIZE)
21# error: You must define X_SIZE in the hard_config.h file
22#endif
23
24#if !defined(X_WIDTH)
25# error: You must define X_WIDTH in the hard_config.h file
26#endif
27
28#if !defined(Y_WIDTH)
29# error: You must define X_WIDTH in the hard_config.h file
30#endif
31
32#if !defined(NB_DMA_CHANNELS)
33# error: You must define NB_DMA_CHANNELS in the hard_config.h file
34#endif
35
36#if !defined(SEG_DMA_BASE)
37# error: You must define SEG_DMA_BASE in the hard_config.h file
38#endif
39
40#if !defined(PERI_CLUSTER_INCREMENT)
41# error: You must define PERI_CLUSTER_INCREMENT in the hard_config.h file
42#endif
43
44extern volatile unsigned int _ptabs_vaddr[];
45
46///////////////////////////////////////////////////////////////////////////////
47// This low level function returns the value contained in register "index"
48// in the DMA component contained in cluster "cluster_xy"
49///////////////////////////////////////////////////////////////////////////////
50
51#if NB_DMA_CHANNELS > 0
52static
53unsigned int _dma_get_register( unsigned int cluster_xy, // cluster index
54                                unsigned int channel_id, // channel index
55                                unsigned int index )     // register index
56{
57    unsigned int vaddr =
58        SEG_DMA_BASE + 
59        (cluster_xy * PERI_CLUSTER_INCREMENT) +
60        (channel_id * DMA_SPAN) +
61        (index << 2);
62
63    return ioread32( (void*)vaddr );
64}
65#endif
66
67///////////////////////////////////////////////////////////////////////////////
68// This low level function sets a new value in register "index"
69// in the DMA component contained in cluster "cluster_xy"
70///////////////////////////////////////////////////////////////////////////////
71
72#if NB_DMA_CHANNELS > 0
73static
74void _dma_set_register( unsigned int cluster_xy,       // cluster index
75                        unsigned int channel_id,       // channel index
76                        unsigned int index,            // register index
77                        unsigned int value )           // value to be written
78{
79    unsigned int vaddr =
80        SEG_DMA_BASE + 
81        (cluster_xy * PERI_CLUSTER_INCREMENT) +
82        (channel_id * DMA_SPAN) +
83        (index << 2);
84
85    iowrite32( (void*)vaddr, value );
86}
87#endif
88
89////////////////////////////////////////////////
90void _dma_disable_irq( unsigned int cluster_xy,
91                       unsigned int channel_id )
92{
93#if NB_DMA_CHANNELS > 0
94
95    // check DMA channel parameters
96    unsigned int x = cluster_xy >> Y_WIDTH;
97    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
98    if ( (x >= X_SIZE) || (y >= Y_SIZE) || (channel_id >= NB_DMA_CHANNELS) )
99    {
100        _puts("\n[DMA ERROR] in _dma_disable_irq() : illegal DMA channel ");
101        _exit();
102    }
103
104    // disable interrupt for selected channel
105    _dma_set_register(cluster_xy, channel_id, DMA_IRQ_DISABLE, 1);
106
107#endif
108}
109
110/////////////////////////////////////////////////
111void _dma_reset_channel( unsigned int cluster_xy, 
112                         unsigned int channel_id ) 
113{
114#if NB_DMA_CHANNELS > 0
115
116    // check DMA channel parameters
117    unsigned int x = cluster_xy >> Y_WIDTH;
118    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
119    if ( (x >= X_SIZE) || (y >= Y_SIZE) || (channel_id >= NB_DMA_CHANNELS) )
120    {
121        _puts("\n[DMA ERROR] in _dma_reset_channel() : illegal DMA channel ");
122        _exit();
123    }
124
125    // reset selected channel
126    _dma_set_register(cluster_xy, channel_id, DMA_RESET, 0);
127
128#endif
129}
130
131///////////////////////////////////////////////////////
132void _dma_get_status( unsigned int  cluster_xy, 
133                      unsigned int  channel_id,
134                      unsigned int* status ) 
135{
136#if NB_DMA_CHANNELS > 0
137
138    // check DMA channel parameters
139    unsigned int x = cluster_xy >> Y_WIDTH;
140    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
141    if ( (x >= X_SIZE) || (y >= Y_SIZE) || (channel_id >= NB_DMA_CHANNELS) )
142    {
143        _puts("\n[DMA ERROR] in _dma_get_status() : illegal DMA channel ");
144        _exit();
145    }
146
147    // returns selected channel status
148    *status = _dma_get_register(cluster_xy, channel_id, DMA_LEN);
149
150#endif
151}
152
153////////////////////////////////////////////////////////
154void _dma_start_transfer( unsigned int       cluster_xy,  // DMA cluster
155                          unsigned int       channel_id,  // DMA channel
156                          unsigned long long dst_paddr,   // physical address
157                          unsigned long long src_paddr,   // physical address
158                          unsigned int       size )       // bytes
159{
160#if NB_DMA_CHANNELS > 0
161
162    // check DMA channel parameters
163    unsigned int x = cluster_xy >> Y_WIDTH;
164    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
165    if ( (x >= X_SIZE) || (y >= Y_SIZE) || (channel_id >= NB_DMA_CHANNELS) )
166    {
167        _puts("\n[DMA ERROR] in _dma_start_transfer() : illegal DMA channel ");
168        _exit();
169    }
170
171    // selected channel configuration and lauching
172    _dma_set_register(cluster_xy, channel_id, DMA_SRC,
173            (unsigned int)(src_paddr));
174    _dma_set_register(cluster_xy, channel_id, DMA_SRC_EXT,
175            (unsigned int)(src_paddr>>32));
176    _dma_set_register(cluster_xy, channel_id, DMA_DST,
177            (unsigned int)(dst_paddr));
178    _dma_set_register(cluster_xy, channel_id, DMA_DST_EXT,
179            (unsigned int)(dst_paddr>>32));
180    _dma_set_register(cluster_xy, channel_id, DMA_LEN,
181            (unsigned int)size);
182#endif
183}
184
185///////////////////////////////////////////////////////
186void _dma_physical_copy( unsigned int       cluster_xy,  // DMA cluster
187                         unsigned int       channel_id,  // DMA channel
188                         unsigned long long dst_paddr,   // dest physical address
189                         unsigned long long src_paddr,   // src physical address
190                         unsigned int       size )       // bytes
191{
192#if NB_DMA_CHANNELS > 0
193
194    // check buffers alignment constraints
195    if ( (dst_paddr & 0x3)   || (src_paddr & 0x3) || (size & 0x3) )
196    {
197        _puts("\n[DMA ERROR] in _dma_physical_copy() : buffer unaligned\n");
198        _exit();
199    }
200
201#if GIET_DEBUG_DMA_DRIVER
202unsigned int x = cluster_xy >> Y_WIDTH;
203unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
204_puts("\n[DMA DEBUG] enter _dma_physical_copy() for channel[");
205_putd( x );
206_puts(",");
207_putd( y );
208_puts(",");
209_putd( channel_id );
210_puts("] at cycle ");
211_putd( _get_proctime() );
212_puts("\n - src_paddr   = ");
213_putl( src_paddr );
214_puts("\n - dst_paddr   = ");
215_putl( dst_paddr );
216_puts("\n - bytes       = ");
217_putx( size );
218_puts("\n");
219#endif
220
221    // dma channel configuration
222    _dma_disable_irq( cluster_xy, channel_id );
223
224    // dma transfer lauching
225    _dma_start_transfer( cluster_xy, channel_id, dst_paddr, src_paddr, size ); 
226
227    // scan dma channel status
228    unsigned int status;
229    do
230    {
231        _dma_get_status( cluster_xy, channel_id , &status );
232
233#if GIET_DEBUG_DMA_DRIVER
234_puts("\n[DMA DEBUG] _dma_physical_copy() : ... waiting on DMA_STATUS\n");
235#endif
236
237    }
238    while( (status != DMA_SUCCESS) && 
239           (status != DMA_READ_ERROR) &&
240           (status != DMA_WRITE_ERROR) );
241   
242    // analyse status
243    if( status != DMA_SUCCESS )
244    {
245        _puts("\n[DMA ERROR] in _dma_physical_copy() : ERROR_STATUS");
246        _exit();
247    }
248
249    // reset dma channel
250    _dma_reset_channel( cluster_xy , channel_id );
251
252#if GIET_DEBUG_DMA_DRIVER
253_puts("\n[DMA DEBUG] exit _dma_physical_copy() at cycle ");
254_putd( _get_proctime() );
255_puts("\n");
256#endif
257
258#else // NB_DMA_CHANNELS == 0
259
260    _puts("\n[DMA ERROR] in _dma_physical_copy() : NB_DMA_CHANNELS == 0\n");
261    _exit();
262
263#endif
264}
265
266
267////////////////////////////////////////
268void  _dma_copy( unsigned int cluster_xy,    // DMA cluster
269                 unsigned int channel_id,    // DMA channel
270                 unsigned int dst_vaddr,     // dst_vaddr buffer vbase
271                 unsigned int src_vaddr,     // src_vaddr buffer vbase
272                 unsigned int size )         // bytes
273{
274#if NB_DMA_CHANNELS > 0
275
276    // check buffers alignment constraints
277    if ( (dst_vaddr & 0x3)   || (src_vaddr & 0x3) || (size & 0x3) )
278    {
279        _puts("\n[DMA ERROR] in _dma_copy() : buffer unaligned\n");
280        _exit();
281    }
282
283    unsigned long long src_paddr;
284    unsigned long long dst_paddr;
285    unsigned int flags;
286
287#if GIET_DEBUG_DMA_DRIVER
288unsigned int x = cluster_xy >> Y_WIDTH;
289unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
290_puts("\n[DMA DEBUG] enter _dma_copy() for channel[");
291_putd( x );
292_puts(",");
293_putd( y );
294_puts(",");
295_putd( channel_id );
296_puts("] at cycle ");
297_putd( _get_proctime() );
298_puts("\n - src_vaddr   = ");
299_putx( src_vaddr );
300_puts("\n - dst_vaddr   = ");
301_putx( dst_vaddr );
302_puts("\n - bytes       = ");
303_putd( size );
304_puts("\n");
305#endif
306
307    // get src_paddr buffer physical addresse
308    src_paddr = _v2p_translate( src_vaddr , &flags );
309
310    // get dst_paddr buffer physical addresse
311    dst_paddr = _v2p_translate( dst_vaddr , &flags );
312
313#if GIET_DEBUG_DMA_DRIVER
314_puts("\n - src_paddr   = ");
315_putl( src_paddr );
316_puts("\n - dst_paddr   = ");
317_putl( dst_paddr );
318_puts("\n");
319#endif
320
321    // dma channel configuration & lauching
322    _dma_start_transfer(  cluster_xy, channel_id, dst_paddr, src_paddr, size ); 
323
324    // scan dma channel status
325    unsigned int status;
326    do
327    {
328        _dma_get_status( cluster_xy, channel_id , &status );
329
330#if GIET_DEBUG_DMA_DRIVER
331_puts("\n[DMA DEBUG] _dma_physical_copy() : ... waiting on DMA_STATUS\n");
332#endif
333
334    }
335    while( (status != DMA_SUCCESS) && 
336           (status != DMA_READ_ERROR) &&
337           (status != DMA_WRITE_ERROR) );
338   
339    // analyse status
340    if( status != DMA_SUCCESS )
341    {
342        _puts("\n[DMA ERROR] in _dma_copy() : bad DMA_STATUS\n");
343        _exit();
344    }
345    // reset dma channel
346    _dma_reset_channel( cluster_xy, channel_id );
347
348#if GIET_DEBUG_DMA_DRIVER
349_puts("\n[DMA DEBUG] exit _dma_copy() at cycle ");
350_putd( _get_proctime() );
351_puts("\n");
352#endif
353
354#else // NB_DMA_CHANNELS == 0
355
356    _puts("\n[DMA ERROR] in _dma_copy() : NB_DMA_CHANNELS == 0\n");
357    _exit();
358
359#endif
360} // end _dma_copy
361
362
363/////////////////////////////////////
364void _dma_isr( unsigned int irq_type,
365               unsigned int irq_id,
366               unsigned int channel )
367{
368    _puts("\n[DMA ERROR] _dma_isr() not implemented\n");
369    _exit();
370}
371
372
373
374
375// tab-width: 4
376// c-basic-offset: 4
377// c-file-offsets:((innamespace . 0)(inline-open . 0))
378// indent-tabs-mode: nil
379// End:
380// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
381
Note: See TracBrowser for help on using the repository browser.