1*c97857dbSAmit Nagal /*
2*c97857dbSAmit Nagal * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved.
3*c97857dbSAmit Nagal * Copyright (c) 2018-2022, Xilinx, Inc. All rights reserved.
4*c97857dbSAmit Nagal * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
5*c97857dbSAmit Nagal *
6*c97857dbSAmit Nagal * SPDX-License-Identifier: BSD-3-Clause
7*c97857dbSAmit Nagal */
8*c97857dbSAmit Nagal
9*c97857dbSAmit Nagal #include <common/debug.h>
10*c97857dbSAmit Nagal #include <common/interrupt_props.h>
11*c97857dbSAmit Nagal #include <drivers/arm/gicv3.h>
12*c97857dbSAmit Nagal #include <lib/utils.h>
13*c97857dbSAmit Nagal #include <plat/common/platform.h>
14*c97857dbSAmit Nagal #include <platform_def.h>
15*c97857dbSAmit Nagal
16*c97857dbSAmit Nagal #include <plat_private.h>
17*c97857dbSAmit Nagal
18*c97857dbSAmit Nagal /******************************************************************************
19*c97857dbSAmit Nagal * The following functions are defined as weak to allow a platform to override
20*c97857dbSAmit Nagal * the way the GICv3 driver is initialised and used.
21*c97857dbSAmit Nagal *****************************************************************************/
22*c97857dbSAmit Nagal #pragma weak plat_gic_driver_init
23*c97857dbSAmit Nagal #pragma weak plat_gic_init
24*c97857dbSAmit Nagal #pragma weak plat_gic_cpuif_enable
25*c97857dbSAmit Nagal #pragma weak plat_gic_cpuif_disable
26*c97857dbSAmit Nagal #pragma weak plat_gic_pcpu_init
27*c97857dbSAmit Nagal #pragma weak plat_gic_redistif_on
28*c97857dbSAmit Nagal #pragma weak plat_gic_redistif_off
29*c97857dbSAmit Nagal
30*c97857dbSAmit Nagal /* The GICv3 driver only needs to be initialized in EL3 */
31*c97857dbSAmit Nagal static uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
32*c97857dbSAmit Nagal
33*c97857dbSAmit Nagal static const interrupt_prop_t _interrupt_props[] = {
34*c97857dbSAmit Nagal PLAT_G1S_IRQ_PROPS(INTR_GROUP1S),
35*c97857dbSAmit Nagal PLAT_G0_IRQ_PROPS(INTR_GROUP0)
36*c97857dbSAmit Nagal };
37*c97857dbSAmit Nagal
38*c97857dbSAmit Nagal /*
39*c97857dbSAmit Nagal * We save and restore the GICv3 context on system suspend. Allocate the
40*c97857dbSAmit Nagal * data in the designated EL3 Secure carve-out memory.
41*c97857dbSAmit Nagal */
42*c97857dbSAmit Nagal static gicv3_redist_ctx_t rdist_ctx __section("._el3_tzc_dram");
43*c97857dbSAmit Nagal static gicv3_dist_ctx_t dist_ctx __section("._el3_tzc_dram");
44*c97857dbSAmit Nagal
45*c97857dbSAmit Nagal /*
46*c97857dbSAmit Nagal * MPIDR hashing function for translating MPIDRs read from GICR_TYPER register
47*c97857dbSAmit Nagal * to core position.
48*c97857dbSAmit Nagal *
49*c97857dbSAmit Nagal * Calculating core position is dependent on MPIDR_EL1.MT bit. However, affinity
50*c97857dbSAmit Nagal * values read from GICR_TYPER don't have an MT field. To reuse the same
51*c97857dbSAmit Nagal * translation used for CPUs, we insert MT bit read from the PE's MPIDR into
52*c97857dbSAmit Nagal * that read from GICR_TYPER.
53*c97857dbSAmit Nagal *
54*c97857dbSAmit Nagal * Assumptions:
55*c97857dbSAmit Nagal *
56*c97857dbSAmit Nagal * - All CPUs implemented in the system have MPIDR_EL1.MT bit set;
57*c97857dbSAmit Nagal * - No CPUs implemented in the system use affinity level 3.
58*c97857dbSAmit Nagal */
_gicv3_mpidr_hash(u_register_t mpidr)59*c97857dbSAmit Nagal static uint32_t _gicv3_mpidr_hash(u_register_t mpidr)
60*c97857dbSAmit Nagal {
61*c97857dbSAmit Nagal mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK);
62*c97857dbSAmit Nagal return plat_core_pos_by_mpidr(mpidr);
63*c97857dbSAmit Nagal }
64*c97857dbSAmit Nagal
65*c97857dbSAmit Nagal static const gicv3_driver_data_t _gic_data __unused = {
66*c97857dbSAmit Nagal .gicd_base = PLAT_GICD_BASE_VALUE,
67*c97857dbSAmit Nagal .gicr_base = PLAT_GICR_BASE_VALUE,
68*c97857dbSAmit Nagal .interrupt_props = _interrupt_props,
69*c97857dbSAmit Nagal .interrupt_props_num = ARRAY_SIZE(_interrupt_props),
70*c97857dbSAmit Nagal .rdistif_num = PLATFORM_CORE_COUNT,
71*c97857dbSAmit Nagal .rdistif_base_addrs = rdistif_base_addrs,
72*c97857dbSAmit Nagal .mpidr_to_core_pos = _gicv3_mpidr_hash
73*c97857dbSAmit Nagal };
74*c97857dbSAmit Nagal
plat_gic_driver_init(void)75*c97857dbSAmit Nagal void __init plat_gic_driver_init(void)
76*c97857dbSAmit Nagal {
77*c97857dbSAmit Nagal /*
78*c97857dbSAmit Nagal * The GICv3 driver is initialized in EL3 and does not need
79*c97857dbSAmit Nagal * to be initialized again in SEL1. This is because the S-EL1
80*c97857dbSAmit Nagal * can use GIC system registers to manage interrupts and does
81*c97857dbSAmit Nagal * not need GIC interface base addresses to be configured.
82*c97857dbSAmit Nagal */
83*c97857dbSAmit Nagal #if IMAGE_BL31
84*c97857dbSAmit Nagal gicv3_driver_init(&_gic_data);
85*c97857dbSAmit Nagal #endif
86*c97857dbSAmit Nagal }
87*c97857dbSAmit Nagal
88*c97857dbSAmit Nagal /******************************************************************************
89*c97857dbSAmit Nagal * common helper to initialize the GIC. Only invoked by BL31
90*c97857dbSAmit Nagal *****************************************************************************/
plat_gic_init(void)91*c97857dbSAmit Nagal void __init plat_gic_init(void)
92*c97857dbSAmit Nagal {
93*c97857dbSAmit Nagal gicv3_distif_init();
94*c97857dbSAmit Nagal gicv3_rdistif_init(plat_my_core_pos());
95*c97857dbSAmit Nagal gicv3_cpuif_enable(plat_my_core_pos());
96*c97857dbSAmit Nagal }
97*c97857dbSAmit Nagal
98*c97857dbSAmit Nagal /******************************************************************************
99*c97857dbSAmit Nagal * common helper to enable the GIC CPU interface
100*c97857dbSAmit Nagal *****************************************************************************/
plat_gic_cpuif_enable(void)101*c97857dbSAmit Nagal void plat_gic_cpuif_enable(void)
102*c97857dbSAmit Nagal {
103*c97857dbSAmit Nagal gicv3_cpuif_enable(plat_my_core_pos());
104*c97857dbSAmit Nagal }
105*c97857dbSAmit Nagal
106*c97857dbSAmit Nagal /******************************************************************************
107*c97857dbSAmit Nagal * common helper to disable the GIC CPU interface
108*c97857dbSAmit Nagal *****************************************************************************/
plat_gic_cpuif_disable(void)109*c97857dbSAmit Nagal void plat_gic_cpuif_disable(void)
110*c97857dbSAmit Nagal {
111*c97857dbSAmit Nagal gicv3_cpuif_disable(plat_my_core_pos());
112*c97857dbSAmit Nagal }
113*c97857dbSAmit Nagal
114*c97857dbSAmit Nagal /******************************************************************************
115*c97857dbSAmit Nagal * common helper to initialize the per-cpu redistributor interface in GICv3
116*c97857dbSAmit Nagal *****************************************************************************/
plat_gic_pcpu_init(void)117*c97857dbSAmit Nagal void plat_gic_pcpu_init(void)
118*c97857dbSAmit Nagal {
119*c97857dbSAmit Nagal gicv3_rdistif_init(plat_my_core_pos());
120*c97857dbSAmit Nagal }
121*c97857dbSAmit Nagal
122*c97857dbSAmit Nagal /******************************************************************************
123*c97857dbSAmit Nagal * common helpers to power GIC redistributor interface
124*c97857dbSAmit Nagal *****************************************************************************/
plat_gic_redistif_on(void)125*c97857dbSAmit Nagal void plat_gic_redistif_on(void)
126*c97857dbSAmit Nagal {
127*c97857dbSAmit Nagal gicv3_rdistif_on(plat_my_core_pos());
128*c97857dbSAmit Nagal }
129*c97857dbSAmit Nagal
plat_gic_redistif_off(void)130*c97857dbSAmit Nagal void plat_gic_redistif_off(void)
131*c97857dbSAmit Nagal {
132*c97857dbSAmit Nagal gicv3_rdistif_off(plat_my_core_pos());
133*c97857dbSAmit Nagal }
134*c97857dbSAmit Nagal
135*c97857dbSAmit Nagal /******************************************************************************
136*c97857dbSAmit Nagal * common helper to save & restore the GICv3 on resume from system suspend
137*c97857dbSAmit Nagal *****************************************************************************/
plat_gic_save(void)138*c97857dbSAmit Nagal void plat_gic_save(void)
139*c97857dbSAmit Nagal {
140*c97857dbSAmit Nagal /*
141*c97857dbSAmit Nagal * If an ITS is available, save its context before
142*c97857dbSAmit Nagal * the Redistributor using:
143*c97857dbSAmit Nagal * gicv3_its_save_disable(gits_base, &its_ctx[i])
144*c97857dbSAmit Nagal * Additionnaly, an implementation-defined sequence may
145*c97857dbSAmit Nagal * be required to save the whole ITS state.
146*c97857dbSAmit Nagal */
147*c97857dbSAmit Nagal
148*c97857dbSAmit Nagal /*
149*c97857dbSAmit Nagal * Save the GIC Redistributors and ITS contexts before the
150*c97857dbSAmit Nagal * Distributor context. As we only handle SYSTEM SUSPEND API,
151*c97857dbSAmit Nagal * we only need to save the context of the CPU that is issuing
152*c97857dbSAmit Nagal * the SYSTEM SUSPEND call, i.e. the current CPU.
153*c97857dbSAmit Nagal */
154*c97857dbSAmit Nagal gicv3_rdistif_save(plat_my_core_pos(), &rdist_ctx);
155*c97857dbSAmit Nagal
156*c97857dbSAmit Nagal /* Save the GIC Distributor context */
157*c97857dbSAmit Nagal gicv3_distif_save(&dist_ctx);
158*c97857dbSAmit Nagal
159*c97857dbSAmit Nagal /*
160*c97857dbSAmit Nagal * From here, all the components of the GIC can be safely powered down
161*c97857dbSAmit Nagal * as long as there is an alternate way to handle wakeup interrupt
162*c97857dbSAmit Nagal * sources.
163*c97857dbSAmit Nagal */
164*c97857dbSAmit Nagal }
165*c97857dbSAmit Nagal
plat_gic_resume(void)166*c97857dbSAmit Nagal void plat_gic_resume(void)
167*c97857dbSAmit Nagal {
168*c97857dbSAmit Nagal /* Restore the GIC Distributor context */
169*c97857dbSAmit Nagal gicv3_distif_init_restore(&dist_ctx);
170*c97857dbSAmit Nagal
171*c97857dbSAmit Nagal /*
172*c97857dbSAmit Nagal * Restore the GIC Redistributor and ITS contexts after the
173*c97857dbSAmit Nagal * Distributor context. As we only handle SYSTEM SUSPEND API,
174*c97857dbSAmit Nagal * we only need to restore the context of the CPU that issued
175*c97857dbSAmit Nagal * the SYSTEM SUSPEND call.
176*c97857dbSAmit Nagal */
177*c97857dbSAmit Nagal gicv3_rdistif_init_restore(plat_my_core_pos(), &rdist_ctx);
178*c97857dbSAmit Nagal
179*c97857dbSAmit Nagal /*
180*c97857dbSAmit Nagal * If an ITS is available, restore its context after
181*c97857dbSAmit Nagal * the Redistributor using:
182*c97857dbSAmit Nagal * gicv3_its_restore(gits_base, &its_ctx[i])
183*c97857dbSAmit Nagal * An implementation-defined sequence may be required to
184*c97857dbSAmit Nagal * restore the whole ITS state. The ITS must also be
185*c97857dbSAmit Nagal * re-enabled after this sequence has been executed.
186*c97857dbSAmit Nagal */
187*c97857dbSAmit Nagal }
188