1 /*
2 * Copyright (c) 2015-2018, 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
12 #include "gic_common_private.h"
13
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 */
gicd_read_igroupr(uintptr_t base,unsigned int id)21 unsigned int gicd_read_igroupr(uintptr_t base, unsigned int id)
22 {
23 unsigned int n = id >> IGROUPR_SHIFT;
24
25 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 */
gicd_read_isenabler(uintptr_t base,unsigned int id)32 unsigned int gicd_read_isenabler(uintptr_t base, unsigned int id)
33 {
34 unsigned int n = id >> ISENABLER_SHIFT;
35
36 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 */
gicd_read_icenabler(uintptr_t base,unsigned int id)43 unsigned int gicd_read_icenabler(uintptr_t base, unsigned int id)
44 {
45 unsigned int n = id >> ICENABLER_SHIFT;
46
47 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 */
gicd_read_ispendr(uintptr_t base,unsigned int id)54 unsigned int gicd_read_ispendr(uintptr_t base, unsigned int id)
55 {
56 unsigned int n = id >> ISPENDR_SHIFT;
57
58 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 */
gicd_read_icpendr(uintptr_t base,unsigned int id)65 unsigned int gicd_read_icpendr(uintptr_t base, unsigned int id)
66 {
67 unsigned int n = id >> ICPENDR_SHIFT;
68
69 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 */
gicd_read_isactiver(uintptr_t base,unsigned int id)76 unsigned int gicd_read_isactiver(uintptr_t base, unsigned int id)
77 {
78 unsigned int n = id >> ISACTIVER_SHIFT;
79
80 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 */
gicd_read_icactiver(uintptr_t base,unsigned int id)87 unsigned int gicd_read_icactiver(uintptr_t base, unsigned int id)
88 {
89 unsigned int n = id >> ICACTIVER_SHIFT;
90
91 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 */
gicd_read_ipriorityr(uintptr_t base,unsigned int id)98 unsigned int gicd_read_ipriorityr(uintptr_t base, unsigned int id)
99 {
100 unsigned int n = id >> IPRIORITYR_SHIFT;
101
102 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 */
gicd_read_icfgr(uintptr_t base,unsigned int id)109 unsigned int gicd_read_icfgr(uintptr_t base, unsigned int id)
110 {
111 unsigned int n = id >> ICFGR_SHIFT;
112
113 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 */
gicd_read_nsacr(uintptr_t base,unsigned int id)120 unsigned int gicd_read_nsacr(uintptr_t base, unsigned int id)
121 {
122 unsigned int n = id >> NSACR_SHIFT;
123
124 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 */
gicd_write_igroupr(uintptr_t base,unsigned int id,unsigned int val)134 void gicd_write_igroupr(uintptr_t base, unsigned int id, unsigned int val)
135 {
136 unsigned int n = id >> IGROUPR_SHIFT;
137
138 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 */
gicd_write_isenabler(uintptr_t base,unsigned int id,unsigned int val)145 void gicd_write_isenabler(uintptr_t base, unsigned int id, unsigned int val)
146 {
147 unsigned int n = id >> ISENABLER_SHIFT;
148
149 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 */
gicd_write_icenabler(uintptr_t base,unsigned int id,unsigned int val)156 void gicd_write_icenabler(uintptr_t base, unsigned int id, unsigned int val)
157 {
158 unsigned int n = id >> ICENABLER_SHIFT;
159
160 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 */
gicd_write_ispendr(uintptr_t base,unsigned int id,unsigned int val)167 void gicd_write_ispendr(uintptr_t base, unsigned int id, unsigned int val)
168 {
169 unsigned int n = id >> ISPENDR_SHIFT;
170
171 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 */
gicd_write_icpendr(uintptr_t base,unsigned int id,unsigned int val)178 void gicd_write_icpendr(uintptr_t base, unsigned int id, unsigned int val)
179 {
180 unsigned int n = id >> ICPENDR_SHIFT;
181
182 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 */
gicd_write_isactiver(uintptr_t base,unsigned int id,unsigned int val)189 void gicd_write_isactiver(uintptr_t base, unsigned int id, unsigned int val)
190 {
191 unsigned int n = id >> ISACTIVER_SHIFT;
192
193 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 */
gicd_write_icactiver(uintptr_t base,unsigned int id,unsigned int val)200 void gicd_write_icactiver(uintptr_t base, unsigned int id, unsigned int val)
201 {
202 unsigned int n = id >> ICACTIVER_SHIFT;
203
204 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 */
gicd_write_ipriorityr(uintptr_t base,unsigned int id,unsigned int val)211 void gicd_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val)
212 {
213 unsigned int n = id >> IPRIORITYR_SHIFT;
214
215 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 */
gicd_write_icfgr(uintptr_t base,unsigned int id,unsigned int val)222 void gicd_write_icfgr(uintptr_t base, unsigned int id, unsigned int val)
223 {
224 unsigned int n = id >> ICFGR_SHIFT;
225
226 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 */
gicd_write_nsacr(uintptr_t base,unsigned int id,unsigned int val)233 void gicd_write_nsacr(uintptr_t base, unsigned int id, unsigned int val)
234 {
235 unsigned int n = id >> NSACR_SHIFT;
236
237 mmio_write_32(base + GICD_NSACR + (n << 2), val);
238 }
239
240 /*******************************************************************************
241 * 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.
245 ******************************************************************************/
gicd_get_igroupr(uintptr_t base,unsigned int id)246 unsigned int gicd_get_igroupr(uintptr_t base, unsigned int id)
247 {
248 unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U);
249 unsigned int reg_val = gicd_read_igroupr(base, id);
250
251 return (reg_val >> bit_num) & 0x1U;
252 }
253
gicd_set_igroupr(uintptr_t base,unsigned int id)254 void gicd_set_igroupr(uintptr_t base, unsigned int id)
255 {
256 unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U);
257 unsigned int reg_val = gicd_read_igroupr(base, id);
258
259 gicd_write_igroupr(base, id, reg_val | (1U << bit_num));
260 }
261
gicd_clr_igroupr(uintptr_t base,unsigned int id)262 void gicd_clr_igroupr(uintptr_t base, unsigned int id)
263 {
264 unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U);
265 unsigned int reg_val = gicd_read_igroupr(base, id);
266
267 gicd_write_igroupr(base, id, reg_val & ~(1U << bit_num));
268 }
269
gicd_set_isenabler(uintptr_t base,unsigned int id)270 void gicd_set_isenabler(uintptr_t base, unsigned int id)
271 {
272 unsigned int bit_num = id & ((1U << ISENABLER_SHIFT) - 1U);
273
274 gicd_write_isenabler(base, id, (1U << bit_num));
275 }
276
gicd_set_icenabler(uintptr_t base,unsigned int id)277 void gicd_set_icenabler(uintptr_t base, unsigned int id)
278 {
279 unsigned int bit_num = id & ((1U << ICENABLER_SHIFT) - 1U);
280
281 gicd_write_icenabler(base, id, (1U << bit_num));
282 }
283
gicd_set_ispendr(uintptr_t base,unsigned int id)284 void gicd_set_ispendr(uintptr_t base, unsigned int id)
285 {
286 unsigned int bit_num = id & ((1U << ISPENDR_SHIFT) - 1U);
287
288 gicd_write_ispendr(base, id, (1U << bit_num));
289 }
290
gicd_set_icpendr(uintptr_t base,unsigned int id)291 void gicd_set_icpendr(uintptr_t base, unsigned int id)
292 {
293 unsigned int bit_num = id & ((1U << ICPENDR_SHIFT) - 1U);
294
295 gicd_write_icpendr(base, id, (1U << bit_num));
296 }
297
gicd_get_isactiver(uintptr_t base,unsigned int id)298 unsigned int gicd_get_isactiver(uintptr_t base, unsigned int id)
299 {
300 unsigned int bit_num = id & ((1U << ISACTIVER_SHIFT) - 1U);
301 unsigned int reg_val = gicd_read_isactiver(base, id);
302
303 return (reg_val >> bit_num) & 0x1U;
304 }
305
gicd_set_isactiver(uintptr_t base,unsigned int id)306 void gicd_set_isactiver(uintptr_t base, unsigned int id)
307 {
308 unsigned int bit_num = id & ((1U << ISACTIVER_SHIFT) - 1U);
309
310 gicd_write_isactiver(base, id, (1U << bit_num));
311 }
312
gicd_set_icactiver(uintptr_t base,unsigned int id)313 void gicd_set_icactiver(uintptr_t base, unsigned int id)
314 {
315 unsigned int bit_num = id & ((1U << ICACTIVER_SHIFT) - 1U);
316
317 gicd_write_icactiver(base, id, (1U << bit_num));
318 }
319
gicd_set_ipriorityr(uintptr_t base,unsigned int id,unsigned int pri)320 void gicd_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri)
321 {
322 uint8_t val = pri & GIC_PRI_MASK;
323
324 mmio_write_8(base + GICD_IPRIORITYR + id, val);
325 }
326
gicd_set_icfgr(uintptr_t base,unsigned int id,unsigned int cfg)327 void gicd_set_icfgr(uintptr_t base, unsigned int id, unsigned int cfg)
328 {
329 /* Interrupt configuration is a 2-bit field */
330 unsigned int bit_num = id & ((1U << ICFGR_SHIFT) - 1U);
331 unsigned int bit_shift = bit_num << 1;
332
333 uint32_t reg_val = gicd_read_icfgr(base, id);
334
335 /* Clear the field, and insert required configuration */
336 reg_val &= ~(GIC_CFG_MASK << bit_shift);
337 reg_val |= ((cfg & GIC_CFG_MASK) << bit_shift);
338
339 gicd_write_icfgr(base, id, reg_val);
340 }
341