blob: 38b2f67190117bc63e26d56b927740adcefd4422 [file] [log] [blame]
Achin Gupta92712a52015-09-03 14:18:02 +01001/*
Jeenu Viswambharanb6982c02018-03-22 08:57:52 +00002 * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
Achin Gupta92712a52015-09-03 14:18:02 +01003 *
dp-armfa3cf0b2017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Achin Gupta92712a52015-09-03 14:18:02 +01005 */
6
7#include <assert.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +00008
9#include <drivers/arm/gic_common.h>
10#include <lib/mmio.h>
11
Soby Mathew50f6fe42016-02-01 17:59:22 +000012#include "gic_common_private.h"
Achin Gupta92712a52015-09-03 14:18:02 +010013
14/*******************************************************************************
15 * GIC Distributor interface accessors for reading entire registers
16 ******************************************************************************/
17/*
18 * Accessor to read the GIC Distributor IGROUPR corresponding to the interrupt
19 * `id`, 32 interrupt ids at a time.
20 */
21unsigned int gicd_read_igroupr(uintptr_t base, unsigned int id)
22{
Antonio Nino Diazca994e72018-08-21 10:02:33 +010023 unsigned int n = id >> IGROUPR_SHIFT;
24
Achin Gupta92712a52015-09-03 14:18:02 +010025 return mmio_read_32(base + GICD_IGROUPR + (n << 2));
26}
27
28/*
29 * Accessor to read the GIC Distributor ISENABLER corresponding to the
30 * interrupt `id`, 32 interrupt ids at a time.
31 */
32unsigned int gicd_read_isenabler(uintptr_t base, unsigned int id)
33{
Antonio Nino Diazca994e72018-08-21 10:02:33 +010034 unsigned int n = id >> ISENABLER_SHIFT;
35
Achin Gupta92712a52015-09-03 14:18:02 +010036 return mmio_read_32(base + GICD_ISENABLER + (n << 2));
37}
38
39/*
40 * Accessor to read the GIC Distributor ICENABLER corresponding to the
41 * interrupt `id`, 32 interrupt IDs at a time.
42 */
43unsigned int gicd_read_icenabler(uintptr_t base, unsigned int id)
44{
Antonio Nino Diazca994e72018-08-21 10:02:33 +010045 unsigned int n = id >> ICENABLER_SHIFT;
46
Achin Gupta92712a52015-09-03 14:18:02 +010047 return mmio_read_32(base + GICD_ICENABLER + (n << 2));
48}
49
50/*
51 * Accessor to read the GIC Distributor ISPENDR corresponding to the
52 * interrupt `id`, 32 interrupt IDs at a time.
53 */
54unsigned int gicd_read_ispendr(uintptr_t base, unsigned int id)
55{
Antonio Nino Diazca994e72018-08-21 10:02:33 +010056 unsigned int n = id >> ISPENDR_SHIFT;
57
Achin Gupta92712a52015-09-03 14:18:02 +010058 return mmio_read_32(base + GICD_ISPENDR + (n << 2));
59}
60
61/*
62 * Accessor to read the GIC Distributor ICPENDR corresponding to the
63 * interrupt `id`, 32 interrupt IDs at a time.
64 */
65unsigned int gicd_read_icpendr(uintptr_t base, unsigned int id)
66{
Antonio Nino Diazca994e72018-08-21 10:02:33 +010067 unsigned int n = id >> ICPENDR_SHIFT;
68
Achin Gupta92712a52015-09-03 14:18:02 +010069 return mmio_read_32(base + GICD_ICPENDR + (n << 2));
70}
71
72/*
73 * Accessor to read the GIC Distributor ISACTIVER corresponding to the
74 * interrupt `id`, 32 interrupt IDs at a time.
75 */
76unsigned int gicd_read_isactiver(uintptr_t base, unsigned int id)
77{
Antonio Nino Diazca994e72018-08-21 10:02:33 +010078 unsigned int n = id >> ISACTIVER_SHIFT;
79
Achin Gupta92712a52015-09-03 14:18:02 +010080 return mmio_read_32(base + GICD_ISACTIVER + (n << 2));
81}
82
83/*
84 * Accessor to read the GIC Distributor ICACTIVER corresponding to the
85 * interrupt `id`, 32 interrupt IDs at a time.
86 */
87unsigned int gicd_read_icactiver(uintptr_t base, unsigned int id)
88{
Antonio Nino Diazca994e72018-08-21 10:02:33 +010089 unsigned int n = id >> ICACTIVER_SHIFT;
90
Achin Gupta92712a52015-09-03 14:18:02 +010091 return mmio_read_32(base + GICD_ICACTIVER + (n << 2));
92}
93
94/*
95 * Accessor to read the GIC Distributor IPRIORITYR corresponding to the
96 * interrupt `id`, 4 interrupt IDs at a time.
97 */
98unsigned int gicd_read_ipriorityr(uintptr_t base, unsigned int id)
99{
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100100 unsigned int n = id >> IPRIORITYR_SHIFT;
101
Achin Gupta92712a52015-09-03 14:18:02 +0100102 return mmio_read_32(base + GICD_IPRIORITYR + (n << 2));
103}
104
105/*
106 * Accessor to read the GIC Distributor ICGFR corresponding to the
107 * interrupt `id`, 16 interrupt IDs at a time.
108 */
109unsigned int gicd_read_icfgr(uintptr_t base, unsigned int id)
110{
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100111 unsigned int n = id >> ICFGR_SHIFT;
112
Achin Gupta92712a52015-09-03 14:18:02 +0100113 return mmio_read_32(base + GICD_ICFGR + (n << 2));
114}
115
116/*
117 * Accessor to read the GIC Distributor NSACR corresponding to the
118 * interrupt `id`, 16 interrupt IDs at a time.
119 */
120unsigned int gicd_read_nsacr(uintptr_t base, unsigned int id)
121{
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100122 unsigned int n = id >> NSACR_SHIFT;
123
Achin Gupta92712a52015-09-03 14:18:02 +0100124 return mmio_read_32(base + GICD_NSACR + (n << 2));
125}
126
127/*******************************************************************************
128 * GIC Distributor interface accessors for writing entire registers
129 ******************************************************************************/
130/*
131 * Accessor to write the GIC Distributor IGROUPR corresponding to the
132 * interrupt `id`, 32 interrupt IDs at a time.
133 */
134void gicd_write_igroupr(uintptr_t base, unsigned int id, unsigned int val)
135{
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100136 unsigned int n = id >> IGROUPR_SHIFT;
137
Achin Gupta92712a52015-09-03 14:18:02 +0100138 mmio_write_32(base + GICD_IGROUPR + (n << 2), val);
139}
140
141/*
142 * Accessor to write the GIC Distributor ISENABLER corresponding to the
143 * interrupt `id`, 32 interrupt IDs at a time.
144 */
145void gicd_write_isenabler(uintptr_t base, unsigned int id, unsigned int val)
146{
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100147 unsigned int n = id >> ISENABLER_SHIFT;
148
Achin Gupta92712a52015-09-03 14:18:02 +0100149 mmio_write_32(base + GICD_ISENABLER + (n << 2), val);
150}
151
152/*
153 * Accessor to write the GIC Distributor ICENABLER corresponding to the
154 * interrupt `id`, 32 interrupt IDs at a time.
155 */
156void gicd_write_icenabler(uintptr_t base, unsigned int id, unsigned int val)
157{
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100158 unsigned int n = id >> ICENABLER_SHIFT;
159
Achin Gupta92712a52015-09-03 14:18:02 +0100160 mmio_write_32(base + GICD_ICENABLER + (n << 2), val);
161}
162
163/*
164 * Accessor to write the GIC Distributor ISPENDR corresponding to the
165 * interrupt `id`, 32 interrupt IDs at a time.
166 */
167void gicd_write_ispendr(uintptr_t base, unsigned int id, unsigned int val)
168{
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100169 unsigned int n = id >> ISPENDR_SHIFT;
170
Achin Gupta92712a52015-09-03 14:18:02 +0100171 mmio_write_32(base + GICD_ISPENDR + (n << 2), val);
172}
173
174/*
175 * Accessor to write the GIC Distributor ICPENDR corresponding to the
176 * interrupt `id`, 32 interrupt IDs at a time.
177 */
178void gicd_write_icpendr(uintptr_t base, unsigned int id, unsigned int val)
179{
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100180 unsigned int n = id >> ICPENDR_SHIFT;
181
Achin Gupta92712a52015-09-03 14:18:02 +0100182 mmio_write_32(base + GICD_ICPENDR + (n << 2), val);
183}
184
185/*
186 * Accessor to write the GIC Distributor ISACTIVER corresponding to the
187 * interrupt `id`, 32 interrupt IDs at a time.
188 */
189void gicd_write_isactiver(uintptr_t base, unsigned int id, unsigned int val)
190{
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100191 unsigned int n = id >> ISACTIVER_SHIFT;
192
Achin Gupta92712a52015-09-03 14:18:02 +0100193 mmio_write_32(base + GICD_ISACTIVER + (n << 2), val);
194}
195
196/*
197 * Accessor to write the GIC Distributor ICACTIVER corresponding to the
198 * interrupt `id`, 32 interrupt IDs at a time.
199 */
200void gicd_write_icactiver(uintptr_t base, unsigned int id, unsigned int val)
201{
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100202 unsigned int n = id >> ICACTIVER_SHIFT;
203
Achin Gupta92712a52015-09-03 14:18:02 +0100204 mmio_write_32(base + GICD_ICACTIVER + (n << 2), val);
205}
206
207/*
208 * Accessor to write the GIC Distributor IPRIORITYR corresponding to the
209 * interrupt `id`, 4 interrupt IDs at a time.
210 */
211void gicd_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val)
212{
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100213 unsigned int n = id >> IPRIORITYR_SHIFT;
214
Achin Gupta92712a52015-09-03 14:18:02 +0100215 mmio_write_32(base + GICD_IPRIORITYR + (n << 2), val);
216}
217
218/*
219 * Accessor to write the GIC Distributor ICFGR corresponding to the
220 * interrupt `id`, 16 interrupt IDs at a time.
221 */
222void gicd_write_icfgr(uintptr_t base, unsigned int id, unsigned int val)
223{
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100224 unsigned int n = id >> ICFGR_SHIFT;
225
Achin Gupta92712a52015-09-03 14:18:02 +0100226 mmio_write_32(base + GICD_ICFGR + (n << 2), val);
227}
228
229/*
230 * Accessor to write the GIC Distributor NSACR corresponding to the
231 * interrupt `id`, 16 interrupt IDs at a time.
232 */
233void gicd_write_nsacr(uintptr_t base, unsigned int id, unsigned int val)
234{
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100235 unsigned int n = id >> NSACR_SHIFT;
236
Achin Gupta92712a52015-09-03 14:18:02 +0100237 mmio_write_32(base + GICD_NSACR + (n << 2), val);
238}
239
240/*******************************************************************************
Soby Mathew50f6fe42016-02-01 17:59:22 +0000241 * GIC Distributor functions for accessing the GIC registers
242 * corresponding to a single interrupt ID. These functions use bitwise
243 * operations or appropriate register accesses to modify or return
244 * the bit-field corresponding the single interrupt ID.
Achin Gupta92712a52015-09-03 14:18:02 +0100245 ******************************************************************************/
246unsigned int gicd_get_igroupr(uintptr_t base, unsigned int id)
247{
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100248 unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U);
Achin Gupta92712a52015-09-03 14:18:02 +0100249 unsigned int reg_val = gicd_read_igroupr(base, id);
250
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100251 return (reg_val >> bit_num) & 0x1U;
Achin Gupta92712a52015-09-03 14:18:02 +0100252}
253
254void gicd_set_igroupr(uintptr_t base, unsigned int id)
255{
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100256 unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U);
Achin Gupta92712a52015-09-03 14:18:02 +0100257 unsigned int reg_val = gicd_read_igroupr(base, id);
258
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100259 gicd_write_igroupr(base, id, reg_val | (1U << bit_num));
Achin Gupta92712a52015-09-03 14:18:02 +0100260}
261
262void gicd_clr_igroupr(uintptr_t base, unsigned int id)
263{
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100264 unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U);
Achin Gupta92712a52015-09-03 14:18:02 +0100265 unsigned int reg_val = gicd_read_igroupr(base, id);
266
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100267 gicd_write_igroupr(base, id, reg_val & ~(1U << bit_num));
Achin Gupta92712a52015-09-03 14:18:02 +0100268}
269
270void gicd_set_isenabler(uintptr_t base, unsigned int id)
271{
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100272 unsigned int bit_num = id & ((1U << ISENABLER_SHIFT) - 1U);
Achin Gupta92712a52015-09-03 14:18:02 +0100273
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100274 gicd_write_isenabler(base, id, (1U << bit_num));
Achin Gupta92712a52015-09-03 14:18:02 +0100275}
276
277void gicd_set_icenabler(uintptr_t base, unsigned int id)
278{
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100279 unsigned int bit_num = id & ((1U << ICENABLER_SHIFT) - 1U);
Achin Gupta92712a52015-09-03 14:18:02 +0100280
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100281 gicd_write_icenabler(base, id, (1U << bit_num));
Achin Gupta92712a52015-09-03 14:18:02 +0100282}
283
284void gicd_set_ispendr(uintptr_t base, unsigned int id)
285{
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100286 unsigned int bit_num = id & ((1U << ISPENDR_SHIFT) - 1U);
Achin Gupta92712a52015-09-03 14:18:02 +0100287
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100288 gicd_write_ispendr(base, id, (1U << bit_num));
Achin Gupta92712a52015-09-03 14:18:02 +0100289}
290
291void gicd_set_icpendr(uintptr_t base, unsigned int id)
292{
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100293 unsigned int bit_num = id & ((1U << ICPENDR_SHIFT) - 1U);
Achin Gupta92712a52015-09-03 14:18:02 +0100294
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100295 gicd_write_icpendr(base, id, (1U << bit_num));
Achin Gupta92712a52015-09-03 14:18:02 +0100296}
297
Jeenu Viswambharan24e70292017-09-22 08:32:09 +0100298unsigned int gicd_get_isactiver(uintptr_t base, unsigned int id)
299{
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100300 unsigned int bit_num = id & ((1U << ISACTIVER_SHIFT) - 1U);
Jeenu Viswambharan24e70292017-09-22 08:32:09 +0100301 unsigned int reg_val = gicd_read_isactiver(base, id);
302
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100303 return (reg_val >> bit_num) & 0x1U;
Jeenu Viswambharan24e70292017-09-22 08:32:09 +0100304}
305
Achin Gupta92712a52015-09-03 14:18:02 +0100306void gicd_set_isactiver(uintptr_t base, unsigned int id)
307{
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100308 unsigned int bit_num = id & ((1U << ISACTIVER_SHIFT) - 1U);
Achin Gupta92712a52015-09-03 14:18:02 +0100309
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100310 gicd_write_isactiver(base, id, (1U << bit_num));
Achin Gupta92712a52015-09-03 14:18:02 +0100311}
312
313void gicd_set_icactiver(uintptr_t base, unsigned int id)
314{
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100315 unsigned int bit_num = id & ((1U << ICACTIVER_SHIFT) - 1U);
Achin Gupta92712a52015-09-03 14:18:02 +0100316
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100317 gicd_write_icactiver(base, id, (1U << bit_num));
Achin Gupta92712a52015-09-03 14:18:02 +0100318}
Soby Mathew421259e2016-01-15 14:20:57 +0000319
320void gicd_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri)
321{
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100322 uint8_t val = pri & GIC_PRI_MASK;
323
324 mmio_write_8(base + GICD_IPRIORITYR + id, val);
Soby Mathew421259e2016-01-15 14:20:57 +0000325}
Jeenu Viswambharan4684bce2017-09-22 08:32:09 +0100326
327void gicd_set_icfgr(uintptr_t base, unsigned int id, unsigned int cfg)
328{
Jeenu Viswambharanb6982c02018-03-22 08:57:52 +0000329 /* Interrupt configuration is a 2-bit field */
Antonio Nino Diazca994e72018-08-21 10:02:33 +0100330 unsigned int bit_num = id & ((1U << ICFGR_SHIFT) - 1U);
Jeenu Viswambharanb6982c02018-03-22 08:57:52 +0000331 unsigned int bit_shift = bit_num << 1;
332
Jeenu Viswambharan4684bce2017-09-22 08:32:09 +0100333 uint32_t reg_val = gicd_read_icfgr(base, id);
334
335 /* Clear the field, and insert required configuration */
Jeenu Viswambharanb6982c02018-03-22 08:57:52 +0000336 reg_val &= ~(GIC_CFG_MASK << bit_shift);
337 reg_val |= ((cfg & GIC_CFG_MASK) << bit_shift);
Jeenu Viswambharan4684bce2017-09-22 08:32:09 +0100338
339 gicd_write_icfgr(base, id, reg_val);
340}