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

Last change on this file since 337 was 333, checked in by alain, 11 years ago

Cosmetic

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 PERI_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( PERI_CLUSTER_INCREMENT )
48# error: You must define PERI_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 * PERI_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 * PERI_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 * PERI_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 * PERI_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 * PERI_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 * PERI_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 * PERI_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 * PERI_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.