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