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 + 1U) << 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 += 32U) 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 += 4U) 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 += 16U) 114 gicd_write_icfgr(gicd_base, index, 0U); 115 } 116 117 /******************************************************************************* 118 * Helper function to configure properties of secure G0 SPIs. 119 ******************************************************************************/ 120 void gicv2_secure_spis_configure_props(uintptr_t gicd_base, 121 const interrupt_prop_t *interrupt_props, 122 unsigned int interrupt_props_num) 123 { 124 unsigned int i; 125 const interrupt_prop_t *prop_desc; 126 127 /* Make sure there's a valid property array */ 128 if (interrupt_props_num != 0U) 129 assert(interrupt_props != NULL); 130 131 for (i = 0; i < interrupt_props_num; i++) { 132 prop_desc = &interrupt_props[i]; 133 134 if (prop_desc->intr_num < MIN_SPI_ID) 135 continue; 136 137 /* Configure this interrupt as a secure interrupt */ 138 assert(prop_desc->intr_grp == GICV2_INTR_GROUP0); 139 gicd_clr_igroupr(gicd_base, prop_desc->intr_num); 140 141 /* Set the priority of this interrupt */ 142 gicd_set_ipriorityr(gicd_base, prop_desc->intr_num, 143 prop_desc->intr_pri); 144 145 /* Target the secure interrupts to primary CPU */ 146 gicd_set_itargetsr(gicd_base, prop_desc->intr_num, 147 gicv2_get_cpuif_id(gicd_base)); 148 149 /* Set interrupt configuration */ 150 gicd_set_icfgr(gicd_base, prop_desc->intr_num, 151 prop_desc->intr_cfg); 152 153 /* Enable this interrupt */ 154 gicd_set_isenabler(gicd_base, prop_desc->intr_num); 155 } 156 } 157 158 /******************************************************************************* 159 * Helper function to configure properties of secure G0 SGIs and PPIs. 160 ******************************************************************************/ 161 void gicv2_secure_ppi_sgi_setup_props(uintptr_t gicd_base, 162 const interrupt_prop_t *interrupt_props, 163 unsigned int interrupt_props_num) 164 { 165 unsigned int i; 166 uint32_t sec_ppi_sgi_mask = 0; 167 const interrupt_prop_t *prop_desc; 168 169 /* Make sure there's a valid property array */ 170 if (interrupt_props_num != 0U) 171 assert(interrupt_props != NULL); 172 173 /* 174 * Disable all SGIs (imp. def.)/PPIs before configuring them. This is a 175 * more scalable approach as it avoids clearing the enable bits in the 176 * GICD_CTLR. 177 */ 178 gicd_write_icenabler(gicd_base, 0U, ~0U); 179 180 /* Setup the default PPI/SGI priorities doing four at a time */ 181 for (i = 0U; i < MIN_SPI_ID; i += 4U) 182 gicd_write_ipriorityr(gicd_base, i, GICD_IPRIORITYR_DEF_VAL); 183 184 for (i = 0U; i < interrupt_props_num; i++) { 185 prop_desc = &interrupt_props[i]; 186 187 if (prop_desc->intr_num >= MIN_SPI_ID) 188 continue; 189 190 /* Configure this interrupt as a secure interrupt */ 191 assert(prop_desc->intr_grp == GICV2_INTR_GROUP0); 192 193 /* 194 * Set interrupt configuration for PPIs. Configuration for SGIs 195 * are ignored. 196 */ 197 if ((prop_desc->intr_num >= MIN_PPI_ID) && 198 (prop_desc->intr_num < MIN_SPI_ID)) { 199 gicd_set_icfgr(gicd_base, prop_desc->intr_num, 200 prop_desc->intr_cfg); 201 } 202 203 /* We have an SGI or a PPI. They are Group0 at reset */ 204 sec_ppi_sgi_mask |= (1u << prop_desc->intr_num); 205 206 /* Set the priority of this interrupt */ 207 gicd_set_ipriorityr(gicd_base, prop_desc->intr_num, 208 prop_desc->intr_pri); 209 } 210 211 /* 212 * Invert the bitmask to create a mask for non-secure PPIs and SGIs. 213 * Program the GICD_IGROUPR0 with this bit mask. 214 */ 215 gicd_write_igroupr(gicd_base, 0, ~sec_ppi_sgi_mask); 216 217 /* Enable the Group 0 SGIs and PPIs */ 218 gicd_write_isenabler(gicd_base, 0, sec_ppi_sgi_mask); 219 } 220