c8097329517cfb03bdfc77cad9ea46e96ab0346b
[project/bcm63xx/atf.git] / drivers / arm / gic / v3 / arm_gicv3_common.c
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