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