1 /*
2 * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <assert.h>
8
9 #include <drivers/arm/gic_common.h>
10 #include <lib/mmio.h>
11 #include <lib/utils_def.h>
12
13 #include "../common/gic_common_private.h"
14
15 /*******************************************************************************
16 * GIC Distributor interface accessors for reading entire registers
17 ******************************************************************************/
18 /*
19 * Accessor to read the GIC Distributor IGROUPR corresponding to the interrupt
20 * `id`, 32 interrupt ids at a time.
21 */
gicd_read_igroupr(uintptr_t base,unsigned int id)22 unsigned int gicd_read_igroupr(uintptr_t base, unsigned int id)
23 {
24 unsigned int n = id >> IGROUPR_SHIFT;
25
26 return mmio_read_32(base + GICD_IGROUPR + (n << 2));
27 }
28
29 /*
30 * Accessor to read the GIC Distributor ISENABLER corresponding to the
31 * interrupt `id`, 32 interrupt ids at a time.
32 */
gicd_read_isenabler(uintptr_t base,unsigned int id)33 unsigned int gicd_read_isenabler(uintptr_t base, unsigned int id)
34 {
35 unsigned int n = id >> ISENABLER_SHIFT;
36
37 return mmio_read_32(base + GICD_ISENABLER + (n << 2));
38 }
39
40 /*
41 * Accessor to read the GIC Distributor ICENABLER corresponding to the
42 * interrupt `id`, 32 interrupt IDs at a time.
43 */
gicd_read_icenabler(uintptr_t base,unsigned int id)44 unsigned int gicd_read_icenabler(uintptr_t base, unsigned int id)
45 {
46 unsigned int n = id >> ICENABLER_SHIFT;
47
48 return mmio_read_32(base + GICD_ICENABLER + (n << 2));
49 }
50
51 /*
52 * Accessor to read the GIC Distributor ISPENDR corresponding to the
53 * interrupt `id`, 32 interrupt IDs at a time.
54 */
gicd_read_ispendr(uintptr_t base,unsigned int id)55 unsigned int gicd_read_ispendr(uintptr_t base, unsigned int id)
56 {
57 unsigned int n = id >> ISPENDR_SHIFT;
58
59 return mmio_read_32(base + GICD_ISPENDR + (n << 2));
60 }
61
62 /*
63 * Accessor to read the GIC Distributor ICPENDR corresponding to the
64 * interrupt `id`, 32 interrupt IDs at a time.
65 */
gicd_read_icpendr(uintptr_t base,unsigned int id)66 unsigned int gicd_read_icpendr(uintptr_t base, unsigned int id)
67 {
68 unsigned int n = id >> ICPENDR_SHIFT;
69
70 return mmio_read_32(base + GICD_ICPENDR + (n << 2));
71 }
72
73 /*
74 * Accessor to read the GIC Distributor ISACTIVER corresponding to the
75 * interrupt `id`, 32 interrupt IDs at a time.
76 */
gicd_read_isactiver(uintptr_t base,unsigned int id)77 unsigned int gicd_read_isactiver(uintptr_t base, unsigned int id)
78 {
79 unsigned int n = id >> ISACTIVER_SHIFT;
80
81 return mmio_read_32(base + GICD_ISACTIVER + (n << 2));
82 }
83
84 /*
85 * Accessor to read the GIC Distributor ICACTIVER corresponding to the
86 * interrupt `id`, 32 interrupt IDs at a time.
87 */
gicd_read_icactiver(uintptr_t base,unsigned int id)88 unsigned int gicd_read_icactiver(uintptr_t base, unsigned int id)
89 {
90 unsigned int n = id >> ICACTIVER_SHIFT;
91
92 return mmio_read_32(base + GICD_ICACTIVER + (n << 2));
93 }
94
95 /*
96 * Accessor to read the GIC Distributor IPRIORITYR corresponding to the
97 * interrupt `id`, 4 interrupt IDs at a time.
98 */
gicd_read_ipriorityr(uintptr_t base,unsigned int id)99 unsigned int gicd_read_ipriorityr(uintptr_t base, unsigned int id)
100 {
101 unsigned int n = id >> IPRIORITYR_SHIFT;
102
103 return mmio_read_32(base + GICD_IPRIORITYR + (n << 2));
104 }
105
106 /*
107 * Accessor to read the GIC Distributor ICGFR corresponding to the
108 * interrupt `id`, 16 interrupt IDs at a time.
109 */
gicd_read_icfgr(uintptr_t base,unsigned int id)110 unsigned int gicd_read_icfgr(uintptr_t base, unsigned int id)
111 {
112 unsigned int n = id >> ICFGR_SHIFT;
113
114 return mmio_read_32(base + GICD_ICFGR + (n << 2));
115 }
116
117 /*
118 * Accessor to read the GIC Distributor NSACR corresponding to the
119 * interrupt `id`, 16 interrupt IDs at a time.
120 */
gicd_read_nsacr(uintptr_t base,unsigned int id)121 unsigned int gicd_read_nsacr(uintptr_t base, unsigned int id)
122 {
123 unsigned int n = id >> NSACR_SHIFT;
124
125 return mmio_read_32(base + GICD_NSACR + (n << 2));
126 }
127
128 /*******************************************************************************
129 * GIC Distributor interface accessors for writing entire registers
130 ******************************************************************************/
131 /*
132 * Accessor to write the GIC Distributor IGROUPR corresponding to the
133 * interrupt `id`, 32 interrupt IDs at a time.
134 */
gicd_write_igroupr(uintptr_t base,unsigned int id,unsigned int val)135 void gicd_write_igroupr(uintptr_t base, unsigned int id, unsigned int val)
136 {
137 unsigned int n = id >> IGROUPR_SHIFT;
138
139 mmio_write_32(base + GICD_IGROUPR + (n << 2), val);
140 }
141
142 /*
143 * Accessor to write the GIC Distributor ISENABLER corresponding to the
144 * interrupt `id`, 32 interrupt IDs at a time.
145 */
gicd_write_isenabler(uintptr_t base,unsigned int id,unsigned int val)146 void gicd_write_isenabler(uintptr_t base, unsigned int id, unsigned int val)
147 {
148 unsigned int n = id >> ISENABLER_SHIFT;
149
150 mmio_write_32(base + GICD_ISENABLER + (n << 2), val);
151 }
152
153 /*
154 * Accessor to write the GIC Distributor ICENABLER corresponding to the
155 * interrupt `id`, 32 interrupt IDs at a time.
156 */
gicd_write_icenabler(uintptr_t base,unsigned int id,unsigned int val)157 void gicd_write_icenabler(uintptr_t base, unsigned int id, unsigned int val)
158 {
159 unsigned int n = id >> ICENABLER_SHIFT;
160
161 mmio_write_32(base + GICD_ICENABLER + (n << 2), val);
162 }
163
164 /*
165 * Accessor to write the GIC Distributor ISPENDR corresponding to the
166 * interrupt `id`, 32 interrupt IDs at a time.
167 */
gicd_write_ispendr(uintptr_t base,unsigned int id,unsigned int val)168 void gicd_write_ispendr(uintptr_t base, unsigned int id, unsigned int val)
169 {
170 unsigned int n = id >> ISPENDR_SHIFT;
171
172 mmio_write_32(base + GICD_ISPENDR + (n << 2), val);
173 }
174
175 /*
176 * Accessor to write the GIC Distributor ICPENDR corresponding to the
177 * interrupt `id`, 32 interrupt IDs at a time.
178 */
gicd_write_icpendr(uintptr_t base,unsigned int id,unsigned int val)179 void gicd_write_icpendr(uintptr_t base, unsigned int id, unsigned int val)
180 {
181 unsigned int n = id >> ICPENDR_SHIFT;
182
183 mmio_write_32(base + GICD_ICPENDR + (n << 2), val);
184 }
185
186 /*
187 * Accessor to write the GIC Distributor ISACTIVER corresponding to the
188 * interrupt `id`, 32 interrupt IDs at a time.
189 */
gicd_write_isactiver(uintptr_t base,unsigned int id,unsigned int val)190 void gicd_write_isactiver(uintptr_t base, unsigned int id, unsigned int val)
191 {
192 unsigned int n = id >> ISACTIVER_SHIFT;
193
194 mmio_write_32(base + GICD_ISACTIVER + (n << 2), val);
195 }
196
197 /*
198 * Accessor to write the GIC Distributor ICACTIVER corresponding to the
199 * interrupt `id`, 32 interrupt IDs at a time.
200 */
gicd_write_icactiver(uintptr_t base,unsigned int id,unsigned int val)201 void gicd_write_icactiver(uintptr_t base, unsigned int id, unsigned int val)
202 {
203 unsigned int n = id >> ICACTIVER_SHIFT;
204
205 mmio_write_32(base + GICD_ICACTIVER + (n << 2), val);
206 }
207
208 /*
209 * Accessor to write the GIC Distributor IPRIORITYR corresponding to the
210 * interrupt `id`, 4 interrupt IDs at a time.
211 */
gicd_write_ipriorityr(uintptr_t base,unsigned int id,unsigned int val)212 void gicd_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val)
213 {
214 unsigned int n = id >> IPRIORITYR_SHIFT;
215
216 mmio_write_32(base + GICD_IPRIORITYR + (n << 2), val);
217 }
218
219 /*
220 * Accessor to write the GIC Distributor ICFGR corresponding to the
221 * interrupt `id`, 16 interrupt IDs at a time.
222 */
gicd_write_icfgr(uintptr_t base,unsigned int id,unsigned int val)223 void gicd_write_icfgr(uintptr_t base, unsigned int id, unsigned int val)
224 {
225 unsigned int n = id >> ICFGR_SHIFT;
226
227 mmio_write_32(base + GICD_ICFGR + (n << 2), val);
228 }
229
230 /*
231 * Accessor to write the GIC Distributor NSACR corresponding to the
232 * interrupt `id`, 16 interrupt IDs at a time.
233 */
gicd_write_nsacr(uintptr_t base,unsigned int id,unsigned int val)234 void gicd_write_nsacr(uintptr_t base, unsigned int id, unsigned int val)
235 {
236 unsigned int n = id >> NSACR_SHIFT;
237
238 mmio_write_32(base + GICD_NSACR + (n << 2), val);
239 }
240
241 /*******************************************************************************
242 * GIC Distributor functions for accessing the GIC registers
243 * corresponding to a single interrupt ID. These functions use bitwise
244 * operations or appropriate register accesses to modify or return
245 * the bit-field corresponding the single interrupt ID.
246 ******************************************************************************/
gicd_get_igroupr(uintptr_t base,unsigned int id)247 unsigned int gicd_get_igroupr(uintptr_t base, unsigned int id)
248 {
249 unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U);
250 unsigned int reg_val = gicd_read_igroupr(base, id);
251
252 return (reg_val >> bit_num) & 0x1U;
253 }
254
gicd_set_igroupr(uintptr_t base,unsigned int id)255 void gicd_set_igroupr(uintptr_t base, unsigned int id)
256 {
257 unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U);
258 unsigned int reg_val = gicd_read_igroupr(base, id);
259
260 gicd_write_igroupr(base, id, reg_val | BIT_32(bit_num));
261 }
262
gicd_clr_igroupr(uintptr_t base,unsigned int id)263 void gicd_clr_igroupr(uintptr_t base, unsigned int id)
264 {
265 unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U);
266 unsigned int reg_val = gicd_read_igroupr(base, id);
267
268 gicd_write_igroupr(base, id, reg_val & ~BIT_32(bit_num));
269 }
270
gicd_set_isenabler(uintptr_t base,unsigned int id)271 void gicd_set_isenabler(uintptr_t base, unsigned int id)
272 {
273 unsigned int bit_num = id & ((1U << ISENABLER_SHIFT) - 1U);
274
275 gicd_write_isenabler(base, id, BIT_32(bit_num));
276 }
277
gicd_set_icenabler(uintptr_t base,unsigned int id)278 void gicd_set_icenabler(uintptr_t base, unsigned int id)
279 {
280 unsigned int bit_num = id & ((1U << ICENABLER_SHIFT) - 1U);
281
282 gicd_write_icenabler(base, id, BIT_32(bit_num));
283 }
284
gicd_set_ispendr(uintptr_t base,unsigned int id)285 void gicd_set_ispendr(uintptr_t base, unsigned int id)
286 {
287 unsigned int bit_num = id & ((1U << ISPENDR_SHIFT) - 1U);
288
289 gicd_write_ispendr(base, id, BIT_32(bit_num));
290 }
291
gicd_set_icpendr(uintptr_t base,unsigned int id)292 void gicd_set_icpendr(uintptr_t base, unsigned int id)
293 {
294 unsigned int bit_num = id & ((1U << ICPENDR_SHIFT) - 1U);
295
296 gicd_write_icpendr(base, id, BIT_32(bit_num));
297 }
298
gicd_get_isactiver(uintptr_t base,unsigned int id)299 unsigned int gicd_get_isactiver(uintptr_t base, unsigned int id)
300 {
301 unsigned int bit_num = id & ((1U << ISACTIVER_SHIFT) - 1U);
302 unsigned int reg_val = gicd_read_isactiver(base, id);
303
304 return (reg_val >> bit_num) & 0x1U;
305 }
306
gicd_set_isactiver(uintptr_t base,unsigned int id)307 void gicd_set_isactiver(uintptr_t base, unsigned int id)
308 {
309 unsigned int bit_num = id & ((1U << ISACTIVER_SHIFT) - 1U);
310
311 gicd_write_isactiver(base, id, BIT_32(bit_num));
312 }
313
gicd_set_icactiver(uintptr_t base,unsigned int id)314 void gicd_set_icactiver(uintptr_t base, unsigned int id)
315 {
316 unsigned int bit_num = id & ((1U << ICACTIVER_SHIFT) - 1U);
317
318 gicd_write_icactiver(base, id, BIT_32(bit_num));
319 }
320
gicd_set_ipriorityr(uintptr_t base,unsigned int id,unsigned int pri)321 void gicd_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri)
322 {
323 uint8_t val = (uint8_t)(pri & GIC_PRI_MASK);
324
325 mmio_write_8(base + GICD_IPRIORITYR + id, val);
326 }
327
gicd_set_icfgr(uintptr_t base,unsigned int id,unsigned int cfg)328 void gicd_set_icfgr(uintptr_t base, unsigned int id, unsigned int cfg)
329 {
330 /* Interrupt configuration is a 2-bit field */
331 unsigned int bit_num = id & ((1U << ICFGR_SHIFT) - 1U);
332 unsigned int bit_shift = bit_num << 1;
333
334 uint32_t reg_val = gicd_read_icfgr(base, id);
335
336 /* Clear the field, and insert required configuration */
337 reg_val &= ~(GIC_CFG_MASK << bit_shift);
338 reg_val |= ((cfg & GIC_CFG_MASK) << bit_shift);
339
340 gicd_write_icfgr(base, id, reg_val);
341 }
342