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