source: soft/giet_vm/giet_drivers/xcu_driver.c @ 320

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

All drivers have been modified to use only the information
contained in the hard_config.h file

File size: 12.2 KB
Line 
1///////////////////////////////////////////////////////////////////////////////////
2// File     : xcu_driver.c
3// Date     : 23/05/2013
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7// This peripheral is replicated in aall clusters containing processors.
8//
9// SEG_XCU_BASE and VSEG_CLUSTER_INCREMENT must be defined in hard_config.h file.
10///////////////////////////////////////////////////////////////////////////////////
11
12#include <hard_config.h>
13#include <giet_config.h>
14#include <xcu_driver.h>
15#include <tty_driver.h>
16#include <mapping_info.h>
17#include <utils.h>
18
19#if !defined(X_SIZE)
20# error: You must define X_SIZE in the hard_config.h file
21#endif
22
23#if !defined(Y_SIZE)
24# error: You must define X_SIZE in the hard_config.h file
25#endif
26
27#if !defined(X_WIDTH)
28# error: You must define X_WIDTH in the hard_config.h file
29#endif
30
31#if !defined(Y_WIDTH)
32# error: You must define X_WIDTH in the hard_config.h file
33#endif
34
35#if !defined(NB_PROCS_MAX)
36# error: You must define NB_PROCS_MAX in the hard_config.h file
37#endif
38
39#if !defined( USE_XCU )
40# error: You must define USE_XCU in the hard_config.h file
41#endif
42
43#if !defined( SEG_XCU_BASE )
44# error: You must define SEG_XCU_BASE in the hard_config.h file
45#endif
46
47#if !defined( VSEG_CLUSTER_INCREMENT )
48# error: You must define VSEG_CLUSTER_INCREMENT in the hard_config.h file
49#endif
50
51
52////////////////////////////////////////////////////////////////////////////////
53// This function set the mask register for the IRQ type defined by "irq_type",
54// and for the channel identified by the "cluster_xy" and "channel" arguments.
55// All '1' bits are set / all '0' bits are not modified.
56////////////////////////////////////////////////////////////////////////////////
57void _xcu_set_mask( unsigned int cluster_xy, 
58                    unsigned int channel, 
59                    unsigned int value,
60                    unsigned int irq_type ) 
61{
62#if USE_XCU
63    // parameters checking
64    unsigned int x = cluster_xy >> Y_WIDTH;
65    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
66    if (x >= X_SIZE)                                   _exit(); 
67    if (y >= Y_SIZE)                                   _exit(); 
68    if (channel >= (NB_PROCS_MAX * IRQ_PER_PROCESSOR)) _exit(); 
69
70    unsigned int* xcu_address = (unsigned int *) ( SEG_XCU_BASE +
71                                (cluster_xy * VSEG_CLUSTER_INCREMENT) );
72
73    unsigned int func;
74    if      (irq_type == IRQ_TYPE_PTI) func = XCU_MSK_PTI_ENABLE;
75    else if (irq_type == IRQ_TYPE_WTI) func = XCU_MSK_WTI_ENABLE;
76    else if (irq_type == IRQ_TYPE_HWI) func = XCU_MSK_HWI_ENABLE;
77    else
78    { 
79        _printf("[GIET ERROR] _xcu_set_mask() receives illegal IRQ type\n");
80        _exit();
81    }
82
83    xcu_address[XCU_REG(func,channel)] = value;
84
85#else
86    _printf("[GIET ERROR] _xcu_set_mask() should not be used if USE_XCU not set\n");
87    _exit();
88#endif
89}
90
91////////////////////////////////////////////////////////////////////////////////
92// This function returns the index and the type of the highest priority
93// - active PTI (Timer Interrupt), then
94// - active HWI (Hardware Interrupt), then
95// - active WTI (Software Interrupt)
96// As the hardware can define more than one IRQ per processor, but the GIET
97// use only one, channel = lpid * IRQ_PER_PROCESSOR.
98////////////////////////////////////////////////////////////////////////////////
99void _xcu_get_index( unsigned int cluster_xy, 
100                     unsigned int channel,   
101                     unsigned int * index, 
102                     unsigned int * irq_type )
103{
104#if USE_XCU
105    // parameters checking
106    unsigned int x = cluster_xy >> Y_WIDTH;
107    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
108    if (x >= X_SIZE)                                   _exit(); 
109    if (y >= Y_SIZE)                                   _exit(); 
110    if (channel >= (NB_PROCS_MAX * IRQ_PER_PROCESSOR)) _exit(); 
111
112    unsigned int* xcu_address = (unsigned int *) ( SEG_XCU_BASE +
113                                (cluster_xy * VSEG_CLUSTER_INCREMENT) );
114
115    unsigned int prio = xcu_address[XCU_REG(XCU_PRIO,channel)];
116    unsigned int pti_ok = (prio & 0x00000001);
117    unsigned int hwi_ok = (prio & 0x00000002);
118    unsigned int wti_ok = (prio & 0x00000004);
119    unsigned int pti_id = (prio & 0x00001F00) >> 8;
120    unsigned int hwi_id = (prio & 0x001F0000) >> 16;
121    unsigned int wti_id = (prio & 0x1F000000) >> 24;
122    if      (pti_ok)
123    {
124        *index    = pti_id;
125        *irq_type = IRQ_TYPE_PTI;
126    }
127    else if (hwi_ok)
128    {
129        *index    = hwi_id;
130        *irq_type = IRQ_TYPE_HWI;
131    }
132    else if (wti_ok) 
133    {
134        *index    = wti_id;
135        *irq_type = IRQ_TYPE_WTI;
136    }
137    else 
138    {
139        *index = 32;
140    }
141 
142#else
143    _printf("[GIET ERROR] _xcu_get_index should not be used if USE_XCU is not set\n");
144    _exit();
145#endif
146}
147
148////////////////////////////////////////////////////////////////////////////////
149// This function writes the "wdata" value in the mailbox defined
150// by the "cluster_xy" and "wti_index" arguments.
151////////////////////////////////////////////////////////////////////////////////
152void _xcu_send_wti( unsigned int cluster_xy,
153                    unsigned int wti_index,
154                    unsigned int wdata )
155{ 
156#if USE_XCU
157    // parameters checking
158    unsigned int x = cluster_xy >> Y_WIDTH;
159    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
160    if (x >= X_SIZE)               _exit(); 
161    if (y >= Y_SIZE)               _exit(); 
162    if (wti_index >= 32)           _exit(); 
163
164    unsigned int* xcu_address = (unsigned int *) ( SEG_XCU_BASE +
165                                (cluster_xy * VSEG_CLUSTER_INCREMENT) );
166
167    xcu_address[XCU_REG(XCU_WTI_REG,wti_index)] = wdata;
168
169#else
170    _printf("[GIET ERROR] _xcu_send_ipi should not be used if USE_XCU is not set\n");
171    _exit();
172#endif
173} 
174
175////////////////////////////////////////////////////////////////////////////////
176// This function returns the value contained in a WTI mailbox defined by
177// the cluster_xy and "wti_index" arguments. This value is written in
178// the "value" argument, and the corresponding WTI is acknowledged.
179// returns 0 if success, > 0 if error.
180////////////////////////////////////////////////////////////////////////////////
181void _xcu_get_wti_value( unsigned int   cluster_xy,
182                         unsigned int   wti_index,
183                         unsigned int * value )
184{
185#if USE_XCU
186    // parameters checking
187    unsigned int x = cluster_xy >> Y_WIDTH;
188    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
189    if (x >= X_SIZE)               _exit(); 
190    if (y >= Y_SIZE)               _exit(); 
191    if (wti_index >= 32)           _exit(); 
192 
193    unsigned int* xcu_address = (unsigned int *) ( SEG_XCU_BASE +
194                                (cluster_xy * VSEG_CLUSTER_INCREMENT) );
195
196    *value = xcu_address[XCU_REG(XCU_WTI_REG, wti_index)]; 
197
198#else
199    _printf("[GIET ERROR] in _xcu_get_wti_value() USE_XCU is not set\n");
200    _exit();
201#endif
202}
203
204////////////////////////////////////////////////////////////////////////////////
205// This function returns the address of a WTI mailbox defined by
206// the "wti_index" argument, in the unsigned int "address" argument.
207// It is used by the GIET to configurate the IOPIC component.
208// There is no access to a specific XCU component in a specific cluster.
209// returns 0 if success, > 0 if error.
210////////////////////////////////////////////////////////////////////////////////
211void _xcu_get_wti_address( unsigned int   wti_index,
212                           unsigned int * address )
213{
214#if USE_XCU
215    if (wti_index >= 32)           _exit(); 
216 
217    unsigned int xcu_address = (unsigned int)SEG_XCU_BASE;
218    *address = xcu_address + (XCU_REG(XCU_WTI_REG, wti_index)<<2); 
219
220#else
221    _printf("[GIET ERROR] in _xcu_get_wti_address() USE_XCU is not set\n");
222    _exit();
223#endif
224}
225
226////////////////////////////////////////////////////////////////////////////////
227// This function activates a timer contained in XCU by writing in the
228// proper register the period value.
229////////////////////////////////////////////////////////////////////////////////
230void _xcu_timer_start( unsigned int cluster_xy,
231                       unsigned int pti_index,
232                       unsigned int period )
233{
234#if USE_XCU
235    // parameters checking
236    unsigned int x = cluster_xy >> Y_WIDTH;
237    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
238    if (x >= X_SIZE)             _exit(); 
239    if (y >= Y_SIZE)             _exit(); 
240
241    unsigned int* xcu_address = (unsigned int *) ( SEG_XCU_BASE +
242                                (cluster_xy * VSEG_CLUSTER_INCREMENT) );
243
244    xcu_address[XCU_REG(XCU_PTI_PER, pti_index)] = period;
245
246#else
247    _printf("[GIET ERROR] in _xcu_timer_start() USE_XCU is not set\n");
248    _exit();
249#endif
250}
251
252//////////////////////////////////////////////////////////////////////////////
253// This function desactivates a timer in XCU component
254// by writing in the proper register.
255//////////////////////////////////////////////////////////////////////////////
256void _xcu_timer_stop( unsigned int cluster_xy, 
257                      unsigned int pti_index) 
258{
259#if USE_XCU
260    // parameters checking
261    unsigned int x = cluster_xy >> Y_WIDTH;
262    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
263    if (x >= X_SIZE)             _exit(); 
264    if (y >= Y_SIZE)             _exit(); 
265
266    unsigned int* xcu_address = (unsigned int *) ( SEG_XCU_BASE +
267                                (cluster_xy * VSEG_CLUSTER_INCREMENT) );
268
269    xcu_address[XCU_REG(XCU_PTI_PER, pti_index)] = 0;
270
271#else
272    _printf("[GIET ERROR] in _xcu_timer_stop() USE_XCU is not set\n");
273    _exit();
274#endif
275}
276
277//////////////////////////////////////////////////////////////////////////////
278// This function acknowlegge a timer interrupt in XCU
279// component by reading in the proper XCU register.
280// It can be used by both the isr_switch() for a "system" timer,
281// or by the _isr_timer() for an "user" timer.
282//////////////////////////////////////////////////////////////////////////////
283unsigned int _xcu_timer_reset_irq( unsigned int cluster_xy, 
284                                   unsigned int pti_index ) 
285{
286#if USE_XCU
287    // parameters checking
288    unsigned int x = cluster_xy >> Y_WIDTH;
289    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
290    if (x >= X_SIZE)             _exit(); 
291    if (y >= Y_SIZE)             _exit(); 
292
293    unsigned int* xcu_address = (unsigned int *) ( SEG_XCU_BASE +
294                                (cluster_xy * VSEG_CLUSTER_INCREMENT) );
295
296    // This return value is not used / avoid a compilation warning.
297    return xcu_address[XCU_REG(XCU_PTI_ACK, pti_index)];
298
299#else
300    _printf("[GIET ERROR] in _xcu_timer_reset_irq() USE_XCU is not set\n");
301    _exit();
302    return 0;
303#endif
304}
305
306//////////////////////////////////////////////////////////////////////////////
307// This function resets a timer counter. To do so, we re-write the period
308// in the proper register, what causes the count to restart.
309// The period value is read from the same (TIMER_PERIOD) register,
310// this is why in appearance we do nothing useful (read a value
311// from a register and write this value in the same register).
312// This function is called during a context switch (user or preemptive)
313/////////////////////////////////////////////////////////////////////////////
314void _xcu_timer_reset_cpt( unsigned int cluster_xy, 
315                           unsigned int pti_index ) 
316{
317#if USE_XCU
318    // parameters checking
319    unsigned int x = cluster_xy >> Y_WIDTH;
320    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
321    if (x >= X_SIZE)             _exit(); 
322    if (y >= Y_SIZE)             _exit(); 
323
324    unsigned int* xcu_address = (unsigned int *) ( SEG_XCU_BASE +
325                                (cluster_xy * VSEG_CLUSTER_INCREMENT) );
326
327    unsigned int period = xcu_address[XCU_REG(XCU_PTI_PER, pti_index)];
328
329    // we write 0 first because if the timer is currently running,
330    // the corresponding timer counter is not reset
331    xcu_address[XCU_REG(XCU_PTI_PER, pti_index)] = 0;
332    xcu_address[XCU_REG(XCU_PTI_PER, pti_index)] = period;
333
334#else
335    _printf("[GIET ERROR] in _xcu_timer_reset_cpt() USE_XCU is not set\n");
336    _exit();
337#endif
338}
339
340
341// Local Variables:
342// tab-width: 4
343// c-basic-offset: 4
344// c-file-offsets:((innamespace . 0)(inline-open . 0))
345// indent-tabs-mode: nil
346// End:
347// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
348
Note: See TracBrowser for help on using the repository browser.