blob: 9001519be12a8f64eb885bc02c83843ef32aea8b [file] [log] [blame]
Sandrine Bailleux798140d2014-07-17 16:06:39 +01001/*
2 * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice, this
8 * list of conditions and the following disclaimer.
9 *
10 * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * Neither the name of ARM nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without specific
16 * prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include <arch_helpers.h>
32#include <assert.h>
33#include <bl_common.h>
34#include <gic_v2.h>
35#include <interrupt_mgmt.h>
36#include <platform.h>
37#include "juno_def.h"
38#include "juno_private.h"
39
40
41/* Value used to initialise Non-Secure irq priorities four at a time */
42#define DEFAULT_NS_PRIORITY_X4 \
43 (GIC_HIGHEST_NS_PRIORITY | \
44 (GIC_HIGHEST_NS_PRIORITY << 8) | \
45 (GIC_HIGHEST_NS_PRIORITY << 16) | \
46 (GIC_HIGHEST_NS_PRIORITY << 24))
47
48
49/*******************************************************************************
50 * Enable secure interrupts and use FIQs to route them. Disable legacy bypass
51 * and set the priority mask register to allow all interrupts to trickle in.
52 ******************************************************************************/
53void gic_cpuif_setup(unsigned int gicc_base)
54{
55 unsigned int val;
56
57 gicc_write_pmr(gicc_base, GIC_PRI_MASK);
58
59 val = ENABLE_GRP0 | FIQ_EN;
60 val |= FIQ_BYP_DIS_GRP0 | IRQ_BYP_DIS_GRP0;
61 val |= FIQ_BYP_DIS_GRP1 | IRQ_BYP_DIS_GRP1;
62 gicc_write_ctlr(gicc_base, val);
63}
64
65/*******************************************************************************
66 * Place the cpu interface in a state where it can never make a cpu exit wfi as
67 * as result of an asserted interrupt. This is critical for powering down a cpu
68 ******************************************************************************/
69void gic_cpuif_deactivate(unsigned int gicc_base)
70{
71 unsigned int val;
72
73 /* Disable secure, non-secure interrupts and disable their bypass */
74 val = gicc_read_ctlr(gicc_base);
75 val &= ~(ENABLE_GRP0 | ENABLE_GRP1);
76 val |= FIQ_BYP_DIS_GRP1 | FIQ_BYP_DIS_GRP0;
77 val |= IRQ_BYP_DIS_GRP0 | IRQ_BYP_DIS_GRP1;
78 gicc_write_ctlr(gicc_base, val);
79}
80
81static void gic_set_secure(unsigned int gicd_base, unsigned id)
82{
83 /* Set interrupt as Group 0 */
84 gicd_clr_igroupr(gicd_base, id);
85
86 /* Set priority to max */
87 gicd_set_ipriorityr(gicd_base, id, GIC_HIGHEST_SEC_PRIORITY);
88}
89
90/*******************************************************************************
91 * Per cpu gic distributor setup which will be done by all cpus after a cold
92 * boot/hotplug. This marks out the secure interrupts & enables them.
93 ******************************************************************************/
94void gic_pcpu_distif_setup(unsigned int gicd_base)
95{
96 unsigned i;
97
98 /* Mark all 32 PPI interrupts as Group 1 (non-secure) */
99 mmio_write_32(gicd_base + GICD_IGROUPR, 0xffffffffu);
100
101 /* Setup PPI priorities doing four at a time */
102 for (i = 0; i < 32; i += 4)
103 mmio_write_32(gicd_base + GICD_IPRIORITYR + i, DEFAULT_NS_PRIORITY_X4);
104
105 /* Configure those PPIs we want as secure, and enable them. */
106 static const char sec_irq[] = {
107 IRQ_SEC_PHY_TIMER,
108 IRQ_SEC_SGI_0,
109 IRQ_SEC_SGI_1,
110 IRQ_SEC_SGI_2,
111 IRQ_SEC_SGI_3,
112 IRQ_SEC_SGI_4,
113 IRQ_SEC_SGI_5,
114 IRQ_SEC_SGI_6,
115 IRQ_SEC_SGI_7
116 };
117 for (i = 0; i < sizeof(sec_irq) / sizeof(sec_irq[0]); i++) {
118 gic_set_secure(gicd_base, sec_irq[i]);
119 gicd_set_isenabler(gicd_base, sec_irq[i]);
120 }
121}
122
123/*******************************************************************************
124 * Global gic distributor setup which will be done by the primary cpu after a
125 * cold boot. It marks out the secure SPIs, PPIs & SGIs and enables them. It
126 * then enables the secure GIC distributor interface.
127 ******************************************************************************/
128static void gic_distif_setup(unsigned int gicd_base)
129{
130 unsigned int i, ctlr;
131 const unsigned int ITLinesNumber =
132 gicd_read_typer(gicd_base) & IT_LINES_NO_MASK;
133
134 /* Disable the distributor before going further */
135 ctlr = gicd_read_ctlr(gicd_base);
136 ctlr &= ~(ENABLE_GRP0 | ENABLE_GRP1);
137 gicd_write_ctlr(gicd_base, ctlr);
138
139 /* Mark all lines of SPIs as Group 1 (non-secure) */
140 for (i = 0; i < ITLinesNumber; i++)
141 mmio_write_32(gicd_base + GICD_IGROUPR + 4 + i * 4, 0xffffffffu);
142
143 /* Setup SPI priorities doing four at a time */
144 for (i = 0; i < ITLinesNumber * 32; i += 4)
145 mmio_write_32(gicd_base + GICD_IPRIORITYR + 32 + i, DEFAULT_NS_PRIORITY_X4);
146
147 /* Configure the SPIs we want as secure */
148 static const char sec_irq[] = {
149 IRQ_MHU,
150 IRQ_GPU_SMMU_0,
151 IRQ_GPU_SMMU_1,
152 IRQ_ETR_SMMU,
153 IRQ_TZC400,
154 IRQ_TZ_WDOG
155 };
156 for (i = 0; i < sizeof(sec_irq) / sizeof(sec_irq[0]); i++)
157 gic_set_secure(gicd_base, sec_irq[i]);
158
159 /* Route watchdog interrupt to this CPU and enable it. */
160 gicd_set_itargetsr(gicd_base, IRQ_TZ_WDOG,
161 platform_get_core_pos(read_mpidr()));
162 gicd_set_isenabler(gicd_base, IRQ_TZ_WDOG);
163
164 /* Now setup the PPIs */
165 gic_pcpu_distif_setup(gicd_base);
166
167 /* Enable Group 0 (secure) interrupts */
168 gicd_write_ctlr(gicd_base, ctlr | ENABLE_GRP0);
169}
170
171void gic_setup(void)
172{
173 gic_cpuif_setup(GICC_BASE);
174 gic_distif_setup(GICD_BASE);
175}
176
177/*******************************************************************************
178 * An ARM processor signals interrupt exceptions through the IRQ and FIQ pins.
179 * The interrupt controller knows which pin/line it uses to signal a type of
180 * interrupt. The platform knows which interrupt controller type is being used
181 * in a particular security state e.g. with an ARM GIC, normal world could use
182 * the GICv2 features while the secure world could use GICv3 features and vice
183 * versa.
184 * This function is exported by the platform to let the interrupt management
185 * framework determine for a type of interrupt and security state, which line
186 * should be used in the SCR_EL3 to control its routing to EL3. The interrupt
187 * line is represented as the bit position of the IRQ or FIQ bit in the SCR_EL3.
188 ******************************************************************************/
189uint32_t plat_interrupt_type_to_line(uint32_t type, uint32_t security_state)
190{
191 assert(type == INTR_TYPE_S_EL1 ||
192 type == INTR_TYPE_EL3 ||
193 type == INTR_TYPE_NS);
194
195 assert(sec_state_is_valid(security_state));
196
197 /*
198 * We ignore the security state parameter because Juno is GICv2 only
199 * so both normal and secure worlds are using ARM GICv2.
200 */
201 return gicv2_interrupt_type_to_line(GICC_BASE, type);
202}
203
204/*******************************************************************************
205 * This function returns the type of the highest priority pending interrupt at
206 * the GIC cpu interface. INTR_TYPE_INVAL is returned when there is no
207 * interrupt pending.
208 ******************************************************************************/
209uint32_t plat_ic_get_pending_interrupt_type(void)
210{
211 uint32_t id;
212
213 id = gicc_read_hppir(GICC_BASE);
214
215 /* Assume that all secure interrupts are S-EL1 interrupts */
216 if (id < 1022)
217 return INTR_TYPE_S_EL1;
218
219 if (id == GIC_SPURIOUS_INTERRUPT)
220 return INTR_TYPE_INVAL;
221
222 return INTR_TYPE_NS;
223}
224
225/*******************************************************************************
226 * This function returns the id of the highest priority pending interrupt at
227 * the GIC cpu interface. INTR_ID_UNAVAILABLE is returned when there is no
228 * interrupt pending.
229 ******************************************************************************/
230uint32_t plat_ic_get_pending_interrupt_id(void)
231{
232 uint32_t id;
233
234 id = gicc_read_hppir(GICC_BASE);
235
236 if (id < 1022)
237 return id;
238
239 if (id == 1023)
240 return INTR_ID_UNAVAILABLE;
241
242 /*
243 * Find out which non-secure interrupt it is under the assumption that
244 * the GICC_CTLR.AckCtl bit is 0.
245 */
246 return gicc_read_ahppir(GICC_BASE);
247}
248
249/*******************************************************************************
250 * This functions reads the GIC cpu interface Interrupt Acknowledge register
251 * to start handling the pending interrupt. It returns the contents of the IAR.
252 ******************************************************************************/
253uint32_t plat_ic_acknowledge_interrupt(void)
254{
255 return gicc_read_IAR(GICC_BASE);
256}
257
258/*******************************************************************************
259 * This functions writes the GIC cpu interface End Of Interrupt register with
260 * the passed value to finish handling the active interrupt
261 ******************************************************************************/
262void plat_ic_end_of_interrupt(uint32_t id)
263{
264 gicc_write_EOIR(GICC_BASE, id);
265}
266
267/*******************************************************************************
268 * This function returns the type of the interrupt id depending upon the group
269 * this interrupt has been configured under by the interrupt controller i.e.
270 * group0 or group1.
271 ******************************************************************************/
272uint32_t plat_ic_get_interrupt_type(uint32_t id)
273{
274 uint32_t group;
275
276 group = gicd_get_igroupr(GICD_BASE, id);
277
278 /* Assume that all secure interrupts are S-EL1 interrupts */
279 if (group == GRP0)
280 return INTR_TYPE_S_EL1;
281 else
282 return INTR_TYPE_NS;
283}