blob: 8d552ca5eee1fa0111f0d6023c13215fa8b9df97 [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 /*
87 * Writes to GICR_WAKER.Sleep bit are ignored if GICR_WAKER.Quiescent
88 * bit is not set. We should be alright on power on path, therefore
89 * coming out of sleep and Quiescent should be set, but we assert in
90 * case.
91 */
92 assert(gicr_read_waker(gicr_base) & WAKER_QSC_BIT);
93
94 /* Clear GICR_WAKER.Sleep */
95 gicr_write_waker(gicr_base, gicr_read_waker(gicr_base) & ~WAKER_SL_BIT);
96
97 /*
98 * We don't know if the effects of setting GICR_WAKER.Sleep bit is
99 * instantaneous, so we wait until the interface is not Quiescent
100 * anymore.
101 */
102 while (gicr_read_waker(gicr_base) & WAKER_QSC_BIT)
103 ;
104}
105