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