blob: 020ec1b635f90d085eb0c8c3f4b822196fcda23a [file] [log] [blame]
Achin Gupta92712a52015-09-03 14:18:02 +01001/*
Jeenu Viswambharanb6982c02018-03-22 08:57:52 +00002 * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
Achin Gupta92712a52015-09-03 14:18:02 +01003 *
dp-armfa3cf0b2017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Achin Gupta92712a52015-09-03 14:18:02 +01005 */
6
7#include <arch.h>
8#include <arch_helpers.h>
9#include <assert.h>
10#include <debug.h>
11#include <gic_common.h>
Jeenu Viswambharanaeb267c2017-09-22 08:32:09 +010012#include <interrupt_props.h>
Soby Mathew50f6fe42016-02-01 17:59:22 +000013#include "../common/gic_common_private.h"
Achin Gupta92712a52015-09-03 14:18:02 +010014#include "gicv3_private.h"
15
16/*
17 * Accessor to read the GIC Distributor IGRPMODR corresponding to the
18 * interrupt `id`, 32 interrupt IDs at a time.
19 */
20unsigned int gicd_read_igrpmodr(uintptr_t base, unsigned int id)
21{
22 unsigned n = id >> IGRPMODR_SHIFT;
23 return mmio_read_32(base + GICD_IGRPMODR + (n << 2));
24}
25
26/*
27 * Accessor to write the GIC Distributor IGRPMODR corresponding to the
28 * interrupt `id`, 32 interrupt IDs at a time.
29 */
30void gicd_write_igrpmodr(uintptr_t base, unsigned int id, unsigned int val)
31{
32 unsigned n = id >> IGRPMODR_SHIFT;
33 mmio_write_32(base + GICD_IGRPMODR + (n << 2), val);
34}
35
36/*
37 * Accessor to get the bit corresponding to interrupt ID
38 * in GIC Distributor IGRPMODR.
39 */
40unsigned int gicd_get_igrpmodr(uintptr_t base, unsigned int id)
41{
42 unsigned bit_num = id & ((1 << IGRPMODR_SHIFT) - 1);
43 unsigned int reg_val = gicd_read_igrpmodr(base, id);
44
45 return (reg_val >> bit_num) & 0x1;
46}
47
48/*
49 * Accessor to set the bit corresponding to interrupt ID
50 * in GIC Distributor IGRPMODR.
51 */
52void gicd_set_igrpmodr(uintptr_t base, unsigned int id)
53{
54 unsigned bit_num = id & ((1 << IGRPMODR_SHIFT) - 1);
55 unsigned int reg_val = gicd_read_igrpmodr(base, id);
56
57 gicd_write_igrpmodr(base, id, reg_val | (1 << bit_num));
58}
59
60/*
61 * Accessor to clear the bit corresponding to interrupt ID
62 * in GIC Distributor IGRPMODR.
63 */
64void gicd_clr_igrpmodr(uintptr_t base, unsigned int id)
65{
66 unsigned bit_num = id & ((1 << IGRPMODR_SHIFT) - 1);
67 unsigned int reg_val = gicd_read_igrpmodr(base, id);
68
69 gicd_write_igrpmodr(base, id, reg_val & ~(1 << bit_num));
70}
71
72/*
73 * Accessor to read the GIC Re-distributor IPRIORITYR corresponding to the
74 * interrupt `id`, 4 interrupts IDs at a time.
75 */
76unsigned int gicr_read_ipriorityr(uintptr_t base, unsigned int id)
77{
78 unsigned n = id >> IPRIORITYR_SHIFT;
79 return mmio_read_32(base + GICR_IPRIORITYR + (n << 2));
80}
81
82/*
83 * Accessor to write the GIC Re-distributor IPRIORITYR corresponding to the
84 * interrupt `id`, 4 interrupts IDs at a time.
85 */
86void gicr_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val)
87{
88 unsigned n = id >> IPRIORITYR_SHIFT;
89 mmio_write_32(base + GICR_IPRIORITYR + (n << 2), val);
90}
91
92/*
93 * Accessor to get the bit corresponding to interrupt ID
94 * from GIC Re-distributor IGROUPR0.
95 */
96unsigned int gicr_get_igroupr0(uintptr_t base, unsigned int id)
97{
98 unsigned bit_num = id & ((1 << IGROUPR_SHIFT) - 1);
99 unsigned int reg_val = gicr_read_igroupr0(base);
100
101 return (reg_val >> bit_num) & 0x1;
102}
103
104/*
105 * Accessor to set the bit corresponding to interrupt ID
106 * in GIC Re-distributor IGROUPR0.
107 */
108void gicr_set_igroupr0(uintptr_t base, unsigned int id)
109{
110 unsigned bit_num = id & ((1 << IGROUPR_SHIFT) - 1);
111 unsigned int reg_val = gicr_read_igroupr0(base);
112
113 gicr_write_igroupr0(base, reg_val | (1 << bit_num));
114}
115
116/*
117 * Accessor to clear the bit corresponding to interrupt ID
118 * in GIC Re-distributor IGROUPR0.
119 */
120void gicr_clr_igroupr0(uintptr_t base, unsigned int id)
121{
122 unsigned bit_num = id & ((1 << IGROUPR_SHIFT) - 1);
123 unsigned int reg_val = gicr_read_igroupr0(base);
124
125 gicr_write_igroupr0(base, reg_val & ~(1 << bit_num));
126}
127
128/*
129 * Accessor to get the bit corresponding to interrupt ID
130 * from GIC Re-distributor IGRPMODR0.
131 */
132unsigned int gicr_get_igrpmodr0(uintptr_t base, unsigned int id)
133{
134 unsigned bit_num = id & ((1 << IGRPMODR_SHIFT) - 1);
135 unsigned int reg_val = gicr_read_igrpmodr0(base);
136
137 return (reg_val >> bit_num) & 0x1;
138}
139
140/*
141 * Accessor to set the bit corresponding to interrupt ID
142 * in GIC Re-distributor IGRPMODR0.
143 */
144void gicr_set_igrpmodr0(uintptr_t base, unsigned int id)
145{
146 unsigned bit_num = id & ((1 << IGRPMODR_SHIFT) - 1);
147 unsigned int reg_val = gicr_read_igrpmodr0(base);
148
149 gicr_write_igrpmodr0(base, reg_val | (1 << bit_num));
150}
151
152/*
153 * Accessor to clear the bit corresponding to interrupt ID
154 * in GIC Re-distributor IGRPMODR0.
155 */
156void gicr_clr_igrpmodr0(uintptr_t base, unsigned int id)
157{
158 unsigned bit_num = id & ((1 << IGRPMODR_SHIFT) - 1);
159 unsigned int reg_val = gicr_read_igrpmodr0(base);
160
161 gicr_write_igrpmodr0(base, reg_val & ~(1 << bit_num));
162}
163
164/*
165 * Accessor to set the bit corresponding to interrupt ID
166 * in GIC Re-distributor ISENABLER0.
167 */
168void gicr_set_isenabler0(uintptr_t base, unsigned int id)
169{
170 unsigned bit_num = id & ((1 << ISENABLER_SHIFT) - 1);
171
172 gicr_write_isenabler0(base, (1 << bit_num));
173}
174
Soby Mathew421259e2016-01-15 14:20:57 +0000175/*
Jeenu Viswambharan24e70292017-09-22 08:32:09 +0100176 * Accessor to set the bit corresponding to interrupt ID in GIC Re-distributor
Jeenu Viswambharan0fcdfff2017-09-22 08:32:09 +0100177 * ICENABLER0.
178 */
179void gicr_set_icenabler0(uintptr_t base, unsigned int id)
180{
181 unsigned bit_num = id & ((1 << ICENABLER_SHIFT) - 1);
182
183 gicr_write_icenabler0(base, (1 << bit_num));
184}
185
186/*
187 * Accessor to set the bit corresponding to interrupt ID in GIC Re-distributor
Jeenu Viswambharan24e70292017-09-22 08:32:09 +0100188 * ISACTIVER0.
189 */
190unsigned int gicr_get_isactiver0(uintptr_t base, unsigned int id)
191{
192 unsigned bit_num = id & ((1 << ISACTIVER_SHIFT) - 1);
193 unsigned int reg_val = gicr_read_isactiver0(base);
194
195 return (reg_val >> bit_num) & 0x1;
196}
197
198/*
Jeenu Viswambharaneb1c12c2017-09-22 08:32:09 +0100199 * Accessor to clear the bit corresponding to interrupt ID in GIC Re-distributor
200 * ICPENDRR0.
201 */
202void gicr_set_icpendr0(uintptr_t base, unsigned int id)
203{
204 unsigned bit_num = id & ((1 << ICPENDR_SHIFT) - 1);
205
206 gicr_write_icpendr0(base, (1 << bit_num));
207}
208
209/*
210 * Accessor to set the bit corresponding to interrupt ID in GIC Re-distributor
211 * ISPENDR0.
212 */
213void gicr_set_ispendr0(uintptr_t base, unsigned int id)
214{
215 unsigned bit_num = id & ((1 << ISPENDR_SHIFT) - 1);
216
217 gicr_write_ispendr0(base, (1 << bit_num));
218}
219
220/*
Soby Mathew421259e2016-01-15 14:20:57 +0000221 * Accessor to set the byte corresponding to interrupt ID
222 * in GIC Re-distributor IPRIORITYR.
223 */
224void gicr_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri)
225{
226 mmio_write_8(base + GICR_IPRIORITYR + id, pri & GIC_PRI_MASK);
227}
228
Jeenu Viswambharan4684bce2017-09-22 08:32:09 +0100229/*
230 * Accessor to set the bit fields corresponding to interrupt ID
231 * in GIC Re-distributor ICFGR0.
232 */
233void gicr_set_icfgr0(uintptr_t base, unsigned int id, unsigned int cfg)
234{
Jeenu Viswambharanb6982c02018-03-22 08:57:52 +0000235 /* Interrupt configuration is a 2-bit field */
236 unsigned int bit_num = id & ((1 << ICFGR_SHIFT) - 1);
237 unsigned int bit_shift = bit_num << 1;
238
Jeenu Viswambharan4684bce2017-09-22 08:32:09 +0100239 uint32_t reg_val = gicr_read_icfgr0(base);
240
241 /* Clear the field, and insert required configuration */
Jeenu Viswambharanb6982c02018-03-22 08:57:52 +0000242 reg_val &= ~(GIC_CFG_MASK << bit_shift);
243 reg_val |= ((cfg & GIC_CFG_MASK) << bit_shift);
Jeenu Viswambharan4684bce2017-09-22 08:32:09 +0100244
245 gicr_write_icfgr0(base, reg_val);
246}
247
248/*
249 * Accessor to set the bit fields corresponding to interrupt ID
250 * in GIC Re-distributor ICFGR1.
251 */
252void gicr_set_icfgr1(uintptr_t base, unsigned int id, unsigned int cfg)
253{
Jeenu Viswambharanb6982c02018-03-22 08:57:52 +0000254 /* Interrupt configuration is a 2-bit field */
255 unsigned int bit_num = id & ((1 << ICFGR_SHIFT) - 1);
256 unsigned int bit_shift = bit_num << 1;
257
Jeenu Viswambharan4684bce2017-09-22 08:32:09 +0100258 uint32_t reg_val = gicr_read_icfgr1(base);
259
260 /* Clear the field, and insert required configuration */
Jeenu Viswambharanb6982c02018-03-22 08:57:52 +0000261 reg_val &= ~(GIC_CFG_MASK << bit_shift);
262 reg_val |= ((cfg & GIC_CFG_MASK) << bit_shift);
Jeenu Viswambharan4684bce2017-09-22 08:32:09 +0100263
264 gicr_write_icfgr1(base, reg_val);
265}
266
Achin Gupta92712a52015-09-03 14:18:02 +0100267/******************************************************************************
268 * This function marks the core as awake in the re-distributor and
269 * ensures that the interface is active.
270 *****************************************************************************/
271void gicv3_rdistif_mark_core_awake(uintptr_t gicr_base)
272{
273 /*
274 * The WAKER_PS_BIT should be changed to 0
275 * only when WAKER_CA_BIT is 1.
276 */
277 assert(gicr_read_waker(gicr_base) & WAKER_CA_BIT);
278
279 /* Mark the connected core as awake */
280 gicr_write_waker(gicr_base, gicr_read_waker(gicr_base) & ~WAKER_PS_BIT);
281
282 /* Wait till the WAKER_CA_BIT changes to 0 */
283 while (gicr_read_waker(gicr_base) & WAKER_CA_BIT)
284 ;
285}
286
287
288/******************************************************************************
289 * This function marks the core as asleep in the re-distributor and ensures
290 * that the interface is quiescent.
291 *****************************************************************************/
292void gicv3_rdistif_mark_core_asleep(uintptr_t gicr_base)
293{
294 /* Mark the connected core as asleep */
295 gicr_write_waker(gicr_base, gicr_read_waker(gicr_base) | WAKER_PS_BIT);
296
297 /* Wait till the WAKER_CA_BIT changes to 1 */
298 while (!(gicr_read_waker(gicr_base) & WAKER_CA_BIT))
299 ;
300}
301
302
303/*******************************************************************************
304 * This function probes the Redistributor frames when the driver is initialised
305 * and saves their base addresses. These base addresses are used later to
306 * initialise each Redistributor interface.
307 ******************************************************************************/
308void gicv3_rdistif_base_addrs_probe(uintptr_t *rdistif_base_addrs,
309 unsigned int rdistif_num,
310 uintptr_t gicr_base,
311 mpidr_hash_fn mpidr_to_core_pos)
312{
Soby Mathewa0fedc42016-06-16 14:52:04 +0100313 u_register_t mpidr;
Achin Gupta92712a52015-09-03 14:18:02 +0100314 unsigned int proc_num;
315 unsigned long long typer_val;
316 uintptr_t rdistif_base = gicr_base;
317
318 assert(rdistif_base_addrs);
319
320 /*
321 * Iterate over the Redistributor frames. Store the base address of each
322 * frame in the platform provided array. Use the "Processor Number"
323 * field to index into the array if the platform has not provided a hash
324 * function to convert an MPIDR (obtained from the "Affinity Value"
325 * field into a linear index.
326 */
327 do {
328 typer_val = gicr_read_typer(rdistif_base);
329 if (mpidr_to_core_pos) {
330 mpidr = mpidr_from_gicr_typer(typer_val);
331 proc_num = mpidr_to_core_pos(mpidr);
332 } else {
333 proc_num = (typer_val >> TYPER_PROC_NUM_SHIFT) &
334 TYPER_PROC_NUM_MASK;
335 }
336 assert(proc_num < rdistif_num);
337 rdistif_base_addrs[proc_num] = rdistif_base;
338 rdistif_base += (1 << GICR_PCPUBASE_SHIFT);
339 } while (!(typer_val & TYPER_LAST_BIT));
340}
341
342/*******************************************************************************
343 * Helper function to configure the default attributes of SPIs.
344 ******************************************************************************/
345void gicv3_spis_configure_defaults(uintptr_t gicd_base)
346{
347 unsigned int index, num_ints;
348
349 num_ints = gicd_read_typer(gicd_base);
350 num_ints &= TYPER_IT_LINES_NO_MASK;
351 num_ints = (num_ints + 1) << 5;
352
353 /*
354 * Treat all SPIs as G1NS by default. The number of interrupts is
355 * calculated as 32 * (IT_LINES + 1). We do 32 at a time.
356 */
357 for (index = MIN_SPI_ID; index < num_ints; index += 32)
358 gicd_write_igroupr(gicd_base, index, ~0U);
359
360 /* Setup the default SPI priorities doing four at a time */
361 for (index = MIN_SPI_ID; index < num_ints; index += 4)
362 gicd_write_ipriorityr(gicd_base,
363 index,
364 GICD_IPRIORITYR_DEF_VAL);
365
366 /*
367 * Treat all SPIs as level triggered by default, write 16 at
368 * a time
369 */
370 for (index = MIN_SPI_ID; index < num_ints; index += 16)
371 gicd_write_icfgr(gicd_base, index, 0);
372}
373
Jeenu Viswambharanaeb267c2017-09-22 08:32:09 +0100374#if !ERROR_DEPRECATED
Achin Gupta92712a52015-09-03 14:18:02 +0100375/*******************************************************************************
376 * Helper function to configure secure G0 and G1S SPIs.
377 ******************************************************************************/
378void gicv3_secure_spis_configure(uintptr_t gicd_base,
379 unsigned int num_ints,
380 const unsigned int *sec_intr_list,
381 unsigned int int_grp)
382{
383 unsigned int index, irq_num;
Soby Mathewa0fedc42016-06-16 14:52:04 +0100384 unsigned long long gic_affinity_val;
Achin Gupta92712a52015-09-03 14:18:02 +0100385
Soby Mathew5c5c36b2015-12-03 14:12:54 +0000386 assert((int_grp == INTR_GROUP1S) || (int_grp == INTR_GROUP0));
Achin Gupta92712a52015-09-03 14:18:02 +0100387 /* If `num_ints` is not 0, ensure that `sec_intr_list` is not NULL */
388 assert(num_ints ? (uintptr_t)sec_intr_list : 1);
389
390 for (index = 0; index < num_ints; index++) {
391 irq_num = sec_intr_list[index];
392 if (irq_num >= MIN_SPI_ID) {
393
394 /* Configure this interrupt as a secure interrupt */
395 gicd_clr_igroupr(gicd_base, irq_num);
396
397 /* Configure this interrupt as G0 or a G1S interrupt */
Soby Mathew5c5c36b2015-12-03 14:12:54 +0000398 if (int_grp == INTR_GROUP1S)
Achin Gupta92712a52015-09-03 14:18:02 +0100399 gicd_set_igrpmodr(gicd_base, irq_num);
400 else
401 gicd_clr_igrpmodr(gicd_base, irq_num);
402
403 /* Set the priority of this interrupt */
Soby Mathew421259e2016-01-15 14:20:57 +0000404 gicd_set_ipriorityr(gicd_base,
Achin Gupta92712a52015-09-03 14:18:02 +0100405 irq_num,
406 GIC_HIGHEST_SEC_PRIORITY);
407
408 /* Target SPIs to the primary CPU */
409 gic_affinity_val =
410 gicd_irouter_val_from_mpidr(read_mpidr(), 0);
411 gicd_write_irouter(gicd_base,
412 irq_num,
413 gic_affinity_val);
414
415 /* Enable this interrupt */
416 gicd_set_isenabler(gicd_base, irq_num);
417 }
418 }
419
420}
Jeenu Viswambharanaeb267c2017-09-22 08:32:09 +0100421#endif
Achin Gupta92712a52015-09-03 14:18:02 +0100422
423/*******************************************************************************
Jeenu Viswambharanaeb267c2017-09-22 08:32:09 +0100424 * Helper function to configure properties of secure SPIs
425 ******************************************************************************/
426unsigned int gicv3_secure_spis_configure_props(uintptr_t gicd_base,
427 const interrupt_prop_t *interrupt_props,
428 unsigned int interrupt_props_num)
429{
430 unsigned int i;
431 const interrupt_prop_t *current_prop;
432 unsigned long long gic_affinity_val;
433 unsigned int ctlr_enable = 0;
434
435 /* Make sure there's a valid property array */
Andre Przywarae8e94e82017-11-09 12:08:00 -0600436 assert(interrupt_props_num > 0 ? interrupt_props != NULL : 1);
Jeenu Viswambharanaeb267c2017-09-22 08:32:09 +0100437
438 for (i = 0; i < interrupt_props_num; i++) {
439 current_prop = &interrupt_props[i];
440
441 if (current_prop->intr_num < MIN_SPI_ID)
442 continue;
443
444 /* Configure this interrupt as a secure interrupt */
445 gicd_clr_igroupr(gicd_base, current_prop->intr_num);
446
447 /* Configure this interrupt as G0 or a G1S interrupt */
448 assert((current_prop->intr_grp == INTR_GROUP0) ||
449 (current_prop->intr_grp == INTR_GROUP1S));
450 if (current_prop->intr_grp == INTR_GROUP1S) {
451 gicd_set_igrpmodr(gicd_base, current_prop->intr_num);
452 ctlr_enable |= CTLR_ENABLE_G1S_BIT;
453 } else {
454 gicd_clr_igrpmodr(gicd_base, current_prop->intr_num);
455 ctlr_enable |= CTLR_ENABLE_G0_BIT;
456 }
457
458 /* Set interrupt configuration */
459 gicd_set_icfgr(gicd_base, current_prop->intr_num,
460 current_prop->intr_cfg);
461
462 /* Set the priority of this interrupt */
463 gicd_set_ipriorityr(gicd_base, current_prop->intr_num,
464 current_prop->intr_pri);
465
466 /* Target SPIs to the primary CPU */
467 gic_affinity_val = gicd_irouter_val_from_mpidr(read_mpidr(), 0);
468 gicd_write_irouter(gicd_base, current_prop->intr_num,
469 gic_affinity_val);
470
471 /* Enable this interrupt */
472 gicd_set_isenabler(gicd_base, current_prop->intr_num);
473 }
474
475 return ctlr_enable;
476}
477
478/*******************************************************************************
Achin Gupta92712a52015-09-03 14:18:02 +0100479 * Helper function to configure the default attributes of SPIs.
480 ******************************************************************************/
481void gicv3_ppi_sgi_configure_defaults(uintptr_t gicr_base)
482{
483 unsigned int index;
484
485 /*
486 * Disable all SGIs (imp. def.)/PPIs before configuring them. This is a
487 * more scalable approach as it avoids clearing the enable bits in the
488 * GICD_CTLR
489 */
490 gicr_write_icenabler0(gicr_base, ~0);
491 gicr_wait_for_pending_write(gicr_base);
492
493 /* Treat all SGIs/PPIs as G1NS by default. */
494 gicr_write_igroupr0(gicr_base, ~0U);
495
496 /* Setup the default PPI/SGI priorities doing four at a time */
497 for (index = 0; index < MIN_SPI_ID; index += 4)
498 gicr_write_ipriorityr(gicr_base,
499 index,
500 GICD_IPRIORITYR_DEF_VAL);
501
502 /* Configure all PPIs as level triggered by default */
503 gicr_write_icfgr1(gicr_base, 0);
504}
505
Jeenu Viswambharanaeb267c2017-09-22 08:32:09 +0100506#if !ERROR_DEPRECATED
Achin Gupta92712a52015-09-03 14:18:02 +0100507/*******************************************************************************
508 * Helper function to configure secure G0 and G1S SPIs.
509 ******************************************************************************/
510void gicv3_secure_ppi_sgi_configure(uintptr_t gicr_base,
511 unsigned int num_ints,
512 const unsigned int *sec_intr_list,
513 unsigned int int_grp)
514{
515 unsigned int index, irq_num;
516
Soby Mathew5c5c36b2015-12-03 14:12:54 +0000517 assert((int_grp == INTR_GROUP1S) || (int_grp == INTR_GROUP0));
Achin Gupta92712a52015-09-03 14:18:02 +0100518 /* If `num_ints` is not 0, ensure that `sec_intr_list` is not NULL */
519 assert(num_ints ? (uintptr_t)sec_intr_list : 1);
520
521 for (index = 0; index < num_ints; index++) {
522 irq_num = sec_intr_list[index];
523 if (irq_num < MIN_SPI_ID) {
524
525 /* Configure this interrupt as a secure interrupt */
526 gicr_clr_igroupr0(gicr_base, irq_num);
527
528 /* Configure this interrupt as G0 or a G1S interrupt */
Soby Mathew5c5c36b2015-12-03 14:12:54 +0000529 if (int_grp == INTR_GROUP1S)
Achin Gupta92712a52015-09-03 14:18:02 +0100530 gicr_set_igrpmodr0(gicr_base, irq_num);
531 else
532 gicr_clr_igrpmodr0(gicr_base, irq_num);
533
534 /* Set the priority of this interrupt */
Soby Mathew421259e2016-01-15 14:20:57 +0000535 gicr_set_ipriorityr(gicr_base,
Achin Gupta92712a52015-09-03 14:18:02 +0100536 irq_num,
537 GIC_HIGHEST_SEC_PRIORITY);
538
539 /* Enable this interrupt */
540 gicr_set_isenabler0(gicr_base, irq_num);
541 }
542 }
543}
Jeenu Viswambharanaeb267c2017-09-22 08:32:09 +0100544#endif
545
546/*******************************************************************************
547 * Helper function to configure properties of secure G0 and G1S PPIs and SGIs.
548 ******************************************************************************/
Jeenu Viswambharan88d8f452017-11-07 08:38:23 +0000549unsigned int gicv3_secure_ppi_sgi_configure_props(uintptr_t gicr_base,
Jeenu Viswambharanaeb267c2017-09-22 08:32:09 +0100550 const interrupt_prop_t *interrupt_props,
551 unsigned int interrupt_props_num)
552{
553 unsigned int i;
554 const interrupt_prop_t *current_prop;
Jeenu Viswambharan88d8f452017-11-07 08:38:23 +0000555 unsigned int ctlr_enable = 0;
Jeenu Viswambharanaeb267c2017-09-22 08:32:09 +0100556
557 /* Make sure there's a valid property array */
Andre Przywarae8e94e82017-11-09 12:08:00 -0600558 assert(interrupt_props_num > 0 ? interrupt_props != NULL : 1);
Jeenu Viswambharanaeb267c2017-09-22 08:32:09 +0100559
560 for (i = 0; i < interrupt_props_num; i++) {
561 current_prop = &interrupt_props[i];
562
563 if (current_prop->intr_num >= MIN_SPI_ID)
564 continue;
565
566 /* Configure this interrupt as a secure interrupt */
567 gicr_clr_igroupr0(gicr_base, current_prop->intr_num);
568
569 /* Configure this interrupt as G0 or a G1S interrupt */
570 assert((current_prop->intr_grp == INTR_GROUP0) ||
571 (current_prop->intr_grp == INTR_GROUP1S));
Jeenu Viswambharan88d8f452017-11-07 08:38:23 +0000572 if (current_prop->intr_grp == INTR_GROUP1S) {
Jeenu Viswambharanaeb267c2017-09-22 08:32:09 +0100573 gicr_set_igrpmodr0(gicr_base, current_prop->intr_num);
Jeenu Viswambharan88d8f452017-11-07 08:38:23 +0000574 ctlr_enable |= CTLR_ENABLE_G1S_BIT;
575 } else {
Jeenu Viswambharanaeb267c2017-09-22 08:32:09 +0100576 gicr_clr_igrpmodr0(gicr_base, current_prop->intr_num);
Jeenu Viswambharan88d8f452017-11-07 08:38:23 +0000577 ctlr_enable |= CTLR_ENABLE_G0_BIT;
578 }
Jeenu Viswambharanaeb267c2017-09-22 08:32:09 +0100579
580 /* Set the priority of this interrupt */
581 gicr_set_ipriorityr(gicr_base, current_prop->intr_num,
582 current_prop->intr_pri);
583
584 /*
585 * Set interrupt configuration for PPIs. Configuration for SGIs
586 * are ignored.
587 */
588 if ((current_prop->intr_num >= MIN_PPI_ID) &&
589 (current_prop->intr_num < MIN_SPI_ID)) {
590 gicr_set_icfgr1(gicr_base, current_prop->intr_num,
591 current_prop->intr_cfg);
592 }
593
594 /* Enable this interrupt */
595 gicr_set_isenabler0(gicr_base, current_prop->intr_num);
596 }
Jeenu Viswambharan88d8f452017-11-07 08:38:23 +0000597
598 return ctlr_enable;
Jeenu Viswambharanaeb267c2017-09-22 08:32:09 +0100599}