blob: 4b3d0c55fd68c293420bb1d27ed885d663bda1cd [file] [log] [blame]
Achin Gupta4f6ad662013-10-25 09:08:21 +01001/*
2 * Copyright (c) 2013, ARM Limited. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice, this
8 * list of conditions and the following disclaimer.
9 *
10 * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * Neither the name of ARM nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without specific
16 * prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include <gic.h>
32#include <mmio.h>
33
34/*******************************************************************************
35 * GIC Distributor interface accessesors for reading entire registers
36 ******************************************************************************/
37inline unsigned int gicd_read_ctlr(unsigned int base)
38{
39 return mmio_read_32(base + GICD_CTLR);
40}
41
42inline unsigned int gicd_read_typer(unsigned int base)
43{
44 return mmio_read_32(base + GICD_TYPER);
45}
46
47unsigned int gicd_read_igroupr(unsigned int base, unsigned int id)
48{
49 unsigned n = id >> IGROUPR_SHIFT;
50 return mmio_read_32(base + GICD_IGROUPR + (n << 2));
51}
52
53unsigned int gicd_read_isenabler(unsigned int base, unsigned int id)
54{
55 unsigned n = id >> ISENABLER_SHIFT;
56 return mmio_read_32(base + GICD_ISENABLER + (n << 2));
57}
58
59unsigned int gicd_read_icenabler(unsigned int base, unsigned int id)
60{
61 unsigned n = id >> ICENABLER_SHIFT;
62 return mmio_read_32(base + GICD_ICENABLER + (n << 2));
63}
64
65unsigned int gicd_read_ispendr(unsigned int base, unsigned int id)
66{
67 unsigned n = id >> ISPENDR_SHIFT;
68 return mmio_read_32(base + GICD_ISPENDR + (n << 2));
69}
70
71unsigned int gicd_read_icpendr(unsigned int base, unsigned int id)
72{
73 unsigned n = id >> ICPENDR_SHIFT;
74 return mmio_read_32(base + GICD_ICPENDR + (n << 2));
75}
76
77unsigned int gicd_read_isactiver(unsigned int base, unsigned int id)
78{
79 unsigned n = id >> ISACTIVER_SHIFT;
80 return mmio_read_32(base + GICD_ISACTIVER + (n << 2));
81}
82
83unsigned int gicd_read_icactiver(unsigned int base, unsigned int id)
84{
85 unsigned n = id >> ICACTIVER_SHIFT;
86 return mmio_read_32(base + GICD_ICACTIVER + (n << 2));
87}
88
89unsigned int gicd_read_ipriorityr(unsigned int base, unsigned int id)
90{
91 unsigned n = id >> IPRIORITYR_SHIFT;
92 return mmio_read_32(base + GICD_IPRIORITYR + (n << 2));
93}
94
95unsigned int gicd_read_itargetsr(unsigned int base, unsigned int id)
96{
97 unsigned n = id >> ITARGETSR_SHIFT;
98 return mmio_read_32(base + GICD_ITARGETSR + (n << 2));
99}
100
101unsigned int gicd_read_icfgr(unsigned int base, unsigned int id)
102{
103 unsigned n = id >> ICFGR_SHIFT;
104 return mmio_read_32(base + GICD_ICFGR + (n << 2));
105}
106
107unsigned int gicd_read_sgir(unsigned int base)
108{
109 return mmio_read_32(base + GICD_SGIR);
110}
111
112unsigned int gicd_read_cpendsgir(unsigned int base, unsigned int id)
113{
114 unsigned n = id >> CPENDSGIR_SHIFT;
115 return mmio_read_32(base + GICD_CPENDSGIR + (n << 2));
116}
117
118unsigned int gicd_read_spendsgir(unsigned int base, unsigned int id)
119{
120 unsigned n = id >> SPENDSGIR_SHIFT;
121 return mmio_read_32(base + GICD_SPENDSGIR + (n << 2));
122}
123
124/*******************************************************************************
125 * GIC Distributor interface accessesors for writing entire registers
126 ******************************************************************************/
127inline void gicd_write_ctlr(unsigned int base, unsigned int val)
128{
129 mmio_write_32(base + GICD_CTLR, val);
130 return;
131}
132
133void gicd_write_igroupr(unsigned int base, unsigned int id, unsigned int val)
134{
135 unsigned n = id >> IGROUPR_SHIFT;
136 mmio_write_32(base + GICD_IGROUPR + (n << 2), val);
137 return;
138}
139
140void gicd_write_isenabler(unsigned int base, unsigned int id, unsigned int val)
141{
142 unsigned n = id >> ISENABLER_SHIFT;
143 mmio_write_32(base + GICD_ISENABLER + (n << 2), val);
144 return;
145}
146
147void gicd_write_icenabler(unsigned int base, unsigned int id, unsigned int val)
148{
149 unsigned n = id >> ICENABLER_SHIFT;
150 mmio_write_32(base + GICD_ICENABLER + (n << 2), val);
151 return;
152}
153
154void gicd_write_ispendr(unsigned int base, unsigned int id, unsigned int val)
155{
156 unsigned n = id >> ISPENDR_SHIFT;
157 mmio_write_32(base + GICD_ISPENDR + (n << 2), val);
158 return;
159}
160
161void gicd_write_icpendr(unsigned int base, unsigned int id, unsigned int val)
162{
163 unsigned n = id >> ICPENDR_SHIFT;
164 mmio_write_32(base + GICD_ICPENDR + (n << 2), val);
165 return;
166}
167
168void gicd_write_isactiver(unsigned int base, unsigned int id, unsigned int val)
169{
170 unsigned n = id >> ISACTIVER_SHIFT;
171 mmio_write_32(base + GICD_ISACTIVER + (n << 2), val);
172 return;
173}
174
175void gicd_write_icactiver(unsigned int base, unsigned int id, unsigned int val)
176{
177 unsigned n = id >> ICACTIVER_SHIFT;
178 mmio_write_32(base + GICD_ICACTIVER + (n << 2), val);
179 return;
180}
181
182void gicd_write_ipriorityr(unsigned int base, unsigned int id, unsigned int val)
183{
184 unsigned n = id >> IPRIORITYR_SHIFT;
185 mmio_write_32(base + GICD_IPRIORITYR + (n << 2), val);
186 return;
187}
188
189void gicd_write_itargetsr(unsigned int base, unsigned int id, unsigned int val)
190{
191 unsigned n = id >> ITARGETSR_SHIFT;
192 mmio_write_32(base + GICD_ITARGETSR + (n << 2), val);
193 return;
194}
195
196void gicd_write_icfgr(unsigned int base, unsigned int id, unsigned int val)
197{
198 unsigned n = id >> ICFGR_SHIFT;
199 mmio_write_32(base + GICD_ICFGR + (n << 2), val);
200 return;
201}
202
203void gicd_write_sgir(unsigned int base, unsigned int val)
204{
205 mmio_write_32(base + GICD_SGIR, val);
206 return;
207}
208
209void gicd_write_cpendsgir(unsigned int base, unsigned int id, unsigned int val)
210{
211 unsigned n = id >> CPENDSGIR_SHIFT;
212 mmio_write_32(base + GICD_CPENDSGIR + (n << 2), val);
213 return;
214}
215
216void gicd_write_spendsgir(unsigned int base, unsigned int id, unsigned int val)
217{
218 unsigned n = id >> SPENDSGIR_SHIFT;
219 mmio_write_32(base + GICD_SPENDSGIR + (n << 2), val);
220 return;
221}
222
223/*******************************************************************************
224 * GIC Distributor interface accessesors for individual interrupt manipulation
225 ******************************************************************************/
226unsigned int gicd_get_igroupr(unsigned int base, unsigned int id)
227{
228 unsigned bit_num = id & ((1 << IGROUPR_SHIFT) - 1);
229 unsigned int reg_val = gicd_read_igroupr(base, id);
230
231 return (reg_val >> bit_num) & 0x1;
232}
233
234void gicd_set_igroupr(unsigned int base, unsigned int id)
235{
236 unsigned bit_num = id & ((1 << IGROUPR_SHIFT) - 1);
237 unsigned int reg_val = gicd_read_igroupr(base, id);
238
239 gicd_write_igroupr(base, id, reg_val | (1 << bit_num));
240 return;
241}
242
243void gicd_clr_igroupr(unsigned int base, unsigned int id)
244{
245 unsigned bit_num = id & ((1 << IGROUPR_SHIFT) - 1);
246 unsigned int reg_val = gicd_read_igroupr(base, id);
247
248 gicd_write_igroupr(base, id, reg_val & ~(1 << bit_num));
249 return;
250}
251
252void gicd_set_isenabler(unsigned int base, unsigned int id)
253{
254 unsigned bit_num = id & ((1 << ISENABLER_SHIFT) - 1);
255 unsigned int reg_val = gicd_read_isenabler(base, id);
256
257 gicd_write_isenabler(base, id, reg_val | (1 << bit_num));
258 return;
259}
260
261void gicd_set_icenabler(unsigned int base, unsigned int id)
262{
263 unsigned bit_num = id & ((1 << ICENABLER_SHIFT) - 1);
264 unsigned int reg_val = gicd_read_icenabler(base, id);
265
266 gicd_write_icenabler(base, id, reg_val & ~(1 << bit_num));
267 return;
268}
269
270void gicd_set_ispendr(unsigned int base, unsigned int id)
271{
272 unsigned bit_num = id & ((1 << ISPENDR_SHIFT) - 1);
273 unsigned int reg_val = gicd_read_ispendr(base, id);
274
275 gicd_write_ispendr(base, id, reg_val | (1 << bit_num));
276 return;
277}
278
279void gicd_set_icpendr(unsigned int base, unsigned int id)
280{
281 unsigned bit_num = id & ((1 << ICPENDR_SHIFT) - 1);
282 unsigned int reg_val = gicd_read_icpendr(base, id);
283
284 gicd_write_icpendr(base, id, reg_val & ~(1 << bit_num));
285 return;
286}
287
288void gicd_set_isactiver(unsigned int base, unsigned int id)
289{
290 unsigned bit_num = id & ((1 << ISACTIVER_SHIFT) - 1);
291 unsigned int reg_val = gicd_read_isactiver(base, id);
292
293 gicd_write_isactiver(base, id, reg_val | (1 << bit_num));
294 return;
295}
296
297void gicd_set_icactiver(unsigned int base, unsigned int id)
298{
299 unsigned bit_num = id & ((1 << ICACTIVER_SHIFT) - 1);
300 unsigned int reg_val = gicd_read_icactiver(base, id);
301
302 gicd_write_icactiver(base, id, reg_val & ~(1 << bit_num));
303 return;
304}
305
306/*
307 * Make sure that the interrupt's group is set before expecting
308 * this function to do its job correctly.
309 */
310void gicd_set_ipriorityr(unsigned int base, unsigned int id, unsigned int pri)
311{
312 unsigned byte_off = id & ((1 << ICACTIVER_SHIFT) - 1);
313 unsigned int reg_val = gicd_read_icactiver(base, id);
314
315 /*
316 * Enforce ARM recommendation to manage priority values such
317 * that group1 interrupts always have a lower priority than
318 * group0 interrupts
319 */
320 if (gicd_get_igroupr(base, id) == GRP1)
321 pri |= 1 << 7;
322 else
323 pri &= ~(1 << 7);
324
325 gicd_write_icactiver(base, id, reg_val & ~(pri << (byte_off << 3)));
326 return;
327}
328
329void gicd_set_itargetsr(unsigned int base, unsigned int id, unsigned int iface)
330{
331 unsigned byte_off = id & ((1 << ITARGETSR_SHIFT) - 1);
332 unsigned int reg_val = gicd_read_itargetsr(base, id);
333
334 gicd_write_itargetsr(base, id, reg_val |
335 (1 << iface) << (byte_off << 3));
336 return;
337}
338
339/*******************************************************************************
340 * GIC CPU interface accessesors for reading entire registers
341 ******************************************************************************/
342inline unsigned int gicc_read_ctlr(unsigned int base)
343{
344 return mmio_read_32(base + GICC_CTLR);
345}
346
347inline unsigned int gicc_read_pmr(unsigned int base)
348{
349 return mmio_read_32(base + GICC_PMR);
350}
351
352inline unsigned int gicc_read_BPR(unsigned int base)
353{
354 return mmio_read_32(base + GICC_BPR);
355}
356
357inline unsigned int gicc_read_IAR(unsigned int base)
358{
359 return mmio_read_32(base + GICC_IAR);
360}
361
362inline unsigned int gicc_read_EOIR(unsigned int base)
363{
364 return mmio_read_32(base + GICC_EOIR);
365}
366
367inline unsigned int gicc_read_hppir(unsigned int base)
368{
369 return mmio_read_32(base + GICC_HPPIR);
370}
371
372inline unsigned int gicc_read_dir(unsigned int base)
373{
374 return mmio_read_32(base + GICC_DIR);
375}
376
377inline unsigned int gicc_read_iidr(unsigned int base)
378{
379 return mmio_read_32(base + GICC_IIDR);
380}
381
382/*******************************************************************************
383 * GIC CPU interface accessesors for writing entire registers
384 ******************************************************************************/
385inline void gicc_write_ctlr(unsigned int base, unsigned int val)
386{
387 mmio_write_32(base + GICC_CTLR, val);
388 return;
389}
390
391inline void gicc_write_pmr(unsigned int base, unsigned int val)
392{
393 mmio_write_32(base + GICC_PMR, val);
394 return;
395}
396
397inline void gicc_write_BPR(unsigned int base, unsigned int val)
398{
399 mmio_write_32(base + GICC_BPR, val);
400 return;
401}
402
403inline void gicc_write_IAR(unsigned int base, unsigned int val)
404{
405 mmio_write_32(base + GICC_IAR, val);
406 return;
407}
408
409inline void gicc_write_EOIR(unsigned int base, unsigned int val)
410{
411 mmio_write_32(base + GICC_EOIR, val);
412 return;
413}
414
415inline void gicc_write_hppir(unsigned int base, unsigned int val)
416{
417 mmio_write_32(base + GICC_HPPIR, val);
418 return;
419}
420
421inline void gicc_write_dir(unsigned int base, unsigned int val)
422{
423 mmio_write_32(base + GICC_DIR, val);
424 return;
425}
426