| 1 | /* | 
|---|
| 2 |  * soclib_pic.c - soclib PIC driver definition. | 
|---|
| 3 |  * | 
|---|
| 4 |  * Author  Alain Greiner (2016,2017) | 
|---|
| 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-kernel; if not, write to the Free Software Foundation, | 
|---|
| 21 |  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 
|---|
| 22 |  */ | 
|---|
| 23 |  | 
|---|
| 24 | #ifndef _SOCLIB_PIC_H_ | 
|---|
| 25 | #define _SOCLIB_PIC_H_ | 
|---|
| 26 |  | 
|---|
| 27 | #include <hal_types.h> | 
|---|
| 28 |  | 
|---|
| 29 | /****  Forward declarations  ****/ | 
|---|
| 30 |  | 
|---|
| 31 | struct chdev_s; | 
|---|
| 32 |  | 
|---|
| 33 | /***************************************************************************************** | 
|---|
| 34 |  * This file defines the driver for the SOCLIB PIC device. | 
|---|
| 35 |  * | 
|---|
| 36 |  * The SOCLIB PIC infrastructure contains two types of components: | 
|---|
| 37 |  * | 
|---|
| 38 |  * - The IOPIC external controller handles the external IRQs generated by the external | 
|---|
| 39 |  *   peripherals. The IOPIC controller provides two services: | 
|---|
| 40 |  *   1) It translate each IRQ hardware signal to a write transactions to a specific | 
|---|
| 41 |  *      mailbox, for a given core in a giveb cluster, as explained below. | 
|---|
| 42 |  *   2) It  allows the kernel to selectively enable/disable any external IRQ  | 
|---|
| 43 |  *      identified by its index. | 
|---|
| 44 |  * | 
|---|
| 45 |  * - The XCU internal controller implement the generic local interrupt controller | 
|---|
| 46 |  *   (LAPIC), replicated in all clusters containing at  least one core. | 
|---|
| 47 |  *   In each cluster, it concentrates all IRQs destinated to one given core, | 
|---|
| 48 |  *   and helps the interrupt handler to select the ISR (Interrupt Service Routine) | 
|---|
| 49 |  *   that must be executed by the target core. It defines three types of IRQs:  | 
|---|
| 50 |  *   1) HWI : The HardWare Interrupts are generated by local internal peripherals. | 
|---|
| 51 |  *      They are connected to the local XCU, to be routed to a given local core. | 
|---|
| 52 |  *   2) WTI : The Write Triggered Interrupts are actually mailboxes implemented in the | 
|---|
| 53 |  *      local XCU. They are used to implement software IPIs (Inter-Processor-Interrupts), | 
|---|
| 54 |  *      or to register the write transactions generated by the IOPIC controller. | 
|---|
| 55 |  *   3) PTI : The Programmable Timer Interrupts are actually timers generating periodic | 
|---|
| 56 |  *      interrupts controled by softare, contained in the local XCU, and routed to | 
|---|
| 57 |  *      a local core. | 
|---|
| 58 |  *   The numbers of interrupts of each type in a given cluster are defined in the  | 
|---|
| 59 |  *   XCU_CONFIG register of the XCU component, and cannot be larger than the | 
|---|
| 60 |  *   SOCLIB_MAX_HWI, SOCLIB_MAX_WTI, SOCLIB_MAX_PTI constants defined below. | 
|---|
| 61 |  *   The XCU controller 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 |  *      for a single core as a given IRQ event should be handled by only one core. | 
|---|
| 65 |  *   2) It makes a global OR between all enabled IRQs for a given core, to interrupt | 
|---|
| 66 |  *      the core when at least one enabled IRQ is active. | 
|---|
| 67 |  *   3) It is capable to return the highest priority active IRQ of each type. | 
|---|
| 68 |  *      For each type, the lowest index have the highest priority. | 
|---|
| 69 |  * | 
|---|
| 70 |  * To select the ISR to be executed for a given HWI or WTI interrupt, the SOCLIB PIC | 
|---|
| 71 |  * infrastructure implements for each core two interrupts vectors, called hwi_vector[] | 
|---|
| 72 |  * and wti_vector[].  Each entry contains a pointer on the local chdev descriptor that | 
|---|
| 73 |  * is the "source" of the interrupt, and contains itself a link to the ISR to be executed. | 
|---|
| 74 |  * These interrupt vectors are stored in the core descriptor extension. | 
|---|
| 75 |  * For the PTI interrupts, there is one PTI per core, and the ISR is simply defined | 
|---|
| 76 |  * by the soclib_pic_timer_isr() function. | 
|---|
| 77 |  * | 
|---|
| 78 |  * There is no specific chdev to describe the current state of a given XCU controller. | 
|---|
| 79 |  * To store the informations attached to a given XCU (namely the WTI allocator), the | 
|---|
| 80 |  * SOCLIB PIC implementation attach a specific PIC extension to the cluster manager,  | 
|---|
| 81 |  * called XCU descriptor. | 
|---|
| 82 |  *****************************************************************************************/ | 
|---|
| 83 |  | 
|---|
| 84 | #define SOCLIB_TYPE_HWI        0 | 
|---|
| 85 | #define SOCLIB_TYPE_WTI        1 | 
|---|
| 86 | #define SOCLIB_TYPE_PTI        2 | 
|---|
| 87 |  | 
|---|
| 88 | #define SOCLIB_MAX_HWI         16  | 
|---|
| 89 | #define SOCLIB_MAX_WTI         16  | 
|---|
| 90 | #define SOCLIB_MAX_PTI         16  | 
|---|
| 91 |  | 
|---|
| 92 | /****************************************************************************************** | 
|---|
| 93 |  * This define the registers offsets for the  external SOCLIB_IOPIC component.  | 
|---|
| 94 |  * There is 4 addressable registers for each external input IRQ. | 
|---|
| 95 |  *****************************************************************************************/ | 
|---|
| 96 |  | 
|---|
| 97 | #define IOPIC_ADDRESS          0 | 
|---|
| 98 | #define IOPIC_EXTEND           1 | 
|---|
| 99 | #define IOPIC_STATUS           2 | 
|---|
| 100 | #define IOPIC_MASK             3 | 
|---|
| 101 |  | 
|---|
| 102 | #define IOPIC_SPAN             4 | 
|---|
| 103 |  | 
|---|
| 104 | /****************************************************************************************** | 
|---|
| 105 |  * This define the registers offsets for the internal SOCLIB_XCU components. | 
|---|
| 106 |  * There is an XCU component in each cluster. | 
|---|
| 107 |  *****************************************************************************************/ | 
|---|
| 108 |  | 
|---|
| 109 | #define XCU_WTI_REG            0 | 
|---|
| 110 | #define XCU_PTI_PER            1 | 
|---|
| 111 | #define XCU_PTI_VAL            2 | 
|---|
| 112 | #define XCU_PTI_ACK            3 | 
|---|
| 113 | #define XCU_MSK_PTI            4 | 
|---|
| 114 | #define XCU_MSK_PTI_ENABLE     5 | 
|---|
| 115 | #define XCU_MSK_PTI_DISABLE    6 | 
|---|
| 116 | #define XCU_PTI_ACTIVE         6 | 
|---|
| 117 | #define XCU_MSK_HWI            8 | 
|---|
| 118 | #define XCU_MSK_HWI_ENABLE     9 | 
|---|
| 119 | #define XCU_MSK_HWI_DISABLE    10 | 
|---|
| 120 | #define XCU_HWI_ACTIVE         10 | 
|---|
| 121 | #define XCU_MSK_WTI            12 | 
|---|
| 122 | #define XCU_MSK_WTI_ENABLE     13 | 
|---|
| 123 | #define XCU_MSK_WTI_DISABLE    14 | 
|---|
| 124 | #define XCU_WTI_ACTIVE         14 | 
|---|
| 125 | #define XCU_PRIO               15 | 
|---|
| 126 | #define XCU_CONFIG             16 | 
|---|
| 127 |  | 
|---|
| 128 | /****************************************************************************************** | 
|---|
| 129 |  * This structure defines the core descriptor extension used by the SOCLIB PIC | 
|---|
| 130 |  * implementation to store the two HWI / WTI interrupts vectors in the core descriptor. | 
|---|
| 131 |  * Each entry contains a local pointer on the chdev that is the source of the IRQ. | 
|---|
| 132 |  * A non allocated entry contains the NULL value. | 
|---|
| 133 |  *****************************************************************************************/ | 
|---|
| 134 |  | 
|---|
| 135 | typedef struct soclib_pic_core_s | 
|---|
| 136 | { | 
|---|
| 137 |     struct chdev_s * hwi_vector[SOCLIB_MAX_HWI]; | 
|---|
| 138 |     struct chdev_s * wti_vector[SOCLIB_MAX_WTI]; | 
|---|
| 139 | } | 
|---|
| 140 | soclib_pic_core_t; | 
|---|
| 141 |  | 
|---|
| 142 | /****************************************************************************************** | 
|---|
| 143 |  * This structure defines the cluster manager extension used by the SOCLIB PIC | 
|---|
| 144 |  * implementation to register the local XCU base address, the number of HWI/WTI/PTI, | 
|---|
| 145 |  * and the WTI allocator. The WTI allocator is very simple, because an allocated WTI | 
|---|
| 146 |  * mailbox is never released. | 
|---|
| 147 |  *****************************************************************************************/ | 
|---|
| 148 |  | 
|---|
| 149 | typedef struct soclib_pic_cluster_s | 
|---|
| 150 | { | 
|---|
| 151 |     uint32_t * xcu_base;           /*! local pointer on xcu segment base                 */ | 
|---|
| 152 |     uint32_t   hwi_nr;             /*! actual number of HWI inputs in XCU                */ | 
|---|
| 153 |     uint32_t   wti_nr;             /*! actual number of HWI inputs in XCU                */ | 
|---|
| 154 |     uint32_t   pti_nr;             /*! actual number of HWI inputs in XCU                */ | 
|---|
| 155 |     uint32_t   first_free_wti;     /*! simple allocator : first free WTI slot index      */ | 
|---|
| 156 | } | 
|---|
| 157 | soclib_pic_cluster_t; | 
|---|
| 158 |  | 
|---|
| 159 |  | 
|---|
| 160 |  | 
|---|
| 161 |  | 
|---|
| 162 | /****************************************************************************************** | 
|---|
| 163 |  *                      Generic PIC API  | 
|---|
| 164 |  *****************************************************************************************/ | 
|---|
| 165 |  | 
|---|
| 166 | /****************************************************************************************** | 
|---|
| 167 |  * This blocking function disables all input IRQs in the IOPIC controller, and | 
|---|
| 168 |  * disables all HWIs, WTIs, and PTIs in the XCU (LAPIC) controllers, for all cores, | 
|---|
| 169 |  * in all clusters. | 
|---|
| 170 |  * It must be called by a thread running in the cluster containing the PIC chdev.  | 
|---|
| 171 | ****************************************************************************************** | 
|---|
| 172 |  * @ chdev    : pointer on PIC chdev descriptor. | 
|---|
| 173 |  *****************************************************************************************/ | 
|---|
| 174 | void   soclib_pic_init( struct chdev_s * pic ); | 
|---|
| 175 |  | 
|---|
| 176 | /***************************************************************************************** | 
|---|
| 177 |  * This function allocates memory from local cluster for the SOCLIB PIC core extensions | 
|---|
| 178 |  * of all cores contained in the cluster, initializes the two HWI, WTI interrupt vectors | 
|---|
| 179 |  * as empty, and registers - for each core - the pointer in core descriptor. | 
|---|
| 180 |  * Then it allocates memory from local cluster for the SOCLIB PIC cluster extension, | 
|---|
| 181 |  * to implement the XCU WTI allocator, and registers the pointer in cluster manager. | 
|---|
| 182 |  * It access the local XCU component to get actual number of HWI / WTI / PTI.  | 
|---|
| 183 |  ***************************************************************************************** | 
|---|
| 184 |  * @ xcu_base  : local pointer on XCU controller segment base. | 
|---|
| 185 |  ****************************************************************************************/ | 
|---|
| 186 | void soclib_pic_extend_init( uint32_t * xcu_base ); | 
|---|
| 187 |  | 
|---|
| 188 | /****************************************************************************************** | 
|---|
| 189 |  * This function configure the PIC device to route the IRQ generated by a local chdev, | 
|---|
| 190 |  * defined by the <src_chdev> argument, to a local core identified by the <lid> argument. | 
|---|
| 191 |  * If the source chdev is external (IOC, TXT, NIC, IOB): | 
|---|
| 192 |  * - it get a WTI mailbox from the XCU. | 
|---|
| 193 |  * - it enables this WTI in XCU. | 
|---|
| 194 |  * - it updates the target core WTI interrupt vector. | 
|---|
| 195 |  * - it link the WTI to the relevant input IRQ in IOPIC. | 
|---|
| 196 |  * If the source chdev is internal (MMC, DMA): | 
|---|
| 197 |  * - it enables the HWI in XCU. | 
|---|
| 198 |  * - it updates the target core HWI interrupt vector. | 
|---|
| 199 |  * It must be called by a thread running in local cluster. | 
|---|
| 200 |  ****************************************************************************************** | 
|---|
| 201 |  * @ lid        : target core local index. | 
|---|
| 202 |  * @ src_chdev  : local pointer on source chdev descriptor. | 
|---|
| 203 |  *****************************************************************************************/ | 
|---|
| 204 | void soclib_pic_bind_irq( lid_t            lid, | 
|---|
| 205 |                           struct chdev_s * src_chdev ); | 
|---|
| 206 |  | 
|---|
| 207 | /****************************************************************************************** | 
|---|
| 208 |  * This function enables a remote HWI/WTI IRQ, identified by the <src_chdev_xp> argument, | 
|---|
| 209 |  * that contains information on the IRQ type (HWI/WTI), and IRQ index.  | 
|---|
| 210 |  * It access the remote XCU mask register, but does not access IOPIC. | 
|---|
| 211 |  ****************************************************************************************** | 
|---|
| 212 |  * @ lid           : target core local index (in cluster containing the source chdev). | 
|---|
| 213 |  * @ src_chdev_xp  : extended pointer on source chdev descriptor. | 
|---|
| 214 |  *****************************************************************************************/ | 
|---|
| 215 | void soclib_pic_enable_irq( lid_t   lid, | 
|---|
| 216 |                             xptr_t  src_chdev_xp ); | 
|---|
| 217 |  | 
|---|
| 218 | /****************************************************************************************** | 
|---|
| 219 |  * This function disables a remote HWI/WTI IRQ, identified by the <src_chdev_xp> argument,  | 
|---|
| 220 |  * that contains information on the IRQ type (HWI/WTI), and IRQ index. | 
|---|
| 221 |  * It access the remote XCU mask register, but does not access IOPIC. | 
|---|
| 222 |  ****************************************************************************************** | 
|---|
| 223 |  * @ lid           : target core local index (in cluster containing the source chdev). | 
|---|
| 224 |  * @ src_chdev_xp  : extended pointer on source chdev descriptor. | 
|---|
| 225 |  *****************************************************************************************/ | 
|---|
| 226 | void soclib_pic_disable_irq( lid_t   lid, | 
|---|
| 227 |                              xptr_t  src_chdev_xp ); | 
|---|
| 228 |  | 
|---|
| 229 | /****************************************************************************************** | 
|---|
| 230 |  * This function activates the PTI timer for the calling core. | 
|---|
| 231 |  * The <period> argument define the number of cycles between IRQs. | 
|---|
| 232 |  ****************************************************************************************** | 
|---|
| 233 |  * @ period      : number of cycles between IRQs. | 
|---|
| 234 |  *****************************************************************************************/ | 
|---|
| 235 | void soclib_pic_enable_timer( uint32_t period ); | 
|---|
| 236 |  | 
|---|
| 237 | /****************************************************************************************** | 
|---|
| 238 |  * This function activates the WTI[lid] in the local cluster, wherehe lid is the calling | 
|---|
| 239 |  * core local index. | 
|---|
| 240 |  *****************************************************************************************/ | 
|---|
| 241 | void soclib_pic_enable_ipi(); | 
|---|
| 242 |  | 
|---|
| 243 | /****************************************************************************************** | 
|---|
| 244 |  * This function allows the calling thread to send an IPI to any core in any cluster. | 
|---|
| 245 |  * It can be called by any thread running on any cluster. | 
|---|
| 246 |  ****************************************************************************************** | 
|---|
| 247 |  * @ cxy        : target core cluster. | 
|---|
| 248 |  * @ lid        : target core local index. | 
|---|
| 249 |  *****************************************************************************************/ | 
|---|
| 250 | void soclib_pic_send_ipi( cxy_t    cxy, | 
|---|
| 251 |                           lid_t    lid ); | 
|---|
| 252 |  | 
|---|
| 253 |  | 
|---|
| 254 |  | 
|---|
| 255 |  | 
|---|
| 256 |  | 
|---|
| 257 |  | 
|---|
| 258 | /****************************************************************************************** | 
|---|
| 259 |  *                    Private PIC API for TSAR. | 
|---|
| 260 |  *****************************************************************************************/ | 
|---|
| 261 |  | 
|---|
| 262 | /****************************************************************************************** | 
|---|
| 263 |  * This function returns the first free WTI mailbox from the XCU descriptor. | 
|---|
| 264 |  * cluster extension containing the current XCU state. It does not access the | 
|---|
| 265 |  * hardware XCU component. This WTI allocator is very simple, because an allocated | 
|---|
| 266 |  * WTI is never released. The first WTIs are preallocated for IPI (wpi_id == lid). | 
|---|
| 267 |  * This allocator does not use a lock, because there is no risk of concurrent access. | 
|---|
| 268 |  * If there is no free slot, it means that the total number of external IRQs is too | 
|---|
| 269 |  * large for the number of cores in the architecture, and the core goes to sleep. | 
|---|
| 270 |  *****************************************************************************************/ | 
|---|
| 271 | uint32_t soclib_pic_wti_alloc(); | 
|---|
| 272 |  | 
|---|
| 273 | /****************************************************************************************** | 
|---|
| 274 |  * This function returns the local pointer on the local XCU base segment. | 
|---|
| 275 |  *****************************************************************************************/ | 
|---|
| 276 | uint32_t * soclib_pic_xcu_base(); | 
|---|
| 277 |  | 
|---|
| 278 | /****************************************************************************************** | 
|---|
| 279 |  * This function returns the local pointer on a remote XCU base segment. | 
|---|
| 280 |  * It is used by the soclip_pic_enable_irq() and soclib_pic_disable_irq() functions. | 
|---|
| 281 |  ****************************************************************************************** | 
|---|
| 282 |  * @ cxy  : target cluster identifier. | 
|---|
| 283 |  *****************************************************************************************/ | 
|---|
| 284 | uint32_t * soclib_pic_remote_xcu_base( cxy_t cxy ); | 
|---|
| 285 |  | 
|---|
| 286 | /****************************************************************************************** | 
|---|
| 287 |  * This function returns in the <hwi_status>, <wti_status>, <pti_status> buffers | 
|---|
| 288 |  * the local XCU status for a given core identidied by the <lid> argument. | 
|---|
| 289 |  *****************************************************************************************/ | 
|---|
| 290 | void soclib_pic_xcu_status( lid_t      lid, | 
|---|
| 291 |                             uint32_t * hwi_status, | 
|---|
| 292 |                             uint32_t * wti_status, | 
|---|
| 293 |                             uint32_t * pti_status ); | 
|---|
| 294 |  | 
|---|
| 295 | /****************************************************************************************** | 
|---|
| 296 |  * This SOCLIB PIC specific is the call-back function is the interrupt handler. | 
|---|
| 297 |  *****************************************************************************************/ | 
|---|
| 298 | void soclib_pic_irq_handler(); | 
|---|
| 299 |  | 
|---|
| 300 |  | 
|---|
| 301 |  | 
|---|
| 302 |  | 
|---|
| 303 |  | 
|---|
| 304 |  | 
|---|
| 305 |  | 
|---|
| 306 | #endif  /* _SOCLIB_PIC_H_ */ | 
|---|