source: soft/giet_vm/giet_drivers/dma_driver.c @ 827

Last change on this file since 827 was 529, checked in by alain, 9 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.