blob: 00464cbd2f86408b3b88eaa91926ad4799109e5e [file] [log] [blame]
Achin Gupta4f6ad662013-10-25 09:08:21 +01001/*
Dan Handleye83b0ca2014-01-14 18:17:09 +00002 * Copyright (c) 2013-2014, 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
Jon Medhurstd0212c22014-02-11 14:48:56 +000031#include <assert.h>
Dan Handley930ee2e2014-04-17 17:48:52 +010032#include <gic_v2.h>
Achin Gupta4f6ad662013-10-25 09:08:21 +010033#include <mmio.h>
34
35/*******************************************************************************
Sandrine Bailleux27866d82013-10-25 15:33:39 +010036 * GIC Distributor interface accessors for reading entire registers
Achin Gupta4f6ad662013-10-25 09:08:21 +010037 ******************************************************************************/
Achin Gupta4f6ad662013-10-25 09:08:21 +010038
39unsigned int gicd_read_igroupr(unsigned int base, unsigned int id)
40{
41 unsigned n = id >> IGROUPR_SHIFT;
42 return mmio_read_32(base + GICD_IGROUPR + (n << 2));
43}
44
45unsigned int gicd_read_isenabler(unsigned int base, unsigned int id)
46{
47 unsigned n = id >> ISENABLER_SHIFT;
48 return mmio_read_32(base + GICD_ISENABLER + (n << 2));
49}
50
51unsigned int gicd_read_icenabler(unsigned int base, unsigned int id)
52{
53 unsigned n = id >> ICENABLER_SHIFT;
54 return mmio_read_32(base + GICD_ICENABLER + (n << 2));
55}
56
57unsigned int gicd_read_ispendr(unsigned int base, unsigned int id)
58{
59 unsigned n = id >> ISPENDR_SHIFT;
60 return mmio_read_32(base + GICD_ISPENDR + (n << 2));
61}
62
63unsigned int gicd_read_icpendr(unsigned int base, unsigned int id)
64{
65 unsigned n = id >> ICPENDR_SHIFT;
66 return mmio_read_32(base + GICD_ICPENDR + (n << 2));
67}
68
69unsigned int gicd_read_isactiver(unsigned int base, unsigned int id)
70{
71 unsigned n = id >> ISACTIVER_SHIFT;
72 return mmio_read_32(base + GICD_ISACTIVER + (n << 2));
73}
74
75unsigned int gicd_read_icactiver(unsigned int base, unsigned int id)
76{
77 unsigned n = id >> ICACTIVER_SHIFT;
78 return mmio_read_32(base + GICD_ICACTIVER + (n << 2));
79}
80
81unsigned int gicd_read_ipriorityr(unsigned int base, unsigned int id)
82{
83 unsigned n = id >> IPRIORITYR_SHIFT;
84 return mmio_read_32(base + GICD_IPRIORITYR + (n << 2));
85}
86
87unsigned int gicd_read_itargetsr(unsigned int base, unsigned int id)
88{
89 unsigned n = id >> ITARGETSR_SHIFT;
90 return mmio_read_32(base + GICD_ITARGETSR + (n << 2));
91}
92
93unsigned int gicd_read_icfgr(unsigned int base, unsigned int id)
94{
95 unsigned n = id >> ICFGR_SHIFT;
96 return mmio_read_32(base + GICD_ICFGR + (n << 2));
97}
98
Achin Gupta4f6ad662013-10-25 09:08:21 +010099unsigned int gicd_read_cpendsgir(unsigned int base, unsigned int id)
100{
101 unsigned n = id >> CPENDSGIR_SHIFT;
102 return mmio_read_32(base + GICD_CPENDSGIR + (n << 2));
103}
104
105unsigned int gicd_read_spendsgir(unsigned int base, unsigned int id)
106{
107 unsigned n = id >> SPENDSGIR_SHIFT;
108 return mmio_read_32(base + GICD_SPENDSGIR + (n << 2));
109}
110
111/*******************************************************************************
Sandrine Bailleux27866d82013-10-25 15:33:39 +0100112 * GIC Distributor interface accessors for writing entire registers
Achin Gupta4f6ad662013-10-25 09:08:21 +0100113 ******************************************************************************/
Achin Gupta4f6ad662013-10-25 09:08:21 +0100114
115void gicd_write_igroupr(unsigned int base, unsigned int id, unsigned int val)
116{
117 unsigned n = id >> IGROUPR_SHIFT;
118 mmio_write_32(base + GICD_IGROUPR + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100119}
120
121void gicd_write_isenabler(unsigned int base, unsigned int id, unsigned int val)
122{
123 unsigned n = id >> ISENABLER_SHIFT;
124 mmio_write_32(base + GICD_ISENABLER + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100125}
126
127void gicd_write_icenabler(unsigned int base, unsigned int id, unsigned int val)
128{
129 unsigned n = id >> ICENABLER_SHIFT;
130 mmio_write_32(base + GICD_ICENABLER + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100131}
132
133void gicd_write_ispendr(unsigned int base, unsigned int id, unsigned int val)
134{
135 unsigned n = id >> ISPENDR_SHIFT;
136 mmio_write_32(base + GICD_ISPENDR + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100137}
138
139void gicd_write_icpendr(unsigned int base, unsigned int id, unsigned int val)
140{
141 unsigned n = id >> ICPENDR_SHIFT;
142 mmio_write_32(base + GICD_ICPENDR + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100143}
144
145void gicd_write_isactiver(unsigned int base, unsigned int id, unsigned int val)
146{
147 unsigned n = id >> ISACTIVER_SHIFT;
148 mmio_write_32(base + GICD_ISACTIVER + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100149}
150
151void gicd_write_icactiver(unsigned int base, unsigned int id, unsigned int val)
152{
153 unsigned n = id >> ICACTIVER_SHIFT;
154 mmio_write_32(base + GICD_ICACTIVER + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100155}
156
157void gicd_write_ipriorityr(unsigned int base, unsigned int id, unsigned int val)
158{
159 unsigned n = id >> IPRIORITYR_SHIFT;
160 mmio_write_32(base + GICD_IPRIORITYR + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100161}
162
163void gicd_write_itargetsr(unsigned int base, unsigned int id, unsigned int val)
164{
165 unsigned n = id >> ITARGETSR_SHIFT;
166 mmio_write_32(base + GICD_ITARGETSR + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100167}
168
169void gicd_write_icfgr(unsigned int base, unsigned int id, unsigned int val)
170{
171 unsigned n = id >> ICFGR_SHIFT;
172 mmio_write_32(base + GICD_ICFGR + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100173}
174
175void gicd_write_cpendsgir(unsigned int base, unsigned int id, unsigned int val)
176{
177 unsigned n = id >> CPENDSGIR_SHIFT;
178 mmio_write_32(base + GICD_CPENDSGIR + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100179}
180
181void gicd_write_spendsgir(unsigned int base, unsigned int id, unsigned int val)
182{
183 unsigned n = id >> SPENDSGIR_SHIFT;
184 mmio_write_32(base + GICD_SPENDSGIR + (n << 2), val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100185}
186
187/*******************************************************************************
Sandrine Bailleux27866d82013-10-25 15:33:39 +0100188 * GIC Distributor interface accessors for individual interrupt manipulation
Achin Gupta4f6ad662013-10-25 09:08:21 +0100189 ******************************************************************************/
190unsigned int gicd_get_igroupr(unsigned int base, unsigned int id)
191{
192 unsigned bit_num = id & ((1 << IGROUPR_SHIFT) - 1);
193 unsigned int reg_val = gicd_read_igroupr(base, id);
194
195 return (reg_val >> bit_num) & 0x1;
196}
197
198void gicd_set_igroupr(unsigned int base, unsigned int id)
199{
200 unsigned bit_num = id & ((1 << IGROUPR_SHIFT) - 1);
201 unsigned int reg_val = gicd_read_igroupr(base, id);
202
203 gicd_write_igroupr(base, id, reg_val | (1 << bit_num));
Achin Gupta4f6ad662013-10-25 09:08:21 +0100204}
205
206void gicd_clr_igroupr(unsigned int base, unsigned int id)
207{
208 unsigned bit_num = id & ((1 << IGROUPR_SHIFT) - 1);
209 unsigned int reg_val = gicd_read_igroupr(base, id);
210
211 gicd_write_igroupr(base, id, reg_val & ~(1 << bit_num));
Achin Gupta4f6ad662013-10-25 09:08:21 +0100212}
213
214void gicd_set_isenabler(unsigned int base, unsigned int id)
215{
216 unsigned bit_num = id & ((1 << ISENABLER_SHIFT) - 1);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100217
Juan Castillo969bdb22014-04-28 12:48:40 +0100218 gicd_write_isenabler(base, id, (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);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100224
Juan Castillo969bdb22014-04-28 12:48:40 +0100225 gicd_write_icenabler(base, id, (1 << bit_num));
Achin Gupta4f6ad662013-10-25 09:08:21 +0100226}
227
228void gicd_set_ispendr(unsigned int base, unsigned int id)
229{
230 unsigned bit_num = id & ((1 << ISPENDR_SHIFT) - 1);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100231
Juan Castillo969bdb22014-04-28 12:48:40 +0100232 gicd_write_ispendr(base, id, (1 << bit_num));
Achin Gupta4f6ad662013-10-25 09:08:21 +0100233}
234
235void gicd_set_icpendr(unsigned int base, unsigned int id)
236{
237 unsigned bit_num = id & ((1 << ICPENDR_SHIFT) - 1);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100238
Juan Castillo969bdb22014-04-28 12:48:40 +0100239 gicd_write_icpendr(base, id, (1 << bit_num));
Achin Gupta4f6ad662013-10-25 09:08:21 +0100240}
241
242void gicd_set_isactiver(unsigned int base, unsigned int id)
243{
244 unsigned bit_num = id & ((1 << ISACTIVER_SHIFT) - 1);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100245
Juan Castillo969bdb22014-04-28 12:48:40 +0100246 gicd_write_isactiver(base, id, (1 << bit_num));
Achin Gupta4f6ad662013-10-25 09:08:21 +0100247}
248
249void gicd_set_icactiver(unsigned int base, unsigned int id)
250{
251 unsigned bit_num = id & ((1 << ICACTIVER_SHIFT) - 1);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100252
Juan Castillo969bdb22014-04-28 12:48:40 +0100253 gicd_write_icactiver(base, id, (1 << bit_num));
Achin Gupta4f6ad662013-10-25 09:08:21 +0100254}
255
256/*
257 * Make sure that the interrupt's group is set before expecting
258 * this function to do its job correctly.
259 */
260void gicd_set_ipriorityr(unsigned int base, unsigned int id, unsigned int pri)
261{
Jon Medhurstd0212c22014-02-11 14:48:56 +0000262 unsigned int reg = base + GICD_IPRIORITYR + (id & ~3);
263 unsigned int shift = (id & 3) << 3;
264 unsigned int reg_val = mmio_read_32(reg);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100265
266 /*
267 * Enforce ARM recommendation to manage priority values such
268 * that group1 interrupts always have a lower priority than
Jon Medhurstd0212c22014-02-11 14:48:56 +0000269 * group0 interrupts.
270 * Note, lower numerical values are higher priorities so the comparison
271 * checks below are reversed from what might be expected.
Achin Gupta4f6ad662013-10-25 09:08:21 +0100272 */
Jon Medhurstd0212c22014-02-11 14:48:56 +0000273 assert(gicd_get_igroupr(base, id) == GRP1 ?
274 pri >= GIC_HIGHEST_NS_PRIORITY &&
275 pri <= GIC_LOWEST_NS_PRIORITY :
276 pri >= GIC_HIGHEST_SEC_PRIORITY &&
277 pri <= GIC_LOWEST_SEC_PRIORITY);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100278
Jon Medhurstd0212c22014-02-11 14:48:56 +0000279 reg_val &= ~(GIC_PRI_MASK << shift);
280 reg_val |= (pri & GIC_PRI_MASK) << shift;
281 mmio_write_32(reg, reg_val);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100282}
283
284void gicd_set_itargetsr(unsigned int base, unsigned int id, unsigned int iface)
285{
286 unsigned byte_off = id & ((1 << ITARGETSR_SHIFT) - 1);
287 unsigned int reg_val = gicd_read_itargetsr(base, id);
288
289 gicd_write_itargetsr(base, id, reg_val |
290 (1 << iface) << (byte_off << 3));
Achin Gupta4f6ad662013-10-25 09:08:21 +0100291}
292