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

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