source: trunk/kernel/devices/dev_icu.h @ 79

Last change on this file since 79 was 14, checked in by alain, 7 years ago

Bugs fix.

File size: 14.5 KB
RevLine 
[1]1/*
2 * dev_icu.h - ICU (Interrupt Controler Unit) generic device API.
3 *
4 * Authors   Alain Greiner  (2016)
5 *
6 * Copyright (c) UPMC Sorbonne Universites
7 *
8 * This file is part of ALMOS-MKH.
9 *
10 * ALMOS-MKH is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 2.0 of the License.
13 *
14 * ALMOS-MKH is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24#ifndef _DEV_ICU_H_
25#define _DEV_ICU_H_
26
[14]27#include <kernel_config.h>
[1]28#include <hal_types.h>
29#include <spinlock.h>
30
31/*****************************************************************************************
32 *     Generic Internal Interrupt Controler definition
33 *
34 * The ICU (Interrupt Controller Unit) device describes an internal peripheral,
35 * acting in all clusters containing cores. He is in charge of concentrating all IRQs
36 * (interrupt requests) generated by peripherals to signal the completion of an I/O
[3]37 * operation. Each IRQ is routed to the core that started the I/O operation.
[1]38 * The ICU device must also help the kernel to select the ISR (Interrupt Service Routine)
39 * that must be executed by the target core.
40 *
[3]41 * This component can be implemented as a dedicated hardware component distributed
[1]42 * in all clusters, or emulated in software, as long as it implements the specified API.
43 * For the TSAR architecture, this generic ICU device is implemented by the two hardware
44 * components soclib_xicu and and soclib_iopic, and their associated drivers.
45 *
[3]46 * ALMOS-MKH defines three types of IRQs, that are handled by this ICU device:
[1]47 * - HWI : The HardWare Interrupts are generated by local internal peripherals.
48 *   They are connected to the local ICU, to be routed to a given local core.
49 * - WTI : The Write Triggered Interrupts are actually mailboxes implemented in the
50 *   local ICU. They are used to implement software IPIs (Inter-Processor-Interrupts),
51 *   or to route an IRQ generated by an external peripheral to a local core.
52 * - PTI : The Programmable Timer Interrupts are actually timers generating periodic
53 *   interrupts controled by softare and contained in the local ICU, and routed to
54 *   a local core.
55 *
56 * The max numbers of interrupts of each type in a given cluster are defined by the
57 * CONFIG_IRQ_HWI_MAX, CONFIG_IRQ_WTI_MAX, and CONFIG_IRQ_PTI_MAX parameters.
58 * The actual numbers (hwi_nr / wti_nr / pti_nr) for a given manycore architecture
59 * are defined in the boot_info file and stored in the ICU device extension.
60 *
61 * The generic ICU device provides three main services:
62 * 1) It allows the kernel to selectively enable/disable any IRQ (identified by its type
63 *    and index) for a given core. It is the kernel responsibility to enable a given IRQ
64 *    to the core that started the I/O operation core, as a given IRQ event should be
65 *    handled by only one core.
66 * 2) It makes a global OR between all enabled IRQs for a given core, to interrupt
67 *    the core when at least one enabled IRQ is active.
68 * 3) It is capable to return the highest priority active IRQ of each type. The priority
69 *    scheme depends on the ICU device implementation.
70 *
71 * To select the ISR to be executed for a given IRQ routed to a given core, ALMOS-MKH
72 * uses three interrupts vectors, implemented as three arrays (HWI/WTI/PTI),
73 * stored in the core descriptor. Each entry in one interrupt vector array contains
[3]74 * a pointer on the chdev descriptor that is the "source" of the interrupt.
75 * This chdev descriptor contains a link to the ISR to be executed.
[1]76 *
77 * The ICU peripheral does not execute I/O operations, but is just acting as a
[3]78 * dynamically configurable interrupt router for other I/O operations.
79 * Therefore, ALMOS-MKH does not use the ICU device waiting queue, but calls directly
[1]80 * the ICU driver blocking functions, using the device lock to get exclusive access to
81 * the ICU device state.
82 ****************************************************************************************/
83 
84/****  Forward declarations  ****/
85
[3]86struct chdev_s;
[1]87
88/*****************************************************************************************
89 * This defines the (implementation independant) extension for the generic ICU device.
90 ****************************************************************************************/
91
92typedef struct icu_extend_s
93{
94    uint32_t    hwi_nr;         /*! actual number of HWI IRQs in the ICU device         */
95    uint32_t    wti_nr;         /*! actual number of WTI IRQs in the ICU device         */
96    uint32_t    pti_nr;         /*! actual number of PTI IRQs in the ICU device         */
97    uint32_t    wti_bitmap;     /*! WTI mailbox allocator / 0 == free entry             */
98    spinlock_t  wti_lock;       /*! lock protecting WTI mailbox allocator               */
99}
100icu_extend_t;
101
102/*****************************************************************************************
103 * This enum defines the various implementations of the ICU internal interrupt controller.
104 * This array must be kept consistent with the define in arch_info.h file
105 ****************************************************************************************/
106
107enum icu_impl_e
108{
109    IMPL_ICU_XCU =   0,         /* vci_xicu component used in TSAR                      */
110    IMPL_ICU_I86 =   1          /* TBD                                                  */
111}
112icu_impl_t;
113
114/*****************************************************************************************
115 * This enum defines the three types of interrupts.
116 ****************************************************************************************/
117
118typedef enum irq_type
119{
120    HWI_TYPE,                   /*! Hardware Interrupt                                  */
121    WTI_TYPE,                   /*! Write Triggered Interrupt                           */
122    PTI_TYPE                    /*! Programmable Timer Interrupt                        */
123}
124irq_type_t;
125
126
127/*****************************************************************************************
128 * This function makes two initialisations:
[3]129 * - It initialises the ICU specific fields of the chdev descriptor.
[1]130 * - it initialises the implementation specific ICU hardware device and associated
131 *   data structures if required.
[3]132 * It must be called by a local thread.
[1]133 *****************************************************************************************
[3]134 * @ icu     : pointer on ICU chdev descriptor.
135 * @ hwi_nr  : number of HWI irqs.
136 * @ wti_nr  : number of WTI irqs.
137 * @ pti_nr  : number of PTI irqs.
[1]138 ****************************************************************************************/
[3]139void dev_icu_init( struct chdev_s  * icu,
140                   uint32_t          hwi_nr,
141                   uint32_t          wti_nr,
142                   uint32_t          pti_nr );
[1]143
144/*****************************************************************************************
[3]145 * This function enables the routing of a given IRQ, to a given core in the local cluster.
146 * This IRQ is identified by its type (HWI/WTI/PTI) and index in the local ICU.
[1]147 * The target core is identified by its local index.
[3]148 * It must be called by a local thread.
149 * - It unmask the selected IRQ in the ICU.
150 * - It registers the pointer on the "source" chdev descriptor in the
[1]151 *   relevant interrupt vector of the selected core.
[3]152 * - It register the IRQ type and index in the "source" chdev descriptor.
[1]153 *****************************************************************************************
[3]154 * @ lid        : local index of selected core.
[1]155 * @ irq_type   : HWI/WTI/PTI.
[3]156 * @ irq_id     : IRQ index in ICU
157 * @ chdev      : pointer on source chdev descriptor.
[1]158 ****************************************************************************************/
[3]159void dev_icu_enable_irq( lid_t             lid,
160                         uint32_t          irq_type,
161                         uint32_t          irq_id,
162                         struct chdev_s  * chdev );
[1]163
164/*****************************************************************************************
[3]165 * This function disables one given IRQ for a given core in the local cluster.
166 * This IRQ is identified by its type (HWI/WTI/PTI) and index in the local ICU.
[1]167 * The core is identified by its local index.
[3]168 * It must be called by a local thread.
169 * - It mask the selected IRQ in the ICU.
170 * - It removes the pointer on the "source" chdev descriptor from the
[1]171 *   relevant interrupt vector of the selected core.
[3]172 * - The IRQ type and index fields are not modified in the "source" chdev descriptor.
[1]173 *****************************************************************************************
174 * @ lid       : local index of selected core in remote cluster.
175 * @ irq_type  : HWI/WTI/PTI.
176 * @ irq_id    : IRQ index.
177 ****************************************************************************************/
[3]178void dev_icu_disable_irq( lid_t      lid,
[1]179                          uint32_t   irq_type,
180                          uint32_t   irq_id );
[14]181
[1]182/*****************************************************************************************
[14]183 * This function returns the set of enabled IRQs for a given core.
184 *****************************************************************************************
185 * @ lid       : local index of selected core in remote cluster.
186 * @ hwi_mask  : each non zero bit define an enabled HWI IRQ.
187 * @ wti_mask  : each non zero bit define an enabled WTI IRQ.
188 * @ pti_mask  : each non zero bit define an enabled PTI IRQ.
189 ****************************************************************************************/
190void dev_icu_get_masks( lid_t      lid,
191                        uint32_t * hwi_mask,
192                        uint32_t * WTi_mask,
193                        uint32_t * pti_mask );
194
195/*****************************************************************************************
[1]196 * This function set the period value for a timer identified by the PTI index,
197 * in the local ICU device descriptor.
[3]198 * It must be called by a local thread.
[1]199 *****************************************************************************************
200 * @ pti_id    : PTI index.
201 * @ period    : number of cycles.
202 ****************************************************************************************/
203void dev_icu_set_period( uint32_t   pti_id,
204                         uint32_t   period );
205
206/*****************************************************************************************
207 * This function acknowledge a PTI IRQ for a timer identified by the PTI index,
208 * in the local ICU device descriptor.
[3]209 * It must be called by a local thread.
[1]210 *****************************************************************************************
211 * @ pti_id    : PTI index.
212 ****************************************************************************************/
213void dev_icu_ack_timer( uint32_t   pti_id );
214
215/*****************************************************************************************
216 * This function send an IPI (Inter Processor Interrupt) to a core identified by
[3]217 * its cluster identifier and local index.
218 * It can be called by any thread running in any cluster.
[1]219 * This IPI force a context switch, and the handling of pending RPC(s).
220 *****************************************************************************************
221 * @ cxy      : destination cluster identifier.
222 * @ lid      : destination core local index.
223 * @ return 0 if success (IPI registered) / returns EINVAL if illegal cxy or lid.
224 ****************************************************************************************/
225void dev_icu_send_ipi( cxy_t    cxy,
226                       lid_t    lid );
227
228/*****************************************************************************************
229 * This function is called by a core when it receives an IRQ from the ICU device.
230 * It access the local ICU device descriptor to get the highest priority IRQ
231 * of each type (HWI / WTI / PTI).
232 * - If it is a WTI or an HWI, the function uses the calling core interrupt-vectors
233 *   to call the relevant ISR, registered in the source device descriptor.
234 * - If it is a PTI, the source device descriptor is the ICU device itself, and it
235 *   call the core_clock() function to execute all operations related to the TICK event.
236 ****************************************************************************************/
237void dev_icu_irq_handler();
238
239/*****************************************************************************************
[3]240 * This function implements the WTI mailbox allocator for the local ICU.
241 * These mailbox are used by I/O operations for completion signaling.
242 * It must be called by a thread running in the cluster containing the target ICU.
[1]243 * If there is no mailbox available, the client thread must deschedule and retry later.
244 * If N is the total number of WTI mailboxes in a cluster, and NC the number of cores,
245 * the number of dynamically allocatable WTI mailboxes is (N-NC) because the first N
246 * WTI mailboxes are used by the IPIs (one IPI per core).
247 * It does not access the hardware device.
248 *****************************************************************************************
249 * @ return WTI index if success / returns 0xFFFFFFFF if no mailbox available.
250 ****************************************************************************************/
251uint32_t dev_icu_wti_alloc();
252
253/*****************************************************************************************
254 * This function releases a dynamically allocated WTI mailbox.
[3]255 * It must be called by a thread running in the cluster containing the target ICU.
[1]256 * It does not access the hardware device.
257 *****************************************************************************************
258 * @ wti_id   : WTI mailbox index.
259 ****************************************************************************************/
260void dev_icu_wti_release( uint32_t wti_id );
261
262/*****************************************************************************************
[3]263 * This function returns a pointer on the WTI mailbox identified by its index
264 * in the local ICU device.
[1]265 *****************************************************************************************
[3]266 * @ wti_id   : WTI mailbox index.
267 * @ returns pointer on mailbox register.
[1]268 ****************************************************************************************/
[3]269uint32_t * dev_icu_wti_ptr( uint32_t wti_id );
[1]270
271#endif  /* _DEV_ICU_H_ */
Note: See TracBrowser for help on using the repository browser.