gic_common.c 9.34 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
 */

#include <assert.h>
8
9
10
11

#include <drivers/arm/gic_common.h>
#include <lib/mmio.h>

12
#include "gic_common_private.h"
13
14
15
16
17
18
19
20
21
22

/*******************************************************************************
 * 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
23
24
	unsigned int n = id >> IGROUPR_SHIFT;

25
26
27
28
29
30
31
32
33
	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
34
35
	unsigned int n = id >> ISENABLER_SHIFT;

36
37
38
39
40
41
42
43
44
	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
45
46
	unsigned int n = id >> ICENABLER_SHIFT;

47
48
49
50
51
52
53
54
55
	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
56
57
	unsigned int n = id >> ISPENDR_SHIFT;

58
59
60
61
62
63
64
65
66
	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
67
68
	unsigned int n = id >> ICPENDR_SHIFT;

69
70
71
72
73
74
75
76
77
	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
78
79
	unsigned int n = id >> ISACTIVER_SHIFT;

80
81
82
83
84
85
86
87
88
	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
89
90
	unsigned int n = id >> ICACTIVER_SHIFT;

91
92
93
94
95
96
97
98
99
	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
100
101
	unsigned int n = id >> IPRIORITYR_SHIFT;

102
103
104
105
106
107
108
109
110
	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
111
112
	unsigned int n = id >> ICFGR_SHIFT;

113
114
115
116
117
118
119
120
121
	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
122
123
	unsigned int n = id >> NSACR_SHIFT;

124
125
126
127
128
129
130
131
132
133
134
135
	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
136
137
	unsigned int n = id >> IGROUPR_SHIFT;

138
139
140
141
142
143
144
145
146
	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
147
148
	unsigned int n = id >> ISENABLER_SHIFT;

149
150
151
152
153
154
155
156
157
	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
158
159
	unsigned int n = id >> ICENABLER_SHIFT;

160
161
162
163
164
165
166
167
168
	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
169
170
	unsigned int n = id >> ISPENDR_SHIFT;

171
172
173
174
175
176
177
178
179
	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
180
181
	unsigned int n = id >> ICPENDR_SHIFT;

182
183
184
185
186
187
188
189
190
	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
191
192
	unsigned int n = id >> ISACTIVER_SHIFT;

193
194
195
196
197
198
199
200
201
	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
202
203
	unsigned int n = id >> ICACTIVER_SHIFT;

204
205
206
207
208
209
210
211
212
	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
213
214
	unsigned int n = id >> IPRIORITYR_SHIFT;

215
216
217
218
219
220
221
222
223
	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
224
225
	unsigned int n = id >> ICFGR_SHIFT;

226
227
228
229
230
231
232
233
234
	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
235
236
	unsigned int n = id >> NSACR_SHIFT;

237
238
239
240
	mmio_write_32(base + GICD_NSACR + (n << 2), val);
}

/*******************************************************************************
241
242
243
244
 * 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.
245
246
247
 ******************************************************************************/
unsigned int gicd_get_igroupr(uintptr_t base, unsigned int id)
{
Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
248
	unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U);
249
250
	unsigned int reg_val = gicd_read_igroupr(base, id);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	mmio_write_8(base + GICD_IPRIORITYR + id, val);
325
}
326
327
328

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

333
334
335
	uint32_t reg_val = gicd_read_icfgr(base, id);

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

	gicd_write_icfgr(base, id, reg_val);
}