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

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

Cosmetic

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//
[333]9// SEG_XCU_BASE and PERI_CLUSTER_INCREMENT must be defined in hard_config.h file.
[320]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
[333]47#if !defined( PERI_CLUSTER_INCREMENT )
48# error: You must define PERI_CLUSTER_INCREMENT in the hard_config.h file
[320]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 +
[333]71                                (cluster_xy * PERI_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 +
[333]113                                (cluster_xy * PERI_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 +
[333]165                                (cluster_xy * PERI_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 +
[333]194                                (cluster_xy * PERI_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 +
[333]242                                (cluster_xy * PERI_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 +
[333]267                                (cluster_xy * PERI_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 +
[333]294                                (cluster_xy * PERI_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 +
[333]325                                (cluster_xy * PERI_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.