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