• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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