blob: d5aaf96966ab2506c1eb7f5318cb3b18f4e9555c [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
Antonio Nino Diaze0f90632018-12-14 00:18:21 +00007#include <assert.h>
8
Achin Gupta92712a52015-09-03 14:18:02 +01009#include <arch.h>
10#include <arch_helpers.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000011#include <common/debug.h>
12#include <common/interrupt_props.h>
13#include <drivers/arm/gic_common.h>
14
Soby Mathew50f6fe42016-02-01 17:59:22 +000015#include "../common/gic_common_private.h"
Achin Gupta92712a52015-09-03 14:18:02 +010016#include "gicv3_private.h"
17
Achin Gupta92712a52015-09-03 14:18:02 +010018/******************************************************************************
19 * This function marks the core as awake in the re-distributor and
20 * ensures that the interface is active.
21 *****************************************************************************/
22void gicv3_rdistif_mark_core_awake(uintptr_t gicr_base)
23{
24 /*
25 * The WAKER_PS_BIT should be changed to 0
26 * only when WAKER_CA_BIT is 1.
27 */
Antonio Nino Diazca994e72018-08-21 10:02:33 +010028 assert((gicr_read_waker(gicr_base) & WAKER_CA_BIT) != 0U);
Achin Gupta92712a52015-09-03 14:18:02 +010029
30 /* Mark the connected core as awake */
31 gicr_write_waker(gicr_base, gicr_read_waker(gicr_base) & ~WAKER_PS_BIT);
32
33 /* Wait till the WAKER_CA_BIT changes to 0 */
Antonio Nino Diazca994e72018-08-21 10:02:33 +010034 while ((gicr_read_waker(gicr_base) & WAKER_CA_BIT) != 0U)
Achin Gupta92712a52015-09-03 14:18:02 +010035 ;
36}
37
Achin Gupta92712a52015-09-03 14:18:02 +010038/******************************************************************************
39 * This function marks the core as asleep in the re-distributor and ensures
40 * that the interface is quiescent.
41 *****************************************************************************/
42void gicv3_rdistif_mark_core_asleep(uintptr_t gicr_base)
43{
44 /* Mark the connected core as asleep */
45 gicr_write_waker(gicr_base, gicr_read_waker(gicr_base) | WAKER_PS_BIT);
46
47 /* Wait till the WAKER_CA_BIT changes to 1 */
Antonio Nino Diazca994e72018-08-21 10:02:33 +010048 while ((gicr_read_waker(gicr_base) & WAKER_CA_BIT) == 0U)
Achin Gupta92712a52015-09-03 14:18:02 +010049 ;
50}
51
52
53/*******************************************************************************
54 * This function probes the Redistributor frames when the driver is initialised
55 * and saves their base addresses. These base addresses are used later to
56 * initialise each Redistributor interface.
57 ******************************************************************************/
58void gicv3_rdistif_base_addrs_probe(uintptr_t *rdistif_base_addrs,
59 unsigned int rdistif_num,
60 uintptr_t gicr_base,
61 mpidr_hash_fn mpidr_to_core_pos)
62{
Soby Mathewa0fedc42016-06-16 14:52:04 +010063 u_register_t mpidr;
Achin Gupta92712a52015-09-03 14:18:02 +010064 unsigned int proc_num;
Antonio Nino Diazca994e72018-08-21 10:02:33 +010065 uint64_t typer_val;
Achin Gupta92712a52015-09-03 14:18:02 +010066 uintptr_t rdistif_base = gicr_base;
67
Antonio Nino Diazca994e72018-08-21 10:02:33 +010068 assert(rdistif_base_addrs != NULL);
Achin Gupta92712a52015-09-03 14:18:02 +010069
70 /*
71 * Iterate over the Redistributor frames. Store the base address of each
72 * frame in the platform provided array. Use the "Processor Number"
73 * field to index into the array if the platform has not provided a hash
74 * function to convert an MPIDR (obtained from the "Affinity Value"
75 * field into a linear index.
76 */
77 do {
78 typer_val = gicr_read_typer(rdistif_base);
Antonio Nino Diazca994e72018-08-21 10:02:33 +010079 if (mpidr_to_core_pos != NULL) {
Achin Gupta92712a52015-09-03 14:18:02 +010080 mpidr = mpidr_from_gicr_typer(typer_val);
81 proc_num = mpidr_to_core_pos(mpidr);
82 } else {
83 proc_num = (typer_val >> TYPER_PROC_NUM_SHIFT) &
84 TYPER_PROC_NUM_MASK;
85 }
Soby Mathewd1463bd2019-01-17 14:57:54 +000086
87 if (proc_num < rdistif_num)
88 rdistif_base_addrs[proc_num] = rdistif_base;
89
Antonio Nino Diazca994e72018-08-21 10:02:33 +010090 rdistif_base += (1U << GICR_PCPUBASE_SHIFT);
91 } while ((typer_val & TYPER_LAST_BIT) == 0U);
Achin Gupta92712a52015-09-03 14:18:02 +010092}
93
94/*******************************************************************************
95 * Helper function to configure the default attributes of SPIs.
96 ******************************************************************************/
Daniel Boulby4e83abb2018-05-01 15:15:34 +010097void gicv3_spis_config_defaults(uintptr_t gicd_base)
Achin Gupta92712a52015-09-03 14:18:02 +010098{
99 unsigned int index, num_ints;
100
101 num_ints = gicd_read_typer(gicd_base);
102 num_ints &= TYPER_IT_LINES_NO_MASK;
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100103 num_ints = (num_ints + 1U) << 5;
Achin Gupta92712a52015-09-03 14:18:02 +0100104
105 /*
106 * Treat all SPIs as G1NS by default. The number of interrupts is
107 * calculated as 32 * (IT_LINES + 1). We do 32 at a time.
108 */
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100109 for (index = MIN_SPI_ID; index < num_ints; index += 32U)
Achin Gupta92712a52015-09-03 14:18:02 +0100110 gicd_write_igroupr(gicd_base, index, ~0U);
111
112 /* Setup the default SPI priorities doing four at a time */
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100113 for (index = MIN_SPI_ID; index < num_ints; index += 4U)
Achin Gupta92712a52015-09-03 14:18:02 +0100114 gicd_write_ipriorityr(gicd_base,
115 index,
116 GICD_IPRIORITYR_DEF_VAL);
117
118 /*
119 * Treat all SPIs as level triggered by default, write 16 at
120 * a time
121 */
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100122 for (index = MIN_SPI_ID; index < num_ints; index += 16U)
123 gicd_write_icfgr(gicd_base, index, 0U);
Achin Gupta92712a52015-09-03 14:18:02 +0100124}
125
Achin Gupta92712a52015-09-03 14:18:02 +0100126/*******************************************************************************
Jeenu Viswambharanaeb267c2017-09-22 08:32:09 +0100127 * Helper function to configure properties of secure SPIs
128 ******************************************************************************/
Daniel Boulby4e83abb2018-05-01 15:15:34 +0100129unsigned int gicv3_secure_spis_config_props(uintptr_t gicd_base,
Jeenu Viswambharanaeb267c2017-09-22 08:32:09 +0100130 const interrupt_prop_t *interrupt_props,
131 unsigned int interrupt_props_num)
132{
133 unsigned int i;
134 const interrupt_prop_t *current_prop;
135 unsigned long long gic_affinity_val;
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100136 unsigned int ctlr_enable = 0U;
Jeenu Viswambharanaeb267c2017-09-22 08:32:09 +0100137
138 /* Make sure there's a valid property array */
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100139 if (interrupt_props_num > 0U)
140 assert(interrupt_props != NULL);
Jeenu Viswambharanaeb267c2017-09-22 08:32:09 +0100141
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100142 for (i = 0U; i < interrupt_props_num; i++) {
Jeenu Viswambharanaeb267c2017-09-22 08:32:09 +0100143 current_prop = &interrupt_props[i];
144
145 if (current_prop->intr_num < MIN_SPI_ID)
146 continue;
147
148 /* Configure this interrupt as a secure interrupt */
149 gicd_clr_igroupr(gicd_base, current_prop->intr_num);
150
151 /* Configure this interrupt as G0 or a G1S interrupt */
152 assert((current_prop->intr_grp == INTR_GROUP0) ||
153 (current_prop->intr_grp == INTR_GROUP1S));
154 if (current_prop->intr_grp == INTR_GROUP1S) {
155 gicd_set_igrpmodr(gicd_base, current_prop->intr_num);
156 ctlr_enable |= CTLR_ENABLE_G1S_BIT;
157 } else {
158 gicd_clr_igrpmodr(gicd_base, current_prop->intr_num);
159 ctlr_enable |= CTLR_ENABLE_G0_BIT;
160 }
161
162 /* Set interrupt configuration */
163 gicd_set_icfgr(gicd_base, current_prop->intr_num,
164 current_prop->intr_cfg);
165
166 /* Set the priority of this interrupt */
167 gicd_set_ipriorityr(gicd_base, current_prop->intr_num,
168 current_prop->intr_pri);
169
170 /* Target SPIs to the primary CPU */
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100171 gic_affinity_val =
172 gicd_irouter_val_from_mpidr(read_mpidr(), 0U);
Jeenu Viswambharanaeb267c2017-09-22 08:32:09 +0100173 gicd_write_irouter(gicd_base, current_prop->intr_num,
174 gic_affinity_val);
175
176 /* Enable this interrupt */
177 gicd_set_isenabler(gicd_base, current_prop->intr_num);
178 }
179
180 return ctlr_enable;
181}
182
183/*******************************************************************************
Achin Gupta92712a52015-09-03 14:18:02 +0100184 * Helper function to configure the default attributes of SPIs.
185 ******************************************************************************/
Daniel Boulby4e83abb2018-05-01 15:15:34 +0100186void gicv3_ppi_sgi_config_defaults(uintptr_t gicr_base)
Achin Gupta92712a52015-09-03 14:18:02 +0100187{
188 unsigned int index;
189
190 /*
191 * Disable all SGIs (imp. def.)/PPIs before configuring them. This is a
192 * more scalable approach as it avoids clearing the enable bits in the
193 * GICD_CTLR
194 */
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100195 gicr_write_icenabler0(gicr_base, ~0U);
Achin Gupta92712a52015-09-03 14:18:02 +0100196 gicr_wait_for_pending_write(gicr_base);
197
198 /* Treat all SGIs/PPIs as G1NS by default. */
199 gicr_write_igroupr0(gicr_base, ~0U);
200
201 /* Setup the default PPI/SGI priorities doing four at a time */
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100202 for (index = 0U; index < MIN_SPI_ID; index += 4U)
Achin Gupta92712a52015-09-03 14:18:02 +0100203 gicr_write_ipriorityr(gicr_base,
204 index,
205 GICD_IPRIORITYR_DEF_VAL);
206
207 /* Configure all PPIs as level triggered by default */
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100208 gicr_write_icfgr1(gicr_base, 0U);
Achin Gupta92712a52015-09-03 14:18:02 +0100209}
Jeenu Viswambharanaeb267c2017-09-22 08:32:09 +0100210
211/*******************************************************************************
212 * Helper function to configure properties of secure G0 and G1S PPIs and SGIs.
213 ******************************************************************************/
Daniel Boulby4e83abb2018-05-01 15:15:34 +0100214unsigned int gicv3_secure_ppi_sgi_config_props(uintptr_t gicr_base,
Jeenu Viswambharanaeb267c2017-09-22 08:32:09 +0100215 const interrupt_prop_t *interrupt_props,
216 unsigned int interrupt_props_num)
217{
218 unsigned int i;
219 const interrupt_prop_t *current_prop;
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100220 unsigned int ctlr_enable = 0U;
Jeenu Viswambharanaeb267c2017-09-22 08:32:09 +0100221
222 /* Make sure there's a valid property array */
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100223 if (interrupt_props_num > 0U)
224 assert(interrupt_props != NULL);
Jeenu Viswambharanaeb267c2017-09-22 08:32:09 +0100225
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100226 for (i = 0U; i < interrupt_props_num; i++) {
Jeenu Viswambharanaeb267c2017-09-22 08:32:09 +0100227 current_prop = &interrupt_props[i];
228
229 if (current_prop->intr_num >= MIN_SPI_ID)
230 continue;
231
232 /* Configure this interrupt as a secure interrupt */
233 gicr_clr_igroupr0(gicr_base, current_prop->intr_num);
234
235 /* Configure this interrupt as G0 or a G1S interrupt */
236 assert((current_prop->intr_grp == INTR_GROUP0) ||
237 (current_prop->intr_grp == INTR_GROUP1S));
Jeenu Viswambharan88d8f452017-11-07 08:38:23 +0000238 if (current_prop->intr_grp == INTR_GROUP1S) {
Jeenu Viswambharanaeb267c2017-09-22 08:32:09 +0100239 gicr_set_igrpmodr0(gicr_base, current_prop->intr_num);
Jeenu Viswambharan88d8f452017-11-07 08:38:23 +0000240 ctlr_enable |= CTLR_ENABLE_G1S_BIT;
241 } else {
Jeenu Viswambharanaeb267c2017-09-22 08:32:09 +0100242 gicr_clr_igrpmodr0(gicr_base, current_prop->intr_num);
Jeenu Viswambharan88d8f452017-11-07 08:38:23 +0000243 ctlr_enable |= CTLR_ENABLE_G0_BIT;
244 }
Jeenu Viswambharanaeb267c2017-09-22 08:32:09 +0100245
246 /* Set the priority of this interrupt */
247 gicr_set_ipriorityr(gicr_base, current_prop->intr_num,
248 current_prop->intr_pri);
249
250 /*
251 * Set interrupt configuration for PPIs. Configuration for SGIs
252 * are ignored.
253 */
254 if ((current_prop->intr_num >= MIN_PPI_ID) &&
255 (current_prop->intr_num < MIN_SPI_ID)) {
256 gicr_set_icfgr1(gicr_base, current_prop->intr_num,
257 current_prop->intr_cfg);
258 }
259
260 /* Enable this interrupt */
261 gicr_set_isenabler0(gicr_base, current_prop->intr_num);
262 }
Jeenu Viswambharan88d8f452017-11-07 08:38:23 +0000263
264 return ctlr_enable;
Jeenu Viswambharanaeb267c2017-09-22 08:32:09 +0100265}