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
Line 
1///////////////////////////////////////////////////////////////////////////////////
2// File     : mmc_driver.c
3// Date     : 23/05/2013
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7
8#include <hard_config.h>
9#include <mmc_driver.h>
10#include <tty0.h>
11#include <kernel_locks.h>
12#include <utils.h>
13
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(SEG_MMC_BASE)
33# error: You must define SEG_MMC_BASE in the hard_config.h file
34#endif
35
36#if !defined(PERI_CLUSTER_INCREMENT)
37# error: You must define PERI_CLUSTER_INCREMENT in the hard_config.h file
38#endif
39
40///////////////////////////////////////////////////////////////////////////////
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.
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.
52///////////////////////////////////////////////////////////////////////////////
53
54__attribute__((section(".kdata")))
55unsigned int  _mmc_boot_mode;
56
57__attribute__((section(".kdata")))
58spin_lock_t           _mmc_lock[X_SIZE][Y_SIZE]  __attribute__((aligned(64)));
59
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{
69    unsigned int x;    // cluster X coordinate
70    unsigned int y;    // cluster Y coordinate
71   
72    for ( x = 0 ; x < X_SIZE ; x++ )
73    {
74        for ( y = 0 ; y < Y_SIZE ; y++ )
75        {
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            }
85        }
86    }
87}
88
89///////////////////////////////////////////////////////////////////////////////
90// This low level function returns the value contained in register
91// defined by the ("func" / "index") arguments,
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///////////////////////////////////////////////////////////////////////////////
108// This low level function sets a new value in register
109// defined by the ("func" / "index") arguments,
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
126/////////////////////////////////////////
127void _mmc_inval( paddr_t      buf_paddr,
128                 unsigned int buf_length )
129{
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);
134
135    // parameters checking
136    if ( (x >= X_SIZE) || (y >= Y_SIZE) )
137    {
138        _puts("\n[GIET ERROR] in _mmc_inval() : illegal cluster coordinates\n");
139        _exit();
140    }
141
142    if ( buf_paddr & 0x3F )
143    {
144        _puts("\n[GIET ERROR] in _mmc_inval() : paddr not 64 bytes aligned\n");
145        _exit();
146    }
147
148    // get the lock protecting exclusive access to MEMC
149    if ( _mmc_boot_mode ) _spin_lock_acquire( &_mmc_lock[x][y] );
150    else                  _spin_lock_acquire( _mmc_distributed_lock[x][y] );
151
152    // write inval arguments
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 );
157
158    // release the lock
159    if ( _mmc_boot_mode ) _spin_lock_release( &_mmc_lock[x][y] );
160    else                  _spin_lock_release( _mmc_distributed_lock[x][y] );
161}
162
163///////////////////////////////////////
164void _mmc_sync( paddr_t      buf_paddr,
165                unsigned int buf_length )
166{
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);
171
172    // parameters checking
173    if ( (x >= X_SIZE) || (y >= Y_SIZE) )
174    {
175        _puts( "\n[GIET ERROR] in _mmc_sync() : illegal cluster coordinates");
176        _exit();
177    }
178
179    if ( buf_paddr & 0x3F )
180    {
181        _puts("\n[GIET ERROR] in _mmc_sync() : paddr not 64 bytes aligned\n");
182        _exit();
183    }
184
185    // get the lock protecting exclusive access to MEMC
186    if ( _mmc_boot_mode ) _spin_lock_acquire( &_mmc_lock[x][y] );
187    else                  _spin_lock_acquire( _mmc_distributed_lock[x][y] );
188
189    // write inval arguments
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);
194
195    // release the lock
196    if ( _mmc_boot_mode ) _spin_lock_release( &_mmc_lock[x][y] );
197    else                  _spin_lock_release( _mmc_distributed_lock[x][y] );
198}
199
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
216///////////////////////////////////////////////////////
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{
221    unsigned int gpid       = _get_procid();
222    unsigned int cluster_xy = gpid >> P_WIDTH;
223    unsigned int x          = cluster_xy >> Y_WIDTH;
224    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
225    unsigned int p          = gpid & ((1<<P_WIDTH)-1);
226
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");
234}
235
236
237
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.