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

Last change on this file since 615 was 615, checked in by bellefin, 9 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.