blob: c8097329517cfb03bdfc77cad9ea46e96ab0346b [file] [log] [blame]
Soby Mathew327548c2017-07-13 15:19:51 +01001/*
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 */
27void 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 */
71void 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 /*
Derek Basehore45bcb6e2018-01-23 15:49:17 -080087 * 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 /*
Soby Mathew327548c2017-07-13 15:19:51 +010096 * 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