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