gic_common.c 9.32 KB
Newer Older
1
/*
2
 * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
3
 *
dp-arm's avatar
dp-arm committed
4
 * SPDX-License-Identifier: BSD-3-Clause
5
6
7
8
9
 */

#include <assert.h>
#include <gic_common.h>
#include <mmio.h>
10
#include "gic_common_private.h"
11
12
13
14
15
16
17
18
19
20

/*******************************************************************************
 * GIC Distributor interface accessors for reading entire registers
 ******************************************************************************/
/*
 * Accessor to read the GIC Distributor IGROUPR corresponding to the interrupt
 * `id`, 32 interrupt ids at a time.
 */
unsigned int gicd_read_igroupr(uintptr_t base, unsigned int id)
{
Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
21
22
	unsigned int n = id >> IGROUPR_SHIFT;

23
24
25
26
27
28
29
30
31
	return mmio_read_32(base + GICD_IGROUPR + (n << 2));
}

/*
 * Accessor to read the GIC Distributor ISENABLER corresponding to the
 * interrupt `id`, 32 interrupt ids at a time.
 */
unsigned int gicd_read_isenabler(uintptr_t base, unsigned int id)
{
Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
32
33
	unsigned int n = id >> ISENABLER_SHIFT;

34
35
36
37
38
39
40
41
42
	return mmio_read_32(base + GICD_ISENABLER + (n << 2));
}

/*
 * Accessor to read the GIC Distributor ICENABLER corresponding to the
 * interrupt `id`, 32 interrupt IDs at a time.
 */
unsigned int gicd_read_icenabler(uintptr_t base, unsigned int id)
{
Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
43
44
	unsigned int n = id >> ICENABLER_SHIFT;

45
46
47
48
49
50
51
52
53
	return mmio_read_32(base + GICD_ICENABLER + (n << 2));
}

/*
 * Accessor to read the GIC Distributor ISPENDR corresponding to the
 * interrupt `id`, 32 interrupt IDs at a time.
 */
unsigned int gicd_read_ispendr(uintptr_t base, unsigned int id)
{
Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
54
55
	unsigned int n = id >> ISPENDR_SHIFT;

56
57
58
59
60
61
62
63
64
	return mmio_read_32(base + GICD_ISPENDR + (n << 2));
}

/*
 * Accessor to read the GIC Distributor ICPENDR corresponding to the
 * interrupt `id`, 32 interrupt IDs at a time.
 */
unsigned int gicd_read_icpendr(uintptr_t base, unsigned int id)
{
Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
65
66
	unsigned int n = id >> ICPENDR_SHIFT;

67
68
69
70
71
72
73
74
75
	return mmio_read_32(base + GICD_ICPENDR + (n << 2));
}

/*
 * Accessor to read the GIC Distributor ISACTIVER corresponding to the
 * interrupt `id`, 32 interrupt IDs at a time.
 */
unsigned int gicd_read_isactiver(uintptr_t base, unsigned int id)
{
Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
76
77
	unsigned int n = id >> ISACTIVER_SHIFT;

78
79
80
81
82
83
84
85
86
	return mmio_read_32(base + GICD_ISACTIVER + (n << 2));
}

/*
 * Accessor to read the GIC Distributor ICACTIVER corresponding to the
 * interrupt `id`, 32 interrupt IDs at a time.
 */
unsigned int gicd_read_icactiver(uintptr_t base, unsigned int id)
{
Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
87
88
	unsigned int n = id >> ICACTIVER_SHIFT;

89
90
91
92
93
94
95
96
97
	return mmio_read_32(base + GICD_ICACTIVER + (n << 2));
}

/*
 * Accessor to read the GIC Distributor IPRIORITYR corresponding to the
 * interrupt `id`, 4 interrupt IDs at a time.
 */
unsigned int gicd_read_ipriorityr(uintptr_t base, unsigned int id)
{
Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
98
99
	unsigned int n = id >> IPRIORITYR_SHIFT;

100
101
102
103
104
105
106
107
108
	return mmio_read_32(base + GICD_IPRIORITYR + (n << 2));
}

/*
 * Accessor to read the GIC Distributor ICGFR corresponding to the
 * interrupt `id`, 16 interrupt IDs at a time.
 */
unsigned int gicd_read_icfgr(uintptr_t base, unsigned int id)
{
Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
109
110
	unsigned int n = id >> ICFGR_SHIFT;

111
112
113
114
115
116
117
118
119
	return mmio_read_32(base + GICD_ICFGR + (n << 2));
}

/*
 * Accessor to read the GIC Distributor NSACR corresponding to the
 * interrupt `id`, 16 interrupt IDs at a time.
 */
unsigned int gicd_read_nsacr(uintptr_t base, unsigned int id)
{
Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
120
121
	unsigned int n = id >> NSACR_SHIFT;

122
123
124
125
126
127
128
129
130
131
132
133
	return mmio_read_32(base + GICD_NSACR + (n << 2));
}

/*******************************************************************************
 * GIC Distributor interface accessors for writing entire registers
 ******************************************************************************/
/*
 * Accessor to write the GIC Distributor IGROUPR corresponding to the
 * interrupt `id`, 32 interrupt IDs at a time.
 */
void gicd_write_igroupr(uintptr_t base, unsigned int id, unsigned int val)
{
Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
134
135
	unsigned int n = id >> IGROUPR_SHIFT;

136
137
138
139
140
141
142
143
144
	mmio_write_32(base + GICD_IGROUPR + (n << 2), val);
}

/*
 * Accessor to write the GIC Distributor ISENABLER corresponding to the
 * interrupt `id`, 32 interrupt IDs at a time.
 */
void gicd_write_isenabler(uintptr_t base, unsigned int id, unsigned int val)
{
Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
145
146
	unsigned int n = id >> ISENABLER_SHIFT;

147
148
149
150
151
152
153
154
155
	mmio_write_32(base + GICD_ISENABLER + (n << 2), val);
}

/*
 * Accessor to write the GIC Distributor ICENABLER corresponding to the
 * interrupt `id`, 32 interrupt IDs at a time.
 */
void gicd_write_icenabler(uintptr_t base, unsigned int id, unsigned int val)
{
Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
156
157
	unsigned int n = id >> ICENABLER_SHIFT;

158
159
160
161
162
163
164
165
166
	mmio_write_32(base + GICD_ICENABLER + (n << 2), val);
}

/*
 * Accessor to write the GIC Distributor ISPENDR corresponding to the
 * interrupt `id`, 32 interrupt IDs at a time.
 */
void gicd_write_ispendr(uintptr_t base, unsigned int id, unsigned int val)
{
Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
167
168
	unsigned int n = id >> ISPENDR_SHIFT;

169
170
171
172
173
174
175
176
177
	mmio_write_32(base + GICD_ISPENDR + (n << 2), val);
}

/*
 * Accessor to write the GIC Distributor ICPENDR corresponding to the
 * interrupt `id`, 32 interrupt IDs at a time.
 */
void gicd_write_icpendr(uintptr_t base, unsigned int id, unsigned int val)
{
Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
178
179
	unsigned int n = id >> ICPENDR_SHIFT;

180
181
182
183
184
185
186
187
188
	mmio_write_32(base + GICD_ICPENDR + (n << 2), val);
}

/*
 * Accessor to write the GIC Distributor ISACTIVER corresponding to the
 * interrupt `id`, 32 interrupt IDs at a time.
 */
void gicd_write_isactiver(uintptr_t base, unsigned int id, unsigned int val)
{
Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
189
190
	unsigned int n = id >> ISACTIVER_SHIFT;

191
192
193
194
195
196
197
198
199
	mmio_write_32(base + GICD_ISACTIVER + (n << 2), val);
}

/*
 * Accessor to write the GIC Distributor ICACTIVER corresponding to the
 * interrupt `id`, 32 interrupt IDs at a time.
 */
void gicd_write_icactiver(uintptr_t base, unsigned int id, unsigned int val)
{
Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
200
201
	unsigned int n = id >> ICACTIVER_SHIFT;

202
203
204
205
206
207
208
209
210
	mmio_write_32(base + GICD_ICACTIVER + (n << 2), val);
}

/*
 * Accessor to write the GIC Distributor IPRIORITYR corresponding to the
 * interrupt `id`, 4 interrupt IDs at a time.
 */
void gicd_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val)
{
Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
211
212
	unsigned int n = id >> IPRIORITYR_SHIFT;

213
214
215
216
217
218
219
220
221
	mmio_write_32(base + GICD_IPRIORITYR + (n << 2), val);
}

/*
 * Accessor to write the GIC Distributor ICFGR corresponding to the
 * interrupt `id`, 16 interrupt IDs at a time.
 */
void gicd_write_icfgr(uintptr_t base, unsigned int id, unsigned int val)
{
Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
222
223
	unsigned int n = id >> ICFGR_SHIFT;

224
225
226
227
228
229
230
231
232
	mmio_write_32(base + GICD_ICFGR + (n << 2), val);
}

/*
 * Accessor to write the GIC Distributor NSACR corresponding to the
 * interrupt `id`, 16 interrupt IDs at a time.
 */
void gicd_write_nsacr(uintptr_t base, unsigned int id, unsigned int val)
{
Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
233
234
	unsigned int n = id >> NSACR_SHIFT;

235
236
237
238
	mmio_write_32(base + GICD_NSACR + (n << 2), val);
}

/*******************************************************************************
239
240
241
242
 * GIC Distributor functions for accessing the GIC registers
 * corresponding to a single interrupt ID. These functions use bitwise
 * operations or appropriate register accesses to modify or return
 * the bit-field corresponding the single interrupt ID.
243
244
245
 ******************************************************************************/
unsigned int gicd_get_igroupr(uintptr_t base, unsigned int id)
{
Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
246
	unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U);
247
248
	unsigned int reg_val = gicd_read_igroupr(base, id);

Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
249
	return (reg_val >> bit_num) & 0x1U;
250
251
252
253
}

void gicd_set_igroupr(uintptr_t base, unsigned int id)
{
Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
254
	unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U);
255
256
	unsigned int reg_val = gicd_read_igroupr(base, id);

Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
257
	gicd_write_igroupr(base, id, reg_val | (1U << bit_num));
258
259
260
261
}

void gicd_clr_igroupr(uintptr_t base, unsigned int id)
{
Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
262
	unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U);
263
264
	unsigned int reg_val = gicd_read_igroupr(base, id);

Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
265
	gicd_write_igroupr(base, id, reg_val & ~(1U << bit_num));
266
267
268
269
}

void gicd_set_isenabler(uintptr_t base, unsigned int id)
{
Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
270
	unsigned int bit_num = id & ((1U << ISENABLER_SHIFT) - 1U);
271

Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
272
	gicd_write_isenabler(base, id, (1U << bit_num));
273
274
275
276
}

void gicd_set_icenabler(uintptr_t base, unsigned int id)
{
Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
277
	unsigned int bit_num = id & ((1U << ICENABLER_SHIFT) - 1U);
278

Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
279
	gicd_write_icenabler(base, id, (1U << bit_num));
280
281
282
283
}

void gicd_set_ispendr(uintptr_t base, unsigned int id)
{
Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
284
	unsigned int bit_num = id & ((1U << ISPENDR_SHIFT) - 1U);
285

Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
286
	gicd_write_ispendr(base, id, (1U << bit_num));
287
288
289
290
}

void gicd_set_icpendr(uintptr_t base, unsigned int id)
{
Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
291
	unsigned int bit_num = id & ((1U << ICPENDR_SHIFT) - 1U);
292

Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
293
	gicd_write_icpendr(base, id, (1U << bit_num));
294
295
}

296
297
unsigned int gicd_get_isactiver(uintptr_t base, unsigned int id)
{
Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
298
	unsigned int bit_num = id & ((1U << ISACTIVER_SHIFT) - 1U);
299
300
	unsigned int reg_val = gicd_read_isactiver(base, id);

Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
301
	return (reg_val >> bit_num) & 0x1U;
302
303
}

304
305
void gicd_set_isactiver(uintptr_t base, unsigned int id)
{
Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
306
	unsigned int bit_num = id & ((1U << ISACTIVER_SHIFT) - 1U);
307

Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
308
	gicd_write_isactiver(base, id, (1U << bit_num));
309
310
311
312
}

void gicd_set_icactiver(uintptr_t base, unsigned int id)
{
Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
313
	unsigned int bit_num = id & ((1U << ICACTIVER_SHIFT) - 1U);
314

Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
315
	gicd_write_icactiver(base, id, (1U << bit_num));
316
}
317
318
319

void gicd_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri)
{
Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
320
321
322
	uint8_t val = pri & GIC_PRI_MASK;

	mmio_write_8(base + GICD_IPRIORITYR + id, val);
323
}
324
325
326

void gicd_set_icfgr(uintptr_t base, unsigned int id, unsigned int cfg)
{
327
	/* Interrupt configuration is a 2-bit field */
Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
328
	unsigned int bit_num = id & ((1U << ICFGR_SHIFT) - 1U);
329
330
	unsigned int bit_shift = bit_num << 1;

331
332
333
	uint32_t reg_val = gicd_read_icfgr(base, id);

	/* Clear the field, and insert required configuration */
334
335
	reg_val &= ~(GIC_CFG_MASK << bit_shift);
	reg_val |= ((cfg & GIC_CFG_MASK) << bit_shift);
336
337
338

	gicd_write_icfgr(base, id, reg_val);
}