blob: 6c928d55d039a0be4a6f67838966182e431e0509 [file] [log] [blame]
Achin Gupta4f6ad662013-10-25 09:08:21 +01001/*
Dan Handleyab2d31e2013-12-02 19:25:12 +00002 * Copyright (c) 2013, ARM Limited and Contributors. All rights reserved.
Achin Gupta4f6ad662013-10-25 09:08:21 +01003 *
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/*******************************************************************************
Sandrine Bailleux27866d82013-10-25 15:33:39 +010035 * GIC Distributor interface accessors for reading entire registers
Achin Gupta4f6ad662013-10-25 09:08:21 +010036 ******************************************************************************/
Achin Gupta4f6ad662013-10-25 09:08:21 +010037
38unsigned int gicd_read_igroupr(unsigned int base, unsigned int id)
39{
40 unsigned n = id >> IGROUPR_SHIFT;
41 return mmio_read_32(base + GICD_IGROUPR + (n << 2));
42}
43
44unsigned int gicd_read_isenabler(unsigned int base, unsigned int id)
45{
46 unsigned n = id >> ISENABLER_SHIFT;
47 return mmio_read_32(base + GICD_ISENABLER + (n << 2));
48}
49
50unsigned int gicd_read_icenabler(unsigned int base, unsigned int id)
51{
52 unsigned n = id >> ICENABLER_SHIFT;
53 return mmio_read_32(base + GICD_ICENABLER + (n << 2));
54}
55
56unsigned int gicd_read_ispendr(unsigned int base, unsigned int id)
57{
58 unsigned n = id >> ISPENDR_SHIFT;
59 return mmio_read_32(base + GICD_ISPENDR + (n << 2));
60}
61
62unsigned int gicd_read_icpendr(unsigned int base, unsigned int id)
63{
64 unsigned n = id >> ICPENDR_SHIFT;
65 return mmio_read_32(base + GICD_ICPENDR + (n << 2));
66}
67
68unsigned int gicd_read_isactiver(unsigned int base, unsigned int id)
69{
70 unsigned n = id >> ISACTIVER_SHIFT;
71 return mmio_read_32(base + GICD_ISACTIVER + (n << 2));
72}
73
74unsigned int gicd_read_icactiver(unsigned int base, unsigned int id)
75{
76 unsigned n = id >> ICACTIVER_SHIFT;
77 return mmio_read_32(base + GICD_ICACTIVER + (n << 2));
78}
79
80unsigned int gicd_read_ipriorityr(unsigned int base, unsigned int id)
81{
82 unsigned n = id >> IPRIORITYR_SHIFT;
83 return mmio_read_32(base + GICD_IPRIORITYR + (n << 2));
84}
85
86unsigned int gicd_read_itargetsr(unsigned int base, unsigned int id)
87{
88 unsigned n = id >> ITARGETSR_SHIFT;
89 return mmio_read_32(base + GICD_ITARGETSR + (n << 2));
90}
91
92unsigned int gicd_read_icfgr(unsigned int base, unsigned int id)
93{
94 unsigned n = id >> ICFGR_SHIFT;
95 return mmio_read_32(base + GICD_ICFGR + (n << 2));
96}
97
Achin Gupta4f6ad662013-10-25 09:08:21 +010098unsigned int gicd_read_cpendsgir(unsigned int base, unsigned int id)
99{
100 unsigned n = id >> CPENDSGIR_SHIFT;
101 return mmio_read_32(base + GICD_CPENDSGIR + (n << 2));
102}
103
104unsigned int gicd_read_spendsgir(unsigned int base, unsigned int id)
105{
106 unsigned n = id >> SPENDSGIR_SHIFT;
107 return mmio_read_32(base + GICD_SPENDSGIR + (n << 2));
108}
109
110/*******************************************************************************
Sandrine Bailleux27866d82013-10-25 15:33:39 +0100111 * GIC Distributor interface accessors for writing entire registers
Achin Gupta4f6ad662013-10-25 09:08:21 +0100112 ******************************************************************************/
Achin Gupta4f6ad662013-10-25 09:08:21 +0100113
114void gicd_write_igroupr(unsigned int base, unsigned int id, unsigned int val)
115{
116 unsigned n = id >> IGROUPR_SHIFT;
117 mmio_write_32(base + GICD_IGROUPR + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100118}
119
120void gicd_write_isenabler(unsigned int base, unsigned int id, unsigned int val)
121{
122 unsigned n = id >> ISENABLER_SHIFT;
123 mmio_write_32(base + GICD_ISENABLER + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100124}
125
126void gicd_write_icenabler(unsigned int base, unsigned int id, unsigned int val)
127{
128 unsigned n = id >> ICENABLER_SHIFT;
129 mmio_write_32(base + GICD_ICENABLER + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100130}
131
132void gicd_write_ispendr(unsigned int base, unsigned int id, unsigned int val)
133{
134 unsigned n = id >> ISPENDR_SHIFT;
135 mmio_write_32(base + GICD_ISPENDR + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100136}
137
138void gicd_write_icpendr(unsigned int base, unsigned int id, unsigned int val)
139{
140 unsigned n = id >> ICPENDR_SHIFT;
141 mmio_write_32(base + GICD_ICPENDR + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100142}
143
144void gicd_write_isactiver(unsigned int base, unsigned int id, unsigned int val)
145{
146 unsigned n = id >> ISACTIVER_SHIFT;
147 mmio_write_32(base + GICD_ISACTIVER + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100148}
149
150void gicd_write_icactiver(unsigned int base, unsigned int id, unsigned int val)
151{
152 unsigned n = id >> ICACTIVER_SHIFT;
153 mmio_write_32(base + GICD_ICACTIVER + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100154}
155
156void gicd_write_ipriorityr(unsigned int base, unsigned int id, unsigned int val)
157{
158 unsigned n = id >> IPRIORITYR_SHIFT;
159 mmio_write_32(base + GICD_IPRIORITYR + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100160}
161
162void gicd_write_itargetsr(unsigned int base, unsigned int id, unsigned int val)
163{
164 unsigned n = id >> ITARGETSR_SHIFT;
165 mmio_write_32(base + GICD_ITARGETSR + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100166}
167
168void gicd_write_icfgr(unsigned int base, unsigned int id, unsigned int val)
169{
170 unsigned n = id >> ICFGR_SHIFT;
171 mmio_write_32(base + GICD_ICFGR + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100172}
173
174void gicd_write_cpendsgir(unsigned int base, unsigned int id, unsigned int val)
175{
176 unsigned n = id >> CPENDSGIR_SHIFT;
177 mmio_write_32(base + GICD_CPENDSGIR + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100178}
179
180void gicd_write_spendsgir(unsigned int base, unsigned int id, unsigned int val)
181{
182 unsigned n = id >> SPENDSGIR_SHIFT;
183 mmio_write_32(base + GICD_SPENDSGIR + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100184}
185
186/*******************************************************************************
Sandrine Bailleux27866d82013-10-25 15:33:39 +0100187 * GIC Distributor interface accessors for individual interrupt manipulation
Achin Gupta4f6ad662013-10-25 09:08:21 +0100188 ******************************************************************************/
189unsigned int gicd_get_igroupr(unsigned int base, unsigned int id)
190{
191 unsigned bit_num = id & ((1 << IGROUPR_SHIFT) - 1);
192 unsigned int reg_val = gicd_read_igroupr(base, id);
193
194 return (reg_val >> bit_num) & 0x1;
195}
196
197void gicd_set_igroupr(unsigned int base, unsigned int id)
198{
199 unsigned bit_num = id & ((1 << IGROUPR_SHIFT) - 1);
200 unsigned int reg_val = gicd_read_igroupr(base, id);
201
202 gicd_write_igroupr(base, id, reg_val | (1 << bit_num));
Achin Gupta4f6ad662013-10-25 09:08:21 +0100203}
204
205void gicd_clr_igroupr(unsigned int base, unsigned int id)
206{
207 unsigned bit_num = id & ((1 << IGROUPR_SHIFT) - 1);
208 unsigned int reg_val = gicd_read_igroupr(base, id);
209
210 gicd_write_igroupr(base, id, reg_val & ~(1 << bit_num));
Achin Gupta4f6ad662013-10-25 09:08:21 +0100211}
212
213void gicd_set_isenabler(unsigned int base, unsigned int id)
214{
215 unsigned bit_num = id & ((1 << ISENABLER_SHIFT) - 1);
216 unsigned int reg_val = gicd_read_isenabler(base, id);
217
218 gicd_write_isenabler(base, id, reg_val | (1 << bit_num));
Achin Gupta4f6ad662013-10-25 09:08:21 +0100219}
220
221void gicd_set_icenabler(unsigned int base, unsigned int id)
222{
223 unsigned bit_num = id & ((1 << ICENABLER_SHIFT) - 1);
224 unsigned int reg_val = gicd_read_icenabler(base, id);
225
226 gicd_write_icenabler(base, id, reg_val & ~(1 << bit_num));
Achin Gupta4f6ad662013-10-25 09:08:21 +0100227}
228
229void gicd_set_ispendr(unsigned int base, unsigned int id)
230{
231 unsigned bit_num = id & ((1 << ISPENDR_SHIFT) - 1);
232 unsigned int reg_val = gicd_read_ispendr(base, id);
233
234 gicd_write_ispendr(base, id, reg_val | (1 << bit_num));
Achin Gupta4f6ad662013-10-25 09:08:21 +0100235}
236
237void gicd_set_icpendr(unsigned int base, unsigned int id)
238{
239 unsigned bit_num = id & ((1 << ICPENDR_SHIFT) - 1);
240 unsigned int reg_val = gicd_read_icpendr(base, id);
241
242 gicd_write_icpendr(base, id, reg_val & ~(1 << bit_num));
Achin Gupta4f6ad662013-10-25 09:08:21 +0100243}
244
245void gicd_set_isactiver(unsigned int base, unsigned int id)
246{
247 unsigned bit_num = id & ((1 << ISACTIVER_SHIFT) - 1);
248 unsigned int reg_val = gicd_read_isactiver(base, id);
249
250 gicd_write_isactiver(base, id, reg_val | (1 << bit_num));
Achin Gupta4f6ad662013-10-25 09:08:21 +0100251}
252
253void gicd_set_icactiver(unsigned int base, unsigned int id)
254{
255 unsigned bit_num = id & ((1 << ICACTIVER_SHIFT) - 1);
256 unsigned int reg_val = gicd_read_icactiver(base, id);
257
258 gicd_write_icactiver(base, id, reg_val & ~(1 << bit_num));
Achin Gupta4f6ad662013-10-25 09:08:21 +0100259}
260
261/*
262 * Make sure that the interrupt's group is set before expecting
263 * this function to do its job correctly.
264 */
265void gicd_set_ipriorityr(unsigned int base, unsigned int id, unsigned int pri)
266{
267 unsigned byte_off = id & ((1 << ICACTIVER_SHIFT) - 1);
268 unsigned int reg_val = gicd_read_icactiver(base, id);
269
270 /*
271 * Enforce ARM recommendation to manage priority values such
272 * that group1 interrupts always have a lower priority than
273 * group0 interrupts
274 */
275 if (gicd_get_igroupr(base, id) == GRP1)
276 pri |= 1 << 7;
277 else
278 pri &= ~(1 << 7);
279
280 gicd_write_icactiver(base, id, reg_val & ~(pri << (byte_off << 3)));
Achin Gupta4f6ad662013-10-25 09:08:21 +0100281}
282
283void gicd_set_itargetsr(unsigned int base, unsigned int id, unsigned int iface)
284{
285 unsigned byte_off = id & ((1 << ITARGETSR_SHIFT) - 1);
286 unsigned int reg_val = gicd_read_itargetsr(base, id);
287
288 gicd_write_itargetsr(base, id, reg_val |
289 (1 << iface) << (byte_off << 3));
Achin Gupta4f6ad662013-10-25 09:08:21 +0100290}
291