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 
12 #include "../common/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