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

Last change on this file since 323 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
RevLine 
[258]1///////////////////////////////////////////////////////////////////////////////////
2// File     : xcu_driver.c
3// Date     : 23/05/2013
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
[320]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///////////////////////////////////////////////////////////////////////////////////
[258]11
[320]12#include <hard_config.h>
[258]13#include <giet_config.h>
14#include <xcu_driver.h>
[263]15#include <tty_driver.h>
16#include <mapping_info.h>
[258]17#include <utils.h>
18
[263]19#if !defined(X_SIZE)
20# error: You must define X_SIZE in the hard_config.h file
[258]21#endif
22
[263]23#if !defined(Y_SIZE)
24# error: You must define X_SIZE in the hard_config.h file
[258]25#endif
26
[263]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
[258]35#if !defined(NB_PROCS_MAX)
36# error: You must define NB_PROCS_MAX in the hard_config.h file
37#endif
38
[320]39#if !defined( USE_XCU )
40# error: You must define USE_XCU in the hard_config.h file
[258]41#endif
42
[320]43#if !defined( SEG_XCU_BASE )
44# error: You must define SEG_XCU_BASE in the hard_config.h file
45#endif
[295]46
[320]47#if !defined( VSEG_CLUSTER_INCREMENT )
48# error: You must define VSEG_CLUSTER_INCREMENT in the hard_config.h file
49#endif
50
51
[258]52////////////////////////////////////////////////////////////////////////////////
[295]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.
[258]55// All '1' bits are set / all '0' bits are not modified.
56////////////////////////////////////////////////////////////////////////////////
[295]57void _xcu_set_mask( unsigned int cluster_xy, 
58                    unsigned int channel, 
59                    unsigned int value,
60                    unsigned int irq_type ) 
[258]61{
[320]62#if USE_XCU
[258]63    // parameters checking
[263]64    unsigned int x = cluster_xy >> Y_WIDTH;
65    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
[295]66    if (x >= X_SIZE)                                   _exit(); 
67    if (y >= Y_SIZE)                                   _exit(); 
68    if (channel >= (NB_PROCS_MAX * IRQ_PER_PROCESSOR)) _exit(); 
[258]69
[320]70    unsigned int* xcu_address = (unsigned int *) ( SEG_XCU_BASE +
71                                (cluster_xy * VSEG_CLUSTER_INCREMENT) );
[275]72
[263]73    unsigned int func;
[320]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;
[295]77    else
78    { 
79        _printf("[GIET ERROR] _xcu_set_mask() receives illegal IRQ type\n");
80        _exit();
81    }
82
[320]83    xcu_address[XCU_REG(func,channel)] = value;
[295]84
[258]85#else
[320]86    _printf("[GIET ERROR] _xcu_set_mask() should not be used if USE_XCU not set\n");
[295]87    _exit();
[258]88#endif
89}
90
91////////////////////////////////////////////////////////////////////////////////
[295]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.
[258]98////////////////////////////////////////////////////////////////////////////////
[295]99void _xcu_get_index( unsigned int cluster_xy, 
100                     unsigned int channel,   
101                     unsigned int * index, 
102                     unsigned int * irq_type )
[258]103{
[320]104#if USE_XCU
[258]105    // parameters checking
[263]106    unsigned int x = cluster_xy >> Y_WIDTH;
107    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
[295]108    if (x >= X_SIZE)                                   _exit(); 
109    if (y >= Y_SIZE)                                   _exit(); 
110    if (channel >= (NB_PROCS_MAX * IRQ_PER_PROCESSOR)) _exit(); 
[258]111
[320]112    unsigned int* xcu_address = (unsigned int *) ( SEG_XCU_BASE +
113                                (cluster_xy * VSEG_CLUSTER_INCREMENT) );
[258]114
[320]115    unsigned int prio = xcu_address[XCU_REG(XCU_PRIO,channel)];
[258]116    unsigned int pti_ok = (prio & 0x00000001);
117    unsigned int hwi_ok = (prio & 0x00000002);
[295]118    unsigned int wti_ok = (prio & 0x00000004);
[258]119    unsigned int pti_id = (prio & 0x00001F00) >> 8;
120    unsigned int hwi_id = (prio & 0x001F0000) >> 16;
[295]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 
[258]142#else
[320]143    _printf("[GIET ERROR] _xcu_get_index should not be used if USE_XCU is not set\n");
[295]144    _exit();
[258]145#endif
146}
147
148////////////////////////////////////////////////////////////////////////////////
[295]149// This function writes the "wdata" value in the mailbox defined
150// by the "cluster_xy" and "wti_index" arguments.
[258]151////////////////////////////////////////////////////////////////////////////////
[295]152void _xcu_send_wti( unsigned int cluster_xy,
153                    unsigned int wti_index,
154                    unsigned int wdata )
[258]155{ 
[320]156#if USE_XCU
[258]157    // parameters checking
[263]158    unsigned int x = cluster_xy >> Y_WIDTH;
159    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
[295]160    if (x >= X_SIZE)               _exit(); 
161    if (y >= Y_SIZE)               _exit(); 
162    if (wti_index >= 32)           _exit(); 
[258]163
[320]164    unsigned int* xcu_address = (unsigned int *) ( SEG_XCU_BASE +
165                                (cluster_xy * VSEG_CLUSTER_INCREMENT) );
[275]166
[320]167    xcu_address[XCU_REG(XCU_WTI_REG,wti_index)] = wdata;
[295]168
[258]169#else
[320]170    _printf("[GIET ERROR] _xcu_send_ipi should not be used if USE_XCU is not set\n");
[295]171    _exit();
[258]172#endif
173} 
174
175////////////////////////////////////////////////////////////////////////////////
[295]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{
[320]185#if USE_XCU
[295]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 
[320]193    unsigned int* xcu_address = (unsigned int *) ( SEG_XCU_BASE +
194                                (cluster_xy * VSEG_CLUSTER_INCREMENT) );
[295]195
[320]196    *value = xcu_address[XCU_REG(XCU_WTI_REG, wti_index)]; 
[295]197
198#else
[320]199    _printf("[GIET ERROR] in _xcu_get_wti_value() USE_XCU is not set\n");
[295]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{
[320]214#if USE_XCU
[295]215    if (wti_index >= 32)           _exit(); 
216 
[320]217    unsigned int xcu_address = (unsigned int)SEG_XCU_BASE;
218    *address = xcu_address + (XCU_REG(XCU_WTI_REG, wti_index)<<2); 
[295]219
220#else
[320]221    _printf("[GIET ERROR] in _xcu_get_wti_address() USE_XCU is not set\n");
[295]222    _exit();
223#endif
224}
225
226////////////////////////////////////////////////////////////////////////////////
[320]227// This function activates a timer contained in XCU by writing in the
[258]228// proper register the period value.
229////////////////////////////////////////////////////////////////////////////////
[295]230void _xcu_timer_start( unsigned int cluster_xy,
231                       unsigned int pti_index,
232                       unsigned int period )
[258]233{
[320]234#if USE_XCU
[258]235    // parameters checking
[263]236    unsigned int x = cluster_xy >> Y_WIDTH;
237    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
[295]238    if (x >= X_SIZE)             _exit(); 
239    if (y >= Y_SIZE)             _exit(); 
[258]240
[320]241    unsigned int* xcu_address = (unsigned int *) ( SEG_XCU_BASE +
242                                (cluster_xy * VSEG_CLUSTER_INCREMENT) );
[275]243
[320]244    xcu_address[XCU_REG(XCU_PTI_PER, pti_index)] = period;
[295]245
[258]246#else
[320]247    _printf("[GIET ERROR] in _xcu_timer_start() USE_XCU is not set\n");
[295]248    _exit();
[258]249#endif
250}
251
252//////////////////////////////////////////////////////////////////////////////
[320]253// This function desactivates a timer in XCU component
[258]254// by writing in the proper register.
255//////////////////////////////////////////////////////////////////////////////
[295]256void _xcu_timer_stop( unsigned int cluster_xy, 
257                      unsigned int pti_index) 
[258]258{
[320]259#if USE_XCU
[258]260    // parameters checking
[263]261    unsigned int x = cluster_xy >> Y_WIDTH;
262    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
[295]263    if (x >= X_SIZE)             _exit(); 
264    if (y >= Y_SIZE)             _exit(); 
[258]265
[320]266    unsigned int* xcu_address = (unsigned int *) ( SEG_XCU_BASE +
267                                (cluster_xy * VSEG_CLUSTER_INCREMENT) );
[275]268
[320]269    xcu_address[XCU_REG(XCU_PTI_PER, pti_index)] = 0;
[295]270
[258]271#else
[320]272    _printf("[GIET ERROR] in _xcu_timer_stop() USE_XCU is not set\n");
[295]273    _exit();
[258]274#endif
275}
276
277//////////////////////////////////////////////////////////////////////////////
[320]278// This function acknowlegge a timer interrupt in XCU
279// component by reading in the proper XCU register.
[258]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//////////////////////////////////////////////////////////////////////////////
[320]283unsigned int _xcu_timer_reset_irq( unsigned int cluster_xy, 
284                                   unsigned int pti_index ) 
[258]285{
[320]286#if USE_XCU
[258]287    // parameters checking
[263]288    unsigned int x = cluster_xy >> Y_WIDTH;
289    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
[295]290    if (x >= X_SIZE)             _exit(); 
291    if (y >= Y_SIZE)             _exit(); 
[258]292
[320]293    unsigned int* xcu_address = (unsigned int *) ( SEG_XCU_BASE +
294                                (cluster_xy * VSEG_CLUSTER_INCREMENT) );
[258]295
[320]296    // This return value is not used / avoid a compilation warning.
297    return xcu_address[XCU_REG(XCU_PTI_ACK, pti_index)];
[295]298
[258]299#else
[320]300    _printf("[GIET ERROR] in _xcu_timer_reset_irq() USE_XCU is not set\n");
[295]301    _exit();
[320]302    return 0;
[258]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
[295]311// from a register and write this value in the same register).
[258]312// This function is called during a context switch (user or preemptive)
313/////////////////////////////////////////////////////////////////////////////
[295]314void _xcu_timer_reset_cpt( unsigned int cluster_xy, 
315                           unsigned int pti_index ) 
[258]316{
[320]317#if USE_XCU
[258]318    // parameters checking
[263]319    unsigned int x = cluster_xy >> Y_WIDTH;
320    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
[295]321    if (x >= X_SIZE)             _exit(); 
322    if (y >= Y_SIZE)             _exit(); 
[258]323
[320]324    unsigned int* xcu_address = (unsigned int *) ( SEG_XCU_BASE +
325                                (cluster_xy * VSEG_CLUSTER_INCREMENT) );
[258]326
[320]327    unsigned int period = xcu_address[XCU_REG(XCU_PTI_PER, pti_index)];
[258]328
329    // we write 0 first because if the timer is currently running,
330    // the corresponding timer counter is not reset
[320]331    xcu_address[XCU_REG(XCU_PTI_PER, pti_index)] = 0;
332    xcu_address[XCU_REG(XCU_PTI_PER, pti_index)] = period;
[295]333
[258]334#else
[320]335    _printf("[GIET ERROR] in _xcu_timer_reset_cpt() USE_XCU is not set\n");
[295]336    _exit();
[258]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.