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

Last change on this file since 315 was 295, checked in by alain, 11 years ago

Introducing a major release, to suppoort the tsar_generic_leti platform
and the various (external or internal) peripherals configurations.
The map.xml format has been modified, in order to support the new
vci_iopic componentand a new policy for peripherals initialisation.
The IRQs are nom described in the XICU and IOPIC components
(and not anymore in the processors).
To enforce this major change, the map.xml file signature changed:
The signature value must be: 0xDACE2014

This new release has been tested on the tsar_generic_leti platform
for the following mappings:

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