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 */
gicd_read_itargetsr(uintptr_t base,unsigned int id)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 */
gicd_read_cpendsgir(uintptr_t base,unsigned int id)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 */
gicd_read_spendsgir(uintptr_t base,unsigned int id)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 */
gicd_write_itargetsr(uintptr_t base,unsigned int id,unsigned int val)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 */
gicd_write_cpendsgir(uintptr_t base,unsigned int id,unsigned int val)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 */
gicd_write_spendsgir(uintptr_t base,unsigned int id,unsigned int val)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 ******************************************************************************/
gicv2_get_cpuif_id(uintptr_t base)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 ******************************************************************************/
gicv2_spis_configure_defaults(uintptr_t gicd_base)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 ******************************************************************************/
gicv2_secure_spis_configure(uintptr_t gicd_base,unsigned int num_ints,const unsigned int * sec_intr_list)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 ******************************************************************************/
gicv2_secure_spis_configure_props(uintptr_t gicd_base,const interrupt_prop_t * interrupt_props,unsigned int interrupt_props_num)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 ******************************************************************************/
gicv2_secure_ppi_sgi_setup(uintptr_t gicd_base,unsigned int num_ints,const unsigned int * sec_intr_list)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 ******************************************************************************/
gicv2_secure_ppi_sgi_setup_props(uintptr_t gicd_base,const interrupt_prop_t * interrupt_props,unsigned int interrupt_props_num)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