blob: 05399c3a7fdec956ead8fcc85f7f4a4e1bcd65e2 [file] [log] [blame]
Achin Gupta4f6ad662013-10-25 09:08:21 +01001/*
Soby Mathew73f92992016-01-15 14:05:37 +00002 * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
Achin Gupta4f6ad662013-10-25 09:08:21 +01003 *
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
Achin Gupta191e86e2014-05-09 10:03:15 +010031#include <arch.h>
Jon Medhurstd0212c22014-02-11 14:48:56 +000032#include <assert.h>
Dan Handley930ee2e2014-04-17 17:48:52 +010033#include <gic_v2.h>
Achin Gupta191e86e2014-05-09 10:03:15 +010034#include <interrupt_mgmt.h>
Achin Gupta4f6ad662013-10-25 09:08:21 +010035#include <mmio.h>
36
37/*******************************************************************************
Sandrine Bailleux27866d82013-10-25 15:33:39 +010038 * GIC Distributor interface accessors for reading entire registers
Achin Gupta4f6ad662013-10-25 09:08:21 +010039 ******************************************************************************/
Achin Gupta4f6ad662013-10-25 09:08:21 +010040
Juan Castillo7f1f0622014-09-09 09:49:23 +010041unsigned int gicd_read_igroupr(uintptr_t base, unsigned int id)
Achin Gupta4f6ad662013-10-25 09:08:21 +010042{
43 unsigned n = id >> IGROUPR_SHIFT;
44 return mmio_read_32(base + GICD_IGROUPR + (n << 2));
45}
46
Juan Castillo7f1f0622014-09-09 09:49:23 +010047unsigned int gicd_read_isenabler(uintptr_t base, unsigned int id)
Achin Gupta4f6ad662013-10-25 09:08:21 +010048{
49 unsigned n = id >> ISENABLER_SHIFT;
50 return mmio_read_32(base + GICD_ISENABLER + (n << 2));
51}
52
Juan Castillo7f1f0622014-09-09 09:49:23 +010053unsigned int gicd_read_icenabler(uintptr_t base, unsigned int id)
Achin Gupta4f6ad662013-10-25 09:08:21 +010054{
55 unsigned n = id >> ICENABLER_SHIFT;
56 return mmio_read_32(base + GICD_ICENABLER + (n << 2));
57}
58
Juan Castillo7f1f0622014-09-09 09:49:23 +010059unsigned int gicd_read_ispendr(uintptr_t base, unsigned int id)
Achin Gupta4f6ad662013-10-25 09:08:21 +010060{
61 unsigned n = id >> ISPENDR_SHIFT;
62 return mmio_read_32(base + GICD_ISPENDR + (n << 2));
63}
64
Juan Castillo7f1f0622014-09-09 09:49:23 +010065unsigned int gicd_read_icpendr(uintptr_t base, unsigned int id)
Achin Gupta4f6ad662013-10-25 09:08:21 +010066{
67 unsigned n = id >> ICPENDR_SHIFT;
68 return mmio_read_32(base + GICD_ICPENDR + (n << 2));
69}
70
Juan Castillo7f1f0622014-09-09 09:49:23 +010071unsigned int gicd_read_isactiver(uintptr_t base, unsigned int id)
Achin Gupta4f6ad662013-10-25 09:08:21 +010072{
73 unsigned n = id >> ISACTIVER_SHIFT;
74 return mmio_read_32(base + GICD_ISACTIVER + (n << 2));
75}
76
Juan Castillo7f1f0622014-09-09 09:49:23 +010077unsigned int gicd_read_icactiver(uintptr_t base, unsigned int id)
Achin Gupta4f6ad662013-10-25 09:08:21 +010078{
79 unsigned n = id >> ICACTIVER_SHIFT;
80 return mmio_read_32(base + GICD_ICACTIVER + (n << 2));
81}
82
Juan Castillo7f1f0622014-09-09 09:49:23 +010083unsigned int gicd_read_ipriorityr(uintptr_t base, unsigned int id)
Achin Gupta4f6ad662013-10-25 09:08:21 +010084{
85 unsigned n = id >> IPRIORITYR_SHIFT;
86 return mmio_read_32(base + GICD_IPRIORITYR + (n << 2));
87}
88
Juan Castillo7f1f0622014-09-09 09:49:23 +010089unsigned int gicd_read_itargetsr(uintptr_t base, unsigned int id)
Achin Gupta4f6ad662013-10-25 09:08:21 +010090{
91 unsigned n = id >> ITARGETSR_SHIFT;
92 return mmio_read_32(base + GICD_ITARGETSR + (n << 2));
93}
94
Juan Castillo7f1f0622014-09-09 09:49:23 +010095unsigned int gicd_read_icfgr(uintptr_t base, unsigned int id)
Achin Gupta4f6ad662013-10-25 09:08:21 +010096{
97 unsigned n = id >> ICFGR_SHIFT;
98 return mmio_read_32(base + GICD_ICFGR + (n << 2));
99}
100
Juan Castillo7f1f0622014-09-09 09:49:23 +0100101unsigned int gicd_read_cpendsgir(uintptr_t base, unsigned int id)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100102{
103 unsigned n = id >> CPENDSGIR_SHIFT;
104 return mmio_read_32(base + GICD_CPENDSGIR + (n << 2));
105}
106
Juan Castillo7f1f0622014-09-09 09:49:23 +0100107unsigned int gicd_read_spendsgir(uintptr_t base, unsigned int id)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100108{
109 unsigned n = id >> SPENDSGIR_SHIFT;
110 return mmio_read_32(base + GICD_SPENDSGIR + (n << 2));
111}
112
113/*******************************************************************************
Sandrine Bailleux27866d82013-10-25 15:33:39 +0100114 * GIC Distributor interface accessors for writing entire registers
Achin Gupta4f6ad662013-10-25 09:08:21 +0100115 ******************************************************************************/
Achin Gupta4f6ad662013-10-25 09:08:21 +0100116
Juan Castillo7f1f0622014-09-09 09:49:23 +0100117void gicd_write_igroupr(uintptr_t base, unsigned int id, unsigned int val)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100118{
119 unsigned n = id >> IGROUPR_SHIFT;
120 mmio_write_32(base + GICD_IGROUPR + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100121}
122
Juan Castillo7f1f0622014-09-09 09:49:23 +0100123void gicd_write_isenabler(uintptr_t base, unsigned int id, unsigned int val)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100124{
125 unsigned n = id >> ISENABLER_SHIFT;
126 mmio_write_32(base + GICD_ISENABLER + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100127}
128
Juan Castillo7f1f0622014-09-09 09:49:23 +0100129void gicd_write_icenabler(uintptr_t base, unsigned int id, unsigned int val)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100130{
131 unsigned n = id >> ICENABLER_SHIFT;
132 mmio_write_32(base + GICD_ICENABLER + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100133}
134
Juan Castillo7f1f0622014-09-09 09:49:23 +0100135void gicd_write_ispendr(uintptr_t base, unsigned int id, unsigned int val)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100136{
137 unsigned n = id >> ISPENDR_SHIFT;
138 mmio_write_32(base + GICD_ISPENDR + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100139}
140
Juan Castillo7f1f0622014-09-09 09:49:23 +0100141void gicd_write_icpendr(uintptr_t base, unsigned int id, unsigned int val)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100142{
143 unsigned n = id >> ICPENDR_SHIFT;
144 mmio_write_32(base + GICD_ICPENDR + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100145}
146
Juan Castillo7f1f0622014-09-09 09:49:23 +0100147void gicd_write_isactiver(uintptr_t base, unsigned int id, unsigned int val)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100148{
149 unsigned n = id >> ISACTIVER_SHIFT;
150 mmio_write_32(base + GICD_ISACTIVER + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100151}
152
Juan Castillo7f1f0622014-09-09 09:49:23 +0100153void gicd_write_icactiver(uintptr_t base, unsigned int id, unsigned int val)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100154{
155 unsigned n = id >> ICACTIVER_SHIFT;
156 mmio_write_32(base + GICD_ICACTIVER + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100157}
158
Juan Castillo7f1f0622014-09-09 09:49:23 +0100159void gicd_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100160{
161 unsigned n = id >> IPRIORITYR_SHIFT;
162 mmio_write_32(base + GICD_IPRIORITYR + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100163}
164
Juan Castillo7f1f0622014-09-09 09:49:23 +0100165void gicd_write_itargetsr(uintptr_t base, unsigned int id, unsigned int val)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100166{
167 unsigned n = id >> ITARGETSR_SHIFT;
168 mmio_write_32(base + GICD_ITARGETSR + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100169}
170
Juan Castillo7f1f0622014-09-09 09:49:23 +0100171void gicd_write_icfgr(uintptr_t base, unsigned int id, unsigned int val)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100172{
173 unsigned n = id >> ICFGR_SHIFT;
174 mmio_write_32(base + GICD_ICFGR + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100175}
176
Juan Castillo7f1f0622014-09-09 09:49:23 +0100177void gicd_write_cpendsgir(uintptr_t base, unsigned int id, unsigned int val)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100178{
179 unsigned n = id >> CPENDSGIR_SHIFT;
180 mmio_write_32(base + GICD_CPENDSGIR + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100181}
182
Juan Castillo7f1f0622014-09-09 09:49:23 +0100183void gicd_write_spendsgir(uintptr_t base, unsigned int id, unsigned int val)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100184{
185 unsigned n = id >> SPENDSGIR_SHIFT;
186 mmio_write_32(base + GICD_SPENDSGIR + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100187}
188
189/*******************************************************************************
Sandrine Bailleux27866d82013-10-25 15:33:39 +0100190 * GIC Distributor interface accessors for individual interrupt manipulation
Achin Gupta4f6ad662013-10-25 09:08:21 +0100191 ******************************************************************************/
Juan Castillo7f1f0622014-09-09 09:49:23 +0100192unsigned int gicd_get_igroupr(uintptr_t base, unsigned int id)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100193{
194 unsigned bit_num = id & ((1 << IGROUPR_SHIFT) - 1);
195 unsigned int reg_val = gicd_read_igroupr(base, id);
196
197 return (reg_val >> bit_num) & 0x1;
198}
199
Juan Castillo7f1f0622014-09-09 09:49:23 +0100200void gicd_set_igroupr(uintptr_t base, unsigned int id)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100201{
202 unsigned bit_num = id & ((1 << IGROUPR_SHIFT) - 1);
203 unsigned int reg_val = gicd_read_igroupr(base, id);
204
205 gicd_write_igroupr(base, id, reg_val | (1 << bit_num));
Achin Gupta4f6ad662013-10-25 09:08:21 +0100206}
207
Juan Castillo7f1f0622014-09-09 09:49:23 +0100208void gicd_clr_igroupr(uintptr_t base, unsigned int id)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100209{
210 unsigned bit_num = id & ((1 << IGROUPR_SHIFT) - 1);
211 unsigned int reg_val = gicd_read_igroupr(base, id);
212
213 gicd_write_igroupr(base, id, reg_val & ~(1 << bit_num));
Achin Gupta4f6ad662013-10-25 09:08:21 +0100214}
215
Juan Castillo7f1f0622014-09-09 09:49:23 +0100216void gicd_set_isenabler(uintptr_t base, unsigned int id)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100217{
218 unsigned bit_num = id & ((1 << ISENABLER_SHIFT) - 1);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100219
Juan Castillo969bdb22014-04-28 12:48:40 +0100220 gicd_write_isenabler(base, id, (1 << bit_num));
Achin Gupta4f6ad662013-10-25 09:08:21 +0100221}
222
Juan Castillo7f1f0622014-09-09 09:49:23 +0100223void gicd_set_icenabler(uintptr_t base, unsigned int id)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100224{
225 unsigned bit_num = id & ((1 << ICENABLER_SHIFT) - 1);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100226
Juan Castillo969bdb22014-04-28 12:48:40 +0100227 gicd_write_icenabler(base, id, (1 << bit_num));
Achin Gupta4f6ad662013-10-25 09:08:21 +0100228}
229
Juan Castillo7f1f0622014-09-09 09:49:23 +0100230void gicd_set_ispendr(uintptr_t base, unsigned int id)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100231{
232 unsigned bit_num = id & ((1 << ISPENDR_SHIFT) - 1);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100233
Juan Castillo969bdb22014-04-28 12:48:40 +0100234 gicd_write_ispendr(base, id, (1 << bit_num));
Achin Gupta4f6ad662013-10-25 09:08:21 +0100235}
236
Juan Castillo7f1f0622014-09-09 09:49:23 +0100237void gicd_set_icpendr(uintptr_t base, unsigned int id)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100238{
239 unsigned bit_num = id & ((1 << ICPENDR_SHIFT) - 1);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100240
Juan Castillo969bdb22014-04-28 12:48:40 +0100241 gicd_write_icpendr(base, id, (1 << bit_num));
Achin Gupta4f6ad662013-10-25 09:08:21 +0100242}
243
Juan Castillo7f1f0622014-09-09 09:49:23 +0100244void gicd_set_isactiver(uintptr_t base, unsigned int id)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100245{
246 unsigned bit_num = id & ((1 << ISACTIVER_SHIFT) - 1);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100247
Juan Castillo969bdb22014-04-28 12:48:40 +0100248 gicd_write_isactiver(base, id, (1 << bit_num));
Achin Gupta4f6ad662013-10-25 09:08:21 +0100249}
250
Juan Castillo7f1f0622014-09-09 09:49:23 +0100251void gicd_set_icactiver(uintptr_t base, unsigned int id)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100252{
253 unsigned bit_num = id & ((1 << ICACTIVER_SHIFT) - 1);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100254
Juan Castillo969bdb22014-04-28 12:48:40 +0100255 gicd_write_icactiver(base, id, (1 << bit_num));
Achin Gupta4f6ad662013-10-25 09:08:21 +0100256}
257
258/*
259 * Make sure that the interrupt's group is set before expecting
260 * this function to do its job correctly.
261 */
Juan Castillo7f1f0622014-09-09 09:49:23 +0100262void gicd_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100263{
Achin Gupta4f6ad662013-10-25 09:08:21 +0100264 /*
265 * Enforce ARM recommendation to manage priority values such
266 * that group1 interrupts always have a lower priority than
Jon Medhurstd0212c22014-02-11 14:48:56 +0000267 * group0 interrupts.
268 * Note, lower numerical values are higher priorities so the comparison
269 * checks below are reversed from what might be expected.
Achin Gupta4f6ad662013-10-25 09:08:21 +0100270 */
Jon Medhurstd0212c22014-02-11 14:48:56 +0000271 assert(gicd_get_igroupr(base, id) == GRP1 ?
272 pri >= GIC_HIGHEST_NS_PRIORITY &&
273 pri <= GIC_LOWEST_NS_PRIORITY :
274 pri >= GIC_HIGHEST_SEC_PRIORITY &&
275 pri <= GIC_LOWEST_SEC_PRIORITY);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100276
Soby Mathew73f92992016-01-15 14:05:37 +0000277 mmio_write_8(base + GICD_IPRIORITYR + id, pri & GIC_PRI_MASK);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100278}
279
Juan Castillo7f1f0622014-09-09 09:49:23 +0100280void gicd_set_itargetsr(uintptr_t base, unsigned int id, unsigned int target)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100281{
Soby Mathew73f92992016-01-15 14:05:37 +0000282 mmio_write_8(base + GICD_ITARGETSR + id, target & GIC_TARGET_CPU_MASK);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100283}
284
Achin Gupta191e86e2014-05-09 10:03:15 +0100285/*******************************************************************************
286 * This function allows the interrupt management framework to determine (through
287 * the platform) which interrupt line (IRQ/FIQ) to use for an interrupt type to
288 * route it to EL3. The interrupt line is represented as the bit position of the
289 * IRQ or FIQ bit in the SCR_EL3.
290 ******************************************************************************/
291uint32_t gicv2_interrupt_type_to_line(uint32_t cpuif_base, uint32_t type)
292{
293 uint32_t gicc_ctlr;
294
295 /* Non-secure interrupts are signalled on the IRQ line always */
296 if (type == INTR_TYPE_NS)
297 return __builtin_ctz(SCR_IRQ_BIT);
298
299 /*
300 * Secure interrupts are signalled using the IRQ line if the FIQ_EN
301 * bit is not set else they are signalled using the FIQ line.
302 */
303 gicc_ctlr = gicc_read_ctlr(cpuif_base);
304 if (gicc_ctlr & FIQ_EN)
305 return __builtin_ctz(SCR_FIQ_BIT);
306 else
307 return __builtin_ctz(SCR_IRQ_BIT);
308}