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 <assert.h>
8
9 #include <arch.h>
10 #include <arch_helpers.h>
11 #include <common/debug.h>
12 #include <common/interrupt_props.h>
13 #include <drivers/arm/gic_common.h>
14
15 #include "../common/gic_common_private.h"
16 #include "gicv3_private.h"
17
18 /*
19 * Accessor to read the GIC Distributor IGRPMODR corresponding to the
20 * interrupt `id`, 32 interrupt IDs at a time.
21 */
gicd_read_igrpmodr(uintptr_t base,unsigned int id)22 unsigned int gicd_read_igrpmodr(uintptr_t base, unsigned int id)
23 {
24 unsigned int n = id >> IGRPMODR_SHIFT;
25
26 return mmio_read_32(base + GICD_IGRPMODR + (n << 2));
27 }
28
29 /*
30 * Accessor to write the GIC Distributor IGRPMODR corresponding to the
31 * interrupt `id`, 32 interrupt IDs at a time.
32 */
gicd_write_igrpmodr(uintptr_t base,unsigned int id,unsigned int val)33 void gicd_write_igrpmodr(uintptr_t base, unsigned int id, unsigned int val)
34 {
35 unsigned int n = id >> IGRPMODR_SHIFT;
36
37 mmio_write_32(base + GICD_IGRPMODR + (n << 2), val);
38 }
39
40 /*
41 * Accessor to get the bit corresponding to interrupt ID
42 * in GIC Distributor IGRPMODR.
43 */
gicd_get_igrpmodr(uintptr_t base,unsigned int id)44 unsigned int gicd_get_igrpmodr(uintptr_t base, unsigned int id)
45 {
46 unsigned int bit_num = id & ((1U << IGRPMODR_SHIFT) - 1U);
47 unsigned int reg_val = gicd_read_igrpmodr(base, id);
48
49 return (reg_val >> bit_num) & 0x1U;
50 }
51
52 /*
53 * Accessor to set the bit corresponding to interrupt ID
54 * in GIC Distributor IGRPMODR.
55 */
gicd_set_igrpmodr(uintptr_t base,unsigned int id)56 void gicd_set_igrpmodr(uintptr_t base, unsigned int id)
57 {
58 unsigned int bit_num = id & ((1U << IGRPMODR_SHIFT) - 1U);
59 unsigned int reg_val = gicd_read_igrpmodr(base, id);
60
61 gicd_write_igrpmodr(base, id, reg_val | (1U << bit_num));
62 }
63
64 /*
65 * Accessor to clear the bit corresponding to interrupt ID
66 * in GIC Distributor IGRPMODR.
67 */
gicd_clr_igrpmodr(uintptr_t base,unsigned int id)68 void gicd_clr_igrpmodr(uintptr_t base, unsigned int id)
69 {
70 unsigned int bit_num = id & ((1U << IGRPMODR_SHIFT) - 1U);
71 unsigned int reg_val = gicd_read_igrpmodr(base, id);
72
73 gicd_write_igrpmodr(base, id, reg_val & ~(1U << bit_num));
74 }
75
76 /*
77 * Accessor to read the GIC Re-distributor IPRIORITYR corresponding to the
78 * interrupt `id`, 4 interrupts IDs at a time.
79 */
gicr_read_ipriorityr(uintptr_t base,unsigned int id)80 unsigned int gicr_read_ipriorityr(uintptr_t base, unsigned int id)
81 {
82 unsigned int n = id >> IPRIORITYR_SHIFT;
83
84 return mmio_read_32(base + GICR_IPRIORITYR + (n << 2));
85 }
86
87 /*
88 * Accessor to write the GIC Re-distributor IPRIORITYR corresponding to the
89 * interrupt `id`, 4 interrupts IDs at a time.
90 */
gicr_write_ipriorityr(uintptr_t base,unsigned int id,unsigned int val)91 void gicr_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val)
92 {
93 unsigned int n = id >> IPRIORITYR_SHIFT;
94
95 mmio_write_32(base + GICR_IPRIORITYR + (n << 2), val);
96 }
97
98 /*
99 * Accessor to get the bit corresponding to interrupt ID
100 * from GIC Re-distributor IGROUPR0.
101 */
gicr_get_igroupr0(uintptr_t base,unsigned int id)102 unsigned int gicr_get_igroupr0(uintptr_t base, unsigned int id)
103 {
104 unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U);
105 unsigned int reg_val = gicr_read_igroupr0(base);
106
107 return (reg_val >> bit_num) & 0x1U;
108 }
109
110 /*
111 * Accessor to set the bit corresponding to interrupt ID
112 * in GIC Re-distributor IGROUPR0.
113 */
gicr_set_igroupr0(uintptr_t base,unsigned int id)114 void gicr_set_igroupr0(uintptr_t base, unsigned int id)
115 {
116 unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U);
117 unsigned int reg_val = gicr_read_igroupr0(base);
118
119 gicr_write_igroupr0(base, reg_val | (1U << bit_num));
120 }
121
122 /*
123 * Accessor to clear the bit corresponding to interrupt ID
124 * in GIC Re-distributor IGROUPR0.
125 */
gicr_clr_igroupr0(uintptr_t base,unsigned int id)126 void gicr_clr_igroupr0(uintptr_t base, unsigned int id)
127 {
128 unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U);
129 unsigned int reg_val = gicr_read_igroupr0(base);
130
131 gicr_write_igroupr0(base, reg_val & ~(1U << bit_num));
132 }
133
134 /*
135 * Accessor to get the bit corresponding to interrupt ID
136 * from GIC Re-distributor IGRPMODR0.
137 */
gicr_get_igrpmodr0(uintptr_t base,unsigned int id)138 unsigned int gicr_get_igrpmodr0(uintptr_t base, unsigned int id)
139 {
140 unsigned int bit_num = id & ((1U << IGRPMODR_SHIFT) - 1U);
141 unsigned int reg_val = gicr_read_igrpmodr0(base);
142
143 return (reg_val >> bit_num) & 0x1U;
144 }
145
146 /*
147 * Accessor to set the bit corresponding to interrupt ID
148 * in GIC Re-distributor IGRPMODR0.
149 */
gicr_set_igrpmodr0(uintptr_t base,unsigned int id)150 void gicr_set_igrpmodr0(uintptr_t base, unsigned int id)
151 {
152 unsigned int bit_num = id & ((1U << IGRPMODR_SHIFT) - 1U);
153 unsigned int reg_val = gicr_read_igrpmodr0(base);
154
155 gicr_write_igrpmodr0(base, reg_val | (1U << bit_num));
156 }
157
158 /*
159 * Accessor to clear the bit corresponding to interrupt ID
160 * in GIC Re-distributor IGRPMODR0.
161 */
gicr_clr_igrpmodr0(uintptr_t base,unsigned int id)162 void gicr_clr_igrpmodr0(uintptr_t base, unsigned int id)
163 {
164 unsigned int bit_num = id & ((1U << IGRPMODR_SHIFT) - 1U);
165 unsigned int reg_val = gicr_read_igrpmodr0(base);
166
167 gicr_write_igrpmodr0(base, reg_val & ~(1U << bit_num));
168 }
169
170 /*
171 * Accessor to set the bit corresponding to interrupt ID
172 * in GIC Re-distributor ISENABLER0.
173 */
gicr_set_isenabler0(uintptr_t base,unsigned int id)174 void gicr_set_isenabler0(uintptr_t base, unsigned int id)
175 {
176 unsigned int bit_num = id & ((1U << ISENABLER_SHIFT) - 1U);
177
178 gicr_write_isenabler0(base, (1U << bit_num));
179 }
180
181 /*
182 * Accessor to set the bit corresponding to interrupt ID in GIC Re-distributor
183 * ICENABLER0.
184 */
gicr_set_icenabler0(uintptr_t base,unsigned int id)185 void gicr_set_icenabler0(uintptr_t base, unsigned int id)
186 {
187 unsigned int bit_num = id & ((1U << ICENABLER_SHIFT) - 1U);
188
189 gicr_write_icenabler0(base, (1U << bit_num));
190 }
191
192 /*
193 * Accessor to set the bit corresponding to interrupt ID in GIC Re-distributor
194 * ISACTIVER0.
195 */
gicr_get_isactiver0(uintptr_t base,unsigned int id)196 unsigned int gicr_get_isactiver0(uintptr_t base, unsigned int id)
197 {
198 unsigned int bit_num = id & ((1U << ISACTIVER_SHIFT) - 1U);
199 unsigned int reg_val = gicr_read_isactiver0(base);
200
201 return (reg_val >> bit_num) & 0x1U;
202 }
203
204 /*
205 * Accessor to clear the bit corresponding to interrupt ID in GIC Re-distributor
206 * ICPENDRR0.
207 */
gicr_set_icpendr0(uintptr_t base,unsigned int id)208 void gicr_set_icpendr0(uintptr_t base, unsigned int id)
209 {
210 unsigned int bit_num = id & ((1U << ICPENDR_SHIFT) - 1U);
211
212 gicr_write_icpendr0(base, (1U << bit_num));
213 }
214
215 /*
216 * Accessor to set the bit corresponding to interrupt ID in GIC Re-distributor
217 * ISPENDR0.
218 */
gicr_set_ispendr0(uintptr_t base,unsigned int id)219 void gicr_set_ispendr0(uintptr_t base, unsigned int id)
220 {
221 unsigned int bit_num = id & ((1U << ISPENDR_SHIFT) - 1U);
222
223 gicr_write_ispendr0(base, (1U << bit_num));
224 }
225
226 /*
227 * Accessor to set the byte corresponding to interrupt ID
228 * in GIC Re-distributor IPRIORITYR.
229 */
gicr_set_ipriorityr(uintptr_t base,unsigned int id,unsigned int pri)230 void gicr_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri)
231 {
232 uint8_t val = pri & GIC_PRI_MASK;
233
234 mmio_write_8(base + GICR_IPRIORITYR + id, val);
235 }
236
237 /*
238 * Accessor to set the bit fields corresponding to interrupt ID
239 * in GIC Re-distributor ICFGR0.
240 */
gicr_set_icfgr0(uintptr_t base,unsigned int id,unsigned int cfg)241 void gicr_set_icfgr0(uintptr_t base, unsigned int id, unsigned int cfg)
242 {
243 /* Interrupt configuration is a 2-bit field */
244 unsigned int bit_num = id & ((1U << ICFGR_SHIFT) - 1U);
245 unsigned int bit_shift = bit_num << 1U;
246
247 uint32_t reg_val = gicr_read_icfgr0(base);
248
249 /* Clear the field, and insert required configuration */
250 reg_val &= ~(GIC_CFG_MASK << bit_shift);
251 reg_val |= ((cfg & GIC_CFG_MASK) << bit_shift);
252
253 gicr_write_icfgr0(base, reg_val);
254 }
255
256 /*
257 * Accessor to set the bit fields corresponding to interrupt ID
258 * in GIC Re-distributor ICFGR1.
259 */
gicr_set_icfgr1(uintptr_t base,unsigned int id,unsigned int cfg)260 void gicr_set_icfgr1(uintptr_t base, unsigned int id, unsigned int cfg)
261 {
262 /* Interrupt configuration is a 2-bit field */
263 unsigned int bit_num = id & ((1U << ICFGR_SHIFT) - 1U);
264 unsigned int bit_shift = bit_num << 1U;
265
266 uint32_t reg_val = gicr_read_icfgr1(base);
267
268 /* Clear the field, and insert required configuration */
269 reg_val &= ~(GIC_CFG_MASK << bit_shift);
270 reg_val |= ((cfg & GIC_CFG_MASK) << bit_shift);
271
272 gicr_write_icfgr1(base, reg_val);
273 }
274
275 /******************************************************************************
276 * This function marks the core as awake in the re-distributor and
277 * ensures that the interface is active.
278 *****************************************************************************/
gicv3_rdistif_mark_core_awake(uintptr_t gicr_base)279 void gicv3_rdistif_mark_core_awake(uintptr_t gicr_base)
280 {
281 /*
282 * The WAKER_PS_BIT should be changed to 0
283 * only when WAKER_CA_BIT is 1.
284 */
285 assert((gicr_read_waker(gicr_base) & WAKER_CA_BIT) != 0U);
286
287 /* Mark the connected core as awake */
288 gicr_write_waker(gicr_base, gicr_read_waker(gicr_base) & ~WAKER_PS_BIT);
289
290 /* Wait till the WAKER_CA_BIT changes to 0 */
291 while ((gicr_read_waker(gicr_base) & WAKER_CA_BIT) != 0U)
292 ;
293 }
294
295
296 /******************************************************************************
297 * This function marks the core as asleep in the re-distributor and ensures
298 * that the interface is quiescent.
299 *****************************************************************************/
gicv3_rdistif_mark_core_asleep(uintptr_t gicr_base)300 void gicv3_rdistif_mark_core_asleep(uintptr_t gicr_base)
301 {
302 /* Mark the connected core as asleep */
303 gicr_write_waker(gicr_base, gicr_read_waker(gicr_base) | WAKER_PS_BIT);
304
305 /* Wait till the WAKER_CA_BIT changes to 1 */
306 while ((gicr_read_waker(gicr_base) & WAKER_CA_BIT) == 0U)
307 ;
308 }
309
310
311 /*******************************************************************************
312 * This function probes the Redistributor frames when the driver is initialised
313 * and saves their base addresses. These base addresses are used later to
314 * initialise each Redistributor interface.
315 ******************************************************************************/
gicv3_rdistif_base_addrs_probe(uintptr_t * rdistif_base_addrs,unsigned int rdistif_num,uintptr_t gicr_base,mpidr_hash_fn mpidr_to_core_pos)316 void gicv3_rdistif_base_addrs_probe(uintptr_t *rdistif_base_addrs,
317 unsigned int rdistif_num,
318 uintptr_t gicr_base,
319 mpidr_hash_fn mpidr_to_core_pos)
320 {
321 u_register_t mpidr;
322 unsigned int proc_num;
323 uint64_t typer_val;
324 uintptr_t rdistif_base = gicr_base;
325
326 assert(rdistif_base_addrs != NULL);
327
328 /*
329 * Iterate over the Redistributor frames. Store the base address of each
330 * frame in the platform provided array. Use the "Processor Number"
331 * field to index into the array if the platform has not provided a hash
332 * function to convert an MPIDR (obtained from the "Affinity Value"
333 * field into a linear index.
334 */
335 do {
336 typer_val = gicr_read_typer(rdistif_base);
337 if (mpidr_to_core_pos != NULL) {
338 mpidr = mpidr_from_gicr_typer(typer_val);
339 proc_num = mpidr_to_core_pos(mpidr);
340 } else {
341 proc_num = (typer_val >> TYPER_PROC_NUM_SHIFT) &
342 TYPER_PROC_NUM_MASK;
343 }
344
345 if (proc_num < rdistif_num)
346 rdistif_base_addrs[proc_num] = rdistif_base;
347
348 rdistif_base += (1U << GICR_PCPUBASE_SHIFT);
349 } while ((typer_val & TYPER_LAST_BIT) == 0U);
350 }
351
352 /*******************************************************************************
353 * Helper function to configure the default attributes of SPIs.
354 ******************************************************************************/
gicv3_spis_config_defaults(uintptr_t gicd_base)355 void gicv3_spis_config_defaults(uintptr_t gicd_base)
356 {
357 unsigned int index, num_ints;
358
359 num_ints = gicd_read_typer(gicd_base);
360 num_ints &= TYPER_IT_LINES_NO_MASK;
361 num_ints = (num_ints + 1U) << 5;
362
363 /*
364 * Treat all SPIs as G1NS by default. The number of interrupts is
365 * calculated as 32 * (IT_LINES + 1). We do 32 at a time.
366 */
367 for (index = MIN_SPI_ID; index < num_ints; index += 32U)
368 gicd_write_igroupr(gicd_base, index, ~0U);
369
370 /* Setup the default SPI priorities doing four at a time */
371 for (index = MIN_SPI_ID; index < num_ints; index += 4U)
372 gicd_write_ipriorityr(gicd_base,
373 index,
374 GICD_IPRIORITYR_DEF_VAL);
375
376 /*
377 * Treat all SPIs as level triggered by default, write 16 at
378 * a time
379 */
380 for (index = MIN_SPI_ID; index < num_ints; index += 16U)
381 gicd_write_icfgr(gicd_base, index, 0U);
382 }
383
384 /*******************************************************************************
385 * Helper function to configure properties of secure SPIs
386 ******************************************************************************/
gicv3_secure_spis_config_props(uintptr_t gicd_base,const interrupt_prop_t * interrupt_props,unsigned int interrupt_props_num)387 unsigned int gicv3_secure_spis_config_props(uintptr_t gicd_base,
388 const interrupt_prop_t *interrupt_props,
389 unsigned int interrupt_props_num)
390 {
391 unsigned int i;
392 const interrupt_prop_t *current_prop;
393 unsigned long long gic_affinity_val;
394 unsigned int ctlr_enable = 0U;
395
396 /* Make sure there's a valid property array */
397 if (interrupt_props_num > 0U)
398 assert(interrupt_props != NULL);
399
400 for (i = 0U; i < interrupt_props_num; i++) {
401 current_prop = &interrupt_props[i];
402
403 if (current_prop->intr_num < MIN_SPI_ID)
404 continue;
405
406 /* Configure this interrupt as a secure interrupt */
407 gicd_clr_igroupr(gicd_base, current_prop->intr_num);
408
409 /* Configure this interrupt as G0 or a G1S interrupt */
410 assert((current_prop->intr_grp == INTR_GROUP0) ||
411 (current_prop->intr_grp == INTR_GROUP1S));
412 if (current_prop->intr_grp == INTR_GROUP1S) {
413 gicd_set_igrpmodr(gicd_base, current_prop->intr_num);
414 ctlr_enable |= CTLR_ENABLE_G1S_BIT;
415 } else {
416 gicd_clr_igrpmodr(gicd_base, current_prop->intr_num);
417 ctlr_enable |= CTLR_ENABLE_G0_BIT;
418 }
419
420 /* Set interrupt configuration */
421 gicd_set_icfgr(gicd_base, current_prop->intr_num,
422 current_prop->intr_cfg);
423
424 /* Set the priority of this interrupt */
425 gicd_set_ipriorityr(gicd_base, current_prop->intr_num,
426 current_prop->intr_pri);
427
428 /* Target SPIs to the primary CPU */
429 gic_affinity_val =
430 gicd_irouter_val_from_mpidr(read_mpidr(), 0U);
431 gicd_write_irouter(gicd_base, current_prop->intr_num,
432 gic_affinity_val);
433
434 /* Enable this interrupt */
435 gicd_set_isenabler(gicd_base, current_prop->intr_num);
436 }
437
438 return ctlr_enable;
439 }
440
441 /*******************************************************************************
442 * Helper function to configure the default attributes of SPIs.
443 ******************************************************************************/
gicv3_ppi_sgi_config_defaults(uintptr_t gicr_base)444 void gicv3_ppi_sgi_config_defaults(uintptr_t gicr_base)
445 {
446 unsigned int index;
447
448 /*
449 * Disable all SGIs (imp. def.)/PPIs before configuring them. This is a
450 * more scalable approach as it avoids clearing the enable bits in the
451 * GICD_CTLR
452 */
453 gicr_write_icenabler0(gicr_base, ~0U);
454 gicr_wait_for_pending_write(gicr_base);
455
456 /* Treat all SGIs/PPIs as G1NS by default. */
457 gicr_write_igroupr0(gicr_base, ~0U);
458
459 /* Setup the default PPI/SGI priorities doing four at a time */
460 for (index = 0U; index < MIN_SPI_ID; index += 4U)
461 gicr_write_ipriorityr(gicr_base,
462 index,
463 GICD_IPRIORITYR_DEF_VAL);
464
465 /* Configure all PPIs as level triggered by default */
466 gicr_write_icfgr1(gicr_base, 0U);
467 }
468
469 /*******************************************************************************
470 * Helper function to configure properties of secure G0 and G1S PPIs and SGIs.
471 ******************************************************************************/
gicv3_secure_ppi_sgi_config_props(uintptr_t gicr_base,const interrupt_prop_t * interrupt_props,unsigned int interrupt_props_num)472 unsigned int gicv3_secure_ppi_sgi_config_props(uintptr_t gicr_base,
473 const interrupt_prop_t *interrupt_props,
474 unsigned int interrupt_props_num)
475 {
476 unsigned int i;
477 const interrupt_prop_t *current_prop;
478 unsigned int ctlr_enable = 0U;
479
480 /* Make sure there's a valid property array */
481 if (interrupt_props_num > 0U)
482 assert(interrupt_props != NULL);
483
484 for (i = 0U; i < interrupt_props_num; i++) {
485 current_prop = &interrupt_props[i];
486
487 if (current_prop->intr_num >= MIN_SPI_ID)
488 continue;
489
490 /* Configure this interrupt as a secure interrupt */
491 gicr_clr_igroupr0(gicr_base, current_prop->intr_num);
492
493 /* Configure this interrupt as G0 or a G1S interrupt */
494 assert((current_prop->intr_grp == INTR_GROUP0) ||
495 (current_prop->intr_grp == INTR_GROUP1S));
496 if (current_prop->intr_grp == INTR_GROUP1S) {
497 gicr_set_igrpmodr0(gicr_base, current_prop->intr_num);
498 ctlr_enable |= CTLR_ENABLE_G1S_BIT;
499 } else {
500 gicr_clr_igrpmodr0(gicr_base, current_prop->intr_num);
501 ctlr_enable |= CTLR_ENABLE_G0_BIT;
502 }
503
504 /* Set the priority of this interrupt */
505 gicr_set_ipriorityr(gicr_base, current_prop->intr_num,
506 current_prop->intr_pri);
507
508 /*
509 * Set interrupt configuration for PPIs. Configuration for SGIs
510 * are ignored.
511 */
512 if ((current_prop->intr_num >= MIN_PPI_ID) &&
513 (current_prop->intr_num < MIN_SPI_ID)) {
514 gicr_set_icfgr1(gicr_base, current_prop->intr_num,
515 current_prop->intr_cfg);
516 }
517
518 /* Enable this interrupt */
519 gicr_set_isenabler0(gicr_base, current_prop->intr_num);
520 }
521
522 return ctlr_enable;
523 }
524