source: soft/giet_vm/giet_drivers/mmc_driver.c @ 739

Last change on this file since 739 was 630, checked in by alain, 9 years ago

Update the peripheral drivers using descheduling,
to comply with the modified NORUN bit-vector in task context.

File size: 8.4 KB
RevLine 
[258]1///////////////////////////////////////////////////////////////////////////////////
2// File     : mmc_driver.c
3// Date     : 23/05/2013
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7
[481]8#include <hard_config.h>
[258]9#include <mmc_driver.h>
[456]10#include <tty0.h>
[496]11#include <kernel_locks.h>
[258]12#include <utils.h>
[481]13
[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
26#endif
27
28#if !defined(Y_WIDTH)
29# error: You must define X_WIDTH in the hard_config.h file
30#endif
31
[320]32#if !defined(SEG_MMC_BASE)
33# error: You must define SEG_MMC_BASE in the hard_config.h file
34#endif
35
[333]36#if !defined(PERI_CLUSTER_INCREMENT)
37# error: You must define PERI_CLUSTER_INCREMENT in the hard_config.h file
[320]38#endif
39
[345]40///////////////////////////////////////////////////////////////////////////////
[630]41//     Global variables
42///////////////////////////////////////////////////////////////////////////////
43// Two kinds of locks protecting the MMC components (one per cluster):
44// - the _mmc_lock array contains spin_locks allocated in cluster[0,0].
45//   They must be used by the boot code because the kernel heap is not set.
46// - the _mmc_distributed_locks array contains pointers on distributed
47//   spin_loks allocated in the distributed heap in each cluster.
48//   Each cluster contains the lock protecting its own mmc_component.
49//   They can be used by the kernel code.
[615]50// The global variable mmc_boot_mode define the type of lock which is used,
51// and must be defined in both kernel_init.c and boot.c files.
[496]52///////////////////////////////////////////////////////////////////////////////
53
[630]54__attribute__((section(".kdata")))
55unsigned int  _mmc_boot_mode;
[615]56
[496]57__attribute__((section(".kdata")))
[615]58spin_lock_t           _mmc_lock[X_SIZE][Y_SIZE]  __attribute__((aligned(64)));
[496]59
[615]60__attribute__((section(".kdata")))
61spin_lock_t*          _mmc_distributed_lock[X_SIZE][Y_SIZE];
62
63//////////////////////////////////////////////////////////////////////////////
64// This function initializes the distributed locks stored in the kernel heaps
65//////////////////////////////////////////////////////////////////////////////
66
67void _mmc_init_locks()
68{
[630]69    unsigned int x;    // cluster X coordinate
70    unsigned int y;    // cluster Y coordinate
[615]71   
[630]72    for ( x = 0 ; x < X_SIZE ; x++ )
[615]73    {
[630]74        for ( y = 0 ; y < Y_SIZE ; y++ )
[615]75        {
[630]76            if ( _mmc_boot_mode )
77            {
78                _spin_lock_init( &_mmc_lock[x][y] );
79            }
80            else
81            {
82                _mmc_distributed_lock[x][y] = _remote_malloc( sizeof(spin_lock_t), x, y );
83                _spin_lock_init( _mmc_distributed_lock[x][y] );
84            }
[615]85        }
86    }
87}
88
[496]89///////////////////////////////////////////////////////////////////////////////
[456]90// This low level function returns the value contained in register
91// defined by the ("func" / "index") arguments,
[345]92// in the MMC component contained in cluster "cluster_xy"
93///////////////////////////////////////////////////////////////////////////////
94static
95unsigned int _mmc_get_register( unsigned int cluster_xy, // cluster index
96                                unsigned int func,       // function index
97                                unsigned int index )     // register index
98{
99    unsigned int vaddr =
100        SEG_MMC_BASE + 
101        (cluster_xy * PERI_CLUSTER_INCREMENT) +
102        (MMC_REG(func, index) << 2);
103
104    return ioread32( (void*)vaddr );
105}
106
107///////////////////////////////////////////////////////////////////////////////
[456]108// This low level function sets a new value in register
109// defined by the ("func" / "index") arguments,
[345]110// in the MMC component contained in cluster "cluster_xy"
111///////////////////////////////////////////////////////////////////////////////
112static
113void _mmc_set_register( unsigned int cluster_xy,       // cluster index
114                        unsigned int func,             // func index
115                        unsigned int index,            // register index
116                        unsigned int value )           // value to be written
117{
118    unsigned int vaddr =
119        SEG_MMC_BASE + 
120        (cluster_xy * PERI_CLUSTER_INCREMENT) +
121        (MMC_REG(func, index) << 2);
122       
123    iowrite32( (void*)vaddr, value );
124}
125
[437]126/////////////////////////////////////////
[297]127void _mmc_inval( paddr_t      buf_paddr,
128                 unsigned int buf_length )
[258]129{
[263]130    // compute cluster coordinates
131    unsigned int cluster_xy = (unsigned int)(buf_paddr>>(40-X_WIDTH-Y_WIDTH));
132    unsigned int x          = cluster_xy >> Y_WIDTH;
133    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
[258]134
[263]135    // parameters checking
136    if ( (x >= X_SIZE) || (y >= Y_SIZE) )
137    {
[496]138        _puts("\n[GIET ERROR] in _mmc_inval() : illegal cluster coordinates\n");
[263]139        _exit();
140    }
141
[545]142    if ( buf_paddr & 0x3F )
143    {
144        _puts("\n[GIET ERROR] in _mmc_inval() : paddr not 64 bytes aligned\n");
145        _exit();
146    }
147
[496]148    // get the lock protecting exclusive access to MEMC
[615]149    if ( _mmc_boot_mode ) _spin_lock_acquire( &_mmc_lock[x][y] );
150    else                  _spin_lock_acquire( _mmc_distributed_lock[x][y] );
[258]151
152    // write inval arguments
[496]153    _mmc_set_register(cluster_xy, 0, MEMC_ADDR_LO   , (unsigned int)buf_paddr );
154    _mmc_set_register(cluster_xy, 0, MEMC_ADDR_HI   , (unsigned int)(buf_paddr>>32) );
155    _mmc_set_register(cluster_xy, 0, MEMC_BUF_LENGTH, buf_length );
156    _mmc_set_register(cluster_xy, 0, MEMC_CMD_TYPE  , MEMC_CMD_INVAL );
[258]157
158    // release the lock
[615]159    if ( _mmc_boot_mode ) _spin_lock_release( &_mmc_lock[x][y] );
160    else                  _spin_lock_release( _mmc_distributed_lock[x][y] );
[258]161}
[437]162
163///////////////////////////////////////
[297]164void _mmc_sync( paddr_t      buf_paddr,
165                unsigned int buf_length )
[258]166{
[263]167    // compute cluster coordinates
168    unsigned int cluster_xy = (unsigned int)(buf_paddr>>(40-X_WIDTH-Y_WIDTH));
169    unsigned int x          = cluster_xy >> Y_WIDTH;
170    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
[258]171
[263]172    // parameters checking
173    if ( (x >= X_SIZE) || (y >= Y_SIZE) )
174    {
[496]175        _puts( "\n[GIET ERROR] in _mmc_sync() : illegal cluster coordinates");
[263]176        _exit();
177    }
178
[545]179    if ( buf_paddr & 0x3F )
180    {
181        _puts("\n[GIET ERROR] in _mmc_sync() : paddr not 64 bytes aligned\n");
182        _exit();
183    }
184
[496]185    // get the lock protecting exclusive access to MEMC
[615]186    if ( _mmc_boot_mode ) _spin_lock_acquire( &_mmc_lock[x][y] );
187    else                  _spin_lock_acquire( _mmc_distributed_lock[x][y] );
[258]188
189    // write inval arguments
[345]190    _mmc_set_register(cluster_xy, 0, MEMC_ADDR_LO   , (unsigned int)buf_paddr);
191    _mmc_set_register(cluster_xy, 0, MEMC_ADDR_HI   , (unsigned int)(buf_paddr>>32));
192    _mmc_set_register(cluster_xy, 0, MEMC_BUF_LENGTH, buf_length);
193    _mmc_set_register(cluster_xy, 0, MEMC_CMD_TYPE  , MEMC_CMD_SYNC);
[258]194
[345]195    // release the lock
[615]196    if ( _mmc_boot_mode ) _spin_lock_release( &_mmc_lock[x][y] );
197    else                  _spin_lock_release( _mmc_distributed_lock[x][y] );
[258]198}
199
[496]200/////////////////////////////////////////////
201unsigned int _mmc_instrument( unsigned int x, 
202                              unsigned int y,
203                              unsigned int reg )
204{
205    // parameters checking
206    if ( (x >= X_SIZE) || (y >= Y_SIZE) )
207    {
208        _puts( "\n[GIET ERROR] in _mmc_instrument() : illegal cluster coordinates");
209        _exit();
210    }
211
212    unsigned int cluster_xy = (x << Y_WIDTH) + y;
213    return( _mmc_get_register(cluster_xy , 1 , reg) );
214}
215
[437]216///////////////////////////////////////////////////////
[297]217void _mmc_isr( unsigned int irq_type,  // should be HWI
218               unsigned int irq_id,    // index returned by ICU
219               unsigned int channel )  // unused
220{
[426]221    unsigned int gpid       = _get_procid();
222    unsigned int cluster_xy = gpid >> P_WIDTH;
[298]223    unsigned int x          = cluster_xy >> Y_WIDTH;
224    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
[437]225    unsigned int p          = gpid & ((1<<P_WIDTH)-1);
[298]226
[437]227    _puts("[GIET ERROR] MMC IRQ received by processor[");
228    _putd( x );
229    _puts(",");
230    _putd( y );
231    _puts(",");
232    _putd( p );
233    _puts("] but _mmc_isr() not implemented\n");
[297]234}
235
236
237
[258]238// Local Variables:
239// tab-width: 4
240// c-basic-offset: 4
241// c-file-offsets:((innamespace . 0)(inline-open . 0))
242// indent-tabs-mode: nil
243// End:
244// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
245
Note: See TracBrowser for help on using the repository browser.