1 /* 2 * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 #include <gic_common.h> 9 #include <mmio.h> 10 #include "gic_common_private.h" 11 12 /******************************************************************************* 13 * GIC Distributor interface accessors for reading entire registers 14 ******************************************************************************/ 15 /* 16 * Accessor to read the GIC Distributor IGROUPR corresponding to the interrupt 17 * `id`, 32 interrupt ids at a time. 18 */ 19 unsigned int gicd_read_igroupr(uintptr_t base, unsigned int id) 20 { 21 unsigned int n = id >> IGROUPR_SHIFT; 22 23 return mmio_read_32(base + GICD_IGROUPR + (n << 2)); 24 } 25 26 /* 27 * Accessor to read the GIC Distributor ISENABLER corresponding to the 28 * interrupt `id`, 32 interrupt ids at a time. 29 */ 30 unsigned int gicd_read_isenabler(uintptr_t base, unsigned int id) 31 { 32 unsigned int n = id >> ISENABLER_SHIFT; 33 34 return mmio_read_32(base + GICD_ISENABLER + (n << 2)); 35 } 36 37 /* 38 * Accessor to read the GIC Distributor ICENABLER corresponding to the 39 * interrupt `id`, 32 interrupt IDs at a time. 40 */ 41 unsigned int gicd_read_icenabler(uintptr_t base, unsigned int id) 42 { 43 unsigned int n = id >> ICENABLER_SHIFT; 44 45 return mmio_read_32(base + GICD_ICENABLER + (n << 2)); 46 } 47 48 /* 49 * Accessor to read the GIC Distributor ISPENDR corresponding to the 50 * interrupt `id`, 32 interrupt IDs at a time. 51 */ 52 unsigned int gicd_read_ispendr(uintptr_t base, unsigned int id) 53 { 54 unsigned int n = id >> ISPENDR_SHIFT; 55 56 return mmio_read_32(base + GICD_ISPENDR + (n << 2)); 57 } 58 59 /* 60 * Accessor to read the GIC Distributor ICPENDR corresponding to the 61 * interrupt `id`, 32 interrupt IDs at a time. 62 */ 63 unsigned int gicd_read_icpendr(uintptr_t base, unsigned int id) 64 { 65 unsigned int n = id >> ICPENDR_SHIFT; 66 67 return mmio_read_32(base + GICD_ICPENDR + (n << 2)); 68 } 69 70 /* 71 * Accessor to read the GIC Distributor ISACTIVER corresponding to the 72 * interrupt `id`, 32 interrupt IDs at a time. 73 */ 74 unsigned int gicd_read_isactiver(uintptr_t base, unsigned int id) 75 { 76 unsigned int n = id >> ISACTIVER_SHIFT; 77 78 return mmio_read_32(base + GICD_ISACTIVER + (n << 2)); 79 } 80 81 /* 82 * Accessor to read the GIC Distributor ICACTIVER corresponding to the 83 * interrupt `id`, 32 interrupt IDs at a time. 84 */ 85 unsigned int gicd_read_icactiver(uintptr_t base, unsigned int id) 86 { 87 unsigned int n = id >> ICACTIVER_SHIFT; 88 89 return mmio_read_32(base + GICD_ICACTIVER + (n << 2)); 90 } 91 92 /* 93 * Accessor to read the GIC Distributor IPRIORITYR corresponding to the 94 * interrupt `id`, 4 interrupt IDs at a time. 95 */ 96 unsigned int gicd_read_ipriorityr(uintptr_t base, unsigned int id) 97 { 98 unsigned int n = id >> IPRIORITYR_SHIFT; 99 100 return mmio_read_32(base + GICD_IPRIORITYR + (n << 2)); 101 } 102 103 /* 104 * Accessor to read the GIC Distributor ICGFR corresponding to the 105 * interrupt `id`, 16 interrupt IDs at a time. 106 */ 107 unsigned int gicd_read_icfgr(uintptr_t base, unsigned int id) 108 { 109 unsigned int n = id >> ICFGR_SHIFT; 110 111 return mmio_read_32(base + GICD_ICFGR + (n << 2)); 112 } 113 114 /* 115 * Accessor to read the GIC Distributor NSACR corresponding to the 116 * interrupt `id`, 16 interrupt IDs at a time. 117 */ 118 unsigned int gicd_read_nsacr(uintptr_t base, unsigned int id) 119 { 120 unsigned int n = id >> NSACR_SHIFT; 121 122 return mmio_read_32(base + GICD_NSACR + (n << 2)); 123 } 124 125 /******************************************************************************* 126 * GIC Distributor interface accessors for writing entire registers 127 ******************************************************************************/ 128 /* 129 * Accessor to write the GIC Distributor IGROUPR corresponding to the 130 * interrupt `id`, 32 interrupt IDs at a time. 131 */ 132 void gicd_write_igroupr(uintptr_t base, unsigned int id, unsigned int val) 133 { 134 unsigned int n = id >> IGROUPR_SHIFT; 135 136 mmio_write_32(base + GICD_IGROUPR + (n << 2), val); 137 } 138 139 /* 140 * Accessor to write the GIC Distributor ISENABLER corresponding to the 141 * interrupt `id`, 32 interrupt IDs at a time. 142 */ 143 void gicd_write_isenabler(uintptr_t base, unsigned int id, unsigned int val) 144 { 145 unsigned int n = id >> ISENABLER_SHIFT; 146 147 mmio_write_32(base + GICD_ISENABLER + (n << 2), val); 148 } 149 150 /* 151 * Accessor to write the GIC Distributor ICENABLER corresponding to the 152 * interrupt `id`, 32 interrupt IDs at a time. 153 */ 154 void gicd_write_icenabler(uintptr_t base, unsigned int id, unsigned int val) 155 { 156 unsigned int n = id >> ICENABLER_SHIFT; 157 158 mmio_write_32(base + GICD_ICENABLER + (n << 2), val); 159 } 160 161 /* 162 * Accessor to write the GIC Distributor ISPENDR corresponding to the 163 * interrupt `id`, 32 interrupt IDs at a time. 164 */ 165 void gicd_write_ispendr(uintptr_t base, unsigned int id, unsigned int val) 166 { 167 unsigned int n = id >> ISPENDR_SHIFT; 168 169 mmio_write_32(base + GICD_ISPENDR + (n << 2), val); 170 } 171 172 /* 173 * Accessor to write the GIC Distributor ICPENDR corresponding to the 174 * interrupt `id`, 32 interrupt IDs at a time. 175 */ 176 void gicd_write_icpendr(uintptr_t base, unsigned int id, unsigned int val) 177 { 178 unsigned int n = id >> ICPENDR_SHIFT; 179 180 mmio_write_32(base + GICD_ICPENDR + (n << 2), val); 181 } 182 183 /* 184 * Accessor to write the GIC Distributor ISACTIVER corresponding to the 185 * interrupt `id`, 32 interrupt IDs at a time. 186 */ 187 void gicd_write_isactiver(uintptr_t base, unsigned int id, unsigned int val) 188 { 189 unsigned int n = id >> ISACTIVER_SHIFT; 190 191 mmio_write_32(base + GICD_ISACTIVER + (n << 2), val); 192 } 193 194 /* 195 * Accessor to write the GIC Distributor ICACTIVER corresponding to the 196 * interrupt `id`, 32 interrupt IDs at a time. 197 */ 198 void gicd_write_icactiver(uintptr_t base, unsigned int id, unsigned int val) 199 { 200 unsigned int n = id >> ICACTIVER_SHIFT; 201 202 mmio_write_32(base + GICD_ICACTIVER + (n << 2), val); 203 } 204 205 /* 206 * Accessor to write the GIC Distributor IPRIORITYR corresponding to the 207 * interrupt `id`, 4 interrupt IDs at a time. 208 */ 209 void gicd_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val) 210 { 211 unsigned int n = id >> IPRIORITYR_SHIFT; 212 213 mmio_write_32(base + GICD_IPRIORITYR + (n << 2), val); 214 } 215 216 /* 217 * Accessor to write the GIC Distributor ICFGR corresponding to the 218 * interrupt `id`, 16 interrupt IDs at a time. 219 */ 220 void gicd_write_icfgr(uintptr_t base, unsigned int id, unsigned int val) 221 { 222 unsigned int n = id >> ICFGR_SHIFT; 223 224 mmio_write_32(base + GICD_ICFGR + (n << 2), val); 225 } 226 227 /* 228 * Accessor to write the GIC Distributor NSACR corresponding to the 229 * interrupt `id`, 16 interrupt IDs at a time. 230 */ 231 void gicd_write_nsacr(uintptr_t base, unsigned int id, unsigned int val) 232 { 233 unsigned int n = id >> NSACR_SHIFT; 234 235 mmio_write_32(base + GICD_NSACR + (n << 2), val); 236 } 237 238 /******************************************************************************* 239 * GIC Distributor functions for accessing the GIC registers 240 * corresponding to a single interrupt ID. These functions use bitwise 241 * operations or appropriate register accesses to modify or return 242 * the bit-field corresponding the single interrupt ID. 243 ******************************************************************************/ 244 unsigned int gicd_get_igroupr(uintptr_t base, unsigned int id) 245 { 246 unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U); 247 unsigned int reg_val = gicd_read_igroupr(base, id); 248 249 return (reg_val >> bit_num) & 0x1U; 250 } 251 252 void gicd_set_igroupr(uintptr_t base, unsigned int id) 253 { 254 unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U); 255 unsigned int reg_val = gicd_read_igroupr(base, id); 256 257 gicd_write_igroupr(base, id, reg_val | (1U << bit_num)); 258 } 259 260 void gicd_clr_igroupr(uintptr_t base, unsigned int id) 261 { 262 unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U); 263 unsigned int reg_val = gicd_read_igroupr(base, id); 264 265 gicd_write_igroupr(base, id, reg_val & ~(1U << bit_num)); 266 } 267 268 void gicd_set_isenabler(uintptr_t base, unsigned int id) 269 { 270 unsigned int bit_num = id & ((1U << ISENABLER_SHIFT) - 1U); 271 272 gicd_write_isenabler(base, id, (1U << bit_num)); 273 } 274 275 void gicd_set_icenabler(uintptr_t base, unsigned int id) 276 { 277 unsigned int bit_num = id & ((1U << ICENABLER_SHIFT) - 1U); 278 279 gicd_write_icenabler(base, id, (1U << bit_num)); 280 } 281 282 void gicd_set_ispendr(uintptr_t base, unsigned int id) 283 { 284 unsigned int bit_num = id & ((1U << ISPENDR_SHIFT) - 1U); 285 286 gicd_write_ispendr(base, id, (1U << bit_num)); 287 } 288 289 void gicd_set_icpendr(uintptr_t base, unsigned int id) 290 { 291 unsigned int bit_num = id & ((1U << ICPENDR_SHIFT) - 1U); 292 293 gicd_write_icpendr(base, id, (1U << bit_num)); 294 } 295 296 unsigned int gicd_get_isactiver(uintptr_t base, unsigned int id) 297 { 298 unsigned int bit_num = id & ((1U << ISACTIVER_SHIFT) - 1U); 299 unsigned int reg_val = gicd_read_isactiver(base, id); 300 301 return (reg_val >> bit_num) & 0x1U; 302 } 303 304 void gicd_set_isactiver(uintptr_t base, unsigned int id) 305 { 306 unsigned int bit_num = id & ((1U << ISACTIVER_SHIFT) - 1U); 307 308 gicd_write_isactiver(base, id, (1U << bit_num)); 309 } 310 311 void gicd_set_icactiver(uintptr_t base, unsigned int id) 312 { 313 unsigned int bit_num = id & ((1U << ICACTIVER_SHIFT) - 1U); 314 315 gicd_write_icactiver(base, id, (1U << bit_num)); 316 } 317 318 void gicd_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri) 319 { 320 uint8_t val = pri & GIC_PRI_MASK; 321 322 mmio_write_8(base + GICD_IPRIORITYR + id, val); 323 } 324 325 void gicd_set_icfgr(uintptr_t base, unsigned int id, unsigned int cfg) 326 { 327 /* Interrupt configuration is a 2-bit field */ 328 unsigned int bit_num = id & ((1U << ICFGR_SHIFT) - 1U); 329 unsigned int bit_shift = bit_num << 1; 330 331 uint32_t reg_val = gicd_read_icfgr(base, id); 332 333 /* Clear the field, and insert required configuration */ 334 reg_val &= ~(GIC_CFG_MASK << bit_shift); 335 reg_val |= ((cfg & GIC_CFG_MASK) << bit_shift); 336 337 gicd_write_icfgr(base, id, reg_val); 338 } 339