blob: 67d52452c70193e02787af3a5fffaf9891a1b42e [file] [log] [blame]
Achin Gupta27573c52015-11-03 14:18:34 +00001/*
Jeenu Viswambharan11ad8f22016-11-15 13:53:57 +00002 * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
Achin Gupta27573c52015-11-03 14:18:34 +00003 *
dp-arm82cb2c12017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Achin Gupta27573c52015-11-03 14:18:34 +00005 */
6
7#include <arm_def.h>
8#include <gicv3.h>
9#include <plat_arm.h>
10#include <platform.h>
11#include <platform_def.h>
12
13/******************************************************************************
14 * The following functions are defined as weak to allow a platform to override
15 * the way the GICv3 driver is initialised and used.
16 *****************************************************************************/
17#pragma weak plat_arm_gic_driver_init
18#pragma weak plat_arm_gic_init
19#pragma weak plat_arm_gic_cpuif_enable
20#pragma weak plat_arm_gic_cpuif_disable
21#pragma weak plat_arm_gic_pcpu_init
Jeenu Viswambharand17b9532016-12-09 11:12:34 +000022#pragma weak plat_arm_gic_redistif_on
23#pragma weak plat_arm_gic_redistif_off
Achin Gupta27573c52015-11-03 14:18:34 +000024
25/* The GICv3 driver only needs to be initialized in EL3 */
Soby Mathew21a39732016-01-13 17:06:00 +000026static uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
Achin Gupta27573c52015-11-03 14:18:34 +000027
28/* Array of Group1 secure interrupts to be configured by the gic driver */
Soby Mathew21a39732016-01-13 17:06:00 +000029static const unsigned int g1s_interrupt_array[] = {
Achin Gupta27573c52015-11-03 14:18:34 +000030 PLAT_ARM_G1S_IRQS
31};
32
33/* Array of Group0 interrupts to be configured by the gic driver */
Soby Mathew21a39732016-01-13 17:06:00 +000034static const unsigned int g0_interrupt_array[] = {
Achin Gupta27573c52015-11-03 14:18:34 +000035 PLAT_ARM_G0_IRQS
36};
37
Jeenu Viswambharan11ad8f22016-11-15 13:53:57 +000038/*
Soby Mathewe35a3fb2017-10-11 16:08:58 +010039 * We save and restore the GICv3 context on system suspend. Allocate the
40 * data in the designated EL3 Secure carve-out memory
41 */
42gicv3_redist_ctx_t rdist_ctx __section("arm_el3_tzc_dram");
43gicv3_dist_ctx_t dist_ctx __section("arm_el3_tzc_dram");
44
45/*
Jeenu Viswambharan11ad8f22016-11-15 13:53:57 +000046 * MPIDR hashing function for translating MPIDRs read from GICR_TYPER register
47 * to core position.
48 *
49 * Calculating core position is dependent on MPIDR_EL1.MT bit. However, affinity
50 * values read from GICR_TYPER don't have an MT field. To reuse the same
51 * translation used for CPUs, we insert MT bit read from the PE's MPIDR into
52 * that read from GICR_TYPER.
53 *
54 * Assumptions:
55 *
56 * - All CPUs implemented in the system have MPIDR_EL1.MT bit set;
57 * - No CPUs implemented in the system use affinity level 3.
58 */
59static unsigned int arm_gicv3_mpidr_hash(u_register_t mpidr)
60{
61 mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK);
62 return plat_arm_calc_core_pos(mpidr);
63}
64
Achin Gupta27573c52015-11-03 14:18:34 +000065const gicv3_driver_data_t arm_gic_data = {
66 .gicd_base = PLAT_ARM_GICD_BASE,
67 .gicr_base = PLAT_ARM_GICR_BASE,
68 .g0_interrupt_num = ARRAY_SIZE(g0_interrupt_array),
69 .g1s_interrupt_num = ARRAY_SIZE(g1s_interrupt_array),
70 .g0_interrupt_array = g0_interrupt_array,
71 .g1s_interrupt_array = g1s_interrupt_array,
72 .rdistif_num = PLATFORM_CORE_COUNT,
73 .rdistif_base_addrs = rdistif_base_addrs,
Jeenu Viswambharan11ad8f22016-11-15 13:53:57 +000074 .mpidr_to_core_pos = arm_gicv3_mpidr_hash
Achin Gupta27573c52015-11-03 14:18:34 +000075};
76
77void plat_arm_gic_driver_init(void)
78{
79 /*
80 * The GICv3 driver is initialized in EL3 and does not need
81 * to be initialized again in SEL1. This is because the S-EL1
82 * can use GIC system registers to manage interrupts and does
83 * not need GIC interface base addresses to be configured.
84 */
Masahiro Yamada6af03f92016-12-26 00:22:47 +090085#if (defined(AARCH32) && defined(IMAGE_BL32)) || \
86 (defined(IMAGE_BL31) && !defined(AARCH32))
Achin Gupta27573c52015-11-03 14:18:34 +000087 gicv3_driver_init(&arm_gic_data);
88#endif
89}
90
91/******************************************************************************
92 * ARM common helper to initialize the GIC. Only invoked by BL31
93 *****************************************************************************/
94void plat_arm_gic_init(void)
95{
96 gicv3_distif_init();
97 gicv3_rdistif_init(plat_my_core_pos());
98 gicv3_cpuif_enable(plat_my_core_pos());
99}
100
101/******************************************************************************
102 * ARM common helper to enable the GIC CPU interface
103 *****************************************************************************/
104void plat_arm_gic_cpuif_enable(void)
105{
106 gicv3_cpuif_enable(plat_my_core_pos());
107}
108
109/******************************************************************************
110 * ARM common helper to disable the GIC CPU interface
111 *****************************************************************************/
112void plat_arm_gic_cpuif_disable(void)
113{
114 gicv3_cpuif_disable(plat_my_core_pos());
115}
116
117/******************************************************************************
118 * ARM common helper to initialize the per-cpu redistributor interface in GICv3
119 *****************************************************************************/
120void plat_arm_gic_pcpu_init(void)
121{
122 gicv3_rdistif_init(plat_my_core_pos());
123}
Jeenu Viswambharand17b9532016-12-09 11:12:34 +0000124
125/******************************************************************************
126 * ARM common helpers to power GIC redistributor interface
127 *****************************************************************************/
128void plat_arm_gic_redistif_on(void)
129{
130 gicv3_rdistif_on(plat_my_core_pos());
131}
132
133void plat_arm_gic_redistif_off(void)
134{
135 gicv3_rdistif_off(plat_my_core_pos());
136}
Soby Mathewe35a3fb2017-10-11 16:08:58 +0100137
138/******************************************************************************
139 * ARM common helper to save & restore the GICv3 on resume from system suspend
140 *****************************************************************************/
141void plat_arm_gic_save(void)
142{
143
144 /*
145 * If an ITS is available, save its context before
146 * the Redistributor using:
147 * gicv3_its_save_disable(gits_base, &its_ctx[i])
148 * Additionnaly, an implementation-defined sequence may
149 * be required to save the whole ITS state.
150 */
151
152 /*
153 * Save the GIC Redistributors and ITS contexts before the
154 * Distributor context. As we only handle SYSTEM SUSPEND API,
155 * we only need to save the context of the CPU that is issuing
156 * the SYSTEM SUSPEND call, i.e. the current CPU.
157 */
158 gicv3_rdistif_save(plat_my_core_pos(), &rdist_ctx);
159
160 /* Save the GIC Distributor context */
161 gicv3_distif_save(&dist_ctx);
162
163 /*
164 * From here, all the components of the GIC can be safely powered down
165 * as long as there is an alternate way to handle wakeup interrupt
166 * sources.
167 */
168}
169
170void plat_arm_gic_resume(void)
171{
172 /* Restore the GIC Distributor context */
173 gicv3_distif_init_restore(&dist_ctx);
174
175 /*
176 * Restore the GIC Redistributor and ITS contexts after the
177 * Distributor context. As we only handle SYSTEM SUSPEND API,
178 * we only need to restore the context of the CPU that issued
179 * the SYSTEM SUSPEND call.
180 */
181 gicv3_rdistif_init_restore(plat_my_core_pos(), &rdist_ctx);
182
183 /*
184 * If an ITS is available, restore its context after
185 * the Redistributor using:
186 * gicv3_its_restore(gits_base, &its_ctx[i])
187 * An implementation-defined sequence may be required to
188 * restore the whole ITS state. The ITS must also be
189 * re-enabled after this sequence has been executed.
190 */
191}