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

Last change on this file since 766 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
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.