xref: /arm-trusted-firmware/drivers/arm/gic/v3/arm_gicv3_common.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  */
6*91f16700Schasinglulu 
7*91f16700Schasinglulu /*
8*91f16700Schasinglulu  * Driver for implementation defined features that are identical in ARM GICv3
9*91f16700Schasinglulu * implementations (GIC-500 and GIC-600 for now). This driver only overrides
10*91f16700Schasinglulu * APIs that are different to those generic ones in GICv3 driver.
11*91f16700Schasinglulu  */
12*91f16700Schasinglulu 
13*91f16700Schasinglulu #include <assert.h>
14*91f16700Schasinglulu 
15*91f16700Schasinglulu #include <arch_helpers.h>
16*91f16700Schasinglulu #include <drivers/arm/arm_gicv3_common.h>
17*91f16700Schasinglulu #include <drivers/arm/gicv3.h>
18*91f16700Schasinglulu 
19*91f16700Schasinglulu #include "gicv3_private.h"
20*91f16700Schasinglulu 
21*91f16700Schasinglulu /*
22*91f16700Schasinglulu  * Flush the internal GIC cache of the LPIs pending tables to memory before
23*91f16700Schasinglulu  * saving the state of the Redistributor. This is required before powering off
24*91f16700Schasinglulu  * the GIC when the pending status must be preserved.
25*91f16700Schasinglulu  * `rdist_proc_num` is the processor number corresponding to the Redistributor of the
26*91f16700Schasinglulu  * current CPU.
27*91f16700Schasinglulu  */
28*91f16700Schasinglulu void arm_gicv3_distif_pre_save(unsigned int rdist_proc_num)
29*91f16700Schasinglulu {
30*91f16700Schasinglulu 	uintptr_t gicr_base = 0;
31*91f16700Schasinglulu 
32*91f16700Schasinglulu 	assert(gicv3_driver_data);
33*91f16700Schasinglulu 	assert(gicv3_driver_data->rdistif_base_addrs);
34*91f16700Schasinglulu 
35*91f16700Schasinglulu 	/*
36*91f16700Schasinglulu 	 * The GICR_WAKER.Sleep bit should be set only when both
37*91f16700Schasinglulu 	 * GICR_WAKER.ChildrenAsleep and GICR_WAKER.ProcessorSleep are set on
38*91f16700Schasinglulu 	 * all the Redistributors.
39*91f16700Schasinglulu 	 */
40*91f16700Schasinglulu 	for (unsigned int i = 0; i < gicv3_driver_data->rdistif_num; i++) {
41*91f16700Schasinglulu 		gicr_base = gicv3_driver_data->rdistif_base_addrs[i];
42*91f16700Schasinglulu 		assert(gicr_base);
43*91f16700Schasinglulu 		assert(gicr_read_waker(gicr_base) & WAKER_CA_BIT);
44*91f16700Schasinglulu 		assert(gicr_read_waker(gicr_base) & WAKER_PS_BIT);
45*91f16700Schasinglulu 	}
46*91f16700Schasinglulu 
47*91f16700Schasinglulu 	gicr_base = gicv3_driver_data->rdistif_base_addrs[rdist_proc_num];
48*91f16700Schasinglulu 	/*
49*91f16700Schasinglulu 	 * According to the TRM, there is only one instance of the
50*91f16700Schasinglulu 	 * GICR_WAKER.Sleep and GICR_WAKER.Quiescent bits that can be accessed
51*91f16700Schasinglulu 	 * through any of the Redistributor.
52*91f16700Schasinglulu 	 */
53*91f16700Schasinglulu 
54*91f16700Schasinglulu 	/*
55*91f16700Schasinglulu 	 * Set GICR_WAKER.Sleep
56*91f16700Schasinglulu 	 * After this point, the system must be configured so that the
57*91f16700Schasinglulu 	 * wake_request signals for the right cores are asserted when a wakeup
58*91f16700Schasinglulu 	 * interrupt is detected. The GIC will not be able to do that anymore
59*91f16700Schasinglulu 	 * when the GICR_WAKER.Sleep bit is set to 1.
60*91f16700Schasinglulu 	 */
61*91f16700Schasinglulu 	gicr_write_waker(gicr_base, gicr_read_waker(gicr_base) | WAKER_SL_BIT);
62*91f16700Schasinglulu 
63*91f16700Schasinglulu 	/* Wait until the GICR_WAKER.Quiescent bit is set */
64*91f16700Schasinglulu 	while (!(gicr_read_waker(gicr_base) & WAKER_QSC_BIT))
65*91f16700Schasinglulu 		;
66*91f16700Schasinglulu }
67*91f16700Schasinglulu 
68*91f16700Schasinglulu /*
69*91f16700Schasinglulu  * Allow the LPIs pending state to be read back from the tables in memory after
70*91f16700Schasinglulu  * having restored the state of the GIC Redistributor.
71*91f16700Schasinglulu  */
72*91f16700Schasinglulu void arm_gicv3_distif_post_restore(unsigned int rdist_proc_num)
73*91f16700Schasinglulu {
74*91f16700Schasinglulu 	uintptr_t gicr_base;
75*91f16700Schasinglulu 
76*91f16700Schasinglulu 	assert(gicv3_driver_data);
77*91f16700Schasinglulu 	assert(gicv3_driver_data->rdistif_base_addrs);
78*91f16700Schasinglulu 
79*91f16700Schasinglulu 	/*
80*91f16700Schasinglulu 	 * According to the TRM, there is only one instance of the
81*91f16700Schasinglulu 	 * GICR_WAKER.Sleep and GICR_WAKER.Quiescent bits that can be accessed
82*91f16700Schasinglulu 	 * through any of the Redistributor.
83*91f16700Schasinglulu 	 */
84*91f16700Schasinglulu 	gicr_base = gicv3_driver_data->rdistif_base_addrs[rdist_proc_num];
85*91f16700Schasinglulu 	assert(gicr_base);
86*91f16700Schasinglulu 
87*91f16700Schasinglulu 	/*
88*91f16700Schasinglulu 	 * If the GIC had power removed, the GICR_WAKER state will be reset.
89*91f16700Schasinglulu 	 * Since the GICR_WAKER.Sleep and GICR_WAKER.Quiescent bits are cleared,
90*91f16700Schasinglulu 	 * we can exit early. This also prevents the following assert from
91*91f16700Schasinglulu 	 * erroneously triggering.
92*91f16700Schasinglulu 	 */
93*91f16700Schasinglulu 	if (!(gicr_read_waker(gicr_base) & WAKER_SL_BIT))
94*91f16700Schasinglulu 		return;
95*91f16700Schasinglulu 
96*91f16700Schasinglulu 	/*
97*91f16700Schasinglulu 	 * Writes to GICR_WAKER.Sleep bit are ignored if GICR_WAKER.Quiescent
98*91f16700Schasinglulu 	 * bit is not set. We should be alright on power on path, therefore
99*91f16700Schasinglulu 	 * coming out of sleep and Quiescent should be set, but we assert in
100*91f16700Schasinglulu 	 * case.
101*91f16700Schasinglulu 	 */
102*91f16700Schasinglulu 	assert(gicr_read_waker(gicr_base) & WAKER_QSC_BIT);
103*91f16700Schasinglulu 
104*91f16700Schasinglulu 	/* Clear GICR_WAKER.Sleep */
105*91f16700Schasinglulu 	gicr_write_waker(gicr_base, gicr_read_waker(gicr_base) & ~WAKER_SL_BIT);
106*91f16700Schasinglulu 
107*91f16700Schasinglulu 	/*
108*91f16700Schasinglulu 	 * We don't know if the effects of setting GICR_WAKER.Sleep bit is
109*91f16700Schasinglulu 	 * instantaneous, so we wait until the interface is not Quiescent
110*91f16700Schasinglulu 	 * anymore.
111*91f16700Schasinglulu 	 */
112*91f16700Schasinglulu 	while (gicr_read_waker(gicr_base) & WAKER_QSC_BIT)
113*91f16700Schasinglulu 		;
114*91f16700Schasinglulu }
115*91f16700Schasinglulu 
116