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

Last change on this file since 442 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
RevLine 
[258]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>
[320]9#include <hard_config.h>
[258]10#include <dma_driver.h>
11#include <tty_driver.h>
12#include <vmem.h>
[320]13#include <utils.h>
[345]14#include <io.h>
[258]15
[263]16#if !defined(X_SIZE)
17# error: You must define X_SIZE in the hard_config.h file
[258]18#endif
19
[263]20#if !defined(Y_SIZE)
21# error: You must define X_SIZE in the hard_config.h file
[258]22#endif
23
[263]24#if !defined(X_WIDTH)
25# error: You must define X_WIDTH in the hard_config.h file
[258]26#endif
27
[263]28#if !defined(Y_WIDTH)
29# error: You must define X_WIDTH in the hard_config.h file
[258]30#endif
31
[263]32#if !defined(NB_DMA_CHANNELS)
33# error: You must define NB_DMA_CHANNELS in the hard_config.h file
[258]34#endif
35
[320]36#if !defined(SEG_DMA_BASE)
37# error: You must define SEG_DMA_BASE in the hard_config.h file
38#endif
39
[333]40#if !defined(PERI_CLUSTER_INCREMENT)
41# error: You must define PERI_CLUSTER_INCREMENT in the hard_config.h file
[320]42#endif
43
[345]44extern volatile unsigned int _ptabs_vaddr[];
[258]45
[345]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
[437]83////////////////////////////////////////////////
[263]84unsigned int _dma_init( unsigned int cluster_xy,
[258]85                        unsigned int channel_id )
86{
87#if NB_DMA_CHANNELS > 0
[263]88
[258]89    // parameters checking
[263]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; 
[258]94    if (channel_id >= NB_DMA_CHANNELS)  return 1; 
95
96    // disable interrupt for selected channel
[345]97    _dma_set_register(cluster_xy, channel_id, DMA_IRQ_DISABLE, 1);
[258]98    return 0;
99#else
100    return 1;
101#endif
102}
103
[437]104//////////////////////////////////////////////////
[263]105unsigned int _dma_reset( unsigned int cluster_xy, 
[258]106                         unsigned int channel_id ) 
107{
108#if NB_DMA_CHANNELS > 0
[263]109
[258]110    // parameters checking
[263]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; 
[258]115    if (channel_id >= NB_DMA_CHANNELS)  return 1; 
116
117    // reset selected channel
[345]118    _dma_set_register(cluster_xy, channel_id, DMA_RESET, 0);
[258]119    return 0;
120#else
121    return 1;
122#endif
123}
124
[437]125//////////////////////////////////////////////////////
[263]126unsigned int _dma_get_status( unsigned int cluster_xy, 
[258]127                              unsigned int channel_id ) 
128{
129#if NB_DMA_CHANNELS > 0
[263]130
[258]131    // parameters checking
[263]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; 
[258]136    if (channel_id >= NB_DMA_CHANNELS)  return 1;
137
138    // get selected channel status
[345]139    return _dma_get_register(cluster_xy, channel_id, DMA_LEN);
[258]140#else
[267]141    return DMA_IDLE;
[258]142#endif
143}
144
[437]145////////////////////////////////////////////////////////
[343]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
[258]151{
152#if NB_DMA_CHANNELS > 0
[263]153
[258]154    // selected channel configuration and lauching
[345]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);
[343]165
[258]166#endif
167}
[343]168
[437]169///////////////////////////////////////////////////////
[343]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    {
[437]183        _puts("\n[DMA ERROR] in _dma_physical_copy() : illegal DMA channel ");
[343]184        _exit();
185    }
186
187    // check buffers alignment constraints
188    if ( (dst_paddr & 0x3)   || (src_paddr & 0x3) || (size & 0x3) )
189    {
[437]190        _puts("\n[DMA ERROR] in _dma_physical_copy() : buffer unaligned\n");
[343]191        _exit();
192    }
193
194#if GIET_DEBUG_DMA_DRIVER
[437]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");
[343]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
[437]224_puts("\n[DMA DEBUG] _dma_physical_copy() : ... waiting on DMA_STATUS register\n");
[343]225#endif
226
227    }
228   
229    // analyse status
230    if( status != DMA_SUCCESS )
231    {
[437]232        _puts("\n[DMA ERROR] in _dma_physical_copy() : bad DMA_STATUS");
[343]233        _exit();
234    }
[437]235
[343]236    // reset dma channel
237    _dma_reset( cluster_xy, channel_id );
238
239#if GIET_DEBUG_DMA_DRIVER
[437]240_puts("\n[DMA DEBUG] exit _dma_physical_copy() at cycle ");
241_putd( _get_proctime() );
242_puts("\n");
[343]243#endif
244
245#else // NB_DMA_CHANNELS == 0
[437]246
247    _puts("\n[DMA ERROR] in _dma_physical_copy() : NB_DMA_CHANNELS == 0\n");
[343]248    _exit();
[437]249
[343]250#endif
251}
252
[437]253
254////////////////////////////////////////
[343]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
[258]261{
262#if NB_DMA_CHANNELS > 0
263
[343]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    {
[437]269        _puts("\n[DMA ERROR] in _dma_copy() : illegal DMA channel ");
[343]270        _exit();
271    }
[258]272
[343]273    // check buffers alignment constraints
274    if ( (dst_vaddr & 0x3)   || (src_vaddr & 0x3) || (size & 0x3) )
275    {
[437]276        _puts("\n[DMA ERROR] in _dma_copy() : buffer unaligned\n");
[343]277        _exit();
278    }
279
[258]280    unsigned int ko;
281    unsigned int ppn;
282    unsigned int flags;
283
284#if GIET_DEBUG_DMA_DRIVER
[437]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");
[258]300#endif
301
302    // checking alignment constraints
[343]303    if ( (((unsigned int)dst_vaddr) & 0x3) ||
304         (((unsigned int)src_vaddr) & 0x3) ||
[258]305         (size & 0x3) )
306    {
[437]307        _puts("\n[DMA ERROR] in _dma_copy() : buffer unaligned\n");
[258]308        _exit();
309    }
310
[343]311    // get vspace page table pointer
[345]312    unsigned int pt = _ptabs_vaddr[vspace_id];
[258]313
[343]314    // get src_paddr buffer physical addresse
[258]315    ko = _v2p_translate( (page_table_t*)pt,              // page table pointer
[343]316                         src_vaddr>>12,                  // vpn
[258]317                         &ppn,                           // ppn
318                         &flags );                       // flags
319    if ( ko ) 
320    {
[437]321        _puts("\n[DMA ERROR] in _dma_copy() : source buffer unmapped\n");
[258]322        _exit();
323    }
324    unsigned long long src_paddr = (((unsigned long long)ppn) << 12) | 
[343]325                                   (unsigned long long)(src_vaddr & 0x00000FFF);
[258]326
[343]327    // get dst_paddr buffer physical addresse
[258]328    ko = _v2p_translate( (page_table_t*)pt,              // page table pointer
[343]329                         dst_vaddr>>12,                  // vpn
[258]330                         &ppn,                           // ppn
331                         &flags );                       // flags
332    if ( ko ) 
333    {
[437]334        _puts("\n[DMA ERROR] in _dma_copy() : dest buffer unmapped\n");
[258]335        _exit();
336    }
337    unsigned long long dst_paddr = (((unsigned long long)ppn) << 12) | 
[343]338                                   (unsigned long long)(dst_vaddr & 0x00000FFF);
[258]339
340#if GIET_DEBUG_DMA_DRIVER
[437]341_puts("\n - src_paddr   = ");
342_putl( src_paddr );
343_puts("\n - dst_paddr   = ");
344_putl( dst_paddr );
345_puts("\n");
[258]346#endif
347
348    // dma channel configuration & lauching
[343]349    _dma_start_transfer(  cluster_xy, channel_id, dst_paddr, src_paddr, size ); 
[258]350
351    // scan dma channel status
[263]352    unsigned int status = _dma_get_status( cluster_xy, channel_id );
[258]353    while( (status != DMA_SUCCESS) && 
354           (status != DMA_READ_ERROR) &&
355           (status != DMA_WRITE_ERROR) )
356    {
[263]357        status = _dma_get_status( cluster_xy, channel_id );
[258]358
359#if GIET_DEBUG_DMA_DRIVER
[437]360_puts("\n[DMA DEBUG] _dma_copy() : ... waiting on DMA_STATUS register\n");
[258]361#endif
362
363    }
364   
365    // analyse status
366    if( status != DMA_SUCCESS )
367    {
[437]368        _puts("\n[DMA ERROR] in _dma_copy() : bad DMA_STATUS\n");
[258]369        _exit();
370    }
371    // reset dma channel
[263]372    _dma_reset( cluster_xy, channel_id );
[258]373
374#if GIET_DEBUG_DMA_DRIVER
[437]375_puts("\n[DMA DEBUG] exit _dma_copy() at cycle ");
376_putd( _get_proctime() );
377_puts("\n");
[258]378#endif
379
380#else // NB_DMA_CHANNELS == 0
[437]381
382    _puts("\n[DMA ERROR] in _dma_copy() : NB_DMA_CHANNELS == 0\n");
[258]383    _exit();
[437]384
[258]385#endif
386} // end _dma_copy
387
[437]388/////////////////////////////////////
[320]389void _dma_isr( unsigned int irq_type,
390               unsigned int irq_id,
391               unsigned int channel )
392{
[437]393    _puts("\n[DMA ERROR] _dma_isr() not implemented\n");
[320]394    _exit();
395}
[258]396
397
398
[320]399
[258]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.