1 /* 2 * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * Redistributions of source code must retain the above copyright notice, this 8 * list of conditions and the following disclaimer. 9 * 10 * Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 14 * Neither the name of ARM nor the names of its contributors may be used 15 * to endorse or promote products derived from this software without specific 16 * prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include <assert.h> 32 #include <gic_common.h> 33 #include <mmio.h> 34 #include "gic_common_private.h" 35 36 /******************************************************************************* 37 * GIC Distributor interface accessors for reading entire registers 38 ******************************************************************************/ 39 /* 40 * Accessor to read the GIC Distributor IGROUPR corresponding to the interrupt 41 * `id`, 32 interrupt ids at a time. 42 */ 43 unsigned int gicd_read_igroupr(uintptr_t base, unsigned int id) 44 { 45 unsigned n = id >> IGROUPR_SHIFT; 46 return mmio_read_32(base + GICD_IGROUPR + (n << 2)); 47 } 48 49 /* 50 * Accessor to read the GIC Distributor ISENABLER corresponding to the 51 * interrupt `id`, 32 interrupt ids at a time. 52 */ 53 unsigned int gicd_read_isenabler(uintptr_t base, unsigned int id) 54 { 55 unsigned n = id >> ISENABLER_SHIFT; 56 return mmio_read_32(base + GICD_ISENABLER + (n << 2)); 57 } 58 59 /* 60 * Accessor to read the GIC Distributor ICENABLER corresponding to the 61 * interrupt `id`, 32 interrupt IDs at a time. 62 */ 63 unsigned int gicd_read_icenabler(uintptr_t base, unsigned int id) 64 { 65 unsigned n = id >> ICENABLER_SHIFT; 66 return mmio_read_32(base + GICD_ICENABLER + (n << 2)); 67 } 68 69 /* 70 * Accessor to read the GIC Distributor ISPENDR corresponding to the 71 * interrupt `id`, 32 interrupt IDs at a time. 72 */ 73 unsigned int gicd_read_ispendr(uintptr_t base, unsigned int id) 74 { 75 unsigned n = id >> ISPENDR_SHIFT; 76 return mmio_read_32(base + GICD_ISPENDR + (n << 2)); 77 } 78 79 /* 80 * Accessor to read the GIC Distributor ICPENDR corresponding to the 81 * interrupt `id`, 32 interrupt IDs at a time. 82 */ 83 unsigned int gicd_read_icpendr(uintptr_t base, unsigned int id) 84 { 85 unsigned n = id >> ICPENDR_SHIFT; 86 return mmio_read_32(base + GICD_ICPENDR + (n << 2)); 87 } 88 89 /* 90 * Accessor to read the GIC Distributor ISACTIVER corresponding to the 91 * interrupt `id`, 32 interrupt IDs at a time. 92 */ 93 unsigned int gicd_read_isactiver(uintptr_t base, unsigned int id) 94 { 95 unsigned n = id >> ISACTIVER_SHIFT; 96 return mmio_read_32(base + GICD_ISACTIVER + (n << 2)); 97 } 98 99 /* 100 * Accessor to read the GIC Distributor ICACTIVER corresponding to the 101 * interrupt `id`, 32 interrupt IDs at a time. 102 */ 103 unsigned int gicd_read_icactiver(uintptr_t base, unsigned int id) 104 { 105 unsigned n = id >> ICACTIVER_SHIFT; 106 return mmio_read_32(base + GICD_ICACTIVER + (n << 2)); 107 } 108 109 /* 110 * Accessor to read the GIC Distributor IPRIORITYR corresponding to the 111 * interrupt `id`, 4 interrupt IDs at a time. 112 */ 113 unsigned int gicd_read_ipriorityr(uintptr_t base, unsigned int id) 114 { 115 unsigned n = id >> IPRIORITYR_SHIFT; 116 return mmio_read_32(base + GICD_IPRIORITYR + (n << 2)); 117 } 118 119 /* 120 * Accessor to read the GIC Distributor ICGFR corresponding to the 121 * interrupt `id`, 16 interrupt IDs at a time. 122 */ 123 unsigned int gicd_read_icfgr(uintptr_t base, unsigned int id) 124 { 125 unsigned n = id >> ICFGR_SHIFT; 126 return mmio_read_32(base + GICD_ICFGR + (n << 2)); 127 } 128 129 /* 130 * Accessor to read the GIC Distributor NSACR corresponding to the 131 * interrupt `id`, 16 interrupt IDs at a time. 132 */ 133 unsigned int gicd_read_nsacr(uintptr_t base, unsigned int id) 134 { 135 unsigned n = id >> NSACR_SHIFT; 136 return mmio_read_32(base + GICD_NSACR + (n << 2)); 137 } 138 139 /******************************************************************************* 140 * GIC Distributor interface accessors for writing entire registers 141 ******************************************************************************/ 142 /* 143 * Accessor to write the GIC Distributor IGROUPR corresponding to the 144 * interrupt `id`, 32 interrupt IDs at a time. 145 */ 146 void gicd_write_igroupr(uintptr_t base, unsigned int id, unsigned int val) 147 { 148 unsigned n = id >> IGROUPR_SHIFT; 149 mmio_write_32(base + GICD_IGROUPR + (n << 2), val); 150 } 151 152 /* 153 * Accessor to write the GIC Distributor ISENABLER corresponding to the 154 * interrupt `id`, 32 interrupt IDs at a time. 155 */ 156 void gicd_write_isenabler(uintptr_t base, unsigned int id, unsigned int val) 157 { 158 unsigned n = id >> ISENABLER_SHIFT; 159 mmio_write_32(base + GICD_ISENABLER + (n << 2), val); 160 } 161 162 /* 163 * Accessor to write the GIC Distributor ICENABLER corresponding to the 164 * interrupt `id`, 32 interrupt IDs at a time. 165 */ 166 void gicd_write_icenabler(uintptr_t base, unsigned int id, unsigned int val) 167 { 168 unsigned n = id >> ICENABLER_SHIFT; 169 mmio_write_32(base + GICD_ICENABLER + (n << 2), val); 170 } 171 172 /* 173 * Accessor to write the GIC Distributor ISPENDR corresponding to the 174 * interrupt `id`, 32 interrupt IDs at a time. 175 */ 176 void gicd_write_ispendr(uintptr_t base, unsigned int id, unsigned int val) 177 { 178 unsigned n = id >> ISPENDR_SHIFT; 179 mmio_write_32(base + GICD_ISPENDR + (n << 2), val); 180 } 181 182 /* 183 * Accessor to write the GIC Distributor ICPENDR corresponding to the 184 * interrupt `id`, 32 interrupt IDs at a time. 185 */ 186 void gicd_write_icpendr(uintptr_t base, unsigned int id, unsigned int val) 187 { 188 unsigned n = id >> ICPENDR_SHIFT; 189 mmio_write_32(base + GICD_ICPENDR + (n << 2), val); 190 } 191 192 /* 193 * Accessor to write the GIC Distributor ISACTIVER corresponding to the 194 * interrupt `id`, 32 interrupt IDs at a time. 195 */ 196 void gicd_write_isactiver(uintptr_t base, unsigned int id, unsigned int val) 197 { 198 unsigned n = id >> ISACTIVER_SHIFT; 199 mmio_write_32(base + GICD_ISACTIVER + (n << 2), val); 200 } 201 202 /* 203 * Accessor to write the GIC Distributor ICACTIVER corresponding to the 204 * interrupt `id`, 32 interrupt IDs at a time. 205 */ 206 void gicd_write_icactiver(uintptr_t base, unsigned int id, unsigned int val) 207 { 208 unsigned n = id >> ICACTIVER_SHIFT; 209 mmio_write_32(base + GICD_ICACTIVER + (n << 2), val); 210 } 211 212 /* 213 * Accessor to write the GIC Distributor IPRIORITYR corresponding to the 214 * interrupt `id`, 4 interrupt IDs at a time. 215 */ 216 void gicd_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val) 217 { 218 unsigned n = id >> IPRIORITYR_SHIFT; 219 mmio_write_32(base + GICD_IPRIORITYR + (n << 2), val); 220 } 221 222 /* 223 * Accessor to write the GIC Distributor ICFGR corresponding to the 224 * interrupt `id`, 16 interrupt IDs at a time. 225 */ 226 void gicd_write_icfgr(uintptr_t base, unsigned int id, unsigned int val) 227 { 228 unsigned n = id >> ICFGR_SHIFT; 229 mmio_write_32(base + GICD_ICFGR + (n << 2), val); 230 } 231 232 /* 233 * Accessor to write the GIC Distributor NSACR corresponding to the 234 * interrupt `id`, 16 interrupt IDs at a time. 235 */ 236 void gicd_write_nsacr(uintptr_t base, unsigned int id, unsigned int val) 237 { 238 unsigned n = id >> NSACR_SHIFT; 239 mmio_write_32(base + GICD_NSACR + (n << 2), val); 240 } 241 242 /******************************************************************************* 243 * GIC Distributor functions for accessing the GIC registers 244 * corresponding to a single interrupt ID. These functions use bitwise 245 * operations or appropriate register accesses to modify or return 246 * the bit-field corresponding the single interrupt ID. 247 ******************************************************************************/ 248 unsigned int gicd_get_igroupr(uintptr_t base, unsigned int id) 249 { 250 unsigned bit_num = id & ((1 << IGROUPR_SHIFT) - 1); 251 unsigned int reg_val = gicd_read_igroupr(base, id); 252 253 return (reg_val >> bit_num) & 0x1; 254 } 255 256 void gicd_set_igroupr(uintptr_t base, unsigned int id) 257 { 258 unsigned bit_num = id & ((1 << IGROUPR_SHIFT) - 1); 259 unsigned int reg_val = gicd_read_igroupr(base, id); 260 261 gicd_write_igroupr(base, id, reg_val | (1 << bit_num)); 262 } 263 264 void gicd_clr_igroupr(uintptr_t base, unsigned int id) 265 { 266 unsigned bit_num = id & ((1 << IGROUPR_SHIFT) - 1); 267 unsigned int reg_val = gicd_read_igroupr(base, id); 268 269 gicd_write_igroupr(base, id, reg_val & ~(1 << bit_num)); 270 } 271 272 void gicd_set_isenabler(uintptr_t base, unsigned int id) 273 { 274 unsigned bit_num = id & ((1 << ISENABLER_SHIFT) - 1); 275 276 gicd_write_isenabler(base, id, (1 << bit_num)); 277 } 278 279 void gicd_set_icenabler(uintptr_t base, unsigned int id) 280 { 281 unsigned bit_num = id & ((1 << ICENABLER_SHIFT) - 1); 282 283 gicd_write_icenabler(base, id, (1 << bit_num)); 284 } 285 286 void gicd_set_ispendr(uintptr_t base, unsigned int id) 287 { 288 unsigned bit_num = id & ((1 << ISPENDR_SHIFT) - 1); 289 290 gicd_write_ispendr(base, id, (1 << bit_num)); 291 } 292 293 void gicd_set_icpendr(uintptr_t base, unsigned int id) 294 { 295 unsigned bit_num = id & ((1 << ICPENDR_SHIFT) - 1); 296 297 gicd_write_icpendr(base, id, (1 << bit_num)); 298 } 299 300 void gicd_set_isactiver(uintptr_t base, unsigned int id) 301 { 302 unsigned bit_num = id & ((1 << ISACTIVER_SHIFT) - 1); 303 304 gicd_write_isactiver(base, id, (1 << bit_num)); 305 } 306 307 void gicd_set_icactiver(uintptr_t base, unsigned int id) 308 { 309 unsigned bit_num = id & ((1 << ICACTIVER_SHIFT) - 1); 310 311 gicd_write_icactiver(base, id, (1 << bit_num)); 312 } 313 314 void gicd_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri) 315 { 316 mmio_write_8(base + GICD_IPRIORITYR + id, pri & GIC_PRI_MASK); 317 } 318