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

Last change on this file since 426 was 426, checked in by alain, 10 years ago

Introducing fixed format (X_WIDTH / Y_WIDTH / P_WIDTH ) for processor index.

File size: 6.9 KB
Line 
1///////////////////////////////////////////////////////////////////////////////////
2// File     : mmc_driver.c
3// Date     : 23/05/2013
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7// The mmc_driver.c and mmc_driver.h files are part ot the GIET-VM nano-kernel.
8// This driver supports the vci_mem_cache component used in the TSAR architecture.
9//
10// This component is replicated in all clusters, and can be accessed through
11// a configuration interface as a set of uncached, memory mapped registers.
12//
13// The (virtual) base address of the associated segment is:
14//       SEG_MMC_BASE + cluster_id * PERI_CLUSTER_INCREMENT
15//
16// SEG_MMC_BASE and PERI_CLUSTER_INCREMENT must be defined in hard_config.h.
17////////////////////////////////////////////////////////////////////////////////
18
19#include <giet_config.h>
20#include <mmc_driver.h>
21#include <tty_driver.h>
22#include <utils.h>
23#include <io.h>
24
25#if !defined(X_SIZE)
26# error: You must define X_SIZE in the hard_config.h file
27#endif
28
29#if !defined(Y_SIZE)
30# error: You must define X_SIZE in the hard_config.h file
31#endif
32
33#if !defined(X_WIDTH)
34# error: You must define X_WIDTH in the hard_config.h file
35#endif
36
37#if !defined(Y_WIDTH)
38# error: You must define X_WIDTH in the hard_config.h file
39#endif
40
41#if !defined(SEG_MMC_BASE)
42# error: You must define SEG_MMC_BASE in the hard_config.h file
43#endif
44
45#if !defined(PERI_CLUSTER_INCREMENT)
46# error: You must define PERI_CLUSTER_INCREMENT in the hard_config.h file
47#endif
48
49///////////////////////////////////////////////////////////////////////////////
50// This low level function returns the value contained in register "index"
51// in the MMC component contained in cluster "cluster_xy"
52///////////////////////////////////////////////////////////////////////////////
53static
54unsigned int _mmc_get_register( unsigned int cluster_xy, // cluster index
55                                unsigned int func,       // function index
56                                unsigned int index )     // register index
57{
58    unsigned int vaddr =
59        SEG_MMC_BASE + 
60        (cluster_xy * PERI_CLUSTER_INCREMENT) +
61        (MMC_REG(func, index) << 2);
62
63    return ioread32( (void*)vaddr );
64}
65
66///////////////////////////////////////////////////////////////////////////////
67// This low level function sets a new value in register "index"
68// in the MMC component contained in cluster "cluster_xy"
69///////////////////////////////////////////////////////////////////////////////
70static
71void _mmc_set_register( unsigned int cluster_xy,       // cluster index
72                        unsigned int func,             // func index
73                        unsigned int index,            // register index
74                        unsigned int value )           // value to be written
75{
76    unsigned int vaddr =
77        SEG_MMC_BASE + 
78        (cluster_xy * PERI_CLUSTER_INCREMENT) +
79        (MMC_REG(func, index) << 2);
80       
81    iowrite32( (void*)vaddr, value );
82}
83
84///////////////////////////////////////////////////////////////////////////////////
85// This function invalidates all cache lines covering a memory buffer defined
86// by the physical base address, and the length.
87// The buffer address MSB are used to compute the cluster index.
88///////////////////////////////////////////////////////////////////////////////////
89void _mmc_inval( paddr_t      buf_paddr,
90                 unsigned int buf_length )
91{
92    // compute cluster coordinates
93    unsigned int cluster_xy = (unsigned int)(buf_paddr>>(40-X_WIDTH-Y_WIDTH));
94    unsigned int x          = cluster_xy >> Y_WIDTH;
95    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
96
97    // parameters checking
98    if ( (x >= X_SIZE) || (y >= Y_SIZE) )
99    {
100        _printf("\n[GIET ERROR] in _memc_inval() : illegal cluster_xy for paddr %l\n",
101                 buf_paddr );
102        _exit();
103    }
104
105    // get the hard lock protecting exclusive access to MEMC
106    while ( _mmc_get_register(cluster_xy, 0, MEMC_LOCK) );
107
108    // write inval arguments
109    _mmc_set_register(cluster_xy, 0, MEMC_ADDR_LO   , (unsigned int)buf_paddr);
110    _mmc_set_register(cluster_xy, 0, MEMC_ADDR_HI   , (unsigned int)(buf_paddr>>32));
111    _mmc_set_register(cluster_xy, 0, MEMC_BUF_LENGTH, buf_length);
112    _mmc_set_register(cluster_xy, 0, MEMC_CMD_TYPE  , MEMC_CMD_INVAL);
113
114    // release the lock
115    _mmc_set_register(cluster_xy, 0, MEMC_LOCK, 0);
116}
117///////////////////////////////////////////////////////////////////////////////////
118// This function copies to external RAM all cache lines covering a memory buffer
119// defined by the physical base address, and the length, if they are dirty.
120// The buffer address MSB are used to compute the cluster index.
121///////////////////////////////////////////////////////////////////////////////////
122void _mmc_sync( paddr_t      buf_paddr,
123                unsigned int buf_length )
124{
125    // compute cluster coordinates
126    unsigned int cluster_xy = (unsigned int)(buf_paddr>>(40-X_WIDTH-Y_WIDTH));
127    unsigned int x          = cluster_xy >> Y_WIDTH;
128    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
129
130    // parameters checking
131    if ( (x >= X_SIZE) || (y >= Y_SIZE) )
132    {
133        _printf( "\n[GIET ERROR] in _memc_sync() : illegal cluster_xy for paddr %l\n",
134                 buf_paddr );
135        _exit();
136    }
137
138    // get the hard lock protecting exclusive access to MEMC
139    while ( _mmc_get_register(cluster_xy, 0, MEMC_LOCK) );
140
141    // write inval arguments
142    _mmc_set_register(cluster_xy, 0, MEMC_ADDR_LO   , (unsigned int)buf_paddr);
143    _mmc_set_register(cluster_xy, 0, MEMC_ADDR_HI   , (unsigned int)(buf_paddr>>32));
144    _mmc_set_register(cluster_xy, 0, MEMC_BUF_LENGTH, buf_length);
145    _mmc_set_register(cluster_xy, 0, MEMC_CMD_TYPE  , MEMC_CMD_SYNC);
146
147    // release the lock
148    _mmc_set_register(cluster_xy, 0, MEMC_LOCK, 0);
149}
150
151//////////////////////////////////////////////////////////////////////////////////
152// This ISR access the vci_mem_cache component to get the faulty physical
153// address and the associated SRCID. It must also acknowledge the IRQ.
154//
155// TODO implement...
156//////////////////////////////////////////////////////////////////////////////////
157void _mmc_isr( unsigned int irq_type,  // should be HWI
158               unsigned int irq_id,    // index returned by ICU
159               unsigned int channel )  // unused
160{
161    unsigned int gpid       = _get_procid();
162    unsigned int cluster_xy = gpid >> P_WIDTH;
163    unsigned int x          = cluster_xy >> Y_WIDTH;
164    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
165    unsigned int lpid       = gpid & ((1<<P_WIDTH)-1);
166
167    _printf("[GIET ERROR] MMC IRQ received by processor[%d,%d,%d]"
168            " but _mmc_isr() not implemented...\n", x, y, lpid );
169}
170
171
172
173// Local Variables:
174// tab-width: 4
175// c-basic-offset: 4
176// c-file-offsets:((innamespace . 0)(inline-open . 0))
177// indent-tabs-mode: nil
178// End:
179// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
180
Note: See TracBrowser for help on using the repository browser.