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

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

Bugs fix.

File size: 14.5 KB
Line 
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
27#include <kernel_config.h>
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
37 * operation. Each IRQ is routed to the core that started the I/O operation.
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 *
41 * This component can be implemented as a dedicated hardware component distributed
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 *
46 * ALMOS-MKH defines three types of IRQs, that are handled by this ICU device:
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
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.
76 *
77 * The ICU peripheral does not execute I/O operations, but is just acting as a
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
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
86struct chdev_s;
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:
129 * - It initialises the ICU specific fields of the chdev descriptor.
130 * - it initialises the implementation specific ICU hardware device and associated
131 *   data structures if required.
132 * It must be called by a local thread.
133 *****************************************************************************************
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.
138 ****************************************************************************************/
139void dev_icu_init( struct chdev_s  * icu,
140                   uint32_t          hwi_nr,
141                   uint32_t          wti_nr,
142                   uint32_t          pti_nr );
143
144/*****************************************************************************************
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.
147 * The target core is identified by its local index.
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
151 *   relevant interrupt vector of the selected core.
152 * - It register the IRQ type and index in the "source" chdev descriptor.
153 *****************************************************************************************
154 * @ lid        : local index of selected core.
155 * @ irq_type   : HWI/WTI/PTI.
156 * @ irq_id     : IRQ index in ICU
157 * @ chdev      : pointer on source chdev descriptor.
158 ****************************************************************************************/
159void dev_icu_enable_irq( lid_t             lid,
160                         uint32_t          irq_type,
161                         uint32_t          irq_id,
162                         struct chdev_s  * chdev );
163
164/*****************************************************************************************
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.
167 * The core is identified by its local index.
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
171 *   relevant interrupt vector of the selected core.
172 * - The IRQ type and index fields are not modified in the "source" chdev descriptor.
173 *****************************************************************************************
174 * @ lid       : local index of selected core in remote cluster.
175 * @ irq_type  : HWI/WTI/PTI.
176 * @ irq_id    : IRQ index.
177 ****************************************************************************************/
178void dev_icu_disable_irq( lid_t      lid,
179                          uint32_t   irq_type,
180                          uint32_t   irq_id );
181
182/*****************************************************************************************
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/*****************************************************************************************
196 * This function set the period value for a timer identified by the PTI index,
197 * in the local ICU device descriptor.
198 * It must be called by a local thread.
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.
209 * It must be called by a local thread.
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
217 * its cluster identifier and local index.
218 * It can be called by any thread running in any cluster.
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/*****************************************************************************************
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.
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.
255 * It must be called by a thread running in the cluster containing the target ICU.
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/*****************************************************************************************
263 * This function returns a pointer on the WTI mailbox identified by its index
264 * in the local ICU device.
265 *****************************************************************************************
266 * @ wti_id   : WTI mailbox index.
267 * @ returns pointer on mailbox register.
268 ****************************************************************************************/
269uint32_t * dev_icu_wti_ptr( uint32_t wti_id );
270
271#endif  /* _DEV_ICU_H_ */
Note: See TracBrowser for help on using the repository browser.