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

Last change on this file since 619 was 615, checked in by bellefin, 10 years ago

Introduce mmc distributed lock
The locks are distributed in the kernel heaps (one lock in each cluster) and there is a global table in the kernel data segment which contains the addresses of all the locks.
The _mmc_boot_mode variable is defined in boot.c and kernel_init.c and defines which kind of lock is used.
The distributed locks are initialized inside the kernel_init() function.

File size: 8.2 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// Locks protecting MMC components (one per cluster)
42// There are two kinds of lock: the _mmc_lock table contains all the locks and
43// and is stored in the kernel data segment, whereas the _mmc_distributed_lock
44// contains the addresses of locks which are distributed in every cluster (each
45// cluster contains the lock which protects its own mmc_component).
46// The global variable mmc_boot_mode define the type of lock which is used,
47// and must be defined in both kernel_init.c and boot.c files.
48// - the boot code must use a spin_lock because the kernel heap is not set.
49// - the kernel code can use a sqt_lock when the kernel heap is set.
50///////////////////////////////////////////////////////////////////////////////
51
52extern unsigned int  _mmc_boot_mode;
53
54__attribute__((section(".kdata")))
55spin_lock_t           _mmc_lock[X_SIZE][Y_SIZE]  __attribute__((aligned(64)));
56
57__attribute__((section(".kdata")))
58spin_lock_t*          _mmc_distributed_lock[X_SIZE][Y_SIZE];
59
60//////////////////////////////////////////////////////////////////////////////
61// This function initializes the distributed locks stored in the kernel heaps
62//////////////////////////////////////////////////////////////////////////////
63
64void _mmc_init_locks()
65{
66    unsigned int cx;    // cluster X coordinate
67    unsigned int cy;    // cluster Y coordinate
68   
69    for ( cx = 0 ; cx < X_SIZE ; cx++ )
70    {
71        for ( cy = 0 ; cy < Y_SIZE ; cy++ )
72        {
73            _mmc_distributed_lock[cx][cy] = _remote_malloc( sizeof(spin_lock_t), cx, cy );
74            _spin_lock_init( _mmc_distributed_lock[cx][cy] );
75        }
76    }
77}
78
79///////////////////////////////////////////////////////////////////////////////
80// This low level function returns the value contained in register
81// defined by the ("func" / "index") arguments,
82// in the MMC component contained in cluster "cluster_xy"
83///////////////////////////////////////////////////////////////////////////////
84static
85unsigned int _mmc_get_register( unsigned int cluster_xy, // cluster index
86                                unsigned int func,       // function index
87                                unsigned int index )     // register index
88{
89    unsigned int vaddr =
90        SEG_MMC_BASE + 
91        (cluster_xy * PERI_CLUSTER_INCREMENT) +
92        (MMC_REG(func, index) << 2);
93
94    return ioread32( (void*)vaddr );
95}
96
97///////////////////////////////////////////////////////////////////////////////
98// This low level function sets a new value in register
99// defined by the ("func" / "index") arguments,
100// in the MMC component contained in cluster "cluster_xy"
101///////////////////////////////////////////////////////////////////////////////
102static
103void _mmc_set_register( unsigned int cluster_xy,       // cluster index
104                        unsigned int func,             // func index
105                        unsigned int index,            // register index
106                        unsigned int value )           // value to be written
107{
108    unsigned int vaddr =
109        SEG_MMC_BASE + 
110        (cluster_xy * PERI_CLUSTER_INCREMENT) +
111        (MMC_REG(func, index) << 2);
112       
113    iowrite32( (void*)vaddr, value );
114}
115
116/////////////////////////////////////////
117void _mmc_inval( paddr_t      buf_paddr,
118                 unsigned int buf_length )
119{
120    // compute cluster coordinates
121    unsigned int cluster_xy = (unsigned int)(buf_paddr>>(40-X_WIDTH-Y_WIDTH));
122    unsigned int x          = cluster_xy >> Y_WIDTH;
123    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
124
125    // parameters checking
126    if ( (x >= X_SIZE) || (y >= Y_SIZE) )
127    {
128        _puts("\n[GIET ERROR] in _mmc_inval() : illegal cluster coordinates\n");
129        _exit();
130    }
131
132    if ( buf_paddr & 0x3F )
133    {
134        _puts("\n[GIET ERROR] in _mmc_inval() : paddr not 64 bytes aligned\n");
135        _exit();
136    }
137
138    // get the lock protecting exclusive access to MEMC
139    if ( _mmc_boot_mode ) _spin_lock_acquire( &_mmc_lock[x][y] );
140    else                  _spin_lock_acquire( _mmc_distributed_lock[x][y] );
141
142    // write inval arguments
143    _mmc_set_register(cluster_xy, 0, MEMC_ADDR_LO   , (unsigned int)buf_paddr );
144    _mmc_set_register(cluster_xy, 0, MEMC_ADDR_HI   , (unsigned int)(buf_paddr>>32) );
145    _mmc_set_register(cluster_xy, 0, MEMC_BUF_LENGTH, buf_length );
146    _mmc_set_register(cluster_xy, 0, MEMC_CMD_TYPE  , MEMC_CMD_INVAL );
147
148    // release the lock
149    if ( _mmc_boot_mode ) _spin_lock_release( &_mmc_lock[x][y] );
150    else                  _spin_lock_release( _mmc_distributed_lock[x][y] );
151}
152
153///////////////////////////////////////
154void _mmc_sync( paddr_t      buf_paddr,
155                unsigned int buf_length )
156{
157    // compute cluster coordinates
158    unsigned int cluster_xy = (unsigned int)(buf_paddr>>(40-X_WIDTH-Y_WIDTH));
159    unsigned int x          = cluster_xy >> Y_WIDTH;
160    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
161
162    // parameters checking
163    if ( (x >= X_SIZE) || (y >= Y_SIZE) )
164    {
165        _puts( "\n[GIET ERROR] in _mmc_sync() : illegal cluster coordinates");
166        _exit();
167    }
168
169    if ( buf_paddr & 0x3F )
170    {
171        _puts("\n[GIET ERROR] in _mmc_sync() : paddr not 64 bytes aligned\n");
172        _exit();
173    }
174
175    // get the lock protecting exclusive access to MEMC
176    if ( _mmc_boot_mode ) _spin_lock_acquire( &_mmc_lock[x][y] );
177    else                  _spin_lock_acquire( _mmc_distributed_lock[x][y] );
178
179    // write inval arguments
180    _mmc_set_register(cluster_xy, 0, MEMC_ADDR_LO   , (unsigned int)buf_paddr);
181    _mmc_set_register(cluster_xy, 0, MEMC_ADDR_HI   , (unsigned int)(buf_paddr>>32));
182    _mmc_set_register(cluster_xy, 0, MEMC_BUF_LENGTH, buf_length);
183    _mmc_set_register(cluster_xy, 0, MEMC_CMD_TYPE  , MEMC_CMD_SYNC);
184
185    // release the lock
186    if ( _mmc_boot_mode ) _spin_lock_release( &_mmc_lock[x][y] );
187    else                  _spin_lock_release( _mmc_distributed_lock[x][y] );
188}
189
190/////////////////////////////////////////////
191unsigned int _mmc_instrument( unsigned int x, 
192                              unsigned int y,
193                              unsigned int reg )
194{
195    // parameters checking
196    if ( (x >= X_SIZE) || (y >= Y_SIZE) )
197    {
198        _puts( "\n[GIET ERROR] in _mmc_instrument() : illegal cluster coordinates");
199        _exit();
200    }
201
202    unsigned int cluster_xy = (x << Y_WIDTH) + y;
203    return( _mmc_get_register(cluster_xy , 1 , reg) );
204}
205
206///////////////////////////////////////////////////////
207void _mmc_isr( unsigned int irq_type,  // should be HWI
208               unsigned int irq_id,    // index returned by ICU
209               unsigned int channel )  // unused
210{
211    unsigned int gpid       = _get_procid();
212    unsigned int cluster_xy = gpid >> P_WIDTH;
213    unsigned int x          = cluster_xy >> Y_WIDTH;
214    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
215    unsigned int p          = gpid & ((1<<P_WIDTH)-1);
216
217    _puts("[GIET ERROR] MMC IRQ received by processor[");
218    _putd( x );
219    _puts(",");
220    _putd( y );
221    _puts(",");
222    _putd( p );
223    _puts("] but _mmc_isr() not implemented\n");
224}
225
226
227
228// Local Variables:
229// tab-width: 4
230// c-basic-offset: 4
231// c-file-offsets:((innamespace . 0)(inline-open . 0))
232// indent-tabs-mode: nil
233// End:
234// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
235
Note: See TracBrowser for help on using the repository browser.