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

Last change on this file since 295 was 295, checked in by alain, 10 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
RevLine 
[258]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>
[263]10#include <tty_driver.h>
11#include <mapping_info.h>
[258]12#include <utils.h>
13
[263]14#if !defined(X_SIZE)
15# error: You must define X_SIZE in the hard_config.h file
[258]16#endif
17
[263]18#if !defined(Y_SIZE)
19# error: You must define X_SIZE in the hard_config.h file
[258]20#endif
21
[263]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
[258]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
[295]38
[258]39////////////////////////////////////////////////////////////////////////////////
[295]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.
[258]42// All '1' bits are set / all '0' bits are not modified.
43////////////////////////////////////////////////////////////////////////////////
[295]44void _xcu_set_mask( unsigned int cluster_xy, 
45                    unsigned int channel, 
46                    unsigned int value,
47                    unsigned int irq_type ) 
[258]48{
[295]49#if USE_XICU
[258]50    // parameters checking
[263]51    unsigned int x = cluster_xy >> Y_WIDTH;
52    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
[295]53    if (x >= X_SIZE)                                   _exit(); 
54    if (y >= Y_SIZE)                                   _exit(); 
55    if (channel >= (NB_PROCS_MAX * IRQ_PER_PROCESSOR)) _exit(); 
[258]56
[275]57    volatile unsigned int* xcu_address =
58        (unsigned int *) ((unsigned int)&seg_xcu_base + 
59        (cluster_xy * (unsigned int)&vseg_cluster_increment));
60
[263]61    unsigned int func;
62    if      (irq_type == IRQ_TYPE_PTI) func = XICU_MSK_PTI_ENABLE;
[295]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
[258]73#else
[295]74    _printf("[GIET ERROR] _xcu_set_mask() should not be used if USE_XICU not set\n");
75    _exit();
[258]76#endif
77}
78
79////////////////////////////////////////////////////////////////////////////////
[295]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.
[258]86////////////////////////////////////////////////////////////////////////////////
[295]87void _xcu_get_index( unsigned int cluster_xy, 
88                     unsigned int channel,   
89                     unsigned int * index, 
90                     unsigned int * irq_type )
[258]91{
[295]92#if USE_XICU
[258]93    // parameters checking
[263]94    unsigned int x = cluster_xy >> Y_WIDTH;
95    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
[295]96    if (x >= X_SIZE)                                   _exit(); 
97    if (y >= Y_SIZE)                                   _exit(); 
98    if (channel >= (NB_PROCS_MAX * IRQ_PER_PROCESSOR)) _exit(); 
[258]99
[275]100    volatile unsigned int* xcu_address =
101        (unsigned int *) ((unsigned int)&seg_xcu_base + 
102        (cluster_xy * (unsigned int)&vseg_cluster_increment));
[258]103
[295]104    unsigned int prio = xcu_address[XICU_REG(XICU_PRIO,channel)];
[258]105    unsigned int pti_ok = (prio & 0x00000001);
106    unsigned int hwi_ok = (prio & 0x00000002);
[295]107    unsigned int wti_ok = (prio & 0x00000004);
[258]108    unsigned int pti_id = (prio & 0x00001F00) >> 8;
109    unsigned int hwi_id = (prio & 0x001F0000) >> 16;
[295]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 
[258]131#else
[295]132    _printf("[GIET ERROR] _xcu_get_index should not be used if USE_XICU is not set\n");
133    _exit();
[258]134#endif
135}
136
137////////////////////////////////////////////////////////////////////////////////
[295]138// This function writes the "wdata" value in the mailbox defined
139// by the "cluster_xy" and "wti_index" arguments.
[258]140////////////////////////////////////////////////////////////////////////////////
[295]141void _xcu_send_wti( unsigned int cluster_xy,
142                    unsigned int wti_index,
143                    unsigned int wdata )
[258]144{ 
[295]145#if USE_XICU
[258]146    // parameters checking
[263]147    unsigned int x = cluster_xy >> Y_WIDTH;
148    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
[295]149    if (x >= X_SIZE)               _exit(); 
150    if (y >= Y_SIZE)               _exit(); 
151    if (wti_index >= 32)           _exit(); 
[258]152
[275]153    volatile unsigned int* xcu_address =
154        (unsigned int *) ((unsigned int)&seg_xcu_base + 
155        (cluster_xy * (unsigned int)&vseg_cluster_increment));
156
[281]157    xcu_address[XICU_REG(XICU_WTI_REG,wti_index)] = wdata;
[295]158
[258]159#else
[295]160    _printf("[GIET ERROR] _xcu_send_ipi should not be used if USE_XICU is not set\n");
161    _exit();
[258]162#endif
163} 
164
165////////////////////////////////////////////////////////////////////////////////
[295]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////////////////////////////////////////////////////////////////////////////////
[258]218// This function activates a timer contained in XICU by writing in the
219// proper register the period value.
220////////////////////////////////////////////////////////////////////////////////
[295]221void _xcu_timer_start( unsigned int cluster_xy,
222                       unsigned int pti_index,
223                       unsigned int period )
[258]224{
[295]225#if USE_XICU
[258]226    // parameters checking
[263]227    unsigned int x = cluster_xy >> Y_WIDTH;
228    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
[295]229    if (x >= X_SIZE)             _exit(); 
230    if (y >= Y_SIZE)             _exit(); 
[258]231
[275]232    volatile unsigned int* xcu_address =
233        (unsigned int *) ((unsigned int)&seg_xcu_base + 
234        (cluster_xy * (unsigned int)&vseg_cluster_increment));
235
[271]236    xcu_address[XICU_REG(XICU_PTI_PER, pti_index)] = period;
[295]237
[258]238#else
[295]239    _printf("[GIET ERROR] in _xcu_timer_start() USE_XICU is not set\n");
240    _exit();
[258]241#endif
242}
243
244//////////////////////////////////////////////////////////////////////////////
245// This function desactivates a timer in XICU component
246// by writing in the proper register.
247//////////////////////////////////////////////////////////////////////////////
[295]248void _xcu_timer_stop( unsigned int cluster_xy, 
249                      unsigned int pti_index) 
[258]250{
[295]251#if USE_XICU
[258]252    // parameters checking
[263]253    unsigned int x = cluster_xy >> Y_WIDTH;
254    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
[295]255    if (x >= X_SIZE)             _exit(); 
256    if (y >= Y_SIZE)             _exit(); 
[258]257
[275]258    volatile unsigned int * xcu_address =
259        (unsigned int *) ((unsigned int)&seg_xcu_base + 
260        (cluster_xy * (unsigned int)&vseg_cluster_increment));
261
[271]262    xcu_address[XICU_REG(XICU_PTI_PER, pti_index)] = 0;
[295]263
[258]264#else
[295]265    _printf("[GIET ERROR] in _xcu_timer_stop() USE_XICU is not set\n");
266    _exit();
[258]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//////////////////////////////////////////////////////////////////////////////
[295]276void _xcu_timer_reset_irq( unsigned int cluster_xy, 
277                           unsigned int pti_index ) 
[258]278{
[295]279#if USE_XICU
[258]280    // parameters checking
[263]281    unsigned int x = cluster_xy >> Y_WIDTH;
282    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
[295]283    if (x >= X_SIZE)             _exit(); 
284    if (y >= Y_SIZE)             _exit(); 
[258]285
[271]286    volatile unsigned int * xcu_address =
287        (unsigned int *) ((unsigned int)&seg_xcu_base +
288        (cluster_xy * (unsigned int)&vseg_cluster_increment));
[258]289
[271]290    xcu_address[XICU_REG(XICU_PTI_ACK, pti_index)];
[295]291
[258]292#else
[295]293    _printf("[GIET ERROR] in _xcu_timer_reset_irq() USE_XICU is not set\n");
294    _exit();
[258]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
[295]303// from a register and write this value in the same register).
[258]304// This function is called during a context switch (user or preemptive)
305/////////////////////////////////////////////////////////////////////////////
[295]306void _xcu_timer_reset_cpt( unsigned int cluster_xy, 
307                           unsigned int pti_index ) 
[258]308{
[295]309#if USE_XICU
[258]310    // parameters checking
[263]311    unsigned int x = cluster_xy >> Y_WIDTH;
312    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
[295]313    if (x >= X_SIZE)             _exit(); 
314    if (y >= Y_SIZE)             _exit(); 
[258]315
[275]316    volatile unsigned int * xcu_address =
317        (unsigned int *) ((unsigned int) &seg_xcu_base + 
318        (cluster_xy * (unsigned int)&vseg_cluster_increment));
[258]319
[271]320    unsigned int period = xcu_address[XICU_REG(XICU_PTI_PER, pti_index)];
[258]321
322    // we write 0 first because if the timer is currently running,
323    // the corresponding timer counter is not reset
[271]324    xcu_address[XICU_REG(XICU_PTI_PER, pti_index)] = 0;
325    xcu_address[XICU_REG(XICU_PTI_PER, pti_index)] = period;
[295]326
[258]327#else
[295]328    _printf("[GIET ERROR] in _xcu_timer_reset_cpt() USE_XICU is not set\n");
329    _exit();
[258]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.