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 <arch.h> 8 #include <arch_helpers.h> 9 #include <assert.h> 10 #include <debug.h> 11 #include <gic_common.h> 12 #include <gicv2.h> 13 #include <interrupt_props.h> 14 #include "../common/gic_common_private.h" 15 #include "gicv2_private.h" 16 17 /* 18 * Accessor to read the GIC Distributor ITARGETSR corresponding to the 19 * interrupt `id`, 4 interrupt IDs at a time. 20 */ 21 unsigned int gicd_read_itargetsr(uintptr_t base, unsigned int id) 22 { 23 unsigned n = id >> ITARGETSR_SHIFT; 24 return mmio_read_32(base + GICD_ITARGETSR + (n << 2)); 25 } 26 27 /* 28 * Accessor to read the GIC Distributor CPENDSGIR corresponding to the 29 * interrupt `id`, 4 interrupt IDs at a time. 30 */ 31 unsigned int gicd_read_cpendsgir(uintptr_t base, unsigned int id) 32 { 33 unsigned n = id >> CPENDSGIR_SHIFT; 34 return mmio_read_32(base + GICD_CPENDSGIR + (n << 2)); 35 } 36 37 /* 38 * Accessor to read the GIC Distributor SPENDSGIR corresponding to the 39 * interrupt `id`, 4 interrupt IDs at a time. 40 */ 41 unsigned int gicd_read_spendsgir(uintptr_t base, unsigned int id) 42 { 43 unsigned n = id >> SPENDSGIR_SHIFT; 44 return mmio_read_32(base + GICD_SPENDSGIR + (n << 2)); 45 } 46 47 /* 48 * Accessor to write the GIC Distributor ITARGETSR corresponding to the 49 * interrupt `id`, 4 interrupt IDs at a time. 50 */ 51 void gicd_write_itargetsr(uintptr_t base, unsigned int id, unsigned int val) 52 { 53 unsigned n = id >> ITARGETSR_SHIFT; 54 mmio_write_32(base + GICD_ITARGETSR + (n << 2), val); 55 } 56 57 /* 58 * Accessor to write the GIC Distributor CPENDSGIR corresponding to the 59 * interrupt `id`, 4 interrupt IDs at a time. 60 */ 61 void gicd_write_cpendsgir(uintptr_t base, unsigned int id, unsigned int val) 62 { 63 unsigned n = id >> CPENDSGIR_SHIFT; 64 mmio_write_32(base + GICD_CPENDSGIR + (n << 2), val); 65 } 66 67 /* 68 * Accessor to write the GIC Distributor SPENDSGIR corresponding to the 69 * interrupt `id`, 4 interrupt IDs at a time. 70 */ 71 void gicd_write_spendsgir(uintptr_t base, unsigned int id, unsigned int val) 72 { 73 unsigned n = id >> SPENDSGIR_SHIFT; 74 mmio_write_32(base + GICD_SPENDSGIR + (n << 2), val); 75 } 76 77 /******************************************************************************* 78 * Get the current CPU bit mask from GICD_ITARGETSR0 79 ******************************************************************************/ 80 unsigned int gicv2_get_cpuif_id(uintptr_t base) 81 { 82 unsigned int val; 83 84 val = gicd_read_itargetsr(base, 0); 85 return val & GIC_TARGET_CPU_MASK; 86 } 87 88 /******************************************************************************* 89 * Helper function to configure the default attributes of SPIs. 90 ******************************************************************************/ 91 void gicv2_spis_configure_defaults(uintptr_t gicd_base) 92 { 93 unsigned int index, num_ints; 94 95 num_ints = gicd_read_typer(gicd_base); 96 num_ints &= TYPER_IT_LINES_NO_MASK; 97 num_ints = (num_ints + 1) << 5; 98 99 /* 100 * Treat all SPIs as G1NS by default. The number of interrupts is 101 * calculated as 32 * (IT_LINES + 1). We do 32 at a time. 102 */ 103 for (index = MIN_SPI_ID; index < num_ints; index += 32) 104 gicd_write_igroupr(gicd_base, index, ~0U); 105 106 /* Setup the default SPI priorities doing four at a time */ 107 for (index = MIN_SPI_ID; index < num_ints; index += 4) 108 gicd_write_ipriorityr(gicd_base, 109 index, 110 GICD_IPRIORITYR_DEF_VAL); 111 112 /* Treat all SPIs as level triggered by default, 16 at a time */ 113 for (index = MIN_SPI_ID; index < num_ints; index += 16) 114 gicd_write_icfgr(gicd_base, index, 0); 115 } 116 117 #if !ERROR_DEPRECATED 118 /******************************************************************************* 119 * Helper function to configure secure G0 SPIs. 120 ******************************************************************************/ 121 void gicv2_secure_spis_configure(uintptr_t gicd_base, 122 unsigned int num_ints, 123 const unsigned int *sec_intr_list) 124 { 125 unsigned int index, irq_num; 126 127 /* If `num_ints` is not 0, ensure that `sec_intr_list` is not NULL */ 128 assert(num_ints ? (uintptr_t)sec_intr_list : 1); 129 130 for (index = 0; index < num_ints; index++) { 131 irq_num = sec_intr_list[index]; 132 if (irq_num >= MIN_SPI_ID) { 133 /* Configure this interrupt as a secure interrupt */ 134 gicd_clr_igroupr(gicd_base, irq_num); 135 136 /* Set the priority of this interrupt */ 137 gicd_set_ipriorityr(gicd_base, 138 irq_num, 139 GIC_HIGHEST_SEC_PRIORITY); 140 141 /* Target the secure interrupts to primary CPU */ 142 gicd_set_itargetsr(gicd_base, irq_num, 143 gicv2_get_cpuif_id(gicd_base)); 144 145 /* Enable this interrupt */ 146 gicd_set_isenabler(gicd_base, irq_num); 147 } 148 } 149 150 } 151 #endif 152 153 /******************************************************************************* 154 * Helper function to configure properties of secure G0 SPIs. 155 ******************************************************************************/ 156 void gicv2_secure_spis_configure_props(uintptr_t gicd_base, 157 const interrupt_prop_t *interrupt_props, 158 unsigned int interrupt_props_num) 159 { 160 unsigned int i; 161 const interrupt_prop_t *prop_desc; 162 163 /* Make sure there's a valid property array */ 164 assert(interrupt_props_num != 0 ? (uintptr_t) interrupt_props : 1); 165 166 for (i = 0; i < interrupt_props_num; i++) { 167 prop_desc = &interrupt_props[i]; 168 169 if (prop_desc->intr_num < MIN_SPI_ID) 170 continue; 171 172 /* Configure this interrupt as a secure interrupt */ 173 assert(prop_desc->intr_grp == GICV2_INTR_GROUP0); 174 gicd_clr_igroupr(gicd_base, prop_desc->intr_num); 175 176 /* Set the priority of this interrupt */ 177 gicd_set_ipriorityr(gicd_base, prop_desc->intr_num, 178 prop_desc->intr_pri); 179 180 /* Target the secure interrupts to primary CPU */ 181 gicd_set_itargetsr(gicd_base, prop_desc->intr_num, 182 gicv2_get_cpuif_id(gicd_base)); 183 184 /* Set interrupt configuration */ 185 gicd_set_icfgr(gicd_base, prop_desc->intr_num, 186 prop_desc->intr_cfg); 187 188 /* Enable this interrupt */ 189 gicd_set_isenabler(gicd_base, prop_desc->intr_num); 190 } 191 } 192 193 #if !ERROR_DEPRECATED 194 /******************************************************************************* 195 * Helper function to configure secure G0 SGIs and PPIs. 196 ******************************************************************************/ 197 void gicv2_secure_ppi_sgi_setup(uintptr_t gicd_base, 198 unsigned int num_ints, 199 const unsigned int *sec_intr_list) 200 { 201 unsigned int index, irq_num, sec_ppi_sgi_mask = 0; 202 203 /* If `num_ints` is not 0, ensure that `sec_intr_list` is not NULL */ 204 assert(num_ints ? (uintptr_t)sec_intr_list : 1); 205 206 /* 207 * Disable all SGIs (imp. def.)/PPIs before configuring them. This is a 208 * more scalable approach as it avoids clearing the enable bits in the 209 * GICD_CTLR. 210 */ 211 gicd_write_icenabler(gicd_base, 0, ~0); 212 213 /* Setup the default PPI/SGI priorities doing four at a time */ 214 for (index = 0; index < MIN_SPI_ID; index += 4) 215 gicd_write_ipriorityr(gicd_base, 216 index, 217 GICD_IPRIORITYR_DEF_VAL); 218 219 for (index = 0; index < num_ints; index++) { 220 irq_num = sec_intr_list[index]; 221 if (irq_num < MIN_SPI_ID) { 222 /* We have an SGI or a PPI. They are Group0 at reset */ 223 sec_ppi_sgi_mask |= 1U << irq_num; 224 225 /* Set the priority of this interrupt */ 226 gicd_set_ipriorityr(gicd_base, 227 irq_num, 228 GIC_HIGHEST_SEC_PRIORITY); 229 } 230 } 231 232 /* 233 * Invert the bitmask to create a mask for non-secure PPIs and 234 * SGIs. Program the GICD_IGROUPR0 with this bit mask. 235 */ 236 gicd_write_igroupr(gicd_base, 0, ~sec_ppi_sgi_mask); 237 238 /* Enable the Group 0 SGIs and PPIs */ 239 gicd_write_isenabler(gicd_base, 0, sec_ppi_sgi_mask); 240 } 241 #endif 242 243 /******************************************************************************* 244 * Helper function to configure properties of secure G0 SGIs and PPIs. 245 ******************************************************************************/ 246 void gicv2_secure_ppi_sgi_setup_props(uintptr_t gicd_base, 247 const interrupt_prop_t *interrupt_props, 248 unsigned int interrupt_props_num) 249 { 250 unsigned int i; 251 uint32_t sec_ppi_sgi_mask = 0; 252 const interrupt_prop_t *prop_desc; 253 254 /* Make sure there's a valid property array */ 255 assert(interrupt_props_num != 0 ? (uintptr_t) interrupt_props : 1); 256 257 /* 258 * Disable all SGIs (imp. def.)/PPIs before configuring them. This is a 259 * more scalable approach as it avoids clearing the enable bits in the 260 * GICD_CTLR. 261 */ 262 gicd_write_icenabler(gicd_base, 0, ~0); 263 264 /* Setup the default PPI/SGI priorities doing four at a time */ 265 for (i = 0; i < MIN_SPI_ID; i += 4) 266 gicd_write_ipriorityr(gicd_base, i, GICD_IPRIORITYR_DEF_VAL); 267 268 for (i = 0; i < interrupt_props_num; i++) { 269 prop_desc = &interrupt_props[i]; 270 271 if (prop_desc->intr_num >= MIN_SPI_ID) 272 continue; 273 274 /* Configure this interrupt as a secure interrupt */ 275 assert(prop_desc->intr_grp == GICV2_INTR_GROUP0); 276 277 /* 278 * Set interrupt configuration for PPIs. Configuration for SGIs 279 * are ignored. 280 */ 281 if ((prop_desc->intr_num >= MIN_PPI_ID) && 282 (prop_desc->intr_num < MIN_SPI_ID)) { 283 gicd_set_icfgr(gicd_base, prop_desc->intr_num, 284 prop_desc->intr_cfg); 285 } 286 287 /* We have an SGI or a PPI. They are Group0 at reset */ 288 sec_ppi_sgi_mask |= (1u << prop_desc->intr_num); 289 290 /* Set the priority of this interrupt */ 291 gicd_set_ipriorityr(gicd_base, prop_desc->intr_num, 292 prop_desc->intr_pri); 293 } 294 295 /* 296 * Invert the bitmask to create a mask for non-secure PPIs and SGIs. 297 * Program the GICD_IGROUPR0 with this bit mask. 298 */ 299 gicd_write_igroupr(gicd_base, 0, ~sec_ppi_sgi_mask); 300 301 /* Enable the Group 0 SGIs and PPIs */ 302 gicd_write_isenabler(gicd_base, 0, sec_ppi_sgi_mask); 303 } 304