xref: /rk3399_ARM-atf/drivers/arm/gic/v3/gicv3_helpers.c (revision 0a0a7a9ac82cb79af91f098cedc69cc67bca3978)
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  * This function marks the core as awake in the re-distributor and
20  * ensures that the interface is active.
21  *****************************************************************************/
22 void 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 	 */
28 	assert((gicr_read_waker(gicr_base) & WAKER_CA_BIT) != 0U);
29 
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 */
34 	while ((gicr_read_waker(gicr_base) & WAKER_CA_BIT) != 0U)
35 		;
36 }
37 
38 /******************************************************************************
39  * This function marks the core as asleep in the re-distributor and ensures
40  * that the interface is quiescent.
41  *****************************************************************************/
42 void 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 */
48 	while ((gicr_read_waker(gicr_base) & WAKER_CA_BIT) == 0U)
49 		;
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  ******************************************************************************/
58 void 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 {
63 	u_register_t mpidr;
64 	unsigned int proc_num;
65 	uint64_t typer_val;
66 	uintptr_t rdistif_base = gicr_base;
67 
68 	assert(rdistif_base_addrs != NULL);
69 
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);
79 		if (mpidr_to_core_pos != NULL) {
80 			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 		}
86 
87 		if (proc_num < rdistif_num)
88 			rdistif_base_addrs[proc_num] = rdistif_base;
89 
90 		rdistif_base += (1U << GICR_PCPUBASE_SHIFT);
91 	} while ((typer_val & TYPER_LAST_BIT) == 0U);
92 }
93 
94 /*******************************************************************************
95  * Helper function to configure the default attributes of SPIs.
96  ******************************************************************************/
97 void gicv3_spis_config_defaults(uintptr_t gicd_base)
98 {
99 	unsigned int index, num_ints;
100 
101 	num_ints = gicd_read_typer(gicd_base);
102 	num_ints &= TYPER_IT_LINES_NO_MASK;
103 	num_ints = (num_ints + 1U) << 5;
104 
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 	 */
109 	for (index = MIN_SPI_ID; index < num_ints; index += 32U)
110 		gicd_write_igroupr(gicd_base, index, ~0U);
111 
112 	/* Setup the default SPI priorities doing four at a time */
113 	for (index = MIN_SPI_ID; index < num_ints; index += 4U)
114 		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 	 */
122 	for (index = MIN_SPI_ID; index < num_ints; index += 16U)
123 		gicd_write_icfgr(gicd_base, index, 0U);
124 }
125 
126 /*******************************************************************************
127  * Helper function to configure properties of secure SPIs
128  ******************************************************************************/
129 unsigned int gicv3_secure_spis_config_props(uintptr_t gicd_base,
130 		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;
136 	unsigned int ctlr_enable = 0U;
137 
138 	/* Make sure there's a valid property array */
139 	if (interrupt_props_num > 0U)
140 		assert(interrupt_props != NULL);
141 
142 	for (i = 0U; i < interrupt_props_num; i++) {
143 		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 */
171 		gic_affinity_val =
172 			gicd_irouter_val_from_mpidr(read_mpidr(), 0U);
173 		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 /*******************************************************************************
184  * Helper function to configure the default attributes of SPIs.
185  ******************************************************************************/
186 void gicv3_ppi_sgi_config_defaults(uintptr_t gicr_base)
187 {
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 	 */
195 	gicr_write_icenabler0(gicr_base, ~0U);
196 	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 */
202 	for (index = 0U; index < MIN_SPI_ID; index += 4U)
203 		gicr_write_ipriorityr(gicr_base,
204 				      index,
205 				      GICD_IPRIORITYR_DEF_VAL);
206 
207 	/* Configure all PPIs as level triggered by default */
208 	gicr_write_icfgr1(gicr_base, 0U);
209 }
210 
211 /*******************************************************************************
212  * Helper function to configure properties of secure G0 and G1S PPIs and SGIs.
213  ******************************************************************************/
214 unsigned int gicv3_secure_ppi_sgi_config_props(uintptr_t gicr_base,
215 		const interrupt_prop_t *interrupt_props,
216 		unsigned int interrupt_props_num)
217 {
218 	unsigned int i;
219 	const interrupt_prop_t *current_prop;
220 	unsigned int ctlr_enable = 0U;
221 
222 	/* Make sure there's a valid property array */
223 	if (interrupt_props_num > 0U)
224 		assert(interrupt_props != NULL);
225 
226 	for (i = 0U; i < interrupt_props_num; i++) {
227 		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));
238 		if (current_prop->intr_grp == INTR_GROUP1S) {
239 			gicr_set_igrpmodr0(gicr_base, current_prop->intr_num);
240 			ctlr_enable |= CTLR_ENABLE_G1S_BIT;
241 		} else {
242 			gicr_clr_igrpmodr0(gicr_base, current_prop->intr_num);
243 			ctlr_enable |= CTLR_ENABLE_G0_BIT;
244 		}
245 
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 	}
263 
264 	return ctlr_enable;
265 }
266