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

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

Introducing dynamic allocation of peripheral channel(TTY, NIC, TIM, CMA)
Removint the ICU driver : ICU component not supported anymore.
Removing the FBF driver.

File size: 12.1 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 <tty_driver.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///////////////////////////////////////////////////////////////////////////////
50static
51unsigned int _dma_get_register( unsigned int cluster_xy, // cluster index
52                                unsigned int channel_id, // channel index
53                                unsigned int index )     // register index
54{
55    unsigned int vaddr =
56        SEG_DMA_BASE + 
57        (cluster_xy * PERI_CLUSTER_INCREMENT) +
58        (channel_id * DMA_SPAN) +
59        (index << 2);
60
61    return ioread32( (void*)vaddr );
62}
63
64///////////////////////////////////////////////////////////////////////////////
65// This low level function sets a new value in register "index"
66// in the DMA component contained in cluster "cluster_xy"
67///////////////////////////////////////////////////////////////////////////////
68static
69void _dma_set_register( unsigned int cluster_xy,       // cluster index
70                        unsigned int channel_id,       // channel index
71                        unsigned int index,            // register index
72                        unsigned int value )           // value to be written
73{
74    unsigned int vaddr =
75        SEG_DMA_BASE + 
76        (cluster_xy * PERI_CLUSTER_INCREMENT) +
77        (channel_id * DMA_SPAN) +
78        (index << 2);
79
80    iowrite32( (void*)vaddr, value );
81}
82
83////////////////////////////////////////////////
84unsigned int _dma_init( unsigned int cluster_xy,
85                        unsigned int channel_id )
86{
87#if NB_DMA_CHANNELS > 0
88
89    // parameters checking
90    unsigned int x = cluster_xy >> Y_WIDTH;
91    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
92    if (x >= X_SIZE)                    return 1; 
93    if (y >= Y_SIZE)                    return 1; 
94    if (channel_id >= NB_DMA_CHANNELS)  return 1; 
95
96    // disable interrupt for selected channel
97    _dma_set_register(cluster_xy, channel_id, DMA_IRQ_DISABLE, 1);
98    return 0;
99#else
100    return 1;
101#endif
102}
103
104//////////////////////////////////////////////////
105unsigned int _dma_reset( unsigned int cluster_xy, 
106                         unsigned int channel_id ) 
107{
108#if NB_DMA_CHANNELS > 0
109
110    // parameters checking
111    unsigned int x = cluster_xy >> Y_WIDTH;
112    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
113    if (x >= X_SIZE)                    return 1; 
114    if (y >= Y_SIZE)                    return 1; 
115    if (channel_id >= NB_DMA_CHANNELS)  return 1; 
116
117    // reset selected channel
118    _dma_set_register(cluster_xy, channel_id, DMA_RESET, 0);
119    return 0;
120#else
121    return 1;
122#endif
123}
124
125//////////////////////////////////////////////////////
126unsigned int _dma_get_status( unsigned int cluster_xy, 
127                              unsigned int channel_id ) 
128{
129#if NB_DMA_CHANNELS > 0
130
131    // parameters checking
132    unsigned int x = cluster_xy >> Y_WIDTH;
133    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
134    if (x >= X_SIZE)                    return 1; 
135    if (y >= Y_SIZE)                    return 1; 
136    if (channel_id >= NB_DMA_CHANNELS)  return 1;
137
138    // get selected channel status
139    return _dma_get_register(cluster_xy, channel_id, DMA_LEN);
140#else
141    return DMA_IDLE;
142#endif
143}
144
145////////////////////////////////////////////////////////
146void _dma_start_transfer( unsigned int       cluster_xy,  // DMA cluster
147                          unsigned int       channel_id,  // DMA channel
148                          unsigned long long dst_paddr,   // physical address
149                          unsigned long long src_paddr,   // physical address
150                          unsigned int       size )       // bytes
151{
152#if NB_DMA_CHANNELS > 0
153
154    // selected channel configuration and lauching
155    _dma_set_register(cluster_xy, channel_id, DMA_SRC,
156            (unsigned int)(src_paddr));
157    _dma_set_register(cluster_xy, channel_id, DMA_SRC_EXT,
158            (unsigned int)(src_paddr>>32));
159    _dma_set_register(cluster_xy, channel_id, DMA_DST,
160            (unsigned int)(dst_paddr));
161    _dma_set_register(cluster_xy, channel_id, DMA_DST_EXT,
162            (unsigned int)(dst_paddr>>32));
163    _dma_set_register(cluster_xy, channel_id, DMA_LEN,
164            (unsigned int)size);
165
166#endif
167}
168
169///////////////////////////////////////////////////////
170void _dma_physical_copy( unsigned int       cluster_xy,  // DMA cluster
171                         unsigned int       channel_id,  // DMA channel
172                         unsigned long long dst_paddr,   // destination physical address
173                         unsigned long long src_paddr,   // source physical address
174                         unsigned int       size )       // bytes
175{
176#if NB_DMA_CHANNELS > 0
177
178    // check DMA channel parameters
179    unsigned int x = cluster_xy >> Y_WIDTH;
180    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
181    if ( (x >= X_SIZE) || (y >= Y_SIZE) || (channel_id >= NB_DMA_CHANNELS) )
182    {
183        _puts("\n[DMA ERROR] in _dma_physical_copy() : illegal DMA channel ");
184        _exit();
185    }
186
187    // check buffers alignment constraints
188    if ( (dst_paddr & 0x3)   || (src_paddr & 0x3) || (size & 0x3) )
189    {
190        _puts("\n[DMA ERROR] in _dma_physical_copy() : buffer unaligned\n");
191        _exit();
192    }
193
194#if GIET_DEBUG_DMA_DRIVER
195_puts("\n[DMA DEBUG] enter _dma_physical_copy() for channel[");
196_putd( x );
197_puts(",");
198_putd( y );
199_puts(",");
200_putd( channel_id );
201_puts("] at cycle ");
202_putd( _get_proctime() );
203_puts("\n - src_paddr   = ");
204_putl( src_paddr );
205_puts("\n - dst_paddr   = ");
206_putl( dst_paddr );
207_puts("\n - bytes       = ");
208_putd( size );
209_puts("\n");
210#endif
211
212    // dma channel configuration & lauching
213    _dma_start_transfer( cluster_xy, channel_id, dst_paddr, src_paddr, size ); 
214
215    // scan dma channel status
216    unsigned int status = _dma_get_status( cluster_xy, channel_id );
217    while( (status != DMA_SUCCESS) && 
218           (status != DMA_READ_ERROR) &&
219           (status != DMA_WRITE_ERROR) )
220    {
221        status = _dma_get_status( cluster_xy, channel_id );
222
223#if GIET_DEBUG_DMA_DRIVER
224_puts("\n[DMA DEBUG] _dma_physical_copy() : ... waiting on DMA_STATUS register\n");
225#endif
226
227    }
228   
229    // analyse status
230    if( status != DMA_SUCCESS )
231    {
232        _puts("\n[DMA ERROR] in _dma_physical_copy() : bad DMA_STATUS");
233        _exit();
234    }
235
236    // reset dma channel
237    _dma_reset( cluster_xy, channel_id );
238
239#if GIET_DEBUG_DMA_DRIVER
240_puts("\n[DMA DEBUG] exit _dma_physical_copy() at cycle ");
241_putd( _get_proctime() );
242_puts("\n");
243#endif
244
245#else // NB_DMA_CHANNELS == 0
246
247    _puts("\n[DMA ERROR] in _dma_physical_copy() : NB_DMA_CHANNELS == 0\n");
248    _exit();
249
250#endif
251}
252
253
254////////////////////////////////////////
255void  _dma_copy( unsigned int cluster_xy,    // DMA cluster
256                 unsigned int channel_id,    // DMA channel
257                 unsigned int vspace_id,     // vspace index for v2p translation
258                 unsigned int dst_vaddr,     // dst_vaddr buffer vbase
259                 unsigned int src_vaddr,     // src_vaddr buffer vbase
260                 unsigned int size )         // bytes
261{
262#if NB_DMA_CHANNELS > 0
263
264    // check DMA channel parameters
265    unsigned int x = cluster_xy >> Y_WIDTH;
266    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
267    if ( (x >= X_SIZE) || (y >= Y_SIZE) || (channel_id >= NB_DMA_CHANNELS) )
268    {
269        _puts("\n[DMA ERROR] in _dma_copy() : illegal DMA channel ");
270        _exit();
271    }
272
273    // check buffers alignment constraints
274    if ( (dst_vaddr & 0x3)   || (src_vaddr & 0x3) || (size & 0x3) )
275    {
276        _puts("\n[DMA ERROR] in _dma_copy() : buffer unaligned\n");
277        _exit();
278    }
279
280    unsigned int ko;
281    unsigned int ppn;
282    unsigned int flags;
283
284#if GIET_DEBUG_DMA_DRIVER
285_puts("\n[DMA DEBUG] enter _dma_copy() for channel[");
286_putd( x );
287_puts(",");
288_putd( y );
289_puts(",");
290_putd( channel_id );
291_puts("] at cycle ");
292_putd( _get_proctime() );
293_puts("\n - src_vaddr   = ");
294_putx( src_vaddr );
295_puts("\n - dst_vaddr   = ");
296_putx( dst_vaddr );
297_puts("\n - bytes       = ");
298_putd( size );
299_puts("\n");
300#endif
301
302    // checking alignment constraints
303    if ( (((unsigned int)dst_vaddr) & 0x3) ||
304         (((unsigned int)src_vaddr) & 0x3) ||
305         (size & 0x3) )
306    {
307        _puts("\n[DMA ERROR] in _dma_copy() : buffer unaligned\n");
308        _exit();
309    }
310
311    // get vspace page table pointer
312    unsigned int pt = _ptabs_vaddr[vspace_id];
313
314    // get src_paddr buffer physical addresse
315    ko = _v2p_translate( (page_table_t*)pt,              // page table pointer
316                         src_vaddr>>12,                  // vpn
317                         &ppn,                           // ppn
318                         &flags );                       // flags
319    if ( ko ) 
320    {
321        _puts("\n[DMA ERROR] in _dma_copy() : source buffer unmapped\n");
322        _exit();
323    }
324    unsigned long long src_paddr = (((unsigned long long)ppn) << 12) | 
325                                   (unsigned long long)(src_vaddr & 0x00000FFF);
326
327    // get dst_paddr buffer physical addresse
328    ko = _v2p_translate( (page_table_t*)pt,              // page table pointer
329                         dst_vaddr>>12,                  // vpn
330                         &ppn,                           // ppn
331                         &flags );                       // flags
332    if ( ko ) 
333    {
334        _puts("\n[DMA ERROR] in _dma_copy() : dest buffer unmapped\n");
335        _exit();
336    }
337    unsigned long long dst_paddr = (((unsigned long long)ppn) << 12) | 
338                                   (unsigned long long)(dst_vaddr & 0x00000FFF);
339
340#if GIET_DEBUG_DMA_DRIVER
341_puts("\n - src_paddr   = ");
342_putl( src_paddr );
343_puts("\n - dst_paddr   = ");
344_putl( dst_paddr );
345_puts("\n");
346#endif
347
348    // dma channel configuration & lauching
349    _dma_start_transfer(  cluster_xy, channel_id, dst_paddr, src_paddr, size ); 
350
351    // scan dma channel status
352    unsigned int status = _dma_get_status( cluster_xy, channel_id );
353    while( (status != DMA_SUCCESS) && 
354           (status != DMA_READ_ERROR) &&
355           (status != DMA_WRITE_ERROR) )
356    {
357        status = _dma_get_status( cluster_xy, channel_id );
358
359#if GIET_DEBUG_DMA_DRIVER
360_puts("\n[DMA DEBUG] _dma_copy() : ... waiting on DMA_STATUS register\n");
361#endif
362
363    }
364   
365    // analyse status
366    if( status != DMA_SUCCESS )
367    {
368        _puts("\n[DMA ERROR] in _dma_copy() : bad DMA_STATUS\n");
369        _exit();
370    }
371    // reset dma channel
372    _dma_reset( cluster_xy, channel_id );
373
374#if GIET_DEBUG_DMA_DRIVER
375_puts("\n[DMA DEBUG] exit _dma_copy() at cycle ");
376_putd( _get_proctime() );
377_puts("\n");
378#endif
379
380#else // NB_DMA_CHANNELS == 0
381
382    _puts("\n[DMA ERROR] in _dma_copy() : NB_DMA_CHANNELS == 0\n");
383    _exit();
384
385#endif
386} // end _dma_copy
387
388/////////////////////////////////////
389void _dma_isr( unsigned int irq_type,
390               unsigned int irq_id,
391               unsigned int channel )
392{
393    _puts("\n[DMA ERROR] _dma_isr() not implemented\n");
394    _exit();
395}
396
397
398
399
400// tab-width: 4
401// c-basic-offset: 4
402// c-file-offsets:((innamespace . 0)(inline-open . 0))
403// indent-tabs-mode: nil
404// End:
405// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
406
Note: See TracBrowser for help on using the repository browser.