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

Last change on this file since 399 was 395, checked in by alain, 10 years ago

Cosmetic.

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