source: soft/giet_vm/giet_drivers/dma_driver.c

Last change on this file 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
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>
[456]11#include <tty0.h>
[258]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///////////////////////////////////////////////////////////////////////////////
[496]50
51#if NB_DMA_CHANNELS > 0
[345]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}
[496]65#endif
[345]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///////////////////////////////////////////////////////////////////////////////
[496]71
72#if NB_DMA_CHANNELS > 0
[345]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}
[496]87#endif
[345]88
[437]89////////////////////////////////////////////////
[529]90void _dma_disable_irq( unsigned int cluster_xy,
91                       unsigned int channel_id )
[258]92{
93#if NB_DMA_CHANNELS > 0
[263]94
[529]95    // check DMA channel parameters
[263]96    unsigned int x = cluster_xy >> Y_WIDTH;
97    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
[529]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    }
[258]103
104    // disable interrupt for selected channel
[345]105    _dma_set_register(cluster_xy, channel_id, DMA_IRQ_DISABLE, 1);
[529]106
[258]107#endif
108}
109
[529]110/////////////////////////////////////////////////
111void _dma_reset_channel( unsigned int cluster_xy, 
[258]112                         unsigned int channel_id ) 
113{
114#if NB_DMA_CHANNELS > 0
[263]115
[529]116    // check DMA channel parameters
[263]117    unsigned int x = cluster_xy >> Y_WIDTH;
118    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
[529]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    }
[258]124
125    // reset selected channel
[345]126    _dma_set_register(cluster_xy, channel_id, DMA_RESET, 0);
[529]127
[258]128#endif
129}
130
[529]131///////////////////////////////////////////////////////
132void _dma_get_status( unsigned int  cluster_xy, 
133                      unsigned int  channel_id,
134                      unsigned int* status ) 
[258]135{
136#if NB_DMA_CHANNELS > 0
[263]137
[529]138    // check DMA channel parameters
[263]139    unsigned int x = cluster_xy >> Y_WIDTH;
140    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
[529]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    }
[258]146
[529]147    // returns selected channel status
148    *status = _dma_get_register(cluster_xy, channel_id, DMA_LEN);
149
[258]150#endif
151}
152
[437]153////////////////////////////////////////////////////////
[343]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
[258]159{
160#if NB_DMA_CHANNELS > 0
[263]161
[529]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
[258]171    // selected channel configuration and lauching
[345]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);
[258]182#endif
183}
[343]184
[437]185///////////////////////////////////////////////////////
[343]186void _dma_physical_copy( unsigned int       cluster_xy,  // DMA cluster
187                         unsigned int       channel_id,  // DMA channel
[529]188                         unsigned long long dst_paddr,   // dest physical address
189                         unsigned long long src_paddr,   // src physical address
[343]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    {
[437]197        _puts("\n[DMA ERROR] in _dma_physical_copy() : buffer unaligned\n");
[343]198        _exit();
199    }
200
201#if GIET_DEBUG_DMA_DRIVER
[529]202unsigned int x = cluster_xy >> Y_WIDTH;
203unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
[437]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       = ");
[529]217_putx( size );
[437]218_puts("\n");
[343]219#endif
220
[529]221    // dma channel configuration
222    _dma_disable_irq( cluster_xy, channel_id );
223
224    // dma transfer lauching
[343]225    _dma_start_transfer( cluster_xy, channel_id, dst_paddr, src_paddr, size ); 
226
227    // scan dma channel status
[529]228    unsigned int status;
229    do
[343]230    {
[529]231        _dma_get_status( cluster_xy, channel_id , &status );
[343]232
233#if GIET_DEBUG_DMA_DRIVER
[529]234_puts("\n[DMA DEBUG] _dma_physical_copy() : ... waiting on DMA_STATUS\n");
[343]235#endif
236
237    }
[529]238    while( (status != DMA_SUCCESS) && 
239           (status != DMA_READ_ERROR) &&
240           (status != DMA_WRITE_ERROR) );
[343]241   
242    // analyse status
243    if( status != DMA_SUCCESS )
244    {
[529]245        _puts("\n[DMA ERROR] in _dma_physical_copy() : ERROR_STATUS");
[343]246        _exit();
247    }
[437]248
[343]249    // reset dma channel
[529]250    _dma_reset_channel( cluster_xy , channel_id );
[343]251
252#if GIET_DEBUG_DMA_DRIVER
[437]253_puts("\n[DMA DEBUG] exit _dma_physical_copy() at cycle ");
254_putd( _get_proctime() );
255_puts("\n");
[343]256#endif
257
258#else // NB_DMA_CHANNELS == 0
[437]259
260    _puts("\n[DMA ERROR] in _dma_physical_copy() : NB_DMA_CHANNELS == 0\n");
[343]261    _exit();
[437]262
[343]263#endif
264}
265
[437]266
267////////////////////////////////////////
[343]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
[258]273{
274#if NB_DMA_CHANNELS > 0
275
[343]276    // check buffers alignment constraints
277    if ( (dst_vaddr & 0x3)   || (src_vaddr & 0x3) || (size & 0x3) )
278    {
[437]279        _puts("\n[DMA ERROR] in _dma_copy() : buffer unaligned\n");
[343]280        _exit();
281    }
282
[529]283    unsigned long long src_paddr;
284    unsigned long long dst_paddr;
[258]285    unsigned int flags;
286
287#if GIET_DEBUG_DMA_DRIVER
[529]288unsigned int x = cluster_xy >> Y_WIDTH;
289unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
[437]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");
[258]305#endif
306
[343]307    // get src_paddr buffer physical addresse
[529]308    src_paddr = _v2p_translate( src_vaddr , &flags );
[258]309
[343]310    // get dst_paddr buffer physical addresse
[529]311    dst_paddr = _v2p_translate( dst_vaddr , &flags );
[258]312
313#if GIET_DEBUG_DMA_DRIVER
[437]314_puts("\n - src_paddr   = ");
315_putl( src_paddr );
316_puts("\n - dst_paddr   = ");
317_putl( dst_paddr );
318_puts("\n");
[258]319#endif
320
321    // dma channel configuration & lauching
[343]322    _dma_start_transfer(  cluster_xy, channel_id, dst_paddr, src_paddr, size ); 
[258]323
324    // scan dma channel status
[529]325    unsigned int status;
326    do
[258]327    {
[529]328        _dma_get_status( cluster_xy, channel_id , &status );
[258]329
330#if GIET_DEBUG_DMA_DRIVER
[529]331_puts("\n[DMA DEBUG] _dma_physical_copy() : ... waiting on DMA_STATUS\n");
[258]332#endif
333
334    }
[529]335    while( (status != DMA_SUCCESS) && 
336           (status != DMA_READ_ERROR) &&
337           (status != DMA_WRITE_ERROR) );
[258]338   
339    // analyse status
340    if( status != DMA_SUCCESS )
341    {
[437]342        _puts("\n[DMA ERROR] in _dma_copy() : bad DMA_STATUS\n");
[258]343        _exit();
344    }
345    // reset dma channel
[529]346    _dma_reset_channel( cluster_xy, channel_id );
[258]347
348#if GIET_DEBUG_DMA_DRIVER
[437]349_puts("\n[DMA DEBUG] exit _dma_copy() at cycle ");
350_putd( _get_proctime() );
351_puts("\n");
[258]352#endif
353
354#else // NB_DMA_CHANNELS == 0
[437]355
356    _puts("\n[DMA ERROR] in _dma_copy() : NB_DMA_CHANNELS == 0\n");
[258]357    _exit();
[437]358
[258]359#endif
360} // end _dma_copy
361
[529]362
[437]363/////////////////////////////////////
[320]364void _dma_isr( unsigned int irq_type,
365               unsigned int irq_id,
366               unsigned int channel )
367{
[437]368    _puts("\n[DMA ERROR] _dma_isr() not implemented\n");
[320]369    _exit();
370}
[258]371
372
373
[320]374
[258]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.