blob: 29c79e07b472940333751a38e9f31edcc09e5d24 [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 *
dp-armfa3cf0b2017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Achin Gupta4f6ad662013-10-25 09:08:21 +01005 */
6
Achin Gupta191e86e2014-05-09 10:03:15 +01007#include <arch.h>
Jon Medhurstd0212c22014-02-11 14:48:56 +00008#include <assert.h>
Dan Handley930ee2e2014-04-17 17:48:52 +01009#include <gic_v2.h>
Achin Gupta191e86e2014-05-09 10:03:15 +010010#include <interrupt_mgmt.h>
Achin Gupta4f6ad662013-10-25 09:08:21 +010011#include <mmio.h>
12
13/*******************************************************************************
Sandrine Bailleux27866d82013-10-25 15:33:39 +010014 * GIC Distributor interface accessors for reading entire registers
Achin Gupta4f6ad662013-10-25 09:08:21 +010015 ******************************************************************************/
Achin Gupta4f6ad662013-10-25 09:08:21 +010016
Juan Castillo7f1f0622014-09-09 09:49:23 +010017unsigned int gicd_read_igroupr(uintptr_t base, unsigned int id)
Achin Gupta4f6ad662013-10-25 09:08:21 +010018{
19 unsigned n = id >> IGROUPR_SHIFT;
20 return mmio_read_32(base + GICD_IGROUPR + (n << 2));
21}
22
Juan Castillo7f1f0622014-09-09 09:49:23 +010023unsigned int gicd_read_isenabler(uintptr_t base, unsigned int id)
Achin Gupta4f6ad662013-10-25 09:08:21 +010024{
25 unsigned n = id >> ISENABLER_SHIFT;
26 return mmio_read_32(base + GICD_ISENABLER + (n << 2));
27}
28
Juan Castillo7f1f0622014-09-09 09:49:23 +010029unsigned int gicd_read_icenabler(uintptr_t base, unsigned int id)
Achin Gupta4f6ad662013-10-25 09:08:21 +010030{
31 unsigned n = id >> ICENABLER_SHIFT;
32 return mmio_read_32(base + GICD_ICENABLER + (n << 2));
33}
34
Juan Castillo7f1f0622014-09-09 09:49:23 +010035unsigned int gicd_read_ispendr(uintptr_t base, unsigned int id)
Achin Gupta4f6ad662013-10-25 09:08:21 +010036{
37 unsigned n = id >> ISPENDR_SHIFT;
38 return mmio_read_32(base + GICD_ISPENDR + (n << 2));
39}
40
Juan Castillo7f1f0622014-09-09 09:49:23 +010041unsigned int gicd_read_icpendr(uintptr_t base, unsigned int id)
Achin Gupta4f6ad662013-10-25 09:08:21 +010042{
43 unsigned n = id >> ICPENDR_SHIFT;
44 return mmio_read_32(base + GICD_ICPENDR + (n << 2));
45}
46
Juan Castillo7f1f0622014-09-09 09:49:23 +010047unsigned int gicd_read_isactiver(uintptr_t base, unsigned int id)
Achin Gupta4f6ad662013-10-25 09:08:21 +010048{
49 unsigned n = id >> ISACTIVER_SHIFT;
50 return mmio_read_32(base + GICD_ISACTIVER + (n << 2));
51}
52
Juan Castillo7f1f0622014-09-09 09:49:23 +010053unsigned int gicd_read_icactiver(uintptr_t base, unsigned int id)
Achin Gupta4f6ad662013-10-25 09:08:21 +010054{
55 unsigned n = id >> ICACTIVER_SHIFT;
56 return mmio_read_32(base + GICD_ICACTIVER + (n << 2));
57}
58
Juan Castillo7f1f0622014-09-09 09:49:23 +010059unsigned int gicd_read_ipriorityr(uintptr_t base, unsigned int id)
Achin Gupta4f6ad662013-10-25 09:08:21 +010060{
61 unsigned n = id >> IPRIORITYR_SHIFT;
62 return mmio_read_32(base + GICD_IPRIORITYR + (n << 2));
63}
64
Juan Castillo7f1f0622014-09-09 09:49:23 +010065unsigned int gicd_read_itargetsr(uintptr_t base, unsigned int id)
Achin Gupta4f6ad662013-10-25 09:08:21 +010066{
67 unsigned n = id >> ITARGETSR_SHIFT;
68 return mmio_read_32(base + GICD_ITARGETSR + (n << 2));
69}
70
Juan Castillo7f1f0622014-09-09 09:49:23 +010071unsigned int gicd_read_icfgr(uintptr_t base, unsigned int id)
Achin Gupta4f6ad662013-10-25 09:08:21 +010072{
73 unsigned n = id >> ICFGR_SHIFT;
74 return mmio_read_32(base + GICD_ICFGR + (n << 2));
75}
76
Juan Castillo7f1f0622014-09-09 09:49:23 +010077unsigned int gicd_read_cpendsgir(uintptr_t base, unsigned int id)
Achin Gupta4f6ad662013-10-25 09:08:21 +010078{
79 unsigned n = id >> CPENDSGIR_SHIFT;
80 return mmio_read_32(base + GICD_CPENDSGIR + (n << 2));
81}
82
Juan Castillo7f1f0622014-09-09 09:49:23 +010083unsigned int gicd_read_spendsgir(uintptr_t base, unsigned int id)
Achin Gupta4f6ad662013-10-25 09:08:21 +010084{
85 unsigned n = id >> SPENDSGIR_SHIFT;
86 return mmio_read_32(base + GICD_SPENDSGIR + (n << 2));
87}
88
89/*******************************************************************************
Sandrine Bailleux27866d82013-10-25 15:33:39 +010090 * GIC Distributor interface accessors for writing entire registers
Achin Gupta4f6ad662013-10-25 09:08:21 +010091 ******************************************************************************/
Achin Gupta4f6ad662013-10-25 09:08:21 +010092
Juan Castillo7f1f0622014-09-09 09:49:23 +010093void gicd_write_igroupr(uintptr_t base, unsigned int id, unsigned int val)
Achin Gupta4f6ad662013-10-25 09:08:21 +010094{
95 unsigned n = id >> IGROUPR_SHIFT;
96 mmio_write_32(base + GICD_IGROUPR + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +010097}
98
Juan Castillo7f1f0622014-09-09 09:49:23 +010099void gicd_write_isenabler(uintptr_t base, unsigned int id, unsigned int val)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100100{
101 unsigned n = id >> ISENABLER_SHIFT;
102 mmio_write_32(base + GICD_ISENABLER + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100103}
104
Juan Castillo7f1f0622014-09-09 09:49:23 +0100105void gicd_write_icenabler(uintptr_t base, unsigned int id, unsigned int val)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100106{
107 unsigned n = id >> ICENABLER_SHIFT;
108 mmio_write_32(base + GICD_ICENABLER + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100109}
110
Juan Castillo7f1f0622014-09-09 09:49:23 +0100111void gicd_write_ispendr(uintptr_t base, unsigned int id, unsigned int val)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100112{
113 unsigned n = id >> ISPENDR_SHIFT;
114 mmio_write_32(base + GICD_ISPENDR + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100115}
116
Juan Castillo7f1f0622014-09-09 09:49:23 +0100117void gicd_write_icpendr(uintptr_t base, unsigned int id, unsigned int val)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100118{
119 unsigned n = id >> ICPENDR_SHIFT;
120 mmio_write_32(base + GICD_ICPENDR + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100121}
122
Juan Castillo7f1f0622014-09-09 09:49:23 +0100123void gicd_write_isactiver(uintptr_t base, unsigned int id, unsigned int val)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100124{
125 unsigned n = id >> ISACTIVER_SHIFT;
126 mmio_write_32(base + GICD_ISACTIVER + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100127}
128
Juan Castillo7f1f0622014-09-09 09:49:23 +0100129void gicd_write_icactiver(uintptr_t base, unsigned int id, unsigned int val)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100130{
131 unsigned n = id >> ICACTIVER_SHIFT;
132 mmio_write_32(base + GICD_ICACTIVER + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100133}
134
Juan Castillo7f1f0622014-09-09 09:49:23 +0100135void gicd_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100136{
137 unsigned n = id >> IPRIORITYR_SHIFT;
138 mmio_write_32(base + GICD_IPRIORITYR + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100139}
140
Juan Castillo7f1f0622014-09-09 09:49:23 +0100141void gicd_write_itargetsr(uintptr_t base, unsigned int id, unsigned int val)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100142{
143 unsigned n = id >> ITARGETSR_SHIFT;
144 mmio_write_32(base + GICD_ITARGETSR + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100145}
146
Juan Castillo7f1f0622014-09-09 09:49:23 +0100147void gicd_write_icfgr(uintptr_t base, unsigned int id, unsigned int val)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100148{
149 unsigned n = id >> ICFGR_SHIFT;
150 mmio_write_32(base + GICD_ICFGR + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100151}
152
Juan Castillo7f1f0622014-09-09 09:49:23 +0100153void gicd_write_cpendsgir(uintptr_t base, unsigned int id, unsigned int val)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100154{
155 unsigned n = id >> CPENDSGIR_SHIFT;
156 mmio_write_32(base + GICD_CPENDSGIR + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100157}
158
Juan Castillo7f1f0622014-09-09 09:49:23 +0100159void gicd_write_spendsgir(uintptr_t base, unsigned int id, unsigned int val)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100160{
161 unsigned n = id >> SPENDSGIR_SHIFT;
162 mmio_write_32(base + GICD_SPENDSGIR + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100163}
164
165/*******************************************************************************
Sandrine Bailleux27866d82013-10-25 15:33:39 +0100166 * GIC Distributor interface accessors for individual interrupt manipulation
Achin Gupta4f6ad662013-10-25 09:08:21 +0100167 ******************************************************************************/
Juan Castillo7f1f0622014-09-09 09:49:23 +0100168unsigned int gicd_get_igroupr(uintptr_t base, unsigned int id)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100169{
170 unsigned bit_num = id & ((1 << IGROUPR_SHIFT) - 1);
171 unsigned int reg_val = gicd_read_igroupr(base, id);
172
173 return (reg_val >> bit_num) & 0x1;
174}
175
Juan Castillo7f1f0622014-09-09 09:49:23 +0100176void gicd_set_igroupr(uintptr_t base, unsigned int id)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100177{
178 unsigned bit_num = id & ((1 << IGROUPR_SHIFT) - 1);
179 unsigned int reg_val = gicd_read_igroupr(base, id);
180
181 gicd_write_igroupr(base, id, reg_val | (1 << bit_num));
Achin Gupta4f6ad662013-10-25 09:08:21 +0100182}
183
Juan Castillo7f1f0622014-09-09 09:49:23 +0100184void gicd_clr_igroupr(uintptr_t base, unsigned int id)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100185{
186 unsigned bit_num = id & ((1 << IGROUPR_SHIFT) - 1);
187 unsigned int reg_val = gicd_read_igroupr(base, id);
188
189 gicd_write_igroupr(base, id, reg_val & ~(1 << bit_num));
Achin Gupta4f6ad662013-10-25 09:08:21 +0100190}
191
Juan Castillo7f1f0622014-09-09 09:49:23 +0100192void gicd_set_isenabler(uintptr_t base, unsigned int id)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100193{
194 unsigned bit_num = id & ((1 << ISENABLER_SHIFT) - 1);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100195
Juan Castillo969bdb22014-04-28 12:48:40 +0100196 gicd_write_isenabler(base, id, (1 << bit_num));
Achin Gupta4f6ad662013-10-25 09:08:21 +0100197}
198
Juan Castillo7f1f0622014-09-09 09:49:23 +0100199void gicd_set_icenabler(uintptr_t base, unsigned int id)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100200{
201 unsigned bit_num = id & ((1 << ICENABLER_SHIFT) - 1);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100202
Juan Castillo969bdb22014-04-28 12:48:40 +0100203 gicd_write_icenabler(base, id, (1 << bit_num));
Achin Gupta4f6ad662013-10-25 09:08:21 +0100204}
205
Juan Castillo7f1f0622014-09-09 09:49:23 +0100206void gicd_set_ispendr(uintptr_t base, unsigned int id)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100207{
208 unsigned bit_num = id & ((1 << ISPENDR_SHIFT) - 1);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100209
Juan Castillo969bdb22014-04-28 12:48:40 +0100210 gicd_write_ispendr(base, id, (1 << bit_num));
Achin Gupta4f6ad662013-10-25 09:08:21 +0100211}
212
Juan Castillo7f1f0622014-09-09 09:49:23 +0100213void gicd_set_icpendr(uintptr_t base, unsigned int id)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100214{
215 unsigned bit_num = id & ((1 << ICPENDR_SHIFT) - 1);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100216
Juan Castillo969bdb22014-04-28 12:48:40 +0100217 gicd_write_icpendr(base, id, (1 << bit_num));
Achin Gupta4f6ad662013-10-25 09:08:21 +0100218}
219
Juan Castillo7f1f0622014-09-09 09:49:23 +0100220void gicd_set_isactiver(uintptr_t base, unsigned int id)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100221{
222 unsigned bit_num = id & ((1 << ISACTIVER_SHIFT) - 1);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100223
Juan Castillo969bdb22014-04-28 12:48:40 +0100224 gicd_write_isactiver(base, id, (1 << bit_num));
Achin Gupta4f6ad662013-10-25 09:08:21 +0100225}
226
Juan Castillo7f1f0622014-09-09 09:49:23 +0100227void gicd_set_icactiver(uintptr_t base, unsigned int id)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100228{
229 unsigned bit_num = id & ((1 << ICACTIVER_SHIFT) - 1);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100230
Juan Castillo969bdb22014-04-28 12:48:40 +0100231 gicd_write_icactiver(base, id, (1 << bit_num));
Achin Gupta4f6ad662013-10-25 09:08:21 +0100232}
233
234/*
235 * Make sure that the interrupt's group is set before expecting
236 * this function to do its job correctly.
237 */
Juan Castillo7f1f0622014-09-09 09:49:23 +0100238void gicd_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100239{
Achin Gupta4f6ad662013-10-25 09:08:21 +0100240 /*
241 * Enforce ARM recommendation to manage priority values such
242 * that group1 interrupts always have a lower priority than
Jon Medhurstd0212c22014-02-11 14:48:56 +0000243 * group0 interrupts.
244 * Note, lower numerical values are higher priorities so the comparison
245 * checks below are reversed from what might be expected.
Achin Gupta4f6ad662013-10-25 09:08:21 +0100246 */
Jon Medhurstd0212c22014-02-11 14:48:56 +0000247 assert(gicd_get_igroupr(base, id) == GRP1 ?
248 pri >= GIC_HIGHEST_NS_PRIORITY &&
249 pri <= GIC_LOWEST_NS_PRIORITY :
250 pri >= GIC_HIGHEST_SEC_PRIORITY &&
251 pri <= GIC_LOWEST_SEC_PRIORITY);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100252
Soby Mathew73f92992016-01-15 14:05:37 +0000253 mmio_write_8(base + GICD_IPRIORITYR + id, pri & GIC_PRI_MASK);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100254}
255
Juan Castillo7f1f0622014-09-09 09:49:23 +0100256void gicd_set_itargetsr(uintptr_t base, unsigned int id, unsigned int target)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100257{
Soby Mathew73f92992016-01-15 14:05:37 +0000258 mmio_write_8(base + GICD_ITARGETSR + id, target & GIC_TARGET_CPU_MASK);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100259}
260
Achin Gupta191e86e2014-05-09 10:03:15 +0100261/*******************************************************************************
262 * This function allows the interrupt management framework to determine (through
263 * the platform) which interrupt line (IRQ/FIQ) to use for an interrupt type to
264 * route it to EL3. The interrupt line is represented as the bit position of the
265 * IRQ or FIQ bit in the SCR_EL3.
266 ******************************************************************************/
267uint32_t gicv2_interrupt_type_to_line(uint32_t cpuif_base, uint32_t type)
268{
269 uint32_t gicc_ctlr;
270
271 /* Non-secure interrupts are signalled on the IRQ line always */
272 if (type == INTR_TYPE_NS)
273 return __builtin_ctz(SCR_IRQ_BIT);
274
275 /*
276 * Secure interrupts are signalled using the IRQ line if the FIQ_EN
277 * bit is not set else they are signalled using the FIQ line.
278 */
279 gicc_ctlr = gicc_read_ctlr(cpuif_base);
280 if (gicc_ctlr & FIQ_EN)
281 return __builtin_ctz(SCR_FIQ_BIT);
282 else
283 return __builtin_ctz(SCR_IRQ_BIT);
284}