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